]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
Horizon validity (anti-aliased) added to Plane2Cylinder
[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) FormatLocaleString(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(MAGICKCORE_QUANTUM_DEPTH);
738       if (strEQ(name,"QuantumRange"))
739         return(QuantumRange);
740       break;
741     }
742     case 'R':
743     {
744       if (strEQ(name,"ResourceLimitError"))
745         return(ResourceLimitError);
746       if (strEQ(name,"ResourceLimitWarning"))
747         return(ResourceLimitWarning);
748       if (strEQ(name,"RegistryError"))
749         return(RegistryError);
750       if (strEQ(name,"RegistryWarning"))
751         return(RegistryWarning);
752       break;
753     }
754     case 'S':
755     {
756       if (strEQ(name,"StreamError"))
757         return(StreamError);
758       if (strEQ(name,"StreamWarning"))
759         return(StreamWarning);
760       if (strEQ(name,"Success"))
761         return(0);
762       break;
763     }
764     case 'T':
765     {
766       if (strEQ(name,"Transparent"))
767         return(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,
847   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
848 {
849   Image
850     *image;
851
852   if (reference == (SV *) NULL)
853     return(NULL);
854   switch (SvTYPE(reference))
855   {
856     case SVt_PVAV:
857     {
858       AV
859         *av;
860
861       Image
862         *head,
863         *previous;
864
865       register ssize_t
866         i;
867
868       ssize_t
869         n;
870
871       /*
872         Array of images.
873       */
874       previous=(Image *) NULL;
875       head=(Image *) NULL;
876       av=(AV *) reference;
877       n=av_len(av);
878       for (i=0; i <= n; i++)
879       {
880         SV
881           **rv;
882
883         rv=av_fetch(av,i,0);
884         if (rv && *rv && sv_isobject(*rv))
885           {
886             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
887               exception);
888             if (image == (Image *) NULL)
889               continue;
890             if (image == previous)
891               {
892                 image=CloneImage(image,0,0,MagickTrue,exception);
893                 if (image == (Image *) NULL)
894                   return(NULL);
895               }
896             image->previous=previous;
897             *(previous ? &previous->next : &head)=image;
898             for (previous=image; previous->next; previous=previous->next) ;
899           }
900       }
901       return(head);
902     }
903     case SVt_PVMG:
904     {
905       /*
906         Blessed scalar, one image.
907       */
908       image=(Image *) SvIV(reference);
909       if (image == (Image *) NULL)
910         return(NULL);
911       image->previous=(Image *) NULL;
912       image->next=(Image *) NULL;
913       if (reference_vector)
914         {
915           if (*current == *last)
916             {
917               *last+=256;
918               if (*reference_vector == (SV **) NULL)
919                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
920                   sizeof(*reference_vector));
921               else
922                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
923                   *last,sizeof(*reference_vector));
924             }
925           if (*reference_vector == (SV **) NULL)
926             {
927               ThrowPerlException(exception,ResourceLimitError,
928                 "MemoryAllocationFailed",PackageName);
929               return((Image *) NULL);
930             }
931           (*reference_vector)[*current]=reference;
932           (*reference_vector)[++(*current)]=NULL;
933         }
934       return(image);
935     }
936     default:
937       break;
938   }
939   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
940     (double) SvTYPE(reference));
941   return((Image *) NULL);
942 }
943 \f
944 /*
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %   G e t P a c k a g e I n f o                                               %
950 %                                                                             %
951 %                                                                             %
952 %                                                                             %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %
955 %  Method GetPackageInfo looks up or creates an info structure for the given
956 %  Image__Magick reference.  If it does create a new one, the information in
957 %  package_info is used to initialize it.
958 %
959 %  The format of the GetPackageInfo routine is:
960 %
961 %      struct PackageInfo *GetPackageInfo(void *reference,
962 %        struct PackageInfo *package_info,ExceptionInfo *exception)
963 %
964 %  A description of each parameter follows:
965 %
966 %    o info: a structure of type info.
967 %
968 %    o exception: Return any errors or warnings in this structure.
969 %
970 */
971 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
972   struct PackageInfo *package_info,ExceptionInfo *exception)
973 {
974   char
975     message[MaxTextExtent];
976
977   struct PackageInfo
978     *clone_info;
979
980   SV
981     *sv;
982
983   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
984     PackageName,XS_VERSION,reference);
985   sv=perl_get_sv(message,(TRUE | 0x02));
986   if (sv == (SV *) NULL)
987     {
988       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
989         message);
990       return(package_info);
991     }
992   if (SvREFCNT(sv) == 0)
993     (void) SvREFCNT_inc(sv);
994   if (SvIOKp(sv) && (clone_info=(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 double SiPrefixToDouble(const char *string,const double interval)
1029 {
1030   char
1031     *q;
1032
1033   double
1034     scale,
1035     value;
1036
1037   value=InterpretLocaleValue(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 ssize_t StringToLong(const char *value)
1058 {
1059   return(strtol(value,(char **) NULL,10));
1060 }
1061
1062 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1063   const char *attribute,SV *sval,ExceptionInfo *exception)
1064 {
1065   GeometryInfo
1066     geometry_info;
1067
1068   long
1069     x,
1070     y;
1071
1072   MagickPixelPacket
1073     pixel;
1074
1075   MagickStatusType
1076     flags;
1077
1078   PixelPacket
1079     *color,
1080     target_color;
1081
1082   ssize_t
1083     sp;
1084
1085   switch (*attribute)
1086   {
1087     case 'A':
1088     case 'a':
1089     {
1090       if (LocaleCompare(attribute,"adjoin") == 0)
1091         {
1092           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1093             SvPV(sval,na)) : SvIV(sval);
1094           if (sp < 0)
1095             {
1096               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1097                 SvPV(sval,na));
1098               break;
1099             }
1100           if (info)
1101             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1102           break;
1103         }
1104       if (LocaleCompare(attribute,"alpha") == 0)
1105         {
1106           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1107             SvPV(sval,na)) : SvIV(sval);
1108           if (sp < 0)
1109             {
1110               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1111                 SvPV(sval,na));
1112               break;
1113             }
1114           for ( ; image; image=image->next)
1115             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1116           break;
1117         }
1118       if (LocaleCompare(attribute,"antialias") == 0)
1119         {
1120           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1121             SvPV(sval,na)) : SvIV(sval);
1122           if (sp < 0)
1123             {
1124               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1125                 SvPV(sval,na));
1126               break;
1127             }
1128           if (info)
1129             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1130           break;
1131         }
1132       if (LocaleCompare(attribute,"area-limit") == 0)
1133         {
1134           MagickSizeType
1135             limit;
1136
1137           limit=MagickResourceInfinity;
1138           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1139             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1140           (void) SetMagickResourceLimit(AreaResource,limit);
1141           break;
1142         }
1143       if (LocaleCompare(attribute,"attenuate") == 0)
1144         {
1145           if (info)
1146             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1147           break;
1148         }
1149       if (LocaleCompare(attribute,"authenticate") == 0)
1150         {
1151           if (info)
1152             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1153           break;
1154         }
1155       if (info)
1156         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1157       for ( ; image; image=image->next)
1158         SetImageProperty(image,attribute,SvPV(sval,na));
1159       break;
1160     }
1161     case 'B':
1162     case 'b':
1163     {
1164       if (LocaleCompare(attribute,"background") == 0)
1165         {
1166           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1167           if (info)
1168             info->image_info->background_color=target_color;
1169           for ( ; image; image=image->next)
1170             image->background_color=target_color;
1171           break;
1172         }
1173       if (LocaleCompare(attribute,"bias") == 0)
1174         {
1175           for ( ; image; image=image->next)
1176             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1177           break;
1178         }
1179       if (LocaleCompare(attribute,"blue-primary") == 0)
1180         {
1181           for ( ; image; image=image->next)
1182           {
1183             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1184             image->chromaticity.blue_primary.x=geometry_info.rho;
1185             image->chromaticity.blue_primary.y=geometry_info.sigma;
1186             if ((flags & SigmaValue) == 0)
1187               image->chromaticity.blue_primary.y=
1188                 image->chromaticity.blue_primary.x;
1189           }
1190           break;
1191         }
1192       if (LocaleCompare(attribute,"bordercolor") == 0)
1193         {
1194           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1195           if (info)
1196             info->image_info->border_color=target_color;
1197           for ( ; image; image=image->next)
1198             image->border_color=target_color;
1199           break;
1200         }
1201       if (info)
1202         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1203       for ( ; image; image=image->next)
1204         SetImageProperty(image,attribute,SvPV(sval,na));
1205       break;
1206     }
1207     case 'C':
1208     case 'c':
1209     {
1210       if (LocaleCompare(attribute,"cache-threshold") == 0)
1211         {
1212           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1213             SiPrefixToDouble(SvPV(sval,na),100.0));
1214           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1215             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1216           break;
1217         }
1218       if (LocaleCompare(attribute,"clip-mask") == 0)
1219         {
1220           Image
1221             *clip_mask;
1222
1223           clip_mask=(Image *) NULL;
1224           if (SvPOK(sval))
1225             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1226           for ( ; image; image=image->next)
1227             SetImageClipMask(image,clip_mask);
1228           break;
1229         }
1230       if (LocaleNCompare(attribute,"colormap",8) == 0)
1231         {
1232           for ( ; image; image=image->next)
1233           {
1234             int
1235               items;
1236
1237             long
1238               i;
1239
1240             if (image->storage_class == DirectClass)
1241               continue;
1242             i=0;
1243             items=sscanf(attribute,"%*[^[][%ld",&i);
1244             (void) items;
1245             if (i > (ssize_t) image->colors)
1246               i%=image->colors;
1247             if ((strchr(SvPV(sval,na),',') == 0) ||
1248                 (strchr(SvPV(sval,na),')') != 0))
1249               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1250             else
1251               {
1252                 color=image->colormap+i;
1253                 pixel.red=color->red;
1254                 pixel.green=color->green;
1255                 pixel.blue=color->blue;
1256                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1257                 pixel.red=geometry_info.rho;
1258                 pixel.green=geometry_info.sigma;
1259                 pixel.blue=geometry_info.xi;
1260                 color->red=ClampToQuantum(pixel.red);
1261                 color->green=ClampToQuantum(pixel.green);
1262                 color->blue=ClampToQuantum(pixel.blue);
1263               }
1264           }
1265           break;
1266         }
1267       if (LocaleCompare(attribute,"colorspace") == 0)
1268         {
1269           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1270             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1271           if (sp < 0)
1272             {
1273               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1274                 SvPV(sval,na));
1275               break;
1276             }
1277           for ( ; image; image=image->next)
1278             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1279           break;
1280         }
1281       if (LocaleCompare(attribute,"comment") == 0)
1282         {
1283           for ( ; image; image=image->next)
1284             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1285               info ? info->image_info : (ImageInfo *) NULL,image,
1286               SvPV(sval,na)));
1287           break;
1288         }
1289       if (LocaleCompare(attribute,"compression") == 0)
1290         {
1291           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1292             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1293           if (sp < 0)
1294             {
1295               ThrowPerlException(exception,OptionError,
1296                 "UnrecognizedImageCompression",SvPV(sval,na));
1297               break;
1298             }
1299           if (info)
1300             info->image_info->compression=(CompressionType) sp;
1301           for ( ; image; image=image->next)
1302             image->compression=(CompressionType) sp;
1303           break;
1304         }
1305       if (info)
1306         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1307       for ( ; image; image=image->next)
1308         SetImageProperty(image,attribute,SvPV(sval,na));
1309       break;
1310     }
1311     case 'D':
1312     case 'd':
1313     {
1314       if (LocaleCompare(attribute,"debug") == 0)
1315         {
1316           SetLogEventMask(SvPV(sval,na));
1317           break;
1318         }
1319       if (LocaleCompare(attribute,"delay") == 0)
1320         {
1321           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1322           for ( ; image; image=image->next)
1323           {
1324             image->delay=(size_t) floor(geometry_info.rho+0.5);
1325             if ((flags & SigmaValue) != 0)
1326               image->ticks_per_second=(ssize_t)
1327                 floor(geometry_info.sigma+0.5);
1328           }
1329           break;
1330         }
1331       if (LocaleCompare(attribute,"disk-limit") == 0)
1332         {
1333           MagickSizeType
1334             limit;
1335
1336           limit=MagickResourceInfinity;
1337           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1338             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1339           (void) SetMagickResourceLimit(DiskResource,limit);
1340           break;
1341         }
1342       if (LocaleCompare(attribute,"density") == 0)
1343         {
1344           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1345             {
1346               ThrowPerlException(exception,OptionError,"MissingGeometry",
1347                 SvPV(sval,na));
1348               break;
1349             }
1350           if (info)
1351             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1352           for ( ; image; image=image->next)
1353           {
1354             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1355             image->x_resolution=geometry_info.rho;
1356             image->y_resolution=geometry_info.sigma;
1357             if ((flags & SigmaValue) == 0)
1358               image->y_resolution=image->x_resolution;
1359           }
1360           break;
1361         }
1362       if (LocaleCompare(attribute,"depth") == 0)
1363         {
1364           if (info)
1365             info->image_info->depth=SvIV(sval);
1366           for ( ; image; image=image->next)
1367             (void) SetImageDepth(image,SvIV(sval));
1368           break;
1369         }
1370       if (LocaleCompare(attribute,"dispose") == 0)
1371         {
1372           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1373             SvPV(sval,na)) : SvIV(sval);
1374           if (sp < 0)
1375             {
1376               ThrowPerlException(exception,OptionError,
1377                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1378               break;
1379             }
1380           for ( ; image; image=image->next)
1381             image->dispose=(DisposeType) sp;
1382           break;
1383         }
1384       if (LocaleCompare(attribute,"dither") == 0)
1385         {
1386           if (info)
1387             {
1388               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1389                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1390               if (sp < 0)
1391                 {
1392                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1393                     SvPV(sval,na));
1394                   break;
1395                 }
1396               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1397             }
1398           break;
1399         }
1400       if (LocaleCompare(attribute,"display") == 0)
1401         {
1402           display:
1403           if (info)
1404             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1405           break;
1406         }
1407       if (info)
1408         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1409       for ( ; image; image=image->next)
1410         SetImageProperty(image,attribute,SvPV(sval,na));
1411       break;
1412     }
1413     case 'E':
1414     case 'e':
1415     {
1416       if (LocaleCompare(attribute,"endian") == 0)
1417         {
1418           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1419             SvPV(sval,na)) : SvIV(sval);
1420           if (sp < 0)
1421             {
1422               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1423                 SvPV(sval,na));
1424               break;
1425             }
1426           if (info)
1427             info->image_info->endian=(EndianType) sp;
1428           for ( ; image; image=image->next)
1429             image->endian=(EndianType) sp;
1430           break;
1431         }
1432       if (LocaleCompare(attribute,"extract") == 0)
1433         {
1434           /*
1435             Set image extract geometry.
1436           */
1437           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1438           break;
1439         }
1440       if (info)
1441         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1442       for ( ; image; image=image->next)
1443         SetImageProperty(image,attribute,SvPV(sval,na));
1444       break;
1445     }
1446     case 'F':
1447     case 'f':
1448     {
1449       if (LocaleCompare(attribute,"filename") == 0)
1450         {
1451           if (info)
1452             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1453               MaxTextExtent);
1454           for ( ; image; image=image->next)
1455             (void) CopyMagickString(image->filename,SvPV(sval,na),
1456               MaxTextExtent);
1457           break;
1458         }
1459       if (LocaleCompare(attribute,"file") == 0)
1460         {
1461           FILE
1462             *file;
1463
1464           PerlIO
1465             *io_info;
1466
1467           if (info == (struct PackageInfo *) NULL)
1468             break;
1469           io_info=IoIFP(sv_2io(sval));
1470           if (io_info == (PerlIO *) NULL)
1471             {
1472               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1473                 PackageName);
1474               break;
1475             }
1476           file=PerlIO_findFILE(io_info);
1477           if (file == (FILE *) NULL)
1478             {
1479               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1480                 PackageName);
1481               break;
1482             }
1483           SetImageInfoFile(info->image_info,file);
1484           break;
1485         }
1486       if (LocaleCompare(attribute,"fill") == 0)
1487         {
1488           if (info)
1489             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1490           break;
1491         }
1492       if (LocaleCompare(attribute,"font") == 0)
1493         {
1494           if (info)
1495             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1496           break;
1497         }
1498       if (LocaleCompare(attribute,"foreground") == 0)
1499         break;
1500       if (LocaleCompare(attribute,"fuzz") == 0)
1501         {
1502           if (info)
1503             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1504           for ( ; image; image=image->next)
1505             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1506           break;
1507         }
1508       if (info)
1509         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1510       for ( ; image; image=image->next)
1511         SetImageProperty(image,attribute,SvPV(sval,na));
1512       break;
1513     }
1514     case 'G':
1515     case 'g':
1516     {
1517       if (LocaleCompare(attribute,"gamma") == 0)
1518         {
1519           for ( ; image; image=image->next)
1520             image->gamma=SvNV(sval);
1521           break;
1522         }
1523       if (LocaleCompare(attribute,"gravity") == 0)
1524         {
1525           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1526             SvPV(sval,na)) : SvIV(sval);
1527           if (sp < 0)
1528             {
1529               ThrowPerlException(exception,OptionError,
1530                 "UnrecognizedGravityType",SvPV(sval,na));
1531               break;
1532             }
1533           if (info)
1534             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1535           for ( ; image; image=image->next)
1536             image->gravity=(GravityType) sp;
1537           break;
1538         }
1539       if (LocaleCompare(attribute,"green-primary") == 0)
1540         {
1541           for ( ; image; image=image->next)
1542           {
1543             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1544             image->chromaticity.green_primary.x=geometry_info.rho;
1545             image->chromaticity.green_primary.y=geometry_info.sigma;
1546             if ((flags & SigmaValue) == 0)
1547               image->chromaticity.green_primary.y=
1548                 image->chromaticity.green_primary.x;
1549           }
1550           break;
1551         }
1552       if (info)
1553         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1554       for ( ; image; image=image->next)
1555         SetImageProperty(image,attribute,SvPV(sval,na));
1556       break;
1557     }
1558     case 'I':
1559     case 'i':
1560     {
1561       if (LocaleNCompare(attribute,"index",5) == 0)
1562         {
1563           IndexPacket
1564             *indexes;
1565
1566           int
1567             items;
1568
1569           long
1570             index;
1571
1572           register PixelPacket
1573             *p;
1574
1575           CacheView
1576             *image_view;
1577
1578           for ( ; image; image=image->next)
1579           {
1580             if (image->storage_class != PseudoClass)
1581               continue;
1582             x=0;
1583             y=0;
1584             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1585             (void) items;
1586             image_view=AcquireCacheView(image);
1587             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1588             if (p != (PixelPacket *) NULL)
1589               {
1590                 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1591                 items=sscanf(SvPV(sval,na),"%ld",&index);
1592                 if ((index >= 0) && (index < (ssize_t) image->colors))
1593                   SetIndexPixelComponent(indexes,index);
1594                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1595               }
1596             image_view=DestroyCacheView(image_view);
1597           }
1598           break;
1599         }
1600       if (LocaleCompare(attribute,"iterations") == 0)
1601         {
1602   iterations:
1603           for ( ; image; image=image->next)
1604             image->iterations=SvIV(sval);
1605           break;
1606         }
1607       if (LocaleCompare(attribute,"interlace") == 0)
1608         {
1609           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1610             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1611           if (sp < 0)
1612             {
1613               ThrowPerlException(exception,OptionError,
1614                 "UnrecognizedInterlaceType",SvPV(sval,na));
1615               break;
1616             }
1617           if (info)
1618             info->image_info->interlace=(InterlaceType) sp;
1619           for ( ; image; image=image->next)
1620             image->interlace=(InterlaceType) sp;
1621           break;
1622         }
1623       if (info)
1624         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1625       for ( ; image; image=image->next)
1626         SetImageProperty(image,attribute,SvPV(sval,na));
1627       break;
1628     }
1629     case 'L':
1630     case 'l':
1631     {
1632       if (LocaleCompare(attribute,"label") == 0)
1633         {
1634           for ( ; image; image=image->next)
1635             (void) SetImageProperty(image,"label",InterpretImageProperties(
1636               info ? info->image_info : (ImageInfo *) NULL,image,
1637               SvPV(sval,na)));
1638           break;
1639         }
1640       if (LocaleCompare(attribute,"loop") == 0)
1641         goto iterations;
1642       if (info)
1643         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1644       for ( ; image; image=image->next)
1645         SetImageProperty(image,attribute,SvPV(sval,na));
1646       break;
1647     }
1648     case 'M':
1649     case 'm':
1650     {
1651       if (LocaleCompare(attribute,"magick") == 0)
1652         {
1653           if (info)
1654             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1655               "%s:",SvPV(sval,na));
1656           for ( ; image; image=image->next)
1657             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1658           break;
1659         }
1660       if (LocaleCompare(attribute,"map-limit") == 0)
1661         {
1662           MagickSizeType
1663             limit;
1664
1665           limit=MagickResourceInfinity;
1666           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1667             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1668           (void) SetMagickResourceLimit(MapResource,limit);
1669           break;
1670         }
1671       if (LocaleCompare(attribute,"mask") == 0)
1672         {
1673           Image
1674             *mask;
1675
1676           mask=(Image *) NULL;
1677           if (SvPOK(sval))
1678             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1679           for ( ; image; image=image->next)
1680             SetImageMask(image,mask);
1681           break;
1682         }
1683       if (LocaleCompare(attribute,"mattecolor") == 0)
1684         {
1685           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1686           if (info)
1687             info->image_info->matte_color=target_color;
1688           for ( ; image; image=image->next)
1689             image->matte_color=target_color;
1690           break;
1691         }
1692       if (LocaleCompare(attribute,"matte") == 0)
1693         {
1694           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1695             SvPV(sval,na)) : SvIV(sval);
1696           if (sp < 0)
1697             {
1698               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1699                 SvPV(sval,na));
1700               break;
1701             }
1702           for ( ; image; image=image->next)
1703             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"memory-limit") == 0)
1707         {
1708           MagickSizeType
1709             limit;
1710
1711           limit=MagickResourceInfinity;
1712           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1713             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1714           (void) SetMagickResourceLimit(MemoryResource,limit);
1715           break;
1716         }
1717       if (LocaleCompare(attribute,"monochrome") == 0)
1718         {
1719           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1720             SvPV(sval,na)) : SvIV(sval);
1721           if (sp < 0)
1722             {
1723               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1724                 SvPV(sval,na));
1725               break;
1726             }
1727           if (info)
1728             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1729           for ( ; image; image=image->next)
1730             (void) SetImageType(image,BilevelType);
1731           break;
1732         }
1733       if (info)
1734         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1735       for ( ; image; image=image->next)
1736         SetImageProperty(image,attribute,SvPV(sval,na));
1737       break;
1738     }
1739     case 'O':
1740     case 'o':
1741     {
1742       if (LocaleCompare(attribute,"option") == 0)
1743         {
1744           if (info)
1745             DefineImageOption(info->image_info,SvPV(sval,na));
1746           break;
1747         }
1748       if (LocaleCompare(attribute,"orientation") == 0)
1749         {
1750           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1751             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1752           if (sp < 0)
1753             {
1754               ThrowPerlException(exception,OptionError,
1755                 "UnrecognizedOrientationType",SvPV(sval,na));
1756               break;
1757             }
1758           if (info)
1759             info->image_info->orientation=(OrientationType) sp;
1760           for ( ; image; image=image->next)
1761             image->orientation=(OrientationType) sp;
1762           break;
1763         }
1764       if (info)
1765         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1766       for ( ; image; image=image->next)
1767         SetImageProperty(image,attribute,SvPV(sval,na));
1768       break;
1769     }
1770     case 'P':
1771     case 'p':
1772     {
1773       if (LocaleCompare(attribute,"page") == 0)
1774         {
1775           char
1776             *geometry;
1777
1778           geometry=GetPageGeometry(SvPV(sval,na));
1779           if (info)
1780             (void) CloneString(&info->image_info->page,geometry);
1781           for ( ; image; image=image->next)
1782             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1783           geometry=(char *) RelinquishMagickMemory(geometry);
1784           break;
1785         }
1786       if (LocaleCompare(attribute,"pen") == 0)
1787         {
1788           if (info)
1789             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1790           break;
1791         }
1792       if (LocaleNCompare(attribute,"pixel",5) == 0)
1793         {
1794           int
1795             items;
1796
1797           MagickPixelPacket
1798             pixel;
1799
1800           register IndexPacket
1801             *indexes;
1802
1803           register PixelPacket
1804             *q;
1805
1806           CacheView
1807             *image_view;
1808
1809           for ( ; image; image=image->next)
1810           {
1811             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1812               break;
1813             x=0;
1814             y=0;
1815             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1816             (void) items;
1817             image_view=AcquireCacheView(image);
1818             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1819             indexes=GetCacheViewAuthenticIndexQueue(image_view);
1820             if (q != (PixelPacket *) NULL)
1821               {
1822                 if ((strchr(SvPV(sval,na),',') == 0) ||
1823                     (strchr(SvPV(sval,na),')') != 0))
1824                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1825                 else
1826                   {
1827                     GetMagickPixelPacket(image,&pixel);
1828                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1829                     pixel.red=geometry_info.rho;
1830                     if ((flags & SigmaValue) != 0)
1831                       pixel.green=geometry_info.sigma;
1832                     if ((flags & XiValue) != 0)
1833                       pixel.blue=geometry_info.xi;
1834                     if ((flags & PsiValue) != 0)
1835                       pixel.opacity=geometry_info.psi;
1836                     if ((flags & ChiValue) != 0)
1837                       pixel.index=geometry_info.chi;
1838                   }
1839                 SetRedPixelComponent(q,ClampToQuantum(pixel.red));
1840                 SetGreenPixelComponent(q,ClampToQuantum(pixel.green));
1841                 SetBluePixelComponent(q,ClampToQuantum(pixel.blue));
1842                 SetOpacityPixelComponent(q,ClampToQuantum(pixel.opacity));
1843                 if (((image->colorspace == CMYKColorspace) ||
1844                      (image->storage_class == PseudoClass)) &&
1845                     (indexes != (IndexPacket *) NULL))
1846                   SetIndexPixelComponent(indexes,ClampToQuantum(pixel.index));
1847                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1848               }
1849             image_view=DestroyCacheView(image_view);
1850           }
1851           break;
1852         }
1853       if (LocaleCompare(attribute,"pointsize") == 0)
1854         {
1855           if (info)
1856             {
1857               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1858               info->image_info->pointsize=geometry_info.rho;
1859             }
1860           break;
1861         }
1862       if (LocaleCompare(attribute,"preview") == 0)
1863         {
1864           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1865             SvPV(sval,na)) : SvIV(sval);
1866           if (sp < 0)
1867             {
1868               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1869                 SvPV(sval,na));
1870               break;
1871             }
1872           if (info)
1873             info->image_info->preview_type=(PreviewType) sp;
1874           break;
1875         }
1876       if (info)
1877         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1878       for ( ; image; image=image->next)
1879         SetImageProperty(image,attribute,SvPV(sval,na));
1880       break;
1881     }
1882     case 'Q':
1883     case 'q':
1884     {
1885       if (LocaleCompare(attribute,"quality") == 0)
1886         {
1887           if (info)
1888             info->image_info->quality=SvIV(sval);
1889           for ( ; image; image=image->next)
1890             image->quality=SvIV(sval);
1891           break;
1892         }
1893       if (info)
1894         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1895       for ( ; image; image=image->next)
1896         SetImageProperty(image,attribute,SvPV(sval,na));
1897       break;
1898     }
1899     case 'R':
1900     case 'r':
1901     {
1902       if (LocaleCompare(attribute,"red-primary") == 0)
1903         {
1904           for ( ; image; image=image->next)
1905           {
1906             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1907             image->chromaticity.red_primary.x=geometry_info.rho;
1908             image->chromaticity.red_primary.y=geometry_info.sigma;
1909             if ((flags & SigmaValue) == 0)
1910               image->chromaticity.red_primary.y=
1911                 image->chromaticity.red_primary.x;
1912           }
1913           break;
1914         }
1915       if (LocaleCompare(attribute,"render") == 0)
1916         {
1917           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1918             SvPV(sval,na)) : SvIV(sval);
1919           if (sp < 0)
1920             {
1921               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1922                 SvPV(sval,na));
1923               break;
1924             }
1925          for ( ; image; image=image->next)
1926            image->rendering_intent=(RenderingIntent) sp;
1927          break;
1928        }
1929       if (LocaleCompare(attribute,"repage") == 0)
1930         {
1931           RectangleInfo
1932             geometry;
1933
1934           for ( ; image; image=image->next)
1935           {
1936             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1937             if ((flags & WidthValue) != 0)
1938               {
1939                 if ((flags & HeightValue) == 0)
1940                   geometry.height=geometry.width;
1941                 image->page.width=geometry.width;
1942                 image->page.height=geometry.height;
1943               }
1944             if ((flags & AspectValue) != 0)
1945               {
1946                 if ((flags & XValue) != 0)
1947                   image->page.x+=geometry.x;
1948                 if ((flags & YValue) != 0)
1949                   image->page.y+=geometry.y;
1950               }
1951             else
1952               {
1953                 if ((flags & XValue) != 0)
1954                   {
1955                     image->page.x=geometry.x;
1956                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1957                       image->page.width=image->columns+geometry.x;
1958                   }
1959                 if ((flags & YValue) != 0)
1960                   {
1961                     image->page.y=geometry.y;
1962                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1963                       image->page.height=image->rows+geometry.y;
1964                   }
1965               }
1966           }
1967           break;
1968         }
1969       if (info)
1970         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1971       for ( ; image; image=image->next)
1972         SetImageProperty(image,attribute,SvPV(sval,na));
1973       break;
1974     }
1975     case 'S':
1976     case 's':
1977     {
1978       if (LocaleCompare(attribute,"sampling-factor") == 0)
1979         {
1980           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1981             {
1982               ThrowPerlException(exception,OptionError,"MissingGeometry",
1983                 SvPV(sval,na));
1984               break;
1985             }
1986           if (info)
1987             (void) CloneString(&info->image_info->sampling_factor,
1988               SvPV(sval,na));
1989           break;
1990         }
1991       if (LocaleCompare(attribute,"scene") == 0)
1992         {
1993           for ( ; image; image=image->next)
1994             image->scene=SvIV(sval);
1995           break;
1996         }
1997       if (LocaleCompare(attribute,"subimage") == 0)
1998         {
1999           if (info)
2000             info->image_info->subimage=SvIV(sval);
2001           break;
2002         }
2003       if (LocaleCompare(attribute,"subrange") == 0)
2004         {
2005           if (info)
2006             info->image_info->subrange=SvIV(sval);
2007           break;
2008         }
2009       if (LocaleCompare(attribute,"server") == 0)
2010         goto display;
2011       if (LocaleCompare(attribute,"size") == 0)
2012         {
2013           if (info)
2014             {
2015               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2016                 {
2017                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2018                     SvPV(sval,na));
2019                   break;
2020                 }
2021               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2022             }
2023           break;
2024         }
2025       if (LocaleCompare(attribute,"stroke") == 0)
2026         {
2027           if (info)
2028             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2029           break;
2030         }
2031       if (info)
2032         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2033       for ( ; image; image=image->next)
2034         SetImageProperty(image,attribute,SvPV(sval,na));
2035       break;
2036     }
2037     case 'T':
2038     case 't':
2039     {
2040       if (LocaleCompare(attribute,"texture") == 0)
2041         {
2042           if (info)
2043             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2044           break;
2045         }
2046       if (LocaleCompare(attribute,"thread-limit") == 0)
2047         {
2048           MagickSizeType
2049             limit;
2050
2051           limit=MagickResourceInfinity;
2052           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2053             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2054           (void) SetMagickResourceLimit(ThreadResource,limit);
2055           break;
2056         }
2057       if (LocaleCompare(attribute,"tile") == 0)
2058         {
2059           if (info)
2060             (void) CloneString(&info->image_info->tile,SvPV(sval,na));
2061           break;
2062         }
2063       if (LocaleCompare(attribute,"tile-offset") == 0)
2064         {
2065           char
2066             *geometry;
2067
2068           geometry=GetPageGeometry(SvPV(sval,na));
2069           if (info)
2070             (void) CloneString(&info->image_info->page,geometry);
2071           for ( ; image; image=image->next)
2072             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2073               exception);
2074           geometry=(char *) RelinquishMagickMemory(geometry);
2075           break;
2076         }
2077       if (LocaleCompare(attribute,"time-limit") == 0)
2078         {
2079           MagickSizeType
2080             limit;
2081
2082           limit=MagickResourceInfinity;
2083           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2084             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2085           (void) SetMagickResourceLimit(TimeResource,limit);
2086           break;
2087         }
2088       if (LocaleCompare(attribute,"transparent-color") == 0)
2089         {
2090           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2091           if (info)
2092             info->image_info->transparent_color=target_color;
2093           for ( ; image; image=image->next)
2094             image->transparent_color=target_color;
2095           break;
2096         }
2097       if (LocaleCompare(attribute,"type") == 0)
2098         {
2099           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2100             SvPV(sval,na)) : SvIV(sval);
2101           if (sp < 0)
2102             {
2103               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2104                 SvPV(sval,na));
2105               break;
2106             }
2107           if (info)
2108             info->image_info->type=(ImageType) sp;
2109           for ( ; image; image=image->next)
2110             SetImageType(image,(ImageType) sp);
2111           break;
2112         }
2113       if (info)
2114         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2115       for ( ; image; image=image->next)
2116         SetImageProperty(image,attribute,SvPV(sval,na));
2117       break;
2118     }
2119     case 'U':
2120     case 'u':
2121     {
2122       if (LocaleCompare(attribute,"units") == 0)
2123         {
2124           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2125             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2126           if (sp < 0)
2127             {
2128               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2129                 SvPV(sval,na));
2130               break;
2131             }
2132           if (info)
2133             info->image_info->units=(ResolutionType) sp;
2134           for ( ; image; image=image->next)
2135           {
2136             ResolutionType
2137               units;
2138
2139             units=(ResolutionType) sp;
2140             if (image->units != units)
2141               switch (image->units)
2142               {
2143                 case UndefinedResolution:
2144                 case PixelsPerInchResolution:
2145                 {
2146                   if (units == PixelsPerCentimeterResolution)
2147                     {
2148                       image->x_resolution*=2.54;
2149                       image->y_resolution*=2.54;
2150                     }
2151                   break;
2152                 }
2153                 case PixelsPerCentimeterResolution:
2154                 {
2155                   if (units == PixelsPerInchResolution)
2156                     {
2157                       image->x_resolution/=2.54;
2158                       image->y_resolution/=2.54;
2159                     }
2160                   break;
2161                 }
2162               }
2163             image->units=units;
2164           }
2165           break;
2166         }
2167       if (info)
2168         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2169       for ( ; image; image=image->next)
2170         SetImageProperty(image,attribute,SvPV(sval,na));
2171       break;
2172     }
2173     case 'V':
2174     case 'v':
2175     {
2176       if (LocaleCompare(attribute,"verbose") == 0)
2177         {
2178           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2179             SvPV(sval,na)) : SvIV(sval);
2180           if (sp < 0)
2181             {
2182               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2183                 SvPV(sval,na));
2184               break;
2185             }
2186           if (info)
2187             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2188           break;
2189         }
2190       if (LocaleCompare(attribute,"view") == 0)
2191         {
2192           if (info)
2193             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2194           break;
2195         }
2196       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2197         {
2198           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2199             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2200           if (sp < 0)
2201             {
2202               ThrowPerlException(exception,OptionError,
2203                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2204               break;
2205             }
2206           if (info)
2207             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2208           for ( ; image; image=image->next)
2209             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2210           break;
2211         }
2212       if (info)
2213         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2214       for ( ; image; image=image->next)
2215         SetImageProperty(image,attribute,SvPV(sval,na));
2216       break;
2217     }
2218     case 'W':
2219     case 'w':
2220     {
2221       if (LocaleCompare(attribute,"white-point") == 0)
2222         {
2223           for ( ; image; image=image->next)
2224           {
2225             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2226             image->chromaticity.white_point.x=geometry_info.rho;
2227             image->chromaticity.white_point.y=geometry_info.sigma;
2228             if ((flags & SigmaValue) == 0)
2229               image->chromaticity.white_point.y=
2230                 image->chromaticity.white_point.x;
2231           }
2232           break;
2233         }
2234       if (info)
2235         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2236       for ( ; image; image=image->next)
2237         SetImageProperty(image,attribute,SvPV(sval,na));
2238       break;
2239     }
2240     default:
2241     {
2242       if (info)
2243         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2244       for ( ; image; image=image->next)
2245         SetImageProperty(image,attribute,SvPV(sval,na));
2246       break;
2247     }
2248   }
2249 }
2250 \f
2251 /*
2252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2253 %                                                                             %
2254 %                                                                             %
2255 %                                                                             %
2256 %   S e t u p L i s t                                                         %
2257 %                                                                             %
2258 %                                                                             %
2259 %                                                                             %
2260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2261 %
2262 %  Method SetupList returns the list of all the images linked by their
2263 %  image->next and image->previous link lists for use with ImageMagick.  If
2264 %  info is non-NULL, an info structure is returned in *info.  If
2265 %  reference_vector is non-NULL,an array of SV* are returned in
2266 %  *reference_vector.  Reference_vector is used when the images are going to be
2267 %  replaced with new Image*'s.
2268 %
2269 %  The format of the SetupList routine is:
2270 %
2271 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2272 %        SV ***reference_vector,ExceptionInfo *exception)
2273 %
2274 %  A description of each parameter follows:
2275 %
2276 %    o list: a list of strings.
2277 %
2278 %    o string: a character string.
2279 %
2280 %    o exception: Return any errors or warnings in this structure.
2281 %
2282 */
2283 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2284   SV ***reference_vector,ExceptionInfo *exception)
2285 {
2286   Image
2287     *image;
2288
2289   ssize_t
2290     current,
2291     last;
2292
2293   if (reference_vector)
2294     *reference_vector=NULL;
2295   if (info)
2296     *info=NULL;
2297   current=0;
2298   last=0;
2299   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2300   if (info && (SvTYPE(reference) == SVt_PVAV))
2301     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2302       exception);
2303   return(image);
2304 }
2305 \f
2306 /*
2307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308 %                                                                             %
2309 %                                                                             %
2310 %                                                                             %
2311 %   s t r E Q c a s e                                                         %
2312 %                                                                             %
2313 %                                                                             %
2314 %                                                                             %
2315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2316 %
2317 %  strEQcase() compares two strings and returns 0 if they are the
2318 %  same or if the second string runs out first.  The comparison is case
2319 %  insensitive.
2320 %
2321 %  The format of the strEQcase routine is:
2322 %
2323 %      ssize_t strEQcase(const char *p,const char *q)
2324 %
2325 %  A description of each parameter follows:
2326 %
2327 %    o p: a character string.
2328 %
2329 %    o q: a character string.
2330 %
2331 %
2332 */
2333 static ssize_t strEQcase(const char *p,const char *q)
2334 {
2335   char
2336     c;
2337
2338   register ssize_t
2339     i;
2340
2341   for (i=0 ; (c=(*q)) != 0; i++)
2342   {
2343     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2344         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2345       return(0);
2346     p++;
2347     q++;
2348   }
2349   return(((*q == 0) && (*p == 0)) ? i : 0);
2350 }
2351 \f
2352 /*
2353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2354 %                                                                             %
2355 %                                                                             %
2356 %                                                                             %
2357 %   I m a g e : : M a g i c k                                                 %
2358 %                                                                             %
2359 %                                                                             %
2360 %                                                                             %
2361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2362 %
2363 %
2364 */
2365 MODULE = Image::Magick PACKAGE = Image::Magick
2366
2367 PROTOTYPES: ENABLE
2368
2369 BOOT:
2370   MagickCoreGenesis("PerlMagick",MagickFalse);
2371   SetWarningHandler(NULL);
2372   SetErrorHandler(NULL);
2373   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2374     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2375
2376 void
2377 UNLOAD()
2378   PPCODE:
2379   {
2380     if (magick_registry != (SplayTreeInfo *) NULL)
2381       magick_registry=DestroySplayTree(magick_registry);
2382     MagickCoreTerminus();
2383   }
2384
2385 double
2386 constant(name,argument)
2387   char *name
2388   ssize_t argument
2389 \f
2390 #
2391 ###############################################################################
2392 #                                                                             #
2393 #                                                                             #
2394 #                                                                             #
2395 #   A n i m a t e                                                             #
2396 #                                                                             #
2397 #                                                                             #
2398 #                                                                             #
2399 ###############################################################################
2400 #
2401 #
2402 void
2403 Animate(ref,...)
2404   Image::Magick ref=NO_INIT
2405   ALIAS:
2406     AnimateImage  = 1
2407     animate       = 2
2408     animateimage  = 3
2409   PPCODE:
2410   {
2411     ExceptionInfo
2412       *exception;
2413
2414     Image
2415       *image;
2416
2417     register ssize_t
2418       i;
2419
2420     struct PackageInfo
2421       *info,
2422       *package_info;
2423
2424     SV
2425       *perl_exception,
2426       *reference;
2427
2428     PERL_UNUSED_VAR(ref);
2429     PERL_UNUSED_VAR(ix);
2430     exception=AcquireExceptionInfo();
2431     perl_exception=newSVpv("",0);
2432     package_info=(struct PackageInfo *) NULL;
2433     if (sv_isobject(ST(0)) == 0)
2434       {
2435         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2436           PackageName);
2437         goto PerlException;
2438       }
2439     reference=SvRV(ST(0));
2440     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2441     if (image == (Image *) NULL)
2442       {
2443         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2444           PackageName);
2445         goto PerlException;
2446       }
2447     package_info=ClonePackageInfo(info,exception);
2448     if (items == 2)
2449       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2450     else
2451       if (items > 2)
2452         for (i=2; i < items; i+=2)
2453           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2454             exception);
2455     (void) AnimateImages(package_info->image_info,image);
2456     (void) CatchImageException(image);
2457     InheritException(exception,&image->exception);
2458
2459   PerlException:
2460     if (package_info != (struct PackageInfo *) NULL)
2461       DestroyPackageInfo(package_info);
2462     InheritPerlException(exception,perl_exception);
2463     exception=DestroyExceptionInfo(exception);
2464     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2465     SvPOK_on(perl_exception);
2466     ST(0)=sv_2mortal(perl_exception);
2467     XSRETURN(1);
2468   }
2469 \f
2470 #
2471 ###############################################################################
2472 #                                                                             #
2473 #                                                                             #
2474 #                                                                             #
2475 #   A p p e n d                                                               #
2476 #                                                                             #
2477 #                                                                             #
2478 #                                                                             #
2479 ###############################################################################
2480 #
2481 #
2482 void
2483 Append(ref,...)
2484   Image::Magick ref=NO_INIT
2485   ALIAS:
2486     AppendImage  = 1
2487     append       = 2
2488     appendimage  = 3
2489   PPCODE:
2490   {
2491     AV
2492       *av;
2493
2494     char
2495       *attribute;
2496
2497     ExceptionInfo
2498       *exception;
2499
2500     HV
2501       *hv;
2502
2503     Image
2504       *image;
2505
2506     register ssize_t
2507       i;
2508
2509     ssize_t
2510       stack;
2511
2512     struct PackageInfo
2513       *info;
2514
2515     SV
2516       *av_reference,
2517       *perl_exception,
2518       *reference,
2519       *rv,
2520       *sv;
2521
2522     PERL_UNUSED_VAR(ref);
2523     PERL_UNUSED_VAR(ix);
2524     exception=AcquireExceptionInfo();
2525     perl_exception=newSVpv("",0);
2526     sv=NULL;
2527     attribute=NULL;
2528     av=NULL;
2529     if (sv_isobject(ST(0)) == 0)
2530       {
2531         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2532           PackageName);
2533         goto PerlException;
2534       }
2535     reference=SvRV(ST(0));
2536     hv=SvSTASH(reference);
2537     av=newAV();
2538     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2539     SvREFCNT_dec(av);
2540     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2541     if (image == (Image *) NULL)
2542       {
2543         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2544           PackageName);
2545         goto PerlException;
2546       }
2547     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2548     /*
2549       Get options.
2550     */
2551     stack=MagickTrue;
2552     for (i=2; i < items; i+=2)
2553     {
2554       attribute=(char *) SvPV(ST(i-1),na);
2555       switch (*attribute)
2556       {
2557         case 'S':
2558         case 's':
2559         {
2560           if (LocaleCompare(attribute,"stack") == 0)
2561             {
2562               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2563                 SvPV(ST(i),na));
2564               if (stack < 0)
2565                 {
2566                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2567                     SvPV(ST(i),na));
2568                   return;
2569                 }
2570               break;
2571             }
2572           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2573             attribute);
2574           break;
2575         }
2576         default:
2577         {
2578           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2579             attribute);
2580           break;
2581         }
2582       }
2583     }
2584     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2585     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2586       goto PerlException;
2587     for ( ; image; image=image->next)
2588     {
2589       AddImageToRegistry(sv,image);
2590       rv=newRV(sv);
2591       av_push(av,sv_bless(rv,hv));
2592       SvREFCNT_dec(sv);
2593     }
2594     exception=DestroyExceptionInfo(exception);
2595     ST(0)=av_reference;
2596     SvREFCNT_dec(perl_exception);
2597     XSRETURN(1);
2598
2599   PerlException:
2600     InheritPerlException(exception,perl_exception);
2601     exception=DestroyExceptionInfo(exception);
2602     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2603     SvPOK_on(perl_exception);
2604     ST(0)=sv_2mortal(perl_exception);
2605     XSRETURN(1);
2606   }
2607 \f
2608 #
2609 ###############################################################################
2610 #                                                                             #
2611 #                                                                             #
2612 #                                                                             #
2613 #   A v e r a g e                                                             #
2614 #                                                                             #
2615 #                                                                             #
2616 #                                                                             #
2617 ###############################################################################
2618 #
2619 #
2620 void
2621 Average(ref)
2622   Image::Magick ref=NO_INIT
2623   ALIAS:
2624     AverageImage   = 1
2625     average        = 2
2626     averageimage   = 3
2627   PPCODE:
2628   {
2629     AV
2630       *av;
2631
2632     char
2633       *p;
2634
2635     ExceptionInfo
2636       *exception;
2637
2638     HV
2639       *hv;
2640
2641     Image
2642       *image;
2643
2644     struct PackageInfo
2645       *info;
2646
2647     SV
2648       *perl_exception,
2649       *reference,
2650       *rv,
2651       *sv;
2652
2653     PERL_UNUSED_VAR(ref);
2654     PERL_UNUSED_VAR(ix);
2655     exception=AcquireExceptionInfo();
2656     perl_exception=newSVpv("",0);
2657     sv=NULL;
2658     if (sv_isobject(ST(0)) == 0)
2659       {
2660         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2661           PackageName);
2662         goto PerlException;
2663       }
2664     reference=SvRV(ST(0));
2665     hv=SvSTASH(reference);
2666     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2667     if (image == (Image *) NULL)
2668       {
2669         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2670           PackageName);
2671         goto PerlException;
2672       }
2673     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2674     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2675       goto PerlException;
2676     /*
2677       Create blessed Perl array for the returned image.
2678     */
2679     av=newAV();
2680     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2681     SvREFCNT_dec(av);
2682     AddImageToRegistry(sv,image);
2683     rv=newRV(sv);
2684     av_push(av,sv_bless(rv,hv));
2685     SvREFCNT_dec(sv);
2686     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2687     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2688       "average-%.*s",(int) (MaxTextExtent-9),
2689       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2690     (void) CopyMagickString(image->filename,info->image_info->filename,
2691       MaxTextExtent);
2692     SetImageInfo(info->image_info,0,exception);
2693     exception=DestroyExceptionInfo(exception);
2694     SvREFCNT_dec(perl_exception);
2695     XSRETURN(1);
2696
2697   PerlException:
2698     InheritPerlException(exception,perl_exception);
2699     exception=DestroyExceptionInfo(exception);
2700     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2701     SvPOK_on(perl_exception);
2702     ST(0)=sv_2mortal(perl_exception);
2703     XSRETURN(1);
2704   }
2705 \f
2706 #
2707 ###############################################################################
2708 #                                                                             #
2709 #                                                                             #
2710 #                                                                             #
2711 #   B l o b T o I m a g e                                                     #
2712 #                                                                             #
2713 #                                                                             #
2714 #                                                                             #
2715 ###############################################################################
2716 #
2717 #
2718 void
2719 BlobToImage(ref,...)
2720   Image::Magick ref=NO_INIT
2721   ALIAS:
2722     BlobToImage  = 1
2723     blobtoimage  = 2
2724     blobto       = 3
2725   PPCODE:
2726   {
2727     AV
2728       *av;
2729
2730     char
2731       **keep,
2732       **list;
2733
2734     ExceptionInfo
2735       *exception;
2736
2737     HV
2738       *hv;
2739
2740     Image
2741       *image;
2742
2743     register char
2744       **p;
2745
2746     register ssize_t
2747       i;
2748
2749     ssize_t
2750       ac,
2751       n,
2752       number_images;
2753
2754     STRLEN
2755       *length;
2756
2757     struct PackageInfo
2758       *info;
2759
2760     SV
2761       *perl_exception,
2762       *reference,
2763       *rv,
2764       *sv;
2765
2766     PERL_UNUSED_VAR(ref);
2767     PERL_UNUSED_VAR(ix);
2768     exception=AcquireExceptionInfo();
2769     perl_exception=newSVpv("",0);
2770     sv=NULL;
2771     number_images=0;
2772     ac=(items < 2) ? 1 : items-1;
2773     length=(STRLEN *) NULL;
2774     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2775     if (list == (char **) NULL)
2776       {
2777         ThrowPerlException(exception,ResourceLimitError,
2778           "MemoryAllocationFailed",PackageName);
2779         goto PerlException;
2780       }
2781     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2782     if (length == (STRLEN *) NULL)
2783       {
2784         ThrowPerlException(exception,ResourceLimitError,
2785           "MemoryAllocationFailed",PackageName);
2786         goto PerlException;
2787       }
2788     if (sv_isobject(ST(0)) == 0)
2789       {
2790         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2791           PackageName);
2792         goto PerlException;
2793       }
2794     reference=SvRV(ST(0));
2795     hv=SvSTASH(reference);
2796     if (SvTYPE(reference) != SVt_PVAV)
2797       {
2798         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2799           PackageName);
2800         goto PerlException;
2801       }
2802     av=(AV *) reference;
2803     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2804       exception);
2805     n=1;
2806     if (items <= 1)
2807       {
2808         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2809         goto PerlException;
2810       }
2811     for (n=0, i=0; i < ac; i++)
2812     {
2813       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2814       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2815         {
2816           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2817           continue;
2818         }
2819       n++;
2820     }
2821     list[n]=(char *) NULL;
2822     keep=list;
2823     for (i=number_images=0; i < n; i++)
2824     {
2825       image=BlobToImage(info->image_info,list[i],length[i],exception);
2826       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2827         break;
2828       for ( ; image; image=image->next)
2829       {
2830         AddImageToRegistry(sv,image);
2831         rv=newRV(sv);
2832         av_push(av,sv_bless(rv,hv));
2833         SvREFCNT_dec(sv);
2834         number_images++;
2835       }
2836     }
2837     /*
2838       Free resources.
2839     */
2840     for (i=0; i < n; i++)
2841       if (list[i] != (char *) NULL)
2842         for (p=keep; list[i] != *p++; )
2843           if (*p == (char *) NULL)
2844             {
2845               list[i]=(char *) RelinquishMagickMemory(list[i]);
2846               break;
2847             }
2848
2849   PerlException:
2850     if (list)
2851       list=(char **) RelinquishMagickMemory(list);
2852     if (length)
2853       length=(STRLEN *) RelinquishMagickMemory(length);
2854     InheritPerlException(exception,perl_exception);
2855     exception=DestroyExceptionInfo(exception);
2856     sv_setiv(perl_exception,(IV) number_images);
2857     SvPOK_on(perl_exception);
2858     ST(0)=sv_2mortal(perl_exception);
2859     XSRETURN(1);
2860   }
2861 \f
2862 #
2863 ###############################################################################
2864 #                                                                             #
2865 #                                                                             #
2866 #                                                                             #
2867 #   C l o n e                                                                 #
2868 #                                                                             #
2869 #                                                                             #
2870 #                                                                             #
2871 ###############################################################################
2872 #
2873 #
2874 void
2875 Clone(ref)
2876   Image::Magick ref=NO_INIT
2877   ALIAS:
2878     CopyImage   = 1
2879     copy        = 2
2880     copyimage   = 3
2881     CloneImage  = 4
2882     clone       = 5
2883     cloneimage  = 6
2884     Clone       = 7
2885   PPCODE:
2886   {
2887     AV
2888       *av;
2889
2890     ExceptionInfo
2891       *exception;
2892
2893     HV
2894       *hv;
2895
2896     Image
2897       *clone,
2898       *image;
2899
2900     struct PackageInfo
2901       *info;
2902
2903     SV
2904       *perl_exception,
2905       *reference,
2906       *rv,
2907       *sv;
2908
2909     PERL_UNUSED_VAR(ref);
2910     PERL_UNUSED_VAR(ix);
2911     exception=AcquireExceptionInfo();
2912     perl_exception=newSVpv("",0);
2913     sv=NULL;
2914     if (sv_isobject(ST(0)) == 0)
2915       {
2916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2917           PackageName);
2918         goto PerlException;
2919       }
2920     reference=SvRV(ST(0));
2921     hv=SvSTASH(reference);
2922     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2923     if (image == (Image *) NULL)
2924       {
2925         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2926           PackageName);
2927         goto PerlException;
2928       }
2929     /*
2930       Create blessed Perl array for the returned image.
2931     */
2932     av=newAV();
2933     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2934     SvREFCNT_dec(av);
2935     for ( ; image; image=image->next)
2936     {
2937       clone=CloneImage(image,0,0,MagickTrue,exception);
2938       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2939         break;
2940       AddImageToRegistry(sv,clone);
2941       rv=newRV(sv);
2942       av_push(av,sv_bless(rv,hv));
2943       SvREFCNT_dec(sv);
2944     }
2945     exception=DestroyExceptionInfo(exception);
2946     SvREFCNT_dec(perl_exception);
2947     XSRETURN(1);
2948
2949   PerlException:
2950     InheritPerlException(exception,perl_exception);
2951     exception=DestroyExceptionInfo(exception);
2952     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2953     SvPOK_on(perl_exception);
2954     ST(0)=sv_2mortal(perl_exception);
2955     XSRETURN(1);
2956   }
2957 \f
2958 #
2959 ###############################################################################
2960 #                                                                             #
2961 #                                                                             #
2962 #                                                                             #
2963 #   C L O N E                                                                 #
2964 #                                                                             #
2965 #                                                                             #
2966 #                                                                             #
2967 ###############################################################################
2968 #
2969 #
2970 void
2971 CLONE(ref,...)
2972   SV *ref;
2973   CODE:
2974   {
2975     PERL_UNUSED_VAR(ref);
2976     if (magick_registry != (SplayTreeInfo *) NULL)
2977       {
2978         register Image
2979           *p;
2980
2981         ResetSplayTreeIterator(magick_registry);
2982         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2983         while (p != (Image *) NULL)
2984         {
2985           ReferenceImage(p);
2986           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2987         }
2988       }
2989   }
2990 \f
2991 #
2992 ###############################################################################
2993 #                                                                             #
2994 #                                                                             #
2995 #                                                                             #
2996 #   C o a l e s c e                                                           #
2997 #                                                                             #
2998 #                                                                             #
2999 #                                                                             #
3000 ###############################################################################
3001 #
3002 #
3003 void
3004 Coalesce(ref)
3005   Image::Magick ref=NO_INIT
3006   ALIAS:
3007     CoalesceImage   = 1
3008     coalesce        = 2
3009     coalesceimage   = 3
3010   PPCODE:
3011   {
3012     AV
3013       *av;
3014
3015     ExceptionInfo
3016       *exception;
3017
3018     HV
3019       *hv;
3020
3021     Image
3022       *image;
3023
3024     struct PackageInfo
3025       *info;
3026
3027     SV
3028       *av_reference,
3029       *perl_exception,
3030       *reference,
3031       *rv,
3032       *sv;
3033
3034     PERL_UNUSED_VAR(ref);
3035     PERL_UNUSED_VAR(ix);
3036     exception=AcquireExceptionInfo();
3037     perl_exception=newSVpv("",0);
3038     sv=NULL;
3039     if (sv_isobject(ST(0)) == 0)
3040       {
3041         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3042           PackageName);
3043         goto PerlException;
3044       }
3045     reference=SvRV(ST(0));
3046     hv=SvSTASH(reference);
3047     av=newAV();
3048     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3049     SvREFCNT_dec(av);
3050     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3051     if (image == (Image *) NULL)
3052       {
3053         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3054           PackageName);
3055         goto PerlException;
3056       }
3057     image=CoalesceImages(image,exception);
3058     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3059       goto PerlException;
3060     for ( ; image; image=image->next)
3061     {
3062       AddImageToRegistry(sv,image);
3063       rv=newRV(sv);
3064       av_push(av,sv_bless(rv,hv));
3065       SvREFCNT_dec(sv);
3066     }
3067     exception=DestroyExceptionInfo(exception);
3068     ST(0)=av_reference;
3069     SvREFCNT_dec(perl_exception);
3070     XSRETURN(1);
3071
3072   PerlException:
3073     InheritPerlException(exception,perl_exception);
3074     exception=DestroyExceptionInfo(exception);
3075     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3076     SvPOK_on(perl_exception);
3077     ST(0)=sv_2mortal(perl_exception);
3078     XSRETURN(1);
3079   }
3080 \f
3081 #
3082 ###############################################################################
3083 #                                                                             #
3084 #                                                                             #
3085 #                                                                             #
3086 #   C o m p a r e                                                             #
3087 #                                                                             #
3088 #                                                                             #
3089 #                                                                             #
3090 ###############################################################################
3091 #
3092 #
3093 void
3094 Compare(ref,...)
3095   Image::Magick ref=NO_INIT
3096   ALIAS:
3097     CompareImage = 1
3098     compare      = 2
3099     compareimage = 3
3100   PPCODE:
3101   {
3102     AV
3103       *av;
3104
3105     char
3106       *attribute;
3107
3108     ChannelType
3109       channel;
3110
3111     double
3112       distortion;
3113
3114     ExceptionInfo
3115       *exception;
3116
3117     HV
3118       *hv;
3119
3120     Image
3121       *difference_image,
3122       *image,
3123       *reconstruct_image;
3124
3125     MetricType
3126       metric;
3127
3128     register ssize_t
3129       i;
3130
3131     ssize_t
3132       option;
3133
3134     struct PackageInfo
3135       *info;
3136
3137     SV
3138       *av_reference,
3139       *perl_exception,
3140       *reference,
3141       *rv,
3142       *sv;
3143
3144     PERL_UNUSED_VAR(ref);
3145     PERL_UNUSED_VAR(ix);
3146     exception=AcquireExceptionInfo();
3147     perl_exception=newSVpv("",0);
3148     sv=NULL;
3149     av=NULL;
3150     attribute=NULL;
3151     if (sv_isobject(ST(0)) == 0)
3152       {
3153         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3154           PackageName);
3155         goto PerlException;
3156       }
3157     reference=SvRV(ST(0));
3158     hv=SvSTASH(reference);
3159     av=newAV();
3160     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3161     SvREFCNT_dec(av);
3162     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3163     if (image == (Image *) NULL)
3164       {
3165         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3166           PackageName);
3167         goto PerlException;
3168       }
3169     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3170     /*
3171       Get attribute.
3172     */
3173     channel=DefaultChannels;
3174     reconstruct_image=image;
3175     metric=RootMeanSquaredErrorMetric;
3176     for (i=2; i < items; i+=2)
3177     {
3178       attribute=(char *) SvPV(ST(i-1),na);
3179       switch (*attribute)
3180       {
3181         case 'C':
3182         case 'c':
3183         {
3184           if (LocaleCompare(attribute,"channel") == 0)
3185             {
3186               ssize_t
3187                 option;
3188
3189               option=ParseChannelOption(SvPV(ST(i),na));
3190               if (option < 0)
3191                 {
3192                   ThrowPerlException(exception,OptionError,
3193                     "UnrecognizedType",SvPV(ST(i),na));
3194                   return;
3195                 }
3196               channel=(ChannelType) option;
3197               break;
3198             }
3199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3200             attribute);
3201           break;
3202         }
3203         case 'F':
3204         case 'f':
3205         {
3206           if (LocaleCompare(attribute,"fuzz") == 0)
3207             {
3208               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3209               break;
3210             }
3211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3212             attribute);
3213           break;
3214         }
3215         case 'I':
3216         case 'i':
3217         {
3218           if (LocaleCompare(attribute,"image") == 0)
3219             {
3220               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3221                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3222               break;
3223             }
3224           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3225             attribute);
3226           break;
3227         }
3228         case 'M':
3229         case 'm':
3230         {
3231           if (LocaleCompare(attribute,"metric") == 0)
3232             {
3233               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3234                 SvPV(ST(i),na));
3235               if (option < 0)
3236                 {
3237                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3238                     SvPV(ST(i),na));
3239                   break;
3240                 }
3241               metric=(MetricType) option;
3242               break;
3243             }
3244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3245             attribute);
3246           break;
3247         }
3248         default:
3249         {
3250           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3251             attribute);
3252           break;
3253         }
3254       }
3255     }
3256     difference_image=CompareImageChannels(image,reconstruct_image,channel,
3257       metric,&distortion,exception);
3258     if (difference_image != (Image *) NULL)
3259       {
3260         difference_image->error.mean_error_per_pixel=distortion;
3261         AddImageToRegistry(sv,difference_image);
3262         rv=newRV(sv);
3263         av_push(av,sv_bless(rv,hv));
3264         SvREFCNT_dec(sv);
3265       }
3266     exception=DestroyExceptionInfo(exception);
3267     ST(0)=av_reference;
3268     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3269     XSRETURN(1);
3270
3271   PerlException:
3272     InheritPerlException(exception,perl_exception);
3273     exception=DestroyExceptionInfo(exception);
3274     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3275     SvPOK_on(perl_exception);
3276     ST(0)=sv_2mortal(perl_exception);
3277     XSRETURN(1);
3278   }
3279 \f
3280 #
3281 ###############################################################################
3282 #                                                                             #
3283 #                                                                             #
3284 #                                                                             #
3285 #   C o m p a r e L a y e r s                                                 #
3286 #                                                                             #
3287 #                                                                             #
3288 #                                                                             #
3289 ###############################################################################
3290 #
3291 #
3292 void
3293 CompareLayers(ref)
3294   Image::Magick ref=NO_INIT
3295   ALIAS:
3296     CompareImageLayers   = 1
3297     comparelayers        = 2
3298     compareimagelayers   = 3
3299   PPCODE:
3300   {
3301     AV
3302       *av;
3303
3304     char
3305       *attribute;
3306
3307     ExceptionInfo
3308       *exception;
3309
3310     HV
3311       *hv;
3312
3313     Image
3314       *image;
3315
3316     ImageLayerMethod
3317       method;
3318
3319     register ssize_t
3320       i;
3321
3322     ssize_t
3323       option;
3324
3325     struct PackageInfo
3326       *info;
3327
3328     SV
3329       *av_reference,
3330       *perl_exception,
3331       *reference,
3332       *rv,
3333       *sv;
3334
3335     PERL_UNUSED_VAR(ref);
3336     PERL_UNUSED_VAR(ix);
3337     exception=AcquireExceptionInfo();
3338     perl_exception=newSVpv("",0);
3339     sv=NULL;
3340     if (sv_isobject(ST(0)) == 0)
3341       {
3342         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3343           PackageName);
3344         goto PerlException;
3345       }
3346     reference=SvRV(ST(0));
3347     hv=SvSTASH(reference);
3348     av=newAV();
3349     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3350     SvREFCNT_dec(av);
3351     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3352     if (image == (Image *) NULL)
3353       {
3354         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3355           PackageName);
3356         goto PerlException;
3357       }
3358     method=CompareAnyLayer;
3359     for (i=2; i < items; i+=2)
3360     {
3361       attribute=(char *) SvPV(ST(i-1),na);
3362       switch (*attribute)
3363       {
3364         case 'M':
3365         case 'm':
3366         {
3367           if (LocaleCompare(attribute,"method") == 0)
3368             {
3369               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3370                 SvPV(ST(i),na));
3371               if (option < 0)
3372                 {
3373                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3374                     SvPV(ST(i),na));
3375                   break;
3376                 }
3377                method=(ImageLayerMethod) option;
3378               break;
3379             }
3380           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3381             attribute);
3382           break;
3383         }
3384         default:
3385         {
3386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3387             attribute);
3388           break;
3389         }
3390       }
3391     }
3392     image=CompareImageLayers(image,method,exception);
3393     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3394       goto PerlException;
3395     for ( ; image; image=image->next)
3396     {
3397       AddImageToRegistry(sv,image);
3398       rv=newRV(sv);
3399       av_push(av,sv_bless(rv,hv));
3400       SvREFCNT_dec(sv);
3401     }
3402     exception=DestroyExceptionInfo(exception);
3403     ST(0)=av_reference;
3404     SvREFCNT_dec(perl_exception);
3405     XSRETURN(1);
3406
3407   PerlException:
3408     InheritPerlException(exception,perl_exception);
3409     exception=DestroyExceptionInfo(exception);
3410     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3411     SvPOK_on(perl_exception);
3412     ST(0)=sv_2mortal(perl_exception);
3413     XSRETURN(1);
3414   }
3415 \f
3416 #
3417 ###############################################################################
3418 #                                                                             #
3419 #                                                                             #
3420 #                                                                             #
3421 #   D e s t r o y                                                             #
3422 #                                                                             #
3423 #                                                                             #
3424 #                                                                             #
3425 ###############################################################################
3426 #
3427 #
3428 void
3429 DESTROY(ref)
3430   Image::Magick ref=NO_INIT
3431   PPCODE:
3432   {
3433     SV
3434       *reference;
3435
3436     PERL_UNUSED_VAR(ref);
3437     if (sv_isobject(ST(0)) == 0)
3438       croak("ReferenceIsNotMyType");
3439     reference=SvRV(ST(0));
3440     switch (SvTYPE(reference))
3441     {
3442       case SVt_PVAV:
3443       {
3444         char
3445           message[MaxTextExtent];
3446
3447         const SV
3448           *key;
3449
3450         HV
3451           *hv;
3452
3453         GV
3454           **gvp;
3455
3456         struct PackageInfo
3457           *info;
3458
3459         SV
3460           *sv;
3461
3462         /*
3463           Array (AV *) reference
3464         */
3465         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3466           XS_VERSION,reference);
3467         hv=gv_stashpv(PackageName, FALSE);
3468         if (!hv)
3469           break;
3470         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3471         if (!gvp)
3472           break;
3473         sv=GvSV(*gvp);
3474         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3475           {
3476             info=(struct PackageInfo *) SvIV(sv);
3477             DestroyPackageInfo(info);
3478           }
3479         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3480         (void) key;
3481         break;
3482       }
3483       case SVt_PVMG:
3484       {
3485         Image
3486           *image;
3487
3488         /*
3489           Blessed scalar = (Image *) SvIV(reference)
3490         */
3491         image=(Image *) SvIV(reference);
3492         if (image != (Image *) NULL)
3493           DeleteImageFromRegistry(reference,image);
3494         break;
3495       }
3496       default:
3497         break;
3498     }
3499   }
3500 \f
3501 #
3502 ###############################################################################
3503 #                                                                             #
3504 #                                                                             #
3505 #                                                                             #
3506 #   D i s p l a y                                                             #
3507 #                                                                             #
3508 #                                                                             #
3509 #                                                                             #
3510 ###############################################################################
3511 #
3512 #
3513 void
3514 Display(ref,...)
3515   Image::Magick ref=NO_INIT
3516   ALIAS:
3517     DisplayImage  = 1
3518     display       = 2
3519     displayimage  = 3
3520   PPCODE:
3521   {
3522     ExceptionInfo
3523       *exception;
3524
3525     Image
3526       *image;
3527
3528     register ssize_t
3529       i;
3530
3531     struct PackageInfo
3532       *info,
3533       *package_info;
3534
3535     SV
3536       *perl_exception,
3537       *reference;
3538
3539     PERL_UNUSED_VAR(ref);
3540     PERL_UNUSED_VAR(ix);
3541     exception=AcquireExceptionInfo();
3542     perl_exception=newSVpv("",0);
3543     package_info=(struct PackageInfo *) NULL;
3544     if (sv_isobject(ST(0)) == 0)
3545       {
3546         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3547           PackageName);
3548         goto PerlException;
3549       }
3550     reference=SvRV(ST(0));
3551     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3552     if (image == (Image *) NULL)
3553       {
3554         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3555           PackageName);
3556         goto PerlException;
3557       }
3558     package_info=ClonePackageInfo(info,exception);
3559     if (items == 2)
3560       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3561     else
3562       if (items > 2)
3563         for (i=2; i < items; i+=2)
3564           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3565             exception);
3566     (void) DisplayImages(package_info->image_info,image);
3567     (void) CatchImageException(image);
3568     InheritException(exception,&image->exception);
3569
3570   PerlException:
3571     if (package_info != (struct PackageInfo *) NULL)
3572       DestroyPackageInfo(package_info);
3573     InheritPerlException(exception,perl_exception);
3574     exception=DestroyExceptionInfo(exception);
3575     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3576     SvPOK_on(perl_exception);
3577     ST(0)=sv_2mortal(perl_exception);
3578     XSRETURN(1);
3579   }
3580 \f
3581 #
3582 ###############################################################################
3583 #                                                                             #
3584 #                                                                             #
3585 #                                                                             #
3586 #   E v a l u a t e I m a g e s                                               #
3587 #                                                                             #
3588 #                                                                             #
3589 #                                                                             #
3590 ###############################################################################
3591 #
3592 #
3593 void
3594 EvaluateImages(ref)
3595   Image::Magick ref=NO_INIT
3596   ALIAS:
3597     EvaluateImages   = 1
3598     evaluateimages   = 2
3599   PPCODE:
3600   {
3601     AV
3602       *av;
3603
3604     char
3605       *attribute,
3606       *p;
3607
3608     ExceptionInfo
3609       *exception;
3610
3611     HV
3612       *hv;
3613
3614     Image
3615       *image;
3616
3617     MagickEvaluateOperator
3618       op;
3619
3620     register ssize_t
3621       i;
3622
3623     struct PackageInfo
3624       *info;
3625
3626     SV
3627       *perl_exception,
3628       *reference,
3629       *rv,
3630       *sv;
3631
3632     PERL_UNUSED_VAR(ref);
3633     PERL_UNUSED_VAR(ix);
3634     exception=AcquireExceptionInfo();
3635     perl_exception=newSVpv("",0);
3636     sv=NULL;
3637     if (sv_isobject(ST(0)) == 0)
3638       {
3639         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3640           PackageName);
3641         goto PerlException;
3642       }
3643     reference=SvRV(ST(0));
3644     hv=SvSTASH(reference);
3645     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3646     if (image == (Image *) NULL)
3647       {
3648         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3649           PackageName);
3650         goto PerlException;
3651       }
3652     op=MeanEvaluateOperator;
3653     if (items == 2)
3654       {
3655         ssize_t
3656           in;
3657
3658         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3659           SvPV(ST(1),na));
3660         if (in < 0)
3661           {
3662             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3663               SvPV(ST(1),na));
3664             return;
3665           }
3666         op=(MagickEvaluateOperator) in;
3667       }
3668     else
3669       for (i=2; i < items; i+=2)
3670       {
3671         attribute=(char *) SvPV(ST(i-1),na);
3672         switch (*attribute)
3673         {
3674           case 'O':
3675           case 'o':
3676           {
3677             if (LocaleCompare(attribute,"operator") == 0)
3678               {
3679                 ssize_t
3680                   in;
3681
3682                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3683                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3684                 if (in < 0)
3685                   {
3686                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3687                       SvPV(ST(i),na));
3688                     return;
3689                   }
3690                 op=(MagickEvaluateOperator) in;
3691                 break;
3692               }
3693             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3694               attribute);
3695             break;
3696           }
3697           default:
3698           {
3699             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3700               attribute);
3701             break;
3702           }
3703         }
3704       }
3705     image=EvaluateImages(image,op,exception);
3706     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3707       goto PerlException;
3708     /*
3709       Create blessed Perl array for the returned image.
3710     */
3711     av=newAV();
3712     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3713     SvREFCNT_dec(av);
3714     AddImageToRegistry(sv,image);
3715     rv=newRV(sv);
3716     av_push(av,sv_bless(rv,hv));
3717     SvREFCNT_dec(sv);
3718     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3719     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3720       "evaluate-%.*s",(int) (MaxTextExtent-9),
3721       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3722     (void) CopyMagickString(image->filename,info->image_info->filename,
3723       MaxTextExtent);
3724     SetImageInfo(info->image_info,0,exception);
3725     exception=DestroyExceptionInfo(exception);
3726     SvREFCNT_dec(perl_exception);
3727     XSRETURN(1);
3728
3729   PerlException:
3730     InheritPerlException(exception,perl_exception);
3731     exception=DestroyExceptionInfo(exception);
3732     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3733     SvPOK_on(perl_exception);
3734     ST(0)=sv_2mortal(perl_exception);
3735     XSRETURN(1);
3736   }
3737 \f
3738 #
3739 ###############################################################################
3740 #                                                                             #
3741 #                                                                             #
3742 #                                                                             #
3743 #   F e a t u r e s                                                           #
3744 #                                                                             #
3745 #                                                                             #
3746 #                                                                             #
3747 ###############################################################################
3748 #
3749 #
3750 void
3751 Features(ref,...)
3752   Image::Magick ref=NO_INIT
3753   ALIAS:
3754     FeaturesImage = 1
3755     features      = 2
3756     featuresimage = 3
3757   PPCODE:
3758   {
3759 #define ChannelFeatures(channel,direction) \
3760 { \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].angular_second_moment[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].contrast[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].contrast[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3771     channel_features[channel].variance_sum_of_squares[direction]); \
3772   PUSHs(sv_2mortal(newSVpv(message,0))); \
3773   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3774     channel_features[channel].inverse_difference_moment[direction]); \
3775   PUSHs(sv_2mortal(newSVpv(message,0))); \
3776   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3777     channel_features[channel].sum_average[direction]); \
3778   PUSHs(sv_2mortal(newSVpv(message,0))); \
3779   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3780     channel_features[channel].sum_variance[direction]); \
3781   PUSHs(sv_2mortal(newSVpv(message,0))); \
3782   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3783     channel_features[channel].sum_entropy[direction]); \
3784   PUSHs(sv_2mortal(newSVpv(message,0))); \
3785   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3786     channel_features[channel].entropy[direction]); \
3787   PUSHs(sv_2mortal(newSVpv(message,0))); \
3788   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3789     channel_features[channel].difference_variance[direction]); \
3790   PUSHs(sv_2mortal(newSVpv(message,0))); \
3791   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3792     channel_features[channel].difference_entropy[direction]); \
3793   PUSHs(sv_2mortal(newSVpv(message,0))); \
3794   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3795     channel_features[channel].measure_of_correlation_1[direction]); \
3796   PUSHs(sv_2mortal(newSVpv(message,0))); \
3797   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3798     channel_features[channel].measure_of_correlation_2[direction]); \
3799   PUSHs(sv_2mortal(newSVpv(message,0))); \
3800   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3801     channel_features[channel].maximum_correlation_coefficient[direction]); \
3802   PUSHs(sv_2mortal(newSVpv(message,0))); \
3803 }
3804
3805     AV
3806       *av;
3807
3808     char
3809       *attribute,
3810       message[MaxTextExtent];
3811
3812     ChannelFeatures
3813       *channel_features;
3814
3815     double
3816       distance;
3817
3818     ExceptionInfo
3819       *exception;
3820
3821     Image
3822       *image;
3823
3824     register ssize_t
3825       i;
3826
3827     ssize_t
3828       count;
3829
3830     struct PackageInfo
3831       *info;
3832
3833     SV
3834       *perl_exception,
3835       *reference;
3836
3837     PERL_UNUSED_VAR(ref);
3838     PERL_UNUSED_VAR(ix);
3839     exception=AcquireExceptionInfo();
3840     perl_exception=newSVpv("",0);
3841     av=NULL;
3842     if (sv_isobject(ST(0)) == 0)
3843       {
3844         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3845           PackageName);
3846         goto PerlException;
3847       }
3848     reference=SvRV(ST(0));
3849     av=newAV();
3850     SvREFCNT_dec(av);
3851     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3852     if (image == (Image *) NULL)
3853       {
3854         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3855           PackageName);
3856         goto PerlException;
3857       }
3858     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3859     distance=1;
3860     for (i=2; i < items; i+=2)
3861     {
3862       attribute=(char *) SvPV(ST(i-1),na);
3863       switch (*attribute)
3864       {
3865         case 'D':
3866         case 'd':
3867         {
3868           if (LocaleCompare(attribute,"distance") == 0)
3869             {
3870               distance=StringToLong((char *) SvPV(ST(1),na));
3871               break;
3872             }
3873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3874             attribute);
3875           break;
3876         }
3877         default:
3878         {
3879           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3880             attribute);
3881           break;
3882         }
3883       }
3884     }
3885     count=0;
3886     for ( ; image; image=image->next)
3887     {
3888       channel_features=GetImageChannelFeatures(image,distance,
3889         &image->exception);
3890       if (channel_features == (ChannelFeatures *) NULL)
3891         continue;
3892       count++;
3893       EXTEND(sp,75*count);
3894       for (i=0; i < 4; i++)
3895       {
3896         ChannelFeatures(RedChannel,i);
3897         ChannelFeatures(GreenChannel,i);
3898         ChannelFeatures(BlueChannel,i);
3899         if (image->colorspace == CMYKColorspace)
3900           ChannelFeatures(IndexChannel,i);
3901         if (image->matte != MagickFalse)
3902           ChannelFeatures(OpacityChannel,i);
3903       }
3904       channel_features=(ChannelFeatures *)
3905         RelinquishMagickMemory(channel_features);
3906     }
3907
3908   PerlException:
3909     InheritPerlException(exception,perl_exception);
3910     exception=DestroyExceptionInfo(exception);
3911     SvREFCNT_dec(perl_exception);
3912   }
3913 \f
3914 #
3915 ###############################################################################
3916 #                                                                             #
3917 #                                                                             #
3918 #                                                                             #
3919 #   F l a t t e n                                                             #
3920 #                                                                             #
3921 #                                                                             #
3922 #                                                                             #
3923 ###############################################################################
3924 #
3925 #
3926 void
3927 Flatten(ref)
3928   Image::Magick ref=NO_INIT
3929   ALIAS:
3930     FlattenImage   = 1
3931     flatten        = 2
3932     flattenimage   = 3
3933   PPCODE:
3934   {
3935     AV
3936       *av;
3937
3938     char
3939       *attribute,
3940       *p;
3941
3942     ExceptionInfo
3943       *exception;
3944
3945     HV
3946       *hv;
3947
3948     Image
3949       *image;
3950
3951     PixelPacket
3952       background_color;
3953
3954     register ssize_t
3955       i;
3956
3957     struct PackageInfo
3958       *info;
3959
3960     SV
3961       *perl_exception,
3962       *reference,
3963       *rv,
3964       *sv;
3965
3966     PERL_UNUSED_VAR(ref);
3967     PERL_UNUSED_VAR(ix);
3968     exception=AcquireExceptionInfo();
3969     perl_exception=newSVpv("",0);
3970     sv=NULL;
3971     if (sv_isobject(ST(0)) == 0)
3972       {
3973         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3974           PackageName);
3975         goto PerlException;
3976       }
3977     reference=SvRV(ST(0));
3978     hv=SvSTASH(reference);
3979     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3980     if (image == (Image *) NULL)
3981       {
3982         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3983           PackageName);
3984         goto PerlException;
3985       }
3986     background_color=image->background_color;
3987     if (items == 2)
3988       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3989         exception);
3990     else
3991       for (i=2; i < items; i+=2)
3992       {
3993         attribute=(char *) SvPV(ST(i-1),na);
3994         switch (*attribute)
3995         {
3996           case 'B':
3997           case 'b':
3998           {
3999             if (LocaleCompare(attribute,"background") == 0)
4000               {
4001                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
4002                   &background_color,exception);
4003                 break;
4004               }
4005             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4006               attribute);
4007             break;
4008           }
4009           default:
4010           {
4011             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4012               attribute);
4013             break;
4014           }
4015         }
4016       }
4017     image->background_color=background_color;
4018     image=MergeImageLayers(image,FlattenLayer,exception);
4019     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4020       goto PerlException;
4021     /*
4022       Create blessed Perl array for the returned image.
4023     */
4024     av=newAV();
4025     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4026     SvREFCNT_dec(av);
4027     AddImageToRegistry(sv,image);
4028     rv=newRV(sv);
4029     av_push(av,sv_bless(rv,hv));
4030     SvREFCNT_dec(sv);
4031     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4032     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4033       "flatten-%.*s",(int) (MaxTextExtent-9),
4034       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4035     (void) CopyMagickString(image->filename,info->image_info->filename,
4036       MaxTextExtent);
4037     SetImageInfo(info->image_info,0,exception);
4038     exception=DestroyExceptionInfo(exception);
4039     SvREFCNT_dec(perl_exception);
4040     XSRETURN(1);
4041
4042   PerlException:
4043     InheritPerlException(exception,perl_exception);
4044     exception=DestroyExceptionInfo(exception);
4045     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4046     SvPOK_on(perl_exception);  /* return messages in string context */
4047     ST(0)=sv_2mortal(perl_exception);
4048     XSRETURN(1);
4049   }
4050 \f
4051 #
4052 ###############################################################################
4053 #                                                                             #
4054 #                                                                             #
4055 #                                                                             #
4056 #   F x                                                                       #
4057 #                                                                             #
4058 #                                                                             #
4059 #                                                                             #
4060 ###############################################################################
4061 #
4062 #
4063 void
4064 Fx(ref,...)
4065   Image::Magick ref=NO_INIT
4066   ALIAS:
4067     FxImage  = 1
4068     fx       = 2
4069     fximage  = 3
4070   PPCODE:
4071   {
4072     AV
4073       *av;
4074
4075     char
4076       *attribute,
4077       expression[MaxTextExtent];
4078
4079     ChannelType
4080       channel;
4081
4082     ExceptionInfo
4083       *exception;
4084
4085     HV
4086       *hv;
4087
4088     Image
4089       *image;
4090
4091     register ssize_t
4092       i;
4093
4094     struct PackageInfo
4095       *info;
4096
4097     SV
4098       *av_reference,
4099       *perl_exception,
4100       *reference,
4101       *rv,
4102       *sv;
4103
4104     PERL_UNUSED_VAR(ref);
4105     PERL_UNUSED_VAR(ix);
4106     exception=AcquireExceptionInfo();
4107     perl_exception=newSVpv("",0);
4108     sv=NULL;
4109     attribute=NULL;
4110     av=NULL;
4111     if (sv_isobject(ST(0)) == 0)
4112       {
4113         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4114           PackageName);
4115         goto PerlException;
4116       }
4117     reference=SvRV(ST(0));
4118     hv=SvSTASH(reference);
4119     av=newAV();
4120     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4121     SvREFCNT_dec(av);
4122     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4123     if (image == (Image *) NULL)
4124       {
4125         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4126           PackageName);
4127         goto PerlException;
4128       }
4129     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4130     /*
4131       Get options.
4132     */
4133     channel=DefaultChannels;
4134     (void) CopyMagickString(expression,"u",MaxTextExtent);
4135     if (items == 2)
4136       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4137     else
4138       for (i=2; i < items; i+=2)
4139       {
4140         attribute=(char *) SvPV(ST(i-1),na);
4141         switch (*attribute)
4142         {
4143           case 'C':
4144           case 'c':
4145           {
4146             if (LocaleCompare(attribute,"channel") == 0)
4147               {
4148                 ssize_t
4149                   option;
4150
4151                 option=ParseChannelOption(SvPV(ST(i),na));
4152                 if (option < 0)
4153                   {
4154                     ThrowPerlException(exception,OptionError,
4155                       "UnrecognizedType",SvPV(ST(i),na));
4156                     return;
4157                   }
4158                 channel=(ChannelType) option;
4159                 break;
4160               }
4161             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4162               attribute);
4163             break;
4164           }
4165           case 'E':
4166           case 'e':
4167           {
4168             if (LocaleCompare(attribute,"expression") == 0)
4169               {
4170                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4171                   MaxTextExtent);
4172                 break;
4173               }
4174             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4175               attribute);
4176             break;
4177           }
4178           default:
4179           {
4180             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4181               attribute);
4182             break;
4183           }
4184         }
4185       }
4186     image=FxImageChannel(image,channel,expression,exception);
4187     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4188       goto PerlException;
4189     for ( ; image; image=image->next)
4190     {
4191       AddImageToRegistry(sv,image);
4192       rv=newRV(sv);
4193       av_push(av,sv_bless(rv,hv));
4194       SvREFCNT_dec(sv);
4195     }
4196     exception=DestroyExceptionInfo(exception);
4197     ST(0)=av_reference;
4198     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4199     XSRETURN(1);
4200
4201   PerlException:
4202     InheritPerlException(exception,perl_exception);
4203     exception=DestroyExceptionInfo(exception);
4204     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4205     SvPOK_on(perl_exception);
4206     ST(0)=sv_2mortal(perl_exception);
4207     XSRETURN(1);
4208   }
4209 \f
4210 #
4211 ###############################################################################
4212 #                                                                             #
4213 #                                                                             #
4214 #                                                                             #
4215 #   G e t                                                                     #
4216 #                                                                             #
4217 #                                                                             #
4218 #                                                                             #
4219 ###############################################################################
4220 #
4221 #
4222 void
4223 Get(ref,...)
4224   Image::Magick ref=NO_INIT
4225   ALIAS:
4226     GetAttributes = 1
4227     GetAttribute  = 2
4228     get           = 3
4229     getattributes = 4
4230     getattribute  = 5
4231   PPCODE:
4232   {
4233     char
4234       *attribute,
4235       color[MaxTextExtent];
4236
4237     const char
4238       *value;
4239
4240     ExceptionInfo
4241       *exception;
4242
4243     Image
4244       *image;
4245
4246     long
4247       j;
4248
4249     register ssize_t
4250       i;
4251
4252     struct PackageInfo
4253       *info;
4254
4255     SV
4256       *perl_exception,
4257       *reference,
4258       *s;
4259
4260     PERL_UNUSED_VAR(ref);
4261     PERL_UNUSED_VAR(ix);
4262     exception=AcquireExceptionInfo();
4263     perl_exception=newSVpv("",0);
4264     if (sv_isobject(ST(0)) == 0)
4265       {
4266         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4267           PackageName);
4268         XSRETURN_EMPTY;
4269       }
4270     reference=SvRV(ST(0));
4271     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4272     if (image == (Image *) NULL && !info)
4273       XSRETURN_EMPTY;
4274     EXTEND(sp,items);
4275     for (i=1; i < items; i++)
4276     {
4277       attribute=(char *) SvPV(ST(i),na);
4278       s=NULL;
4279       switch (*attribute)
4280       {
4281         case 'A':
4282         case 'a':
4283         {
4284           if (LocaleCompare(attribute,"adjoin") == 0)
4285             {
4286               if (info)
4287                 s=newSViv((ssize_t) info->image_info->adjoin);
4288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4289               continue;
4290             }
4291           if (LocaleCompare(attribute,"antialias") == 0)
4292             {
4293               if (info)
4294                 s=newSViv((ssize_t) info->image_info->antialias);
4295               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4296               continue;
4297             }
4298           if (LocaleCompare(attribute,"area") == 0)
4299             {
4300               s=newSViv(GetMagickResource(AreaResource));
4301               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4302               continue;
4303             }
4304           if (LocaleCompare(attribute,"attenuate") == 0)
4305             {
4306               const char
4307                 *value;
4308
4309               value=GetImageProperty(image,attribute);
4310               if (value != (const char *) NULL)
4311                 s=newSVpv(value,0);
4312               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4313               continue;
4314             }
4315           if (LocaleCompare(attribute,"authenticate") == 0)
4316             {
4317               if (info)
4318                 s=newSVpv(info->image_info->authenticate,0);
4319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4320               continue;
4321             }
4322           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4323             attribute);
4324           break;
4325         }
4326         case 'B':
4327         case 'b':
4328         {
4329           if (LocaleCompare(attribute,"background") == 0)
4330             {
4331               if (image == (Image *) NULL)
4332                 break;
4333               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4334                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4335                 image->background_color.red,image->background_color.green,
4336                 image->background_color.blue,image->background_color.opacity);
4337               s=newSVpv(color,0);
4338               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4339               continue;
4340             }
4341           if (LocaleCompare(attribute,"base-columns") == 0)
4342             {
4343               if (image != (Image *) NULL)
4344                 s=newSViv((ssize_t) image->magick_columns);
4345               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4346               continue;
4347             }
4348           if (LocaleCompare(attribute,"base-filename") == 0)
4349             {
4350               if (image != (Image *) NULL)
4351                 s=newSVpv(image->magick_filename,0);
4352               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4353               continue;
4354             }
4355           if (LocaleCompare(attribute,"base-height") == 0)
4356             {
4357               if (image != (Image *) NULL)
4358                 s=newSViv((ssize_t) image->magick_rows);
4359               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4360               continue;
4361             }
4362           if (LocaleCompare(attribute,"base-rows") == 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-width") == 0)
4370             {
4371               if (image != (Image *) NULL)
4372                 s=newSViv((ssize_t) image->magick_columns);
4373               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4374               continue;
4375             }
4376           if (LocaleCompare(attribute,"bias") == 0)
4377             {
4378               if (image != (Image *) NULL)
4379                 s=newSVnv(image->bias);
4380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4381               continue;
4382             }
4383           if (LocaleCompare(attribute,"blue-primary") == 0)
4384             {
4385               if (image == (Image *) NULL)
4386                 break;
4387               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4388                 image->chromaticity.blue_primary.x,
4389                 image->chromaticity.blue_primary.y);
4390               s=newSVpv(color,0);
4391               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4392               continue;
4393             }
4394           if (LocaleCompare(attribute,"bordercolor") == 0)
4395             {
4396               if (image == (Image *) NULL)
4397                 break;
4398               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4399                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4400                 image->border_color.red,image->border_color.green,
4401                 image->border_color.blue,image->border_color.opacity);
4402               s=newSVpv(color,0);
4403               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4404               continue;
4405             }
4406           if (LocaleCompare(attribute,"bounding-box") == 0)
4407             {
4408               char
4409                 geometry[MaxTextExtent];
4410
4411               RectangleInfo
4412                 page;
4413
4414               if (image == (Image *) NULL)
4415                 break;
4416               page=GetImageBoundingBox(image,&image->exception);
4417               (void) FormatLocaleString(geometry,MaxTextExtent,
4418                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4419                 page.height,(double) page.x,(double) page.y);
4420               s=newSVpv(geometry,0);
4421               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4422               continue;
4423             }
4424           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4425             attribute);
4426           break;
4427         }
4428         case 'C':
4429         case 'c':
4430         {
4431           if (LocaleCompare(attribute,"class") == 0)
4432             {
4433               if (image == (Image *) NULL)
4434                 break;
4435               s=newSViv(image->storage_class);
4436               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4437                 image->storage_class));
4438               SvIOK_on(s);
4439               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4440               continue;
4441             }
4442           if (LocaleCompare(attribute,"clip-mask") == 0)
4443             {
4444               if (image != (Image *) NULL)
4445                 {
4446                   SV
4447                     *sv;
4448
4449                   sv=NULL;
4450                   if (image->mask == (Image *) NULL)
4451                     ClipImage(image);
4452                   if (image->mask != (Image *) NULL)
4453                     {
4454                       AddImageToRegistry(sv,image->mask);
4455                       s=sv_bless(newRV(sv),SvSTASH(reference));
4456                     }
4457                 }
4458               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4459               continue;
4460             }
4461           if (LocaleCompare(attribute,"clip-path") == 0)
4462             {
4463               if (image != (Image *) NULL)
4464                 {
4465                   SV
4466                     *sv;
4467
4468                   sv=NULL;
4469                   if (image->clip_mask == (Image *) NULL)
4470                     ClipImage(image);
4471                   if (image->clip_mask != (Image *) NULL)
4472                     {
4473                       AddImageToRegistry(sv,image->clip_mask);
4474                       s=sv_bless(newRV(sv),SvSTASH(reference));
4475                     }
4476                 }
4477               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4478               continue;
4479             }
4480           if (LocaleCompare(attribute,"compression") == 0)
4481             {
4482               j=info ? info->image_info->compression : image ?
4483                 image->compression : UndefinedCompression;
4484               if (info)
4485                 if (info->image_info->compression == UndefinedCompression)
4486                   j=image->compression;
4487               s=newSViv(j);
4488               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4489                 j));
4490               SvIOK_on(s);
4491               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4492               continue;
4493             }
4494           if (LocaleCompare(attribute,"colorspace") == 0)
4495             {
4496               j=image ? image->colorspace : RGBColorspace;
4497               s=newSViv(j);
4498               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4499                 j));
4500               SvIOK_on(s);
4501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4502               continue;
4503             }
4504           if (LocaleCompare(attribute,"colors") == 0)
4505             {
4506               if (image != (Image *) NULL)
4507                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4508                   &image->exception));
4509               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4510               continue;
4511             }
4512           if (LocaleNCompare(attribute,"colormap",8) == 0)
4513             {
4514               int
4515                 items;
4516
4517               if (image == (Image *) NULL || !image->colormap)
4518                 break;
4519               j=0;
4520               items=sscanf(attribute,"%*[^[][%ld",&j);
4521               (void) items;
4522               if (j > (ssize_t) image->colors)
4523                 j%=image->colors;
4524               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4525                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4526                 image->colormap[j].red,image->colormap[j].green,
4527                 image->colormap[j].blue,image->colormap[j].opacity);
4528               s=newSVpv(color,0);
4529               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4530               continue;
4531             }
4532           if (LocaleCompare(attribute,"columns") == 0)
4533             {
4534               if (image != (Image *) NULL)
4535                 s=newSViv((ssize_t) image->columns);
4536               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4537               continue;
4538             }
4539           if (LocaleCompare(attribute,"comment") == 0)
4540             {
4541               const char
4542                 *value;
4543
4544               value=GetImageProperty(image,attribute);
4545               if (value != (const char *) NULL)
4546                 s=newSVpv(value,0);
4547               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4548               continue;
4549             }
4550           if (LocaleCompare(attribute,"copyright") == 0)
4551             {
4552               s=newSVpv(GetMagickCopyright(),0);
4553               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4554               continue;
4555             }
4556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4557             attribute);
4558           break;
4559         }
4560         case 'D':
4561         case 'd':
4562         {
4563           if (LocaleCompare(attribute,"density") == 0)
4564             {
4565               char
4566                 geometry[MaxTextExtent];
4567
4568               if (image == (Image *) NULL)
4569                 break;
4570               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4571                 image->x_resolution,image->y_resolution);
4572               s=newSVpv(geometry,0);
4573               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4574               continue;
4575             }
4576           if (LocaleCompare(attribute,"delay") == 0)
4577             {
4578               if (image != (Image *) NULL)
4579                 s=newSViv((ssize_t) image->delay);
4580               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4581               continue;
4582             }
4583           if (LocaleCompare(attribute,"depth") == 0)
4584             {
4585               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4586               if (image != (Image *) NULL)
4587                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4588               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4589               continue;
4590             }
4591           if (LocaleCompare(attribute,"directory") == 0)
4592             {
4593               if (image && image->directory)
4594                 s=newSVpv(image->directory,0);
4595               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4596               continue;
4597             }
4598           if (LocaleCompare(attribute,"dispose") == 0)
4599             {
4600               if (image == (Image *) NULL)
4601                 break;
4602
4603               s=newSViv(image->dispose);
4604               (void) sv_setpv(s,
4605                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4606               SvIOK_on(s);
4607               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4608               continue;
4609             }
4610           if (LocaleCompare(attribute,"disk") == 0)
4611             {
4612               s=newSViv(GetMagickResource(DiskResource));
4613               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4614               continue;
4615             }
4616           if (LocaleCompare(attribute,"dither") == 0)
4617             {
4618               if (info)
4619                 s=newSViv((ssize_t) info->image_info->dither);
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4624             {
4625               if (info && info->image_info->server_name)
4626                 s=newSVpv(info->image_info->server_name,0);
4627               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4628               continue;
4629             }
4630           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4631             attribute);
4632           break;
4633         }
4634         case 'E':
4635         case 'e':
4636         {
4637           if (LocaleCompare(attribute,"elapsed-time") == 0)
4638             {
4639               if (image != (Image *) NULL)
4640                 s=newSVnv(GetElapsedTime(&image->timer));
4641               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4642               continue;
4643             }
4644           if (LocaleCompare(attribute,"endian") == 0)
4645             {
4646               j=info ? info->image_info->endian : image ? image->endian :
4647                 UndefinedEndian;
4648               s=newSViv(j);
4649               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4650               SvIOK_on(s);
4651               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4652               continue;
4653             }
4654           if (LocaleCompare(attribute,"error") == 0)
4655             {
4656               if (image != (Image *) NULL)
4657                 s=newSVnv(image->error.mean_error_per_pixel);
4658               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4659               continue;
4660             }
4661           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4662             attribute);
4663           break;
4664         }
4665         case 'F':
4666         case 'f':
4667         {
4668           if (LocaleCompare(attribute,"filesize") == 0)
4669             {
4670               if (image != (Image *) NULL)
4671                 s=newSViv((ssize_t) GetBlobSize(image));
4672               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4673               continue;
4674             }
4675           if (LocaleCompare(attribute,"filename") == 0)
4676             {
4677               if (info && info->image_info->filename &&
4678                   *info->image_info->filename)
4679                 s=newSVpv(info->image_info->filename,0);
4680               if (image != (Image *) NULL)
4681                 s=newSVpv(image->filename,0);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"filter") == 0)
4686             {
4687               s=image ? newSViv(image->filter) : newSViv(0);
4688               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4689                 image->filter));
4690               SvIOK_on(s);
4691               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4692               continue;
4693             }
4694           if (LocaleCompare(attribute,"font") == 0)
4695             {
4696               if (info && info->image_info->font)
4697                 s=newSVpv(info->image_info->font,0);
4698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699               continue;
4700             }
4701           if (LocaleCompare(attribute,"foreground") == 0)
4702             continue;
4703           if (LocaleCompare(attribute,"format") == 0)
4704             {
4705               const MagickInfo
4706                 *magick_info;
4707
4708               magick_info=(const MagickInfo *) NULL;
4709               if (info && (*info->image_info->magick != '\0'))
4710                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4711               if (image != (Image *) NULL)
4712                 magick_info=GetMagickInfo(image->magick,&image->exception);
4713               if ((magick_info != (const MagickInfo *) NULL) &&
4714                   (*magick_info->description != '\0'))
4715                 s=newSVpv((char *) magick_info->description,0);
4716               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4717               continue;
4718             }
4719           if (LocaleCompare(attribute,"fuzz") == 0)
4720             {
4721               if (info)
4722                 s=newSVnv(info->image_info->fuzz);
4723               if (image != (Image *) NULL)
4724                 s=newSVnv(image->fuzz);
4725               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4726               continue;
4727             }
4728           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4729             attribute);
4730           break;
4731         }
4732         case 'G':
4733         case 'g':
4734         {
4735           if (LocaleCompare(attribute,"gamma") == 0)
4736             {
4737               if (image != (Image *) NULL)
4738                 s=newSVnv(image->gamma);
4739               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4740               continue;
4741             }
4742           if (LocaleCompare(attribute,"geometry") == 0)
4743             {
4744               if (image && image->geometry)
4745                 s=newSVpv(image->geometry,0);
4746               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4747               continue;
4748             }
4749           if (LocaleCompare(attribute,"gravity") == 0)
4750             {
4751               s=image ? newSViv(image->gravity) : newSViv(0);
4752               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4753                 image->gravity));
4754               SvIOK_on(s);
4755               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4756               continue;
4757             }
4758           if (LocaleCompare(attribute,"green-primary") == 0)
4759             {
4760               if (image == (Image *) NULL)
4761                 break;
4762               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4763                 image->chromaticity.green_primary.x,
4764                 image->chromaticity.green_primary.y);
4765               s=newSVpv(color,0);
4766               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4767               continue;
4768             }
4769           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4770             attribute);
4771           break;
4772         }
4773         case 'H':
4774         case 'h':
4775         {
4776           if (LocaleCompare(attribute,"height") == 0)
4777             {
4778               if (image != (Image *) NULL)
4779                 s=newSViv((ssize_t) image->rows);
4780               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4781               continue;
4782             }
4783           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4784             attribute);
4785           break;
4786         }
4787         case 'I':
4788         case 'i':
4789         {
4790           if (LocaleCompare(attribute,"icc") == 0)
4791             {
4792               if (image != (Image *) NULL)
4793                 {
4794                   const StringInfo
4795                     *profile;
4796
4797                   profile=GetImageProfile(image,"icc");
4798                   if (profile != (StringInfo *) NULL)
4799                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4800                       GetStringInfoLength(profile));
4801                 }
4802               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4803               continue;
4804             }
4805           if (LocaleCompare(attribute,"icm") == 0)
4806             {
4807               if (image != (Image *) NULL)
4808                 {
4809                   const StringInfo
4810                     *profile;
4811
4812                   profile=GetImageProfile(image,"icm");
4813                   if (profile != (const StringInfo *) NULL)
4814                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4815                       GetStringInfoLength(profile));
4816                 }
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           if (LocaleCompare(attribute,"id") == 0)
4821             {
4822               if (image != (Image *) NULL)
4823                 {
4824                   char
4825                     key[MaxTextExtent];
4826
4827                   MagickBooleanType
4828                     status;
4829
4830                   static ssize_t
4831                     id = 0;
4832
4833                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4834                     id);
4835                   status=SetImageRegistry(ImageRegistryType,key,image,
4836                     &image->exception);
4837                   (void) status;
4838                   s=newSViv(id++);
4839                 }
4840               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4841               continue;
4842             }
4843           if (LocaleNCompare(attribute,"index",5) == 0)
4844             {
4845               char
4846                 name[MaxTextExtent];
4847
4848               int
4849                 items;
4850
4851               long
4852                 x,
4853                 y;
4854
4855               register const IndexPacket
4856                 *indexes;
4857
4858               register const PixelPacket
4859                 *p;
4860
4861               CacheView
4862                 *image_view;
4863
4864               if (image == (Image *) NULL)
4865                 break;
4866               if (image->storage_class != PseudoClass)
4867                 break;
4868               x=0;
4869               y=0;
4870               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4871               (void) items;
4872               image_view=AcquireCacheView(image);
4873               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4874               if (p != (const PixelPacket *) NULL)
4875                 {
4876                   indexes=GetCacheViewVirtualIndexQueue(image_view);
4877                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4878                     GetIndexPixelComponent(indexes));
4879                   s=newSVpv(name,0);
4880                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4881                 }
4882               image_view=DestroyCacheView(image_view);
4883               continue;
4884             }
4885           if (LocaleCompare(attribute,"iptc") == 0)
4886             {
4887               if (image != (Image *) NULL)
4888                 {
4889                   const StringInfo
4890                     *profile;
4891
4892                   profile=GetImageProfile(image,"iptc");
4893                   if (profile != (const StringInfo *) NULL)
4894                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4895                       GetStringInfoLength(profile));
4896                 }
4897               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4898               continue;
4899             }
4900           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4901             {
4902               if (image != (Image *) NULL)
4903                 s=newSViv((ssize_t) image->iterations);
4904               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4905               continue;
4906             }
4907           if (LocaleCompare(attribute,"interlace") == 0)
4908             {
4909               j=info ? info->image_info->interlace : image ? image->interlace :
4910                 UndefinedInterlace;
4911               s=newSViv(j);
4912               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4913                 j));
4914               SvIOK_on(s);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4919             attribute);
4920           break;
4921         }
4922         case 'L':
4923         case 'l':
4924         {
4925           if (LocaleCompare(attribute,"label") == 0)
4926             {
4927               const char
4928                 *value;
4929
4930               if (image == (Image *) NULL)
4931                 break;
4932               value=GetImageProperty(image,"Label");
4933               if (value != (const char *) NULL)
4934                 s=newSVpv(value,0);
4935               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4936               continue;
4937             }
4938           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4939             {
4940               if (image != (Image *) NULL)
4941                 s=newSViv((ssize_t) image->iterations);
4942               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4943               continue;
4944             }
4945           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4946             attribute);
4947           break;
4948         }
4949         case 'M':
4950         case 'm':
4951         {
4952           if (LocaleCompare(attribute,"magick") == 0)
4953             {
4954               if (info && *info->image_info->magick)
4955                 s=newSVpv(info->image_info->magick,0);
4956               if (image != (Image *) NULL)
4957                 s=newSVpv(image->magick,0);
4958               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959               continue;
4960             }
4961           if (LocaleCompare(attribute,"map") == 0)
4962             {
4963               s=newSViv(GetMagickResource(MapResource));
4964               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4965               continue;
4966             }
4967           if (LocaleCompare(attribute,"maximum-error") == 0)
4968             {
4969               if (image != (Image *) NULL)
4970                 s=newSVnv(image->error.normalized_maximum_error);
4971               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972               continue;
4973             }
4974           if (LocaleCompare(attribute,"memory") == 0)
4975             {
4976               s=newSViv(GetMagickResource(MemoryResource));
4977               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978               continue;
4979             }
4980           if (LocaleCompare(attribute,"mean-error") == 0)
4981             {
4982               if (image != (Image *) NULL)
4983                 s=newSVnv(image->error.normalized_mean_error);
4984               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4985               continue;
4986             }
4987           if (LocaleCompare(attribute,"mime") == 0)
4988             {
4989               if (info && *info->image_info->magick)
4990                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4991               if (image != (Image *) NULL)
4992                 s=newSVpv(MagickToMime(image->magick),0);
4993               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4994               continue;
4995             }
4996           if (LocaleCompare(attribute,"mattecolor") == 0)
4997             {
4998               if (image == (Image *) NULL)
4999                 break;
5000               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5001                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5002                 image->matte_color.red,image->matte_color.green,
5003                 image->matte_color.blue,image->matte_color.opacity);
5004               s=newSVpv(color,0);
5005               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5006               continue;
5007             }
5008           if (LocaleCompare(attribute,"matte") == 0)
5009             {
5010               if (image != (Image *) NULL)
5011                 s=newSViv((ssize_t) image->matte);
5012               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5013               continue;
5014             }
5015           if (LocaleCompare(attribute,"mime") == 0)
5016             {
5017               const char
5018                 *magick;
5019
5020               magick=NULL;
5021               if (info && *info->image_info->magick)
5022                 magick=info->image_info->magick;
5023               if (image != (Image *) NULL)
5024                 magick=image->magick;
5025               if (magick)
5026                 {
5027                   char
5028                     *mime;
5029
5030                   mime=MagickToMime(magick);
5031                   s=newSVpv(mime,0);
5032                   mime=(char *) RelinquishMagickMemory(mime);
5033                 }
5034               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5035               continue;
5036             }
5037           if (LocaleCompare(attribute,"monochrome") == 0)
5038             {
5039               if (image == (Image *) NULL)
5040                 continue;
5041               j=info ? info->image_info->monochrome :
5042                 IsMonochromeImage(image,&image->exception);
5043               s=newSViv(j);
5044               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5045               continue;
5046             }
5047           if (LocaleCompare(attribute,"montage") == 0)
5048             {
5049               if (image && image->montage)
5050                 s=newSVpv(image->montage,0);
5051               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5052               continue;
5053             }
5054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5055             attribute);
5056           break;
5057         }
5058         case 'O':
5059         case 'o':
5060         {
5061           if (LocaleCompare(attribute,"orientation") == 0)
5062             {
5063               j=info ? info->image_info->orientation : image ?
5064                 image->orientation : UndefinedOrientation;
5065               s=newSViv(j);
5066               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5067                 j));
5068               SvIOK_on(s);
5069               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5070               continue;
5071             }
5072           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5073             attribute);
5074           break;
5075         }
5076         case 'P':
5077         case 'p':
5078         {
5079           if (LocaleCompare(attribute,"page") == 0)
5080             {
5081               if (info && info->image_info->page)
5082                 s=newSVpv(info->image_info->page,0);
5083               if (image != (Image *) NULL)
5084                 {
5085                   char
5086                     geometry[MaxTextExtent];
5087
5088                   (void) FormatLocaleString(geometry,MaxTextExtent,
5089                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5090                     (double) image->page.height,(double) image->page.x,(double)
5091                     image->page.y);
5092                   s=newSVpv(geometry,0);
5093                 }
5094               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095               continue;
5096             }
5097           if (LocaleCompare(attribute,"page.x") == 0)
5098             {
5099               if (image != (Image *) NULL)
5100                 s=newSViv((ssize_t) image->page.x);
5101               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5102               continue;
5103             }
5104           if (LocaleCompare(attribute,"page.y") == 0)
5105             {
5106               if (image != (Image *) NULL)
5107                 s=newSViv((ssize_t) image->page.y);
5108               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5109               continue;
5110             }
5111           if (LocaleNCompare(attribute,"pixel",5) == 0)
5112             {
5113               char
5114                 tuple[MaxTextExtent];
5115
5116               int
5117                 items;
5118
5119               long
5120                 x,
5121                 y;
5122
5123               register const PixelPacket
5124                 *p;
5125
5126               register const IndexPacket
5127                 *indexes;
5128
5129               if (image == (Image *) NULL)
5130                 break;
5131               x=0;
5132               y=0;
5133               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5134               (void) items;
5135               p=GetVirtualPixels(image,x,y,1,1,exception);
5136               indexes=GetVirtualIndexQueue(image);
5137               if (image->colorspace != CMYKColorspace)
5138                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5139                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5140                   GetRedPixelComponent(p),GetGreenPixelComponent(p),
5141                   GetBluePixelComponent(p),GetOpacityPixelComponent(p));
5142               else
5143                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5144                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5145                   QuantumFormat,GetRedPixelComponent(p),
5146                   GetGreenPixelComponent(p),GetBluePixelComponent(p),
5147                   GetIndexPixelComponent(indexes),GetOpacityPixelComponent(p));
5148               s=newSVpv(tuple,0);
5149               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5150               continue;
5151             }
5152           if (LocaleCompare(attribute,"pointsize") == 0)
5153             {
5154               if (info)
5155                 s=newSViv((ssize_t) info->image_info->pointsize);
5156               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5157               continue;
5158             }
5159           if (LocaleCompare(attribute,"preview") == 0)
5160             {
5161               s=newSViv(info->image_info->preview_type);
5162               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5163                 info->image_info->preview_type));
5164               SvIOK_on(s);
5165               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5166               continue;
5167             }
5168           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5169             attribute);
5170           break;
5171         }
5172         case 'Q':
5173         case 'q':
5174         {
5175           if (LocaleCompare(attribute,"quality") == 0)
5176             {
5177               if (info)
5178                 s=newSViv((ssize_t) info->image_info->quality);
5179               if (image != (Image *) NULL)
5180                 s=newSViv((ssize_t) image->quality);
5181               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5182               continue;
5183             }
5184           if (LocaleCompare(attribute,"quantum") == 0)
5185             {
5186               if (info)
5187                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5188               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5189               continue;
5190             }
5191           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5192             attribute);
5193           break;
5194         }
5195         case 'R':
5196         case 'r':
5197         {
5198           if (LocaleCompare(attribute,"rendering-intent") == 0)
5199             {
5200               s=newSViv(image->rendering_intent);
5201               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5202                 image->rendering_intent));
5203               SvIOK_on(s);
5204               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5205               continue;
5206             }
5207           if (LocaleCompare(attribute,"red-primary") == 0)
5208             {
5209               if (image == (Image *) NULL)
5210                 break;
5211               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5212                 image->chromaticity.red_primary.x,
5213                 image->chromaticity.red_primary.y);
5214               s=newSVpv(color,0);
5215               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5216               continue;
5217             }
5218           if (LocaleCompare(attribute,"rows") == 0)
5219             {
5220               if (image != (Image *) NULL)
5221                 s=newSViv((ssize_t) image->rows);
5222               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5223               continue;
5224             }
5225           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5226             attribute);
5227           break;
5228         }
5229         case 'S':
5230         case 's':
5231         {
5232           if (LocaleCompare(attribute,"sampling-factor") == 0)
5233             {
5234               if (info && info->image_info->sampling_factor)
5235                 s=newSVpv(info->image_info->sampling_factor,0);
5236               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237               continue;
5238             }
5239           if (LocaleCompare(attribute,"subimage") == 0)
5240             {
5241               if (info)
5242                 s=newSViv((ssize_t) info->image_info->subimage);
5243               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5244               continue;
5245             }
5246           if (LocaleCompare(attribute,"subrange") == 0)
5247             {
5248               if (info)
5249                 s=newSViv((ssize_t) info->image_info->subrange);
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5254             {
5255               if (info && info->image_info->server_name)
5256                 s=newSVpv(info->image_info->server_name,0);
5257               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5258               continue;
5259             }
5260           if (LocaleCompare(attribute,"size") == 0)
5261             {
5262               if (info && info->image_info->size)
5263                 s=newSVpv(info->image_info->size,0);
5264               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5265               continue;
5266             }
5267           if (LocaleCompare(attribute,"scene") == 0)
5268             {
5269               if (image != (Image *) NULL)
5270                 s=newSViv((ssize_t) image->scene);
5271               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5272               continue;
5273             }
5274           if (LocaleCompare(attribute,"scenes") == 0)
5275             {
5276               if (image != (Image *) NULL)
5277                 s=newSViv((ssize_t) info->image_info->number_scenes);
5278               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5279               continue;
5280             }
5281           if (LocaleCompare(attribute,"signature") == 0)
5282             {
5283               const char
5284                 *value;
5285
5286               if (image == (Image *) NULL)
5287                 break;
5288               (void) SignatureImage(image);
5289               value=GetImageProperty(image,"Signature");
5290               if (value != (const char *) NULL)
5291                 s=newSVpv(value,0);
5292               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5293               continue;
5294             }
5295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5296             attribute);
5297           break;
5298         }
5299         case 'T':
5300         case 't':
5301         {
5302           if (LocaleCompare(attribute,"taint") == 0)
5303             {
5304               if (image != (Image *) NULL)
5305                 s=newSViv((ssize_t) IsTaintImage(image));
5306               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5307               continue;
5308             }
5309           if (LocaleCompare(attribute,"tile") == 0)
5310             {
5311               if (info && info->image_info->tile)
5312                 s=newSVpv(info->image_info->tile,0);
5313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5314               continue;
5315             }
5316           if (LocaleCompare(attribute,"texture") == 0)
5317             {
5318               if (info && info->image_info->texture)
5319                 s=newSVpv(info->image_info->texture,0);
5320               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5321               continue;
5322             }
5323           if (LocaleCompare(attribute,"total-ink-density") == 0)
5324             {
5325               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5326               if (image != (Image *) NULL)
5327                 s=newSVnv(GetImageTotalInkDensity(image));
5328               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5329               continue;
5330             }
5331           if (LocaleCompare(attribute,"transparent-color") == 0)
5332             {
5333               if (image == (Image *) NULL)
5334                 break;
5335               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5336                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5337                 image->transparent_color.red,image->transparent_color.green,
5338                 image->transparent_color.blue,image->transparent_color.opacity);
5339               s=newSVpv(color,0);
5340               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5341               continue;
5342             }
5343           if (LocaleCompare(attribute,"type") == 0)
5344             {
5345               if (image == (Image *) NULL)
5346                 break;
5347               j=(ssize_t) GetImageType(image,&image->exception);
5348               s=newSViv(j);
5349               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5350               SvIOK_on(s);
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5355             attribute);
5356           break;
5357         }
5358         case 'U':
5359         case 'u':
5360         {
5361           if (LocaleCompare(attribute,"units") == 0)
5362             {
5363               j=info ? info->image_info->units : image ? image->units :
5364                 UndefinedResolution;
5365               if (info && (info->image_info->units == UndefinedResolution))
5366                 if (image)
5367                   j=image->units;
5368               if (j == UndefinedResolution)
5369                 s=newSVpv("undefined units",0);
5370               else
5371                 if (j == PixelsPerInchResolution)
5372                   s=newSVpv("pixels / inch",0);
5373                 else
5374                   s=newSVpv("pixels / centimeter",0);
5375               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5376               continue;
5377             }
5378           if (LocaleCompare(attribute,"user-time") == 0)
5379             {
5380               if (image != (Image *) NULL)
5381                 s=newSVnv(GetUserTime(&image->timer));
5382               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5383               continue;
5384             }
5385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5386             attribute);
5387           break;
5388         }
5389         case 'V':
5390         case 'v':
5391         {
5392           if (LocaleCompare(attribute,"verbose") == 0)
5393             {
5394               if (info)
5395                 s=newSViv((ssize_t) info->image_info->verbose);
5396               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5397               continue;
5398             }
5399           if (LocaleCompare(attribute,"version") == 0)
5400             {
5401               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           if (LocaleCompare(attribute,"view") == 0)
5406             {
5407               if (info && info->image_info->view)
5408                 s=newSVpv(info->image_info->view,0);
5409               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5410               continue;
5411             }
5412           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5413             {
5414               if (image == (Image *) NULL)
5415                 break;
5416               j=(ssize_t) GetImageVirtualPixelMethod(image);
5417               s=newSViv(j);
5418               (void) sv_setpv(s,CommandOptionToMnemonic(
5419                 MagickVirtualPixelOptions,j));
5420               SvIOK_on(s);
5421               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5422               continue;
5423             }
5424           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5425             attribute);
5426           break;
5427         }
5428         case 'W':
5429         case 'w':
5430         {
5431           if (LocaleCompare(attribute,"white-point") == 0)
5432             {
5433               if (image == (Image *) NULL)
5434                 break;
5435               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5436                 image->chromaticity.white_point.x,
5437                 image->chromaticity.white_point.y);
5438               s=newSVpv(color,0);
5439               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5440               continue;
5441             }
5442           if (LocaleCompare(attribute,"width") == 0)
5443             {
5444               if (image != (Image *) NULL)
5445                 s=newSViv((ssize_t) image->columns);
5446               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447               continue;
5448             }
5449           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5450              attribute);
5451           break;
5452         }
5453         case 'X':
5454         case 'x':
5455         {
5456           if (LocaleCompare(attribute,"x-resolution") == 0)
5457             {
5458               if (image != (Image *) NULL)
5459                 s=newSVnv(image->x_resolution);
5460               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5461               continue;
5462             }
5463           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5464             attribute);
5465           break;
5466         }
5467         case 'Y':
5468         case 'y':
5469         {
5470           if (LocaleCompare(attribute,"y-resolution") == 0)
5471             {
5472               if (image != (Image *) NULL)
5473                 s=newSVnv(image->y_resolution);
5474               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5475               continue;
5476             }
5477           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5478             attribute);
5479           break;
5480         }
5481         default:
5482           break;
5483       }
5484       if (image == (Image *) NULL)
5485         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5486           attribute)
5487       else
5488         {
5489           value=GetImageProperty(image,attribute);
5490           if (value != (const char *) NULL)
5491             {
5492               s=newSVpv(value,0);
5493               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5494             }
5495           else
5496             if (*attribute != '%')
5497               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5498                 attribute)
5499             else
5500               {
5501                  char
5502                    *meta;
5503
5504                  meta=InterpretImageProperties(info ? info->image_info :
5505                    (ImageInfo *) NULL,image,attribute);
5506                  s=newSVpv(meta,0);
5507                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5508                  meta=(char *) RelinquishMagickMemory(meta);
5509               }
5510         }
5511     }
5512     exception=DestroyExceptionInfo(exception);
5513     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5514   }
5515 \f
5516 #
5517 ###############################################################################
5518 #                                                                             #
5519 #                                                                             #
5520 #                                                                             #
5521 #   G e t A u t h e n t i c P i x e l s                                       #
5522 #                                                                             #
5523 #                                                                             #
5524 #                                                                             #
5525 ###############################################################################
5526 #
5527 #
5528 void *
5529 GetAuthenticPixels(ref,...)
5530   Image::Magick ref = NO_INIT
5531   ALIAS:
5532     getauthenticpixels = 1
5533     GetImagePixels = 2
5534     getimagepixels = 3
5535   CODE:
5536   {
5537     char
5538       *attribute;
5539
5540     ExceptionInfo
5541       *exception;
5542
5543     Image
5544       *image;
5545
5546     RectangleInfo
5547       region;
5548
5549     ssize_t
5550       i;
5551
5552     struct PackageInfo
5553       *info;
5554
5555     SV
5556       *perl_exception,
5557       *reference;
5558
5559     void
5560       *blob = NULL;
5561
5562     PERL_UNUSED_VAR(ref);
5563     PERL_UNUSED_VAR(ix);
5564     exception=AcquireExceptionInfo();
5565     perl_exception=newSVpv("",0);
5566     if (sv_isobject(ST(0)) == 0)
5567       {
5568         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5569           PackageName);
5570         goto PerlException;
5571       }
5572     reference=SvRV(ST(0));
5573
5574     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5575     if (image == (Image *) NULL)
5576       {
5577         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5578           PackageName);
5579         goto PerlException;
5580       }
5581
5582     region.x=0;
5583     region.y=0;
5584     region.width=image->columns;
5585     region.height=1;
5586     if (items == 1)
5587       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5588     for (i=2; i < items; i+=2)
5589     {
5590       attribute=(char *) SvPV(ST(i-1),na);
5591       switch (*attribute)
5592       {
5593         case 'g':
5594         case 'G':
5595         {
5596           if (LocaleCompare(attribute,"geometry") == 0)
5597             {
5598               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5599               break;
5600             }
5601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5602             attribute);
5603           break;
5604         }
5605         case 'H':
5606         case 'h':
5607         {
5608           if (LocaleCompare(attribute,"height") == 0)
5609             {
5610               region.height=SvIV(ST(i));
5611               continue;
5612             }
5613           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5614             attribute);
5615           break;
5616         }
5617         case 'X':
5618         case 'x':
5619         {
5620           if (LocaleCompare(attribute,"x") == 0)
5621             {
5622               region.x=SvIV(ST(i));
5623               continue;
5624             }
5625           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5626             attribute);
5627           break;
5628         }
5629         case 'Y':
5630         case 'y':
5631         {
5632           if (LocaleCompare(attribute,"y") == 0)
5633             {
5634               region.y=SvIV(ST(i));
5635               continue;
5636             }
5637           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5638             attribute);
5639           break;
5640         }
5641         case 'W':
5642         case 'w':
5643         {
5644           if (LocaleCompare(attribute,"width") == 0)
5645             {
5646               region.width=SvIV(ST(i));
5647               continue;
5648             }
5649           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5650             attribute);
5651           break;
5652         }
5653       }
5654     }
5655     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5656       region.height,exception);
5657     if (blob != (void *) NULL)
5658       goto PerlEnd;
5659
5660   PerlException:
5661     InheritPerlException(exception,perl_exception);
5662     exception=DestroyExceptionInfo(exception);
5663     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5664
5665   PerlEnd:
5666     RETVAL = blob;
5667   }
5668   OUTPUT:
5669     RETVAL
5670 \f
5671 #
5672 ###############################################################################
5673 #                                                                             #
5674 #                                                                             #
5675 #                                                                             #
5676 #   G e t V i r t u a l P i x e l s                                           #
5677 #                                                                             #
5678 #                                                                             #
5679 #                                                                             #
5680 ###############################################################################
5681 #
5682 #
5683 void *
5684 GetVirtualPixels(ref,...)
5685   Image::Magick ref = NO_INIT
5686   ALIAS:
5687     getvirtualpixels = 1
5688     AcquireImagePixels = 2
5689     acquireimagepixels = 3
5690   CODE:
5691   {
5692     char
5693       *attribute;
5694
5695     const void
5696       *blob = NULL;
5697
5698     ExceptionInfo
5699       *exception;
5700
5701     Image
5702       *image;
5703
5704     RectangleInfo
5705       region;
5706
5707     ssize_t
5708       i;
5709
5710     struct PackageInfo
5711       *info;
5712
5713     SV
5714       *perl_exception,
5715       *reference;
5716
5717     PERL_UNUSED_VAR(ref);
5718     PERL_UNUSED_VAR(ix);
5719     exception=AcquireExceptionInfo();
5720     perl_exception=newSVpv("",0);
5721     if (sv_isobject(ST(0)) == 0)
5722       {
5723         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5724           PackageName);
5725         goto PerlException;
5726       }
5727     reference=SvRV(ST(0));
5728
5729     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5730     if (image == (Image *) NULL)
5731       {
5732         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5733           PackageName);
5734         goto PerlException;
5735       }
5736
5737     region.x=0;
5738     region.y=0;
5739     region.width=image->columns;
5740     region.height=1;
5741     if (items == 1)
5742       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5743     for (i=2; i < items; i+=2)
5744     {
5745       attribute=(char *) SvPV(ST(i-1),na);
5746       switch (*attribute)
5747       {
5748         case 'g':
5749         case 'G':
5750         {
5751           if (LocaleCompare(attribute,"geometry") == 0)
5752             {
5753               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5754               break;
5755             }
5756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5757             attribute);
5758           break;
5759         }
5760         case 'H':
5761         case 'h':
5762         {
5763           if (LocaleCompare(attribute,"height") == 0)
5764             {
5765               region.height=SvIV(ST(i));
5766               continue;
5767             }
5768           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5769             attribute);
5770           break;
5771         }
5772         case 'X':
5773         case 'x':
5774         {
5775           if (LocaleCompare(attribute,"x") == 0)
5776             {
5777               region.x=SvIV(ST(i));
5778               continue;
5779             }
5780           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5781             attribute);
5782           break;
5783         }
5784         case 'Y':
5785         case 'y':
5786         {
5787           if (LocaleCompare(attribute,"y") == 0)
5788             {
5789               region.y=SvIV(ST(i));
5790               continue;
5791             }
5792           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5793             attribute);
5794           break;
5795         }
5796         case 'W':
5797         case 'w':
5798         {
5799           if (LocaleCompare(attribute,"width") == 0)
5800             {
5801               region.width=SvIV(ST(i));
5802               continue;
5803             }
5804           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5805             attribute);
5806           break;
5807         }
5808       }
5809     }
5810     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5811       region.height,exception);
5812     if (blob != (void *) NULL)
5813       goto PerlEnd;
5814
5815   PerlException:
5816     InheritPerlException(exception,perl_exception);
5817     exception=DestroyExceptionInfo(exception);
5818     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5819
5820   PerlEnd:
5821     RETVAL = (void *) blob;
5822   }
5823   OUTPUT:
5824     RETVAL
5825 \f
5826 #
5827 ###############################################################################
5828 #                                                                             #
5829 #                                                                             #
5830 #                                                                             #
5831 #   G e t A u t h e n t i c I n d e x Q u e u e                               #
5832 #                                                                             #
5833 #                                                                             #
5834 #                                                                             #
5835 ###############################################################################
5836 #
5837 #
5838 void *
5839 GetAuthenticIndexQueue(ref,...)
5840   Image::Magick ref = NO_INIT
5841   ALIAS:
5842     getauthenticindexqueue = 1
5843     GetIndexes = 2
5844     getindexes = 3
5845   CODE:
5846   {
5847     ExceptionInfo
5848       *exception;
5849
5850     Image
5851       *image;
5852
5853     struct PackageInfo
5854       *info;
5855
5856     SV
5857       *perl_exception,
5858       *reference;
5859
5860     void
5861       *blob = NULL;
5862
5863     PERL_UNUSED_VAR(ref);
5864     PERL_UNUSED_VAR(ix);
5865     exception=AcquireExceptionInfo();
5866     perl_exception=newSVpv("",0);
5867     if (sv_isobject(ST(0)) == 0)
5868       {
5869         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5870           PackageName);
5871         goto PerlException;
5872       }
5873     reference=SvRV(ST(0));
5874
5875     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5876     if (image == (Image *) NULL)
5877       {
5878         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5879           PackageName);
5880         goto PerlException;
5881       }
5882
5883     blob=(void *) GetAuthenticIndexQueue(image);
5884     if (blob != (void *) NULL)
5885       goto PerlEnd;
5886
5887   PerlException:
5888     InheritPerlException(exception,perl_exception);
5889     exception=DestroyExceptionInfo(exception);
5890     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5891
5892   PerlEnd:
5893     RETVAL = blob;
5894   }
5895   OUTPUT:
5896     RETVAL
5897 \f
5898 #
5899 ###############################################################################
5900 #                                                                             #
5901 #                                                                             #
5902 #                                                                             #
5903 #   G e t V i r t u a l I n d e x Q u e u e                                   #
5904 #                                                                             #
5905 #                                                                             #
5906 #                                                                             #
5907 ###############################################################################
5908 #
5909 #
5910 void *
5911 GetVirtualIndexQueue(ref,...)
5912   Image::Magick ref = NO_INIT
5913   ALIAS:
5914     getvirtualindexqueue = 1
5915   CODE:
5916   {
5917     ExceptionInfo
5918       *exception;
5919
5920     Image
5921       *image;
5922
5923     struct PackageInfo
5924       *info;
5925
5926     SV
5927       *perl_exception,
5928       *reference;
5929
5930     void
5931       *blob = NULL;
5932
5933     PERL_UNUSED_VAR(ref);
5934     PERL_UNUSED_VAR(ix);
5935     exception=AcquireExceptionInfo();
5936     perl_exception=newSVpv("",0);
5937     if (sv_isobject(ST(0)) == 0)
5938       {
5939         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5940           PackageName);
5941         goto PerlException;
5942       }
5943     reference=SvRV(ST(0));
5944
5945     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5946     if (image == (Image *) NULL)
5947       {
5948         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5949           PackageName);
5950         goto PerlException;
5951       }
5952
5953     blob=(void *) GetVirtualIndexQueue(image);
5954     if (blob != (void *) NULL)
5955       goto PerlEnd;
5956
5957   PerlException:
5958     InheritPerlException(exception,perl_exception);
5959     exception=DestroyExceptionInfo(exception);
5960     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5961
5962   PerlEnd:
5963     RETVAL = blob;
5964   }
5965   OUTPUT:
5966     RETVAL
5967 \f
5968 #
5969 ###############################################################################
5970 #                                                                             #
5971 #                                                                             #
5972 #                                                                             #
5973 #   H i s t o g r a m                                                         #
5974 #                                                                             #
5975 #                                                                             #
5976 #                                                                             #
5977 ###############################################################################
5978 #
5979 #
5980 void
5981 Histogram(ref,...)
5982   Image::Magick ref=NO_INIT
5983   ALIAS:
5984     HistogramImage = 1
5985     histogram      = 2
5986     histogramimage = 3
5987   PPCODE:
5988   {
5989     AV
5990       *av;
5991
5992     char
5993       message[MaxTextExtent];
5994
5995     ColorPacket
5996       *histogram;
5997
5998     ExceptionInfo
5999       *exception;
6000
6001     Image
6002       *image;
6003
6004     register ssize_t
6005       i;
6006
6007     ssize_t
6008       count;
6009
6010     struct PackageInfo
6011       *info;
6012
6013     SV
6014       *perl_exception,
6015       *reference;
6016
6017     size_t
6018       number_colors;
6019
6020     PERL_UNUSED_VAR(ref);
6021     PERL_UNUSED_VAR(ix);
6022     exception=AcquireExceptionInfo();
6023     perl_exception=newSVpv("",0);
6024     av=NULL;
6025     if (sv_isobject(ST(0)) == 0)
6026       {
6027         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6028           PackageName);
6029         goto PerlException;
6030       }
6031     reference=SvRV(ST(0));
6032     av=newAV();
6033     SvREFCNT_dec(av);
6034     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6035     if (image == (Image *) NULL)
6036       {
6037         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6038           PackageName);
6039         goto PerlException;
6040       }
6041     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6042     count=0;
6043     for ( ; image; image=image->next)
6044     {
6045       histogram=GetImageHistogram(image,&number_colors,&image->exception);
6046       if (histogram == (ColorPacket *) NULL)
6047         continue;
6048       count+=(ssize_t) number_colors;
6049       EXTEND(sp,6*count);
6050       for (i=0; i < (ssize_t) number_colors; i++)
6051       {
6052         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6053           histogram[i].pixel.red);
6054         PUSHs(sv_2mortal(newSVpv(message,0)));
6055         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6056           histogram[i].pixel.green);
6057         PUSHs(sv_2mortal(newSVpv(message,0)));
6058         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6059           histogram[i].pixel.blue);
6060         PUSHs(sv_2mortal(newSVpv(message,0)));
6061         if (image->colorspace == CMYKColorspace)
6062           {
6063             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6064               histogram[i].index);
6065             PUSHs(sv_2mortal(newSVpv(message,0)));
6066           }
6067         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6068           histogram[i].pixel.opacity);
6069         PUSHs(sv_2mortal(newSVpv(message,0)));
6070         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6071           histogram[i].count);
6072         PUSHs(sv_2mortal(newSVpv(message,0)));
6073       }
6074       histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
6075     }
6076
6077   PerlException:
6078     InheritPerlException(exception,perl_exception);
6079     exception=DestroyExceptionInfo(exception);
6080     SvREFCNT_dec(perl_exception);
6081   }
6082 \f
6083 #
6084 ###############################################################################
6085 #                                                                             #
6086 #                                                                             #
6087 #                                                                             #
6088 #   G e t P i x e l                                                           #
6089 #                                                                             #
6090 #                                                                             #
6091 #                                                                             #
6092 ###############################################################################
6093 #
6094 #
6095 void
6096 GetPixel(ref,...)
6097   Image::Magick ref=NO_INIT
6098   ALIAS:
6099     getpixel = 1
6100     getPixel = 2
6101   PPCODE:
6102   {
6103     AV
6104       *av;
6105
6106     char
6107       *attribute;
6108
6109     ChannelType
6110       channel;
6111
6112     ExceptionInfo
6113       *exception;
6114
6115     Image
6116       *image;
6117
6118     MagickBooleanType
6119       normalize;
6120
6121     RectangleInfo
6122       region;
6123
6124     register const IndexPacket
6125       *indexes;
6126
6127     register const PixelPacket
6128       *p;
6129
6130     register ssize_t
6131       i;
6132
6133     ssize_t
6134       option;
6135
6136     struct PackageInfo
6137       *info;
6138
6139     SV
6140       *perl_exception,
6141       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6142
6143     PERL_UNUSED_VAR(ref);
6144     PERL_UNUSED_VAR(ix);
6145     exception=AcquireExceptionInfo();
6146     perl_exception=newSVpv("",0);
6147     reference=SvRV(ST(0));
6148     av=(AV *) reference;
6149     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6150       exception);
6151     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6152     if (image == (Image *) NULL)
6153       {
6154         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6155           PackageName);
6156         goto PerlException;
6157       }
6158     channel=DefaultChannels;
6159     normalize=MagickTrue;
6160     region.x=0;
6161     region.y=0;
6162     region.width=image->columns;
6163     region.height=1;
6164     if (items == 1)
6165       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6166     for (i=2; i < items; i+=2)
6167     {
6168       attribute=(char *) SvPV(ST(i-1),na);
6169       switch (*attribute)
6170       {
6171         case 'C':
6172         case 'c':
6173         {
6174           if (LocaleCompare(attribute,"channel") == 0)
6175             {
6176               ssize_t
6177                 option;
6178
6179               option=ParseChannelOption(SvPV(ST(i),na));
6180               if (option < 0)
6181                 {
6182                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6183                     SvPV(ST(i),na));
6184                   return;
6185                 }
6186                channel=(ChannelType) option;
6187               break;
6188             }
6189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6190             attribute);
6191           break;
6192         }
6193         case 'g':
6194         case 'G':
6195         {
6196           if (LocaleCompare(attribute,"geometry") == 0)
6197             {
6198               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6199               break;
6200             }
6201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6202             attribute);
6203           break;
6204         }
6205         case 'N':
6206         case 'n':
6207         {
6208           if (LocaleCompare(attribute,"normalize") == 0)
6209             {
6210               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6211                 SvPV(ST(i),na));
6212               if (option < 0)
6213                 {
6214                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6215                     SvPV(ST(i),na));
6216                   break;
6217                 }
6218              normalize=option != 0 ? MagickTrue : MagickFalse;
6219              break;
6220             }
6221           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6222             attribute);
6223           break;
6224         }
6225         case 'x':
6226         case 'X':
6227         {
6228           if (LocaleCompare(attribute,"x") == 0)
6229             {
6230               region.x=SvIV(ST(i));
6231               break;
6232             }
6233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6234             attribute);
6235           break;
6236         }
6237         case 'y':
6238         case 'Y':
6239         {
6240           if (LocaleCompare(attribute,"y") == 0)
6241             {
6242               region.y=SvIV(ST(i));
6243               break;
6244             }
6245           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6246             attribute);
6247           break;
6248         }
6249         default:
6250         {
6251           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6252             attribute);
6253           break;
6254         }
6255       }
6256     }
6257     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6258     if (p == (const PixelPacket *) NULL)
6259       PUSHs(&sv_undef);
6260     else
6261       {
6262         double
6263           scale;
6264
6265         indexes=GetVirtualIndexQueue(image);
6266         scale=1.0;
6267         if (normalize != MagickFalse)
6268           scale=1.0/QuantumRange;
6269         if ((channel & RedChannel) != 0)
6270           PUSHs(sv_2mortal(newSVnv(scale*GetRedPixelComponent(p))));
6271         if ((channel & GreenChannel) != 0)
6272           PUSHs(sv_2mortal(newSVnv(scale*GetGreenPixelComponent(p))));
6273         if ((channel & BlueChannel) != 0)
6274           PUSHs(sv_2mortal(newSVnv(scale*GetBluePixelComponent(p))));
6275         if (((channel & IndexChannel) != 0) &&
6276             (image->colorspace == CMYKColorspace))
6277           PUSHs(sv_2mortal(newSVnv(scale*GetIndexPixelComponent(indexes))));
6278         if ((channel & OpacityChannel) != 0)
6279           PUSHs(sv_2mortal(newSVnv(scale*GetOpacityPixelComponent(p))));
6280       }
6281
6282   PerlException:
6283     InheritPerlException(exception,perl_exception);
6284     exception=DestroyExceptionInfo(exception);
6285     SvREFCNT_dec(perl_exception);
6286   }
6287 \f
6288 #
6289 ###############################################################################
6290 #                                                                             #
6291 #                                                                             #
6292 #                                                                             #
6293 #   G e t P i x e l s                                                         #
6294 #                                                                             #
6295 #                                                                             #
6296 #                                                                             #
6297 ###############################################################################
6298 #
6299 #
6300 void
6301 GetPixels(ref,...)
6302   Image::Magick ref=NO_INIT
6303   ALIAS:
6304     getpixels = 1
6305     getPixels = 2
6306   PPCODE:
6307   {
6308     AV
6309       *av;
6310
6311     char
6312       *attribute;
6313
6314     const char
6315       *map;
6316
6317     ExceptionInfo
6318       *exception;
6319
6320     Image
6321       *image;
6322
6323     MagickBooleanType
6324       normalize,
6325       status;
6326
6327     RectangleInfo
6328       region;
6329
6330     register ssize_t
6331       i;
6332
6333     ssize_t
6334       option;
6335
6336     struct PackageInfo
6337       *info;
6338
6339     SV
6340       *perl_exception,
6341       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6342
6343     PERL_UNUSED_VAR(ref);
6344     PERL_UNUSED_VAR(ix);
6345     exception=AcquireExceptionInfo();
6346     perl_exception=newSVpv("",0);
6347     reference=SvRV(ST(0));
6348     av=(AV *) reference;
6349     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6350       exception);
6351     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6352     if (image == (Image *) NULL)
6353       {
6354         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6355           PackageName);
6356         goto PerlException;
6357       }
6358     map="RGB";
6359     if (image->matte != MagickFalse)
6360       map="RGBA";
6361     if (image->colorspace == CMYKColorspace)
6362       {
6363         map="CMYK";
6364         if (image->matte != MagickFalse)
6365           map="CMYKA";
6366       }
6367     normalize=MagickFalse;
6368     region.x=0;
6369     region.y=0;
6370     region.width=image->columns;
6371     region.height=1;
6372     if (items == 1)
6373       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6374     for (i=2; i < items; i+=2)
6375     {
6376       attribute=(char *) SvPV(ST(i-1),na);
6377       switch (*attribute)
6378       {
6379         case 'g':
6380         case 'G':
6381         {
6382           if (LocaleCompare(attribute,"geometry") == 0)
6383             {
6384               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6385               break;
6386             }
6387           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6388             attribute);
6389           break;
6390         }
6391         case 'H':
6392         case 'h':
6393         {
6394           if (LocaleCompare(attribute,"height") == 0)
6395             {
6396               region.height=SvIV(ST(i));
6397               break;
6398             }
6399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6400             attribute);
6401           break;
6402         }
6403         case 'M':
6404         case 'm':
6405         {
6406           if (LocaleCompare(attribute,"map") == 0)
6407             {
6408               map=SvPV(ST(i),na);
6409               break;
6410             }
6411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6412             attribute);
6413           break;
6414         }
6415         case 'N':
6416         case 'n':
6417         {
6418           if (LocaleCompare(attribute,"normalize") == 0)
6419             {
6420               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6421                 SvPV(ST(i),na));
6422               if (option < 0)
6423                 {
6424                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6425                     SvPV(ST(i),na));
6426                   break;
6427                 }
6428              normalize=option != 0 ? MagickTrue : MagickFalse;
6429              break;
6430             }
6431           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6432             attribute);
6433           break;
6434         }
6435         case 'W':
6436         case 'w':
6437         {
6438           if (LocaleCompare(attribute,"width") == 0)
6439             {
6440               region.width=SvIV(ST(i));
6441               break;
6442             }
6443           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6444             attribute);
6445           break;
6446         }
6447         case 'x':
6448         case 'X':
6449         {
6450           if (LocaleCompare(attribute,"x") == 0)
6451             {
6452               region.x=SvIV(ST(i));
6453               break;
6454             }
6455           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6456             attribute);
6457           break;
6458         }
6459         case 'y':
6460         case 'Y':
6461         {
6462           if (LocaleCompare(attribute,"y") == 0)
6463             {
6464               region.y=SvIV(ST(i));
6465               break;
6466             }
6467           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6468             attribute);
6469           break;
6470         }
6471         default:
6472         {
6473           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6474             attribute);
6475           break;
6476         }
6477       }
6478     }
6479     if (normalize != MagickFalse)
6480       {
6481         float
6482           *pixels;
6483
6484         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6485           region.height*sizeof(*pixels));
6486         if (pixels == (float *) NULL)
6487           {
6488             ThrowPerlException(exception,ResourceLimitError,
6489               "MemoryAllocationFailed",PackageName);
6490             goto PerlException;
6491           }
6492         status=ExportImagePixels(image,region.x,region.y,region.width,
6493           region.height,map,FloatPixel,pixels,exception);
6494         if (status == MagickFalse)
6495           PUSHs(&sv_undef);
6496         else
6497           {
6498             EXTEND(sp,strlen(map)*region.width*region.height);
6499             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6500               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6501           }
6502         pixels=(float *) RelinquishMagickMemory(pixels);
6503       }
6504     else
6505       {
6506         Quantum
6507           *pixels;
6508
6509         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6510           region.height*sizeof(*pixels));
6511         if (pixels == (Quantum *) NULL)
6512           {
6513             ThrowPerlException(exception,ResourceLimitError,
6514               "MemoryAllocationFailed",PackageName);
6515             goto PerlException;
6516           }
6517         status=ExportImagePixels(image,region.x,region.y,region.width,
6518           region.height,map,QuantumPixel,pixels,exception);
6519         if (status == MagickFalse)
6520           PUSHs(&sv_undef);
6521         else
6522           {
6523             EXTEND(sp,strlen(map)*region.width*region.height);
6524             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6525               PUSHs(sv_2mortal(newSViv(pixels[i])));
6526           }
6527         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6528       }
6529
6530   PerlException:
6531     InheritPerlException(exception,perl_exception);
6532     exception=DestroyExceptionInfo(exception);
6533     SvREFCNT_dec(perl_exception);
6534   }
6535 \f
6536 #
6537 ###############################################################################
6538 #                                                                             #
6539 #                                                                             #
6540 #                                                                             #
6541 #   I m a g e T o B l o b                                                     #
6542 #                                                                             #
6543 #                                                                             #
6544 #                                                                             #
6545 ###############################################################################
6546 #
6547 #
6548 void
6549 ImageToBlob(ref,...)
6550   Image::Magick ref=NO_INIT
6551   ALIAS:
6552     ImageToBlob  = 1
6553     imagetoblob  = 2
6554     toblob       = 3
6555     blob         = 4
6556   PPCODE:
6557   {
6558     char
6559       filename[MaxTextExtent];
6560
6561     ExceptionInfo
6562       *exception;
6563
6564     Image
6565       *image,
6566       *next;
6567
6568     register ssize_t
6569       i;
6570
6571     struct PackageInfo
6572       *info,
6573       *package_info;
6574
6575     size_t
6576       length;
6577
6578     ssize_t
6579       scene;
6580
6581     SV
6582       *perl_exception,
6583       *reference;
6584
6585     void
6586       *blob;
6587
6588     PERL_UNUSED_VAR(ref);
6589     PERL_UNUSED_VAR(ix);
6590     exception=AcquireExceptionInfo();
6591     perl_exception=newSVpv("",0);
6592     package_info=(struct PackageInfo *) NULL;
6593     if (sv_isobject(ST(0)) == 0)
6594       {
6595         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6596           PackageName);
6597         goto PerlException;
6598       }
6599     reference=SvRV(ST(0));
6600     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6601     if (image == (Image *) NULL)
6602       {
6603         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6604           PackageName);
6605         goto PerlException;
6606       }
6607     package_info=ClonePackageInfo(info,exception);
6608     for (i=2; i < items; i+=2)
6609       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6610     (void) CopyMagickString(filename,package_info->image_info->filename,
6611       MaxTextExtent);
6612     scene=0;
6613     for (next=image; next; next=next->next)
6614     {
6615       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6616       next->scene=scene++;
6617     }
6618     SetImageInfo(package_info->image_info,(unsigned int)
6619       GetImageListLength(image),&image->exception);
6620     EXTEND(sp,(ssize_t) GetImageListLength(image));
6621     for ( ; image; image=image->next)
6622     {
6623       length=0;
6624       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6625       if (blob != (char *) NULL)
6626         {
6627           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6628           blob=(unsigned char *) RelinquishMagickMemory(blob);
6629         }
6630       if (package_info->image_info->adjoin)
6631         break;
6632     }
6633
6634   PerlException:
6635     if (package_info != (struct PackageInfo *) NULL)
6636       DestroyPackageInfo(package_info);
6637     InheritPerlException(exception,perl_exception);
6638     exception=DestroyExceptionInfo(exception);
6639     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6640   }
6641 \f
6642 #
6643 ###############################################################################
6644 #                                                                             #
6645 #                                                                             #
6646 #                                                                             #
6647 #   L a y e r s                                                               #
6648 #                                                                             #
6649 #                                                                             #
6650 #                                                                             #
6651 ###############################################################################
6652 #
6653 #
6654 void
6655 Layers(ref,...)
6656   Image::Magick ref=NO_INIT
6657   ALIAS:
6658     Layers                = 1
6659     layers           = 2
6660     OptimizeImageLayers   = 3
6661     optimizelayers        = 4
6662     optimizeimagelayers   = 5
6663   PPCODE:
6664   {
6665     AV
6666       *av;
6667
6668     char
6669       *attribute;
6670
6671     CompositeOperator
6672       compose;
6673
6674     ExceptionInfo
6675       *exception;
6676
6677     HV
6678       *hv;
6679
6680     Image
6681       *image,
6682       *layers;
6683
6684     ImageLayerMethod
6685       method;
6686
6687     register ssize_t
6688       i;
6689
6690     ssize_t
6691       option,
6692       sp;
6693
6694     struct PackageInfo
6695       *info;
6696
6697     SV
6698       *av_reference,
6699       *perl_exception,
6700       *reference,
6701       *rv,
6702       *sv;
6703
6704     PERL_UNUSED_VAR(ref);
6705     PERL_UNUSED_VAR(ix);
6706     exception=AcquireExceptionInfo();
6707     perl_exception=newSVpv("",0);
6708     sv=NULL;
6709     if (sv_isobject(ST(0)) == 0)
6710       {
6711         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6712           PackageName);
6713         goto PerlException;
6714       }
6715     reference=SvRV(ST(0));
6716     hv=SvSTASH(reference);
6717     av=newAV();
6718     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6719     SvREFCNT_dec(av);
6720     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6721     if (image == (Image *) NULL)
6722       {
6723         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6724           PackageName);
6725         goto PerlException;
6726       }
6727     compose=image->compose;
6728     method=OptimizeLayer;
6729     for (i=2; i < items; i+=2)
6730     {
6731       attribute=(char *) SvPV(ST(i-1),na);
6732       switch (*attribute)
6733       {
6734         case 'C':
6735         case 'c':
6736         {
6737           if (LocaleCompare(attribute,"compose") == 0)
6738             {
6739               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6740                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6741               if (sp < 0)
6742                 {
6743                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6744                     SvPV(ST(i),na));
6745                   break;
6746                 }
6747               compose=(CompositeOperator) sp;
6748               break;
6749             }
6750           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6751             attribute);
6752           break;
6753         }
6754         case 'M':
6755         case 'm':
6756         {
6757           if (LocaleCompare(attribute,"method") == 0)
6758             {
6759               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6760                 SvPV(ST(i),na));
6761               if (option < 0)
6762                 {
6763                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6764                     SvPV(ST(i),na));
6765                   break;
6766                 }
6767               method=(ImageLayerMethod) option;
6768               break;
6769             }
6770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6771             attribute);
6772           break;
6773         }
6774         default:
6775         {
6776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6777             attribute);
6778           break;
6779         }
6780       }
6781     }
6782     layers=(Image *) NULL;
6783     switch (method)
6784     {
6785       case CompareAnyLayer:
6786       case CompareClearLayer:
6787       case CompareOverlayLayer:
6788       default:
6789       {
6790         layers=CompareImageLayers(image,method,exception);
6791         break;
6792       }
6793       case MergeLayer:
6794       case FlattenLayer:
6795       case MosaicLayer:
6796       {
6797         layers=MergeImageLayers(image,method,exception);
6798         break;
6799       }
6800       case DisposeLayer:
6801       {
6802         layers=DisposeImages(image,exception);
6803         break;
6804       }
6805       case OptimizeImageLayer:
6806       {
6807         layers=OptimizeImageLayers(image,exception);
6808         break;
6809       }
6810       case OptimizePlusLayer:
6811       {
6812         layers=OptimizePlusImageLayers(image,exception);
6813         break;
6814       }
6815       case OptimizeTransLayer:
6816       {
6817         OptimizeImageTransparency(image,exception);
6818         InheritException(&(image->exception),exception);
6819         break;
6820       }
6821       case RemoveDupsLayer:
6822       {
6823         RemoveDuplicateLayers(&image,exception);
6824         InheritException(&(image->exception),exception);
6825         break;
6826       }
6827       case RemoveZeroLayer:
6828       {
6829         RemoveZeroDelayLayers(&image,exception);
6830         InheritException(&(image->exception),exception);
6831         break;
6832       }
6833       case OptimizeLayer:
6834       {
6835         QuantizeInfo
6836           *quantize_info;
6837
6838         /*
6839           General Purpose, GIF Animation Optimizer.
6840         */
6841         layers=CoalesceImages(image,exception);
6842         if (layers == (Image *) NULL)
6843           break;
6844         InheritException(&(layers->exception),exception);
6845         image=layers;
6846         layers=OptimizeImageLayers(image,exception);
6847         if (layers == (Image *) NULL)
6848           break;
6849         InheritException(&(layers->exception),exception);
6850         image=DestroyImageList(image);
6851         image=layers;
6852         layers=(Image *) NULL;
6853         OptimizeImageTransparency(image,exception);
6854         InheritException(&(image->exception),exception);
6855         quantize_info=AcquireQuantizeInfo(info->image_info);
6856         (void) RemapImages(quantize_info,image,(Image *) NULL);
6857         quantize_info=DestroyQuantizeInfo(quantize_info);
6858         break;
6859       }
6860       case CompositeLayer:
6861       {
6862         Image
6863           *source;
6864
6865         RectangleInfo
6866           geometry;
6867
6868         /*
6869           Split image sequence at the first 'NULL:' image.
6870         */
6871         source=image;
6872         while (source != (Image *) NULL)
6873         {
6874           source=GetNextImageInList(source);
6875           if ((source != (Image *) NULL) &&
6876               (LocaleCompare(source->magick,"NULL") == 0))
6877             break;
6878         }
6879         if (source != (Image *) NULL)
6880           {
6881             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6882                 (GetNextImageInList(source) == (Image *) NULL))
6883               source=(Image *) NULL;
6884             else
6885               {
6886                 /*
6887                   Separate the two lists, junk the null: image.
6888                 */
6889                 source=SplitImageList(source->previous);
6890                 DeleteImageFromList(&source);
6891               }
6892           }
6893         if (source == (Image *) NULL)
6894           {
6895             (void) ThrowMagickException(exception,GetMagickModule(),
6896               OptionError,"MissingNullSeparator","layers Composite");
6897             break;
6898           }
6899         /*
6900           Adjust offset with gravity and virtual canvas.
6901         */
6902         SetGeometry(image,&geometry);
6903         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6904         geometry.width=source->page.width != 0 ? source->page.width :
6905           source->columns;
6906         geometry.height=source->page.height != 0 ? source->page.height :
6907           source->rows;
6908         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6909           image->columns,image->page.height != 0 ? image->page.height :
6910           image->rows,image->gravity,&geometry);
6911         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6912         source=DestroyImageList(source);
6913         InheritException(&(image->exception),exception);
6914         break;
6915       }
6916     }
6917     if (layers != (Image *) NULL)
6918       {
6919         InheritException(&(layers->exception),exception);
6920         image=layers;
6921       }
6922     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6923       goto PerlException;
6924     for ( ; image; image=image->next)
6925     {
6926       AddImageToRegistry(sv,image);
6927       rv=newRV(sv);
6928       av_push(av,sv_bless(rv,hv));
6929       SvREFCNT_dec(sv);
6930     }
6931     exception=DestroyExceptionInfo(exception);
6932     ST(0)=av_reference;
6933     SvREFCNT_dec(perl_exception);
6934     XSRETURN(1);
6935
6936   PerlException:
6937     InheritPerlException(exception,perl_exception);
6938     exception=DestroyExceptionInfo(exception);
6939     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6940     SvPOK_on(perl_exception);
6941     ST(0)=sv_2mortal(perl_exception);
6942     XSRETURN(1);
6943   }
6944 \f
6945 #
6946 ###############################################################################
6947 #                                                                             #
6948 #                                                                             #
6949 #                                                                             #
6950 #   M a g i c k T o M i m e                                                   #
6951 #                                                                             #
6952 #                                                                             #
6953 #                                                                             #
6954 ###############################################################################
6955 #
6956 #
6957 SV *
6958 MagickToMime(ref,name)
6959   Image::Magick ref=NO_INIT
6960   char *name
6961   ALIAS:
6962     magicktomime = 1
6963   CODE:
6964   {
6965     char
6966       *mime;
6967
6968     PERL_UNUSED_VAR(ref);
6969     PERL_UNUSED_VAR(ix);
6970     mime=MagickToMime(name);
6971     RETVAL=newSVpv(mime,0);
6972     mime=(char *) RelinquishMagickMemory(mime);
6973   }
6974   OUTPUT:
6975     RETVAL
6976 \f
6977 #
6978 ###############################################################################
6979 #                                                                             #
6980 #                                                                             #
6981 #                                                                             #
6982 #   M o g r i f y                                                             #
6983 #                                                                             #
6984 #                                                                             #
6985 #                                                                             #
6986 ###############################################################################
6987 #
6988 #
6989 void
6990 Mogrify(ref,...)
6991   Image::Magick ref=NO_INIT
6992   ALIAS:
6993     Comment            =   1
6994     CommentImage       =   2
6995     Label              =   3
6996     LabelImage         =   4
6997     AddNoise           =   5
6998     AddNoiseImage      =   6
6999     Colorize           =   7
7000     ColorizeImage      =   8
7001     Border             =   9
7002     BorderImage        =  10
7003     Blur               =  11
7004     BlurImage          =  12
7005     Chop               =  13
7006     ChopImage          =  14
7007     Crop               =  15
7008     CropImage          =  16
7009     Despeckle          =  17
7010     DespeckleImage     =  18
7011     Edge               =  19
7012     EdgeImage          =  20
7013     Emboss             =  21
7014     EmbossImage        =  22
7015     Enhance            =  23
7016     EnhanceImage       =  24
7017     Flip               =  25
7018     FlipImage          =  26
7019     Flop               =  27
7020     FlopImage          =  28
7021     Frame              =  29
7022     FrameImage         =  30
7023     Implode            =  31
7024     ImplodeImage       =  32
7025     Magnify            =  33
7026     MagnifyImage       =  34
7027     MedianFilter       =  35
7028     MedianFilterImage  =  36
7029     Minify             =  37
7030     MinifyImage        =  38
7031     OilPaint           =  39
7032     OilPaintImage      =  40
7033     ReduceNoise        =  41
7034     ReduceNoiseImage   =  42
7035     Roll               =  43
7036     RollImage          =  44
7037     Rotate             =  45
7038     RotateImage        =  46
7039     Sample             =  47
7040     SampleImage        =  48
7041     Scale              =  49
7042     ScaleImage         =  50
7043     Shade              =  51
7044     ShadeImage         =  52
7045     Sharpen            =  53
7046     SharpenImage       =  54
7047     Shear              =  55
7048     ShearImage         =  56
7049     Spread             =  57
7050     SpreadImage        =  58
7051     Swirl              =  59
7052     SwirlImage         =  60
7053     Resize             =  61
7054     ResizeImage        =  62
7055     Zoom               =  63
7056     ZoomImage          =  64
7057     Annotate           =  65
7058     AnnotateImage      =  66
7059     ColorFloodfill     =  67
7060     ColorFloodfillImage=  68
7061     Composite          =  69
7062     CompositeImage     =  70
7063     Contrast           =  71
7064     ContrastImage      =  72
7065     CycleColormap      =  73
7066     CycleColormapImage =  74
7067     Draw               =  75
7068     DrawImage          =  76
7069     Equalize           =  77
7070     EqualizeImage      =  78
7071     Gamma              =  79
7072     GammaImage         =  80
7073     Map                =  81
7074     MapImage           =  82
7075     MatteFloodfill     =  83
7076     MatteFloodfillImage=  84
7077     Modulate           =  85
7078     ModulateImage      =  86
7079     Negate             =  87
7080     NegateImage        =  88
7081     Normalize          =  89
7082     NormalizeImage     =  90
7083     NumberColors       =  91
7084     NumberColorsImage  =  92
7085     Opaque             =  93
7086     OpaqueImage        =  94
7087     Quantize           =  95
7088     QuantizeImage      =  96
7089     Raise              =  97
7090     RaiseImage         =  98
7091     Segment            =  99
7092     SegmentImage       = 100
7093     Signature          = 101
7094     SignatureImage     = 102
7095     Solarize           = 103
7096     SolarizeImage      = 104
7097     Sync               = 105
7098     SyncImage          = 106
7099     Texture            = 107
7100     TextureImage       = 108
7101     Evaluate           = 109
7102     EvaluateImage      = 110
7103     Transparent        = 111
7104     TransparentImage   = 112
7105     Threshold          = 113
7106     ThresholdImage     = 114
7107     Charcoal           = 115
7108     CharcoalImage      = 116
7109     Trim               = 117
7110     TrimImage          = 118
7111     Wave               = 119
7112     WaveImage          = 120
7113     Separate           = 121
7114     SeparateImage      = 122
7115     Stereo             = 125
7116     StereoImage        = 126
7117     Stegano            = 127
7118     SteganoImage       = 128
7119     Deconstruct        = 129
7120     DeconstructImage   = 130
7121     GaussianBlur       = 131
7122     GaussianBlurImage  = 132
7123     Convolve           = 133
7124     ConvolveImage      = 134
7125     Profile            = 135
7126     ProfileImage       = 136
7127     UnsharpMask        = 137
7128     UnsharpMaskImage   = 138
7129     MotionBlur         = 139
7130     MotionBlurImage    = 140
7131     OrderedDither      = 141
7132     OrderedDitherImage = 142
7133     Shave              = 143
7134     ShaveImage         = 144
7135     Level              = 145
7136     LevelImage         = 146
7137     Clip               = 147
7138     ClipImage          = 148
7139     AffineTransform    = 149
7140     AffineTransformImage = 150
7141     Difference         = 151
7142     DifferenceImage    = 152
7143     AdaptiveThreshold  = 153
7144     AdaptiveThresholdImage = 154
7145     Resample           = 155
7146     ResampleImage      = 156
7147     Describe           = 157
7148     DescribeImage      = 158
7149     BlackThreshold     = 159
7150     BlackThresholdImage= 160
7151     WhiteThreshold     = 161
7152     WhiteThresholdImage= 162
7153     RadialBlur         = 163
7154     RadialBlurImage    = 164
7155     Thumbnail          = 165
7156     ThumbnailImage     = 166
7157     Strip              = 167
7158     StripImage         = 168
7159     Tint               = 169
7160     TintImage          = 170
7161     Channel            = 171
7162     ChannelImage       = 172
7163     Splice             = 173
7164     SpliceImage        = 174
7165     Posterize          = 175
7166     PosterizeImage     = 176
7167     Shadow             = 177
7168     ShadowImage        = 178
7169     Identify           = 179
7170     IdentifyImage      = 180
7171     SepiaTone          = 181
7172     SepiaToneImage     = 182
7173     SigmoidalContrast  = 183
7174     SigmoidalContrastImage = 184
7175     Extent             = 185
7176     ExtentImage        = 186
7177     Vignette           = 187
7178     VignetteImage      = 188
7179     ContrastStretch    = 189
7180     ContrastStretchImage = 190
7181     Sans0              = 191
7182     Sans0Image         = 192
7183     Sans1              = 193
7184     Sans1Image         = 194
7185     AdaptiveSharpen    = 195
7186     AdaptiveSharpenImage = 196
7187     Transpose          = 197
7188     TransposeImage     = 198
7189     Transverse         = 199
7190     TransverseImage    = 200
7191     AutoOrient         = 201
7192     AutoOrientImage    = 202
7193     AdaptiveBlur       = 203
7194     AdaptiveBlurImage  = 204
7195     Sketch             = 205
7196     SketchImage        = 206
7197     UniqueColors       = 207
7198     UniqueColorsImage  = 208
7199     AdaptiveResize     = 209
7200     AdaptiveResizeImage= 210
7201     ClipMask           = 211
7202     ClipMaskImage      = 212
7203     LinearStretch      = 213
7204     LinearStretchImage = 214
7205     RecolorImage       = 215
7206     Recolor            = 216
7207     Mask               = 217
7208     MaskImage          = 218
7209     Polaroid           = 219
7210     PolaroidImage      = 220
7211     FloodfillPaint     = 221
7212     FloodfillPaintImage= 222
7213     Distort            = 223
7214     DistortImage       = 224
7215     Clut               = 225
7216     ClutImage          = 226
7217     LiquidRescale      = 227
7218     LiquidRescaleImage = 228
7219     Encipher           = 229
7220     EncipherImage      = 230
7221     Decipher           = 231
7222     DecipherImage      = 232
7223     Deskew             = 233
7224     DeskewImage        = 234
7225     Remap              = 235
7226     RemapImage         = 236
7227     SparseColor        = 237
7228     SparseColorImage   = 238
7229     Function           = 239
7230     FunctionImage      = 240
7231     SelectiveBlur      = 241
7232     SelectiveBlurImage = 242
7233     HaldClut           = 243
7234     HaldClutImage      = 244
7235     BlueShift          = 245
7236     BlueShiftImage     = 246
7237     ForwardFourierTransform  = 247
7238     ForwardFourierTransformImage = 248
7239     InverseFourierTransform = 249
7240     InverseFourierTransformImage = 250
7241     ColorDecisionList  = 251
7242     ColorDecisionListImage = 252
7243     AutoGamma          = 253
7244     AutoGammaImage     = 254
7245     AutoLevel          = 255
7246     AutoLevelImage     = 256
7247     LevelColors        = 257
7248     LevelColorsImage   = 258
7249     Clamp              = 259
7250     ClampImage         = 260
7251     Filter             = 261
7252     FilterImage        = 262
7253     BrightnessContrast = 263
7254     BrightnessContrastImage = 264
7255     Morphology         = 265
7256     MorphologyImage    = 266
7257     ColorMatrix        = 267
7258     ColorMatrixImage   = 268
7259     Color              = 269
7260     ColorImage         = 270
7261     Mode               = 271
7262     ModeImage          = 272
7263     Statistic          = 273
7264     StatisticImage     = 274
7265     MogrifyRegion      = 666
7266   PPCODE:
7267   {
7268     AffineMatrix
7269       affine,
7270       current;
7271
7272     char
7273       attribute_flag[MaxArguments],
7274       message[MaxTextExtent];
7275
7276     ChannelType
7277       channel;
7278
7279     CompositeOperator
7280       compose;
7281
7282     const char
7283       *attribute,
7284       *value;
7285
7286     double
7287       angle;
7288
7289     ExceptionInfo
7290       *exception;
7291
7292     GeometryInfo
7293       geometry_info;
7294
7295     Image
7296       *image,
7297       *next,
7298       *region_image;
7299
7300     MagickBooleanType
7301       status;
7302
7303     MagickStatusType
7304       flags;
7305
7306     PixelPacket
7307       fill_color;
7308
7309     RectangleInfo
7310       geometry,
7311       region_info;
7312
7313     register ssize_t
7314       i;
7315
7316     ssize_t
7317       base,
7318       j,
7319       number_images;
7320
7321     struct Methods
7322       *rp;
7323
7324     struct PackageInfo
7325       *info;
7326
7327     SV
7328       *perl_exception,
7329       **pv,
7330       *reference,
7331       **reference_vector;
7332
7333     struct ArgumentList
7334       argument_list[MaxArguments];
7335
7336     PERL_UNUSED_VAR(ref);
7337     PERL_UNUSED_VAR(ix);
7338     exception=AcquireExceptionInfo();
7339     perl_exception=newSVpv("",0);
7340     reference_vector=NULL;
7341     region_image=NULL;
7342     number_images=0;
7343     base=2;
7344     if (sv_isobject(ST(0)) == 0)
7345       {
7346         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7347           PackageName);
7348         goto PerlException;
7349       }
7350     reference=SvRV(ST(0));
7351     region_info.width=0;
7352     region_info.height=0;
7353     region_info.x=0;
7354     region_info.y=0;
7355     region_image=(Image *) NULL;
7356     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7357     if (ix && (ix != 666))
7358       {
7359         /*
7360           Called as Method(...)
7361         */
7362         ix=(ix+1)/2;
7363         rp=(&Methods[ix-1]);
7364         attribute=rp->name;
7365       }
7366     else
7367       {
7368         /*
7369           Called as Mogrify("Method",...)
7370         */
7371         attribute=(char *) SvPV(ST(1),na);
7372         if (ix)
7373           {
7374             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7375             attribute=(char *) SvPV(ST(2),na);
7376             base++;
7377           }
7378         for (rp=Methods; ; rp++)
7379         {
7380           if (rp >= EndOf(Methods))
7381             {
7382               ThrowPerlException(exception,OptionError,
7383                 "UnrecognizedPerlMagickMethod",attribute);
7384               goto PerlException;
7385             }
7386           if (strEQcase(attribute,rp->name))
7387             break;
7388         }
7389         ix=rp-Methods+1;
7390         base++;
7391       }
7392     if (image == (Image *) NULL)
7393       {
7394         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7395         goto PerlException;
7396       }
7397     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7398     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7399     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7400     {
7401       Arguments
7402         *pp,
7403         *qq;
7404
7405       ssize_t
7406         ssize_test;
7407
7408       struct ArgumentList
7409         *al;
7410
7411       SV
7412         *sv;
7413
7414       sv=NULL;
7415       ssize_test=0;
7416       pp=(Arguments *) NULL;
7417       qq=rp->arguments;
7418       if (i == items)
7419         {
7420           pp=rp->arguments,
7421           sv=ST(i-1);
7422         }
7423       else
7424         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7425         {
7426           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7427             break;
7428           if (strEQcase(attribute,qq->method) > ssize_test)
7429             {
7430               pp=qq;
7431               ssize_test=strEQcase(attribute,qq->method);
7432             }
7433         }
7434       if (pp == (Arguments *) NULL)
7435         {
7436           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7437             attribute);
7438           goto continue_outer_loop;
7439         }
7440       al=(&argument_list[pp-rp->arguments]);
7441       switch (pp->type)
7442       {
7443         case ArrayReference:
7444         {
7445           if (SvTYPE(sv) != SVt_RV)
7446             {
7447               (void) FormatLocaleString(message,MaxTextExtent,
7448                 "invalid %.60s value",pp->method);
7449               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7450               goto continue_outer_loop;
7451             }
7452           al->array_reference=SvRV(sv);
7453           break;
7454         }
7455         case RealReference:
7456         {
7457           al->real_reference=SvNV(sv);
7458           break;
7459         }
7460         case FileReference:
7461         {
7462           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7463           break;
7464         }
7465         case ImageReference:
7466         {
7467           if (!sv_isobject(sv) ||
7468               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7469                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7470             {
7471               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7472                 PackageName);
7473               goto PerlException;
7474             }
7475           break;
7476         }
7477         case IntegerReference:
7478         {
7479           al->integer_reference=SvIV(sv);
7480           break;
7481         }
7482         case StringReference:
7483         {
7484           al->string_reference=(char *) SvPV(sv,al->length);
7485           if (sv_isobject(sv))
7486             al->image_reference=SetupList(aTHX_ SvRV(sv),
7487               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7488           break;
7489         }
7490         default:
7491         {
7492           /*
7493             Is a string; look up name.
7494           */
7495           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7496             {
7497               al->string_reference=(char *) SvPV(sv,al->length);
7498               al->integer_reference=(-1);
7499               break;
7500             }
7501           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7502             MagickFalse,SvPV(sv,na));
7503           if (pp->type == MagickChannelOptions)
7504             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7505           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7506             {
7507               (void) FormatLocaleString(message,MaxTextExtent,
7508                 "invalid %.60s value",pp->method);
7509               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7510               goto continue_outer_loop;
7511             }
7512           break;
7513         }
7514       }
7515       attribute_flag[pp-rp->arguments]++;
7516       continue_outer_loop: ;
7517     }
7518     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7519     pv=reference_vector;
7520     SetGeometryInfo(&geometry_info);
7521     channel=DefaultChannels;
7522     for (next=image; next; next=next->next)
7523     {
7524       image=next;
7525       SetGeometry(image,&geometry);
7526       if ((region_info.width*region_info.height) != 0)
7527         {
7528           region_image=image;
7529           image=CropImage(image,&region_info,exception);
7530         }
7531       switch (ix)
7532       {
7533         default:
7534         {
7535           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7536           ThrowPerlException(exception,OptionError,
7537             "UnrecognizedPerlMagickMethod",message);
7538           goto PerlException;
7539         }
7540         case 1:  /* Comment */
7541         {
7542           if (attribute_flag[0] == 0)
7543             argument_list[0].string_reference=(char *) NULL;
7544           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7545             info ? info->image_info : (ImageInfo *) NULL,image,
7546             argument_list[0].string_reference));
7547           break;
7548         }
7549         case 2:  /* Label */
7550         {
7551           if (attribute_flag[0] == 0)
7552             argument_list[0].string_reference=(char *) NULL;
7553           (void) SetImageProperty(image,"label",InterpretImageProperties(
7554             info ? info->image_info : (ImageInfo *) NULL,image,
7555             argument_list[0].string_reference));
7556           break;
7557         }
7558         case 3:  /* AddNoise */
7559         {
7560           if (attribute_flag[0] == 0)
7561             argument_list[0].integer_reference=UniformNoise;
7562           if (attribute_flag[1] != 0)
7563             channel=(ChannelType) argument_list[1].integer_reference;
7564           image=AddNoiseImageChannel(image,channel,(NoiseType)
7565             argument_list[0].integer_reference,exception);
7566           break;
7567         }
7568         case 4:  /* Colorize */
7569         {
7570           PixelPacket
7571             target;
7572
7573           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7574           if (attribute_flag[0] != 0)
7575             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7576               exception);
7577           if (attribute_flag[1] == 0)
7578             argument_list[1].string_reference="100%";
7579           image=ColorizeImage(image,argument_list[1].string_reference,target,
7580             exception);
7581           break;
7582         }
7583         case 5:  /* Border */
7584         {
7585           geometry.width=0;
7586           geometry.height=0;
7587           if (attribute_flag[0] != 0)
7588             {
7589               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7590                 &geometry,exception);
7591               if ((flags & HeightValue) == 0)
7592                 geometry.height=geometry.width;
7593             }
7594           if (attribute_flag[1] != 0)
7595             geometry.width=argument_list[1].integer_reference;
7596           if (attribute_flag[2] != 0)
7597             geometry.height=argument_list[2].integer_reference;
7598           if (attribute_flag[3] != 0)
7599             QueryColorDatabase(argument_list[3].string_reference,
7600               &image->border_color,exception);
7601           if (attribute_flag[4] != 0)
7602             QueryColorDatabase(argument_list[4].string_reference,
7603               &image->border_color,exception);
7604           if (attribute_flag[5] != 0)
7605             QueryColorDatabase(argument_list[5].string_reference,
7606               &image->border_color,exception);
7607           if (attribute_flag[6] != 0)
7608             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7609           image=BorderImage(image,&geometry,exception);
7610           break;
7611         }
7612         case 6:  /* Blur */
7613         {
7614           if (attribute_flag[0] != 0)
7615             {
7616               flags=ParseGeometry(argument_list[0].string_reference,
7617                 &geometry_info);
7618               if ((flags & SigmaValue) == 0)
7619                 geometry_info.sigma=1.0;
7620             }
7621           if (attribute_flag[1] != 0)
7622             geometry_info.rho=argument_list[1].real_reference;
7623           if (attribute_flag[2] != 0)
7624             geometry_info.sigma=argument_list[2].real_reference;
7625           if (attribute_flag[3] != 0)
7626             channel=(ChannelType) argument_list[3].integer_reference;
7627           image=BlurImageChannel(image,channel,geometry_info.rho,
7628             geometry_info.sigma,exception);
7629           break;
7630         }
7631         case 7:  /* Chop */
7632         {
7633           if (attribute_flag[0] != 0)
7634             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7635               &geometry,exception);
7636           if (attribute_flag[1] != 0)
7637             geometry.width=argument_list[1].integer_reference;
7638           if (attribute_flag[2] != 0)
7639             geometry.height=argument_list[2].integer_reference;
7640           if (attribute_flag[3] != 0)
7641             geometry.x=argument_list[3].integer_reference;
7642           if (attribute_flag[4] != 0)
7643             geometry.y=argument_list[4].integer_reference;
7644           image=ChopImage(image,&geometry,exception);
7645           break;
7646         }
7647         case 8:  /* Crop */
7648         {
7649           if (attribute_flag[6] != 0)
7650             image->gravity=(GravityType) argument_list[6].integer_reference;
7651           if (attribute_flag[0] != 0)
7652             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7653               &geometry,exception);
7654           if (attribute_flag[1] != 0)
7655             geometry.width=argument_list[1].integer_reference;
7656           if (attribute_flag[2] != 0)
7657             geometry.height=argument_list[2].integer_reference;
7658           if (attribute_flag[3] != 0)
7659             geometry.x=argument_list[3].integer_reference;
7660           if (attribute_flag[4] != 0)
7661             geometry.y=argument_list[4].integer_reference;
7662           if (attribute_flag[5] != 0)
7663             image->fuzz=
7664               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7665           image=CropImage(image,&geometry,exception);
7666           break;
7667         }
7668         case 9:  /* Despeckle */
7669         {
7670           image=DespeckleImage(image,exception);
7671           break;
7672         }
7673         case 10:  /* Edge */
7674         {
7675           if (attribute_flag[0] != 0)
7676             geometry_info.rho=argument_list[0].real_reference;
7677           image=EdgeImage(image,geometry_info.rho,exception);
7678           break;
7679         }
7680         case 11:  /* Emboss */
7681         {
7682           if (attribute_flag[0] != 0)
7683             {
7684               flags=ParseGeometry(argument_list[0].string_reference,
7685                 &geometry_info);
7686               if ((flags & SigmaValue) == 0)
7687                 geometry_info.sigma=1.0;
7688             }
7689           if (attribute_flag[1] != 0)
7690             geometry_info.rho=argument_list[1].real_reference;
7691           if (attribute_flag[2] != 0)
7692             geometry_info.sigma=argument_list[2].real_reference;
7693           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7694             exception);
7695           break;
7696         }
7697         case 12:  /* Enhance */
7698         {
7699           image=EnhanceImage(image,exception);
7700           break;
7701         }
7702         case 13:  /* Flip */
7703         {
7704           image=FlipImage(image,exception);
7705           break;
7706         }
7707         case 14:  /* Flop */
7708         {
7709           image=FlopImage(image,exception);
7710           break;
7711         }
7712         case 15:  /* Frame */
7713         {
7714           FrameInfo
7715             frame_info;
7716
7717           if (attribute_flag[0] != 0)
7718             {
7719               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7720                 &geometry,exception);
7721               if ((flags & HeightValue) == 0)
7722                 geometry.height=geometry.width;
7723               frame_info.width=geometry.width;
7724               frame_info.height=geometry.height;
7725               frame_info.outer_bevel=geometry.x;
7726               frame_info.inner_bevel=geometry.y;
7727             }
7728           if (attribute_flag[1] != 0)
7729             frame_info.width=argument_list[1].integer_reference;
7730           if (attribute_flag[2] != 0)
7731             frame_info.height=argument_list[2].integer_reference;
7732           if (attribute_flag[3] != 0)
7733             frame_info.inner_bevel=argument_list[3].integer_reference;
7734           if (attribute_flag[4] != 0)
7735             frame_info.outer_bevel=argument_list[4].integer_reference;
7736           if (attribute_flag[5] != 0)
7737             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7738               exception);
7739           if (attribute_flag[6] != 0)
7740             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7741               exception);
7742           frame_info.x=(ssize_t) frame_info.width;
7743           frame_info.y=(ssize_t) frame_info.height;
7744           frame_info.width=image->columns+2*frame_info.x;
7745           frame_info.height=image->rows+2*frame_info.y;
7746           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7747             image->matte_color=fill_color;
7748           if (attribute_flag[7] != 0)
7749             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7750           image=FrameImage(image,&frame_info,exception);
7751           break;
7752         }
7753         case 16:  /* Implode */
7754         {
7755           if (attribute_flag[0] == 0)
7756             argument_list[0].real_reference=0.5;
7757           if (attribute_flag[1] != 0)
7758             image->interpolate=(InterpolatePixelMethod)
7759               argument_list[1].integer_reference;
7760           image=ImplodeImage(image,argument_list[0].real_reference,
7761             exception);
7762           break;
7763         }
7764         case 17:  /* Magnify */
7765         {
7766           image=MagnifyImage(image,exception);
7767           break;
7768         }
7769         case 18:  /* MedianFilter */
7770         {
7771           if (attribute_flag[0] != 0)
7772             {
7773               flags=ParseGeometry(argument_list[0].string_reference,
7774                 &geometry_info);
7775               if ((flags & SigmaValue) == 0)
7776                 geometry_info.sigma=1.0;
7777             }
7778           if (attribute_flag[1] != 0)
7779             geometry_info.rho=argument_list[1].real_reference;
7780           if (attribute_flag[2] != 0)
7781             geometry_info.sigma=argument_list[2].real_reference;
7782           if (attribute_flag[3] != 0)
7783             channel=(ChannelType) argument_list[3].integer_reference;
7784           image=StatisticImageChannel(image,channel,MedianStatistic,
7785             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7786           break;
7787         }
7788         case 19:  /* Minify */
7789         {
7790           image=MinifyImage(image,exception);
7791           break;
7792         }
7793         case 20:  /* OilPaint */
7794         {
7795           if (attribute_flag[0] == 0)
7796             argument_list[0].real_reference=0.0;
7797           image=OilPaintImage(image,argument_list[0].real_reference,
7798             exception);
7799           break;
7800         }
7801         case 21:  /* ReduceNoise */
7802         {
7803           if (attribute_flag[0] != 0)
7804             {
7805               flags=ParseGeometry(argument_list[0].string_reference,
7806                 &geometry_info);
7807               if ((flags & SigmaValue) == 0)
7808                 geometry_info.sigma=1.0;
7809             }
7810           if (attribute_flag[1] != 0)
7811             geometry_info.rho=argument_list[1].real_reference;
7812           if (attribute_flag[2] != 0)
7813             geometry_info.sigma=argument_list[2].real_reference;
7814           if (attribute_flag[3] != 0)
7815             channel=(ChannelType) argument_list[3].integer_reference;
7816           image=StatisticImageChannel(image,channel,NonpeakStatistic,
7817             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7818           break;
7819         }
7820         case 22:  /* Roll */
7821         {
7822           if (attribute_flag[0] != 0)
7823             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7824               &geometry,exception);
7825           if (attribute_flag[1] != 0)
7826             geometry.x=argument_list[1].integer_reference;
7827           if (attribute_flag[2] != 0)
7828             geometry.y=argument_list[2].integer_reference;
7829           image=RollImage(image,geometry.x,geometry.y,exception);
7830           break;
7831         }
7832         case 23:  /* Rotate */
7833         {
7834           if (attribute_flag[0] == 0)
7835             argument_list[0].real_reference=90.0;
7836           if (attribute_flag[1] != 0)
7837             QueryColorDatabase(argument_list[1].string_reference,
7838               &image->background_color,exception);
7839           if (attribute_flag[2] != 0)
7840             QueryColorDatabase(argument_list[2].string_reference,
7841               &image->background_color,exception);
7842           if (attribute_flag[3] != 0)
7843             QueryColorDatabase(argument_list[3].string_reference,
7844               &image->background_color,exception);
7845           image=RotateImage(image,argument_list[0].real_reference,exception);
7846           break;
7847         }
7848         case 24:  /* Sample */
7849         {
7850           if (attribute_flag[0] != 0)
7851             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7852               &geometry,exception);
7853           if (attribute_flag[1] != 0)
7854             geometry.width=argument_list[1].integer_reference;
7855           if (attribute_flag[2] != 0)
7856             geometry.height=argument_list[2].integer_reference;
7857           image=SampleImage(image,geometry.width,geometry.height,exception);
7858           break;
7859         }
7860         case 25:  /* Scale */
7861         {
7862           if (attribute_flag[0] != 0)
7863             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7864               &geometry,exception);
7865           if (attribute_flag[1] != 0)
7866             geometry.width=argument_list[1].integer_reference;
7867           if (attribute_flag[2] != 0)
7868             geometry.height=argument_list[2].integer_reference;
7869           image=ScaleImage(image,geometry.width,geometry.height,exception);
7870           break;
7871         }
7872         case 26:  /* Shade */
7873         {
7874           if (attribute_flag[0] != 0)
7875             {
7876               flags=ParseGeometry(argument_list[0].string_reference,
7877                 &geometry_info);
7878               if ((flags & SigmaValue) == 0)
7879                 geometry_info.sigma=0.0;
7880             }
7881           if (attribute_flag[1] != 0)
7882             geometry_info.rho=argument_list[1].real_reference;
7883           if (attribute_flag[2] != 0)
7884             geometry_info.sigma=argument_list[2].real_reference;
7885           image=ShadeImage(image,
7886             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7887             geometry_info.rho,geometry_info.sigma,exception);
7888           break;
7889         }
7890         case 27:  /* Sharpen */
7891         {
7892           if (attribute_flag[0] != 0)
7893             {
7894               flags=ParseGeometry(argument_list[0].string_reference,
7895                 &geometry_info);
7896               if ((flags & SigmaValue) == 0)
7897                 geometry_info.sigma=1.0;
7898             }
7899           if (attribute_flag[1] != 0)
7900             geometry_info.rho=argument_list[1].real_reference;
7901           if (attribute_flag[2] != 0)
7902             geometry_info.sigma=argument_list[2].real_reference;
7903           if (attribute_flag[3] != 0)
7904             channel=(ChannelType) argument_list[3].integer_reference;
7905           image=SharpenImageChannel(image,channel,geometry_info.rho,
7906             geometry_info.sigma,exception);
7907           break;
7908         }
7909         case 28:  /* Shear */
7910         {
7911           if (attribute_flag[0] != 0)
7912             {
7913               flags=ParseGeometry(argument_list[0].string_reference,
7914                 &geometry_info);
7915               if ((flags & SigmaValue) == 0)
7916                 geometry_info.sigma=geometry_info.rho;
7917             }
7918           if (attribute_flag[1] != 0)
7919             geometry_info.rho=argument_list[1].real_reference;
7920           if (attribute_flag[2] != 0)
7921             geometry_info.sigma=argument_list[2].real_reference;
7922           if (attribute_flag[3] != 0)
7923             QueryColorDatabase(argument_list[3].string_reference,
7924               &image->background_color,exception);
7925           if (attribute_flag[4] != 0)
7926             QueryColorDatabase(argument_list[4].string_reference,
7927               &image->background_color,exception);
7928           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7929             exception);
7930           break;
7931         }
7932         case 29:  /* Spread */
7933         {
7934           if (attribute_flag[0] == 0)
7935             argument_list[0].real_reference=1.0;
7936           image=SpreadImage(image,argument_list[0].real_reference,exception);
7937           break;
7938         }
7939         case 30:  /* Swirl */
7940         {
7941           if (attribute_flag[0] == 0)
7942             argument_list[0].real_reference=50.0;
7943           if (attribute_flag[1] != 0)
7944             image->interpolate=(InterpolatePixelMethod)
7945               argument_list[1].integer_reference;
7946           image=SwirlImage(image,argument_list[0].real_reference,exception);
7947           break;
7948         }
7949         case 31:  /* Resize */
7950         case 32:  /* Zoom */
7951         {
7952           if (attribute_flag[0] != 0)
7953             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7954               &geometry,exception);
7955           if (attribute_flag[1] != 0)
7956             geometry.width=argument_list[1].integer_reference;
7957           if (attribute_flag[2] != 0)
7958             geometry.height=argument_list[2].integer_reference;
7959           if (attribute_flag[3] == 0)
7960             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7961           if (attribute_flag[4] != 0)
7962             SetImageArtifact(image,"filter:support",
7963               argument_list[4].string_reference);
7964           if (attribute_flag[5] == 0)
7965             argument_list[5].real_reference=1.0;
7966           image=ResizeImage(image,geometry.width,geometry.height,
7967             (FilterTypes) argument_list[3].integer_reference,
7968             argument_list[5].real_reference,exception);
7969           break;
7970         }
7971         case 33:  /* Annotate */
7972         {
7973           DrawInfo
7974             *draw_info;
7975
7976           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7977             (DrawInfo *) NULL);
7978           if (attribute_flag[0] != 0)
7979             {
7980               char
7981                 *text;
7982
7983               text=InterpretImageProperties(info ? info->image_info :
7984                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7985               (void) CloneString(&draw_info->text,text);
7986               text=DestroyString(text);
7987             }
7988           if (attribute_flag[1] != 0)
7989             (void) CloneString(&draw_info->font,
7990               argument_list[1].string_reference);
7991           if (attribute_flag[2] != 0)
7992             draw_info->pointsize=argument_list[2].real_reference;
7993           if (attribute_flag[3] != 0)
7994             (void) CloneString(&draw_info->density,
7995               argument_list[3].string_reference);
7996           if (attribute_flag[4] != 0)
7997             (void) QueryColorDatabase(argument_list[4].string_reference,
7998               &draw_info->undercolor,exception);
7999           if (attribute_flag[5] != 0)
8000             {
8001               (void) QueryColorDatabase(argument_list[5].string_reference,
8002                 &draw_info->stroke,exception);
8003               if (argument_list[5].image_reference != (Image *) NULL)
8004                 draw_info->stroke_pattern=CloneImage(
8005                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8006             }
8007           if (attribute_flag[6] != 0)
8008             {
8009               (void) QueryColorDatabase(argument_list[6].string_reference,
8010                 &draw_info->fill,exception);
8011               if (argument_list[6].image_reference != (Image *) NULL)
8012                 draw_info->fill_pattern=CloneImage(
8013                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8014             }
8015           if (attribute_flag[7] != 0)
8016             {
8017               (void) CloneString(&draw_info->geometry,
8018                 argument_list[7].string_reference);
8019               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8020                 &geometry,exception);
8021               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8022                 geometry_info.sigma=geometry_info.xi;
8023             }
8024           if (attribute_flag[8] != 0)
8025             (void) QueryColorDatabase(argument_list[8].string_reference,
8026               &draw_info->fill,exception);
8027           if (attribute_flag[11] != 0)
8028             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
8029           if (attribute_flag[25] != 0)
8030             {
8031               AV
8032                 *av;
8033
8034               av=(AV *) argument_list[25].array_reference;
8035               if ((av_len(av) != 3) && (av_len(av) != 5))
8036                 {
8037                   ThrowPerlException(exception,OptionError,
8038                     "affine matrix must have 4 or 6 elements",PackageName);
8039                   goto PerlException;
8040                 }
8041               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8042               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8043               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8044               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8045               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8046                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8047                 {
8048                   ThrowPerlException(exception,OptionError,
8049                     "affine matrix is singular",PackageName);
8050                    goto PerlException;
8051                 }
8052               if (av_len(av) == 5)
8053                 {
8054                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8055                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8056                 }
8057             }
8058           for (j=12; j < 17; j++)
8059           {
8060             if (attribute_flag[j] == 0)
8061               continue;
8062             value=argument_list[j].string_reference;
8063             angle=argument_list[j].real_reference;
8064             current=draw_info->affine;
8065             GetAffineMatrix(&affine);
8066             switch (j)
8067             {
8068               case 12:
8069               {
8070                 /*
8071                   Translate.
8072                 */
8073                 flags=ParseGeometry(value,&geometry_info);
8074                 affine.tx=geometry_info.xi;
8075                 affine.ty=geometry_info.psi;
8076                 if ((flags & PsiValue) == 0)
8077                   affine.ty=affine.tx;
8078                 break;
8079               }
8080               case 13:
8081               {
8082                 /*
8083                   Scale.
8084                 */
8085                 flags=ParseGeometry(value,&geometry_info);
8086                 affine.sx=geometry_info.rho;
8087                 affine.sy=geometry_info.sigma;
8088                 if ((flags & SigmaValue) == 0)
8089                   affine.sy=affine.sx;
8090                 break;
8091               }
8092               case 14:
8093               {
8094                 /*
8095                   Rotate.
8096                 */
8097                 if (angle == 0.0)
8098                   break;
8099                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8100                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8101                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8102                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8103                 break;
8104               }
8105               case 15:
8106               {
8107                 /*
8108                   SkewX.
8109                 */
8110                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8111                 break;
8112               }
8113               case 16:
8114               {
8115                 /*
8116                   SkewY.
8117                 */
8118                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8119                 break;
8120               }
8121             }
8122             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8123             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8124             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8125             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8126             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8127               current.tx;
8128             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8129               current.ty;
8130           }
8131           if (attribute_flag[9] == 0)
8132             argument_list[9].real_reference=0.0;
8133           if (attribute_flag[10] == 0)
8134             argument_list[10].real_reference=0.0;
8135           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8136             {
8137               char
8138                 geometry[MaxTextExtent];
8139
8140               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8141                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8142                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8143               (void) CloneString(&draw_info->geometry,geometry);
8144             }
8145           if (attribute_flag[17] != 0)
8146             draw_info->stroke_width=argument_list[17].real_reference;
8147           if (attribute_flag[18] != 0)
8148             {
8149               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8150                 MagickTrue : MagickFalse;
8151               draw_info->stroke_antialias=draw_info->text_antialias;
8152             }
8153           if (attribute_flag[19] != 0)
8154             (void) CloneString(&draw_info->family,
8155               argument_list[19].string_reference);
8156           if (attribute_flag[20] != 0)
8157             draw_info->style=(StyleType) argument_list[20].integer_reference;
8158           if (attribute_flag[21] != 0)
8159             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8160           if (attribute_flag[22] != 0)
8161             draw_info->weight=argument_list[22].integer_reference;
8162           if (attribute_flag[23] != 0)
8163             draw_info->align=(AlignType) argument_list[23].integer_reference;
8164           if (attribute_flag[24] != 0)
8165             (void) CloneString(&draw_info->encoding,
8166               argument_list[24].string_reference);
8167           if (attribute_flag[25] != 0)
8168             draw_info->fill_pattern=CloneImage(
8169               argument_list[25].image_reference,0,0,MagickTrue,exception);
8170           if (attribute_flag[26] != 0)
8171             draw_info->fill_pattern=CloneImage(
8172               argument_list[26].image_reference,0,0,MagickTrue,exception);
8173           if (attribute_flag[27] != 0)
8174             draw_info->stroke_pattern=CloneImage(
8175               argument_list[27].image_reference,0,0,MagickTrue,exception);
8176           if (attribute_flag[29] != 0)
8177             draw_info->kerning=argument_list[29].real_reference;
8178           if (attribute_flag[30] != 0)
8179             draw_info->interline_spacing=argument_list[30].real_reference;
8180           if (attribute_flag[31] != 0)
8181             draw_info->interword_spacing=argument_list[31].real_reference;
8182           if (attribute_flag[32] != 0)
8183             draw_info->direction=(DirectionType)
8184               argument_list[32].integer_reference;
8185           (void) AnnotateImage(image,draw_info);
8186           draw_info=DestroyDrawInfo(draw_info);
8187           break;
8188         }
8189         case 34:  /* ColorFloodfill */
8190         {
8191           DrawInfo
8192             *draw_info;
8193
8194           MagickBooleanType
8195             invert;
8196
8197           MagickPixelPacket
8198             target;
8199
8200           draw_info=CloneDrawInfo(info ? info->image_info :
8201             (ImageInfo *) NULL,(DrawInfo *) NULL);
8202           if (attribute_flag[0] != 0)
8203             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8204               &geometry,exception);
8205           if (attribute_flag[1] != 0)
8206             geometry.x=argument_list[1].integer_reference;
8207           if (attribute_flag[2] != 0)
8208             geometry.y=argument_list[2].integer_reference;
8209           if (attribute_flag[3] != 0)
8210             (void) QueryColorDatabase(argument_list[3].string_reference,
8211               &draw_info->fill,exception);
8212           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8213             exception);
8214           invert=MagickFalse;
8215           if (attribute_flag[4] != 0)
8216             {
8217               QueryMagickColor(argument_list[4].string_reference,&target,
8218                 exception);
8219               invert=MagickTrue;
8220             }
8221           if (attribute_flag[5] != 0)
8222             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8223               QuantumRange);
8224           if (attribute_flag[6] != 0)
8225             invert=(MagickBooleanType) argument_list[6].integer_reference;
8226           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8227             geometry.x,geometry.y,invert);
8228           draw_info=DestroyDrawInfo(draw_info);
8229           break;
8230         }
8231         case 35:  /* Composite */
8232         {
8233           char
8234             composite_geometry[MaxTextExtent];
8235
8236           Image
8237             *composite_image,
8238             *rotate_image;
8239
8240           compose=OverCompositeOp;
8241           if (attribute_flag[0] != 0)
8242             composite_image=argument_list[0].image_reference;
8243           else
8244             {
8245               ThrowPerlException(exception,OptionError,
8246                 "CompositeImageRequired",PackageName);
8247               goto PerlException;
8248             }
8249           /*
8250             Parameter Handling used for BOTH normal and tiled composition.
8251           */
8252           if (attribute_flag[1] != 0) /* compose */
8253             compose=(CompositeOperator) argument_list[1].integer_reference;
8254           if (attribute_flag[6] != 0) /* opacity  */
8255             {
8256               if (compose != DissolveCompositeOp)
8257                 (void) SetImageOpacity(composite_image,(Quantum) (QuantumRange-
8258                   SiPrefixToDouble(argument_list[6].string_reference,
8259                   QuantumRange)));
8260               else
8261                 {
8262                   CacheView
8263                     *composite_view;
8264
8265                   double
8266                     opacity;
8267
8268                   MagickBooleanType
8269                     sync;
8270
8271                   register ssize_t
8272                     x;
8273
8274                   register PixelPacket
8275                     *q;
8276
8277                   ssize_t
8278                     y;
8279
8280                   /*
8281                     Handle dissolve composite operator (patch by
8282                     Kevin A. McGrail).
8283                   */
8284                   (void) CloneString(&image->geometry,
8285                     argument_list[6].string_reference);
8286                   opacity=(Quantum) (QuantumRange-SiPrefixToDouble(
8287                     argument_list[6].string_reference,QuantumRange));
8288                   if (composite_image->matte != MagickTrue)
8289                     (void) SetImageOpacity(composite_image,OpaqueOpacity);
8290                   composite_view=AcquireCacheView(composite_image);
8291                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8292                   {
8293                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8294                       composite_image->columns,1,exception);
8295                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8296                     {
8297                       if (q->opacity == OpaqueOpacity)
8298                         q->opacity=ClampToQuantum(opacity);
8299                       q++;
8300                     }
8301                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8302                     if (sync == MagickFalse)
8303                       break;
8304                   }
8305                   composite_view=DestroyCacheView(composite_view);
8306                 }
8307             }
8308           if (attribute_flag[9] != 0)    /* "color=>" */
8309             QueryColorDatabase(argument_list[9].string_reference,
8310               &composite_image->background_color,exception);
8311           if (attribute_flag[12] != 0) /* "interpolate=>" */
8312             image->interpolate=(InterpolatePixelMethod)
8313               argument_list[12].integer_reference;
8314           if (attribute_flag[13] != 0)   /* "args=>" */
8315             (void) SetImageArtifact(composite_image,"compose:args",
8316               argument_list[13].string_reference);
8317           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8318             (void) SetImageArtifact(composite_image,"compose:args",
8319               argument_list[14].string_reference);
8320           /*
8321             Tiling Composition (with orthogonal rotate).
8322           */
8323           rotate_image=(Image *) NULL;
8324           if (attribute_flag[8] != 0)   /* "rotate=>" */
8325             {
8326                /*
8327                  Rotate image.
8328                */
8329                rotate_image=RotateImage(composite_image,
8330                  argument_list[8].real_reference,exception);
8331                if (rotate_image == (Image *) NULL)
8332                  break;
8333             }
8334           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8335             {
8336               ssize_t
8337                 x,
8338                 y;
8339
8340               /*
8341                 Tile the composite image.
8342               */
8343              if (attribute_flag[8] != 0)   /* "tile=>" */
8344                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8345                  "false");
8346              else
8347                (void) SetImageArtifact(composite_image,
8348                  "compose:outside-overlay","false");
8349              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8350                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8351                 {
8352                   if (attribute_flag[8] != 0) /* rotate */
8353                     (void) CompositeImage(image,compose,rotate_image,x,y);
8354                   else
8355                     (void) CompositeImage(image,compose,composite_image,x,y);
8356                 }
8357               if (attribute_flag[8] != 0) /* rotate */
8358                 rotate_image=DestroyImage(rotate_image);
8359               break;
8360             }
8361           /*
8362             Parameter Handling used used ONLY for normal composition.
8363           */
8364           if (attribute_flag[5] != 0) /* gravity */
8365             image->gravity=(GravityType) argument_list[5].integer_reference;
8366           if (attribute_flag[2] != 0) /* geometry offset */
8367             {
8368               SetGeometry(image,&geometry);
8369               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8370                 &geometry);
8371               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8372                 &geometry);
8373             }
8374           if (attribute_flag[3] != 0) /* x offset */
8375             geometry.x=argument_list[3].integer_reference;
8376           if (attribute_flag[4] != 0) /* y offset */
8377             geometry.y=argument_list[4].integer_reference;
8378           if (attribute_flag[10] != 0) /* mask */
8379             {
8380               if ((image->compose == DisplaceCompositeOp) ||
8381                   (image->compose == DistortCompositeOp))
8382                 {
8383                   /*
8384                     Merge Y displacement into X displacement image.
8385                   */
8386                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8387                     &image->exception);
8388                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8389                     argument_list[10].image_reference,0,0);
8390                 }
8391               else
8392                 {
8393                   /*
8394                     Set a blending mask for the composition.
8395                   */
8396                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8397                     MagickTrue,&image->exception);
8398                   (void) NegateImage(image->mask,MagickFalse);
8399                 }
8400             }
8401           if (attribute_flag[11] != 0) /* channel */
8402             channel=(ChannelType) argument_list[11].integer_reference;
8403           /*
8404             Composite two images (normal composition).
8405           */
8406           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8407             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8408             (double) composite_image->rows,(double) geometry.x,(double)
8409             geometry.y);
8410           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8411             exception);
8412           if (attribute_flag[8] == 0) /* no rotate */
8413             CompositeImageChannel(image,channel,compose,composite_image,
8414               geometry.x,geometry.y);
8415           else
8416             {
8417               /*
8418                 Position adjust rotated image then composite.
8419               */
8420               geometry.x-=(ssize_t) (rotate_image->columns-
8421                 composite_image->columns)/2;
8422               geometry.y-=(ssize_t) (rotate_image->rows-
8423                 composite_image->rows)/2;
8424               CompositeImageChannel(image,channel,compose,rotate_image,
8425                 geometry.x,geometry.y);
8426               rotate_image=DestroyImage(rotate_image);
8427             }
8428           if (attribute_flag[10] != 0) /* mask */
8429             {
8430               if ((image->compose == DisplaceCompositeOp) ||
8431                   (image->compose == DistortCompositeOp))
8432                 composite_image=DestroyImage(composite_image);
8433               else
8434                 image->mask=DestroyImage(image->mask);
8435             }
8436           break;
8437         }
8438         case 36:  /* Contrast */
8439         {
8440           if (attribute_flag[0] == 0)
8441             argument_list[0].integer_reference=0;
8442           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8443             MagickTrue : MagickFalse);
8444           break;
8445         }
8446         case 37:  /* CycleColormap */
8447         {
8448           if (attribute_flag[0] == 0)
8449             argument_list[0].integer_reference=6;
8450           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8451           break;
8452         }
8453         case 38:  /* Draw */
8454         {
8455           DrawInfo
8456             *draw_info;
8457
8458           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8459             (DrawInfo *) NULL);
8460           (void) CloneString(&draw_info->primitive,"point");
8461           if (attribute_flag[0] != 0)
8462             {
8463               if (argument_list[0].integer_reference < 0)
8464                 (void) CloneString(&draw_info->primitive,
8465                   argument_list[0].string_reference);
8466               else
8467                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8468                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8469             }
8470           if (attribute_flag[1] != 0)
8471             {
8472               if (LocaleCompare(draw_info->primitive,"path") == 0)
8473                 {
8474                   (void) ConcatenateString(&draw_info->primitive," '");
8475                   ConcatenateString(&draw_info->primitive,
8476                     argument_list[1].string_reference);
8477                   (void) ConcatenateString(&draw_info->primitive,"'");
8478                 }
8479               else
8480                 {
8481                   (void) ConcatenateString(&draw_info->primitive," ");
8482                   ConcatenateString(&draw_info->primitive,
8483                     argument_list[1].string_reference);
8484                 }
8485             }
8486           if (attribute_flag[2] != 0)
8487             {
8488               (void) ConcatenateString(&draw_info->primitive," ");
8489               (void) ConcatenateString(&draw_info->primitive,
8490                 CommandOptionToMnemonic(MagickMethodOptions,
8491                 argument_list[2].integer_reference));
8492             }
8493           if (attribute_flag[3] != 0)
8494             {
8495               (void) QueryColorDatabase(argument_list[3].string_reference,
8496                 &draw_info->stroke,exception);
8497               if (argument_list[3].image_reference != (Image *) NULL)
8498                 draw_info->stroke_pattern=CloneImage(
8499                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8500             }
8501           if (attribute_flag[4] != 0)
8502             {
8503               (void) QueryColorDatabase(argument_list[4].string_reference,
8504                 &draw_info->fill,exception);
8505               if (argument_list[4].image_reference != (Image *) NULL)
8506                 draw_info->fill_pattern=CloneImage(
8507                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8508             }
8509           if (attribute_flag[5] != 0)
8510             draw_info->stroke_width=argument_list[5].real_reference;
8511           if (attribute_flag[6] != 0)
8512             (void) CloneString(&draw_info->font,
8513               argument_list[6].string_reference);
8514           if (attribute_flag[7] != 0)
8515             (void) QueryColorDatabase(argument_list[7].string_reference,
8516               &draw_info->border_color,exception);
8517           if (attribute_flag[8] != 0)
8518             draw_info->affine.tx=argument_list[8].real_reference;
8519           if (attribute_flag[9] != 0)
8520             draw_info->affine.ty=argument_list[9].real_reference;
8521           if (attribute_flag[20] != 0)
8522             {
8523               AV
8524                 *av;
8525
8526               av=(AV *) argument_list[20].array_reference;
8527               if ((av_len(av) != 3) && (av_len(av) != 5))
8528                 {
8529                   ThrowPerlException(exception,OptionError,
8530                     "affine matrix must have 4 or 6 elements",PackageName);
8531                   goto PerlException;
8532                 }
8533               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8534               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8535               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8536               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8537               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8538                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8539                 {
8540                   ThrowPerlException(exception,OptionError,
8541                     "affine matrix is singular",PackageName);
8542                    goto PerlException;
8543                 }
8544               if (av_len(av) == 5)
8545                 {
8546                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8547                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8548                 }
8549             }
8550           for (j=10; j < 15; j++)
8551           {
8552             if (attribute_flag[j] == 0)
8553               continue;
8554             value=argument_list[j].string_reference;
8555             angle=argument_list[j].real_reference;
8556             current=draw_info->affine;
8557             GetAffineMatrix(&affine);
8558             switch (j)
8559             {
8560               case 10:
8561               {
8562                 /*
8563                   Translate.
8564                 */
8565                 flags=ParseGeometry(value,&geometry_info);
8566                 affine.tx=geometry_info.xi;
8567                 affine.ty=geometry_info.psi;
8568                 if ((flags & PsiValue) == 0)
8569                   affine.ty=affine.tx;
8570                 break;
8571               }
8572               case 11:
8573               {
8574                 /*
8575                   Scale.
8576                 */
8577                 flags=ParseGeometry(value,&geometry_info);
8578                 affine.sx=geometry_info.rho;
8579                 affine.sy=geometry_info.sigma;
8580                 if ((flags & SigmaValue) == 0)
8581                   affine.sy=affine.sx;
8582                 break;
8583               }
8584               case 12:
8585               {
8586                 /*
8587                   Rotate.
8588                 */
8589                 if (angle == 0.0)
8590                   break;
8591                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8592                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8593                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8594                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8595                 break;
8596               }
8597               case 13:
8598               {
8599                 /*
8600                   SkewX.
8601                 */
8602                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8603                 break;
8604               }
8605               case 14:
8606               {
8607                 /*
8608                   SkewY.
8609                 */
8610                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8611                 break;
8612               }
8613             }
8614             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8615             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8616             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8617             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8618             draw_info->affine.tx=
8619               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8620             draw_info->affine.ty=
8621               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8622           }
8623           if (attribute_flag[15] != 0)
8624             draw_info->fill_pattern=CloneImage(
8625               argument_list[15].image_reference,0,0,MagickTrue,exception);
8626           if (attribute_flag[16] != 0)
8627             draw_info->pointsize=argument_list[16].real_reference;
8628           if (attribute_flag[17] != 0)
8629             {
8630               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8631                 ? MagickTrue : MagickFalse;
8632               draw_info->text_antialias=draw_info->stroke_antialias;
8633             }
8634           if (attribute_flag[18] != 0)
8635             (void) CloneString(&draw_info->density,
8636               argument_list[18].string_reference);
8637           if (attribute_flag[19] != 0)
8638             draw_info->stroke_width=argument_list[19].real_reference;
8639           if (attribute_flag[21] != 0)
8640             draw_info->dash_offset=argument_list[21].real_reference;
8641           if (attribute_flag[22] != 0)
8642             {
8643               AV
8644                 *av;
8645
8646               av=(AV *) argument_list[22].array_reference;
8647               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8648                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8649               if (draw_info->dash_pattern != (double *) NULL)
8650                 {
8651                   for (i=0; i <= av_len(av); i++)
8652                     draw_info->dash_pattern[i]=(double)
8653                       SvNV(*(av_fetch(av,i,0)));
8654                   draw_info->dash_pattern[i]=0.0;
8655                 }
8656             }
8657           if (attribute_flag[23] != 0)
8658             image->interpolate=(InterpolatePixelMethod)
8659               argument_list[23].integer_reference;
8660           if ((attribute_flag[24] != 0) &&
8661               (draw_info->fill_pattern != (Image *) NULL))
8662             flags=ParsePageGeometry(draw_info->fill_pattern,
8663               argument_list[24].string_reference,
8664               &draw_info->fill_pattern->tile_offset,exception);
8665           if (attribute_flag[25] != 0)
8666             {
8667               (void) ConcatenateString(&draw_info->primitive," '");
8668               (void) ConcatenateString(&draw_info->primitive,
8669                 argument_list[25].string_reference);
8670               (void) ConcatenateString(&draw_info->primitive,"'");
8671             }
8672           if (attribute_flag[26] != 0)
8673             draw_info->fill_pattern=CloneImage(
8674               argument_list[26].image_reference,0,0,MagickTrue,exception);
8675           if (attribute_flag[27] != 0)
8676             draw_info->stroke_pattern=CloneImage(
8677               argument_list[27].image_reference,0,0,MagickTrue,exception);
8678           if (attribute_flag[28] != 0)
8679             (void) CloneString(&draw_info->primitive,
8680               argument_list[28].string_reference);
8681           if (attribute_flag[29] != 0)
8682             draw_info->kerning=argument_list[29].real_reference;
8683           if (attribute_flag[30] != 0)
8684             draw_info->interline_spacing=argument_list[30].real_reference;
8685           if (attribute_flag[31] != 0)
8686             draw_info->interword_spacing=argument_list[31].real_reference;
8687           if (attribute_flag[32] != 0)
8688             draw_info->direction=(DirectionType)
8689               argument_list[32].integer_reference;
8690           DrawImage(image,draw_info);
8691           draw_info=DestroyDrawInfo(draw_info);
8692           break;
8693         }
8694         case 39:  /* Equalize */
8695         {
8696           if (attribute_flag[0] != 0)
8697             channel=(ChannelType) argument_list[0].integer_reference;
8698           EqualizeImageChannel(image,channel);
8699           break;
8700         }
8701         case 40:  /* Gamma */
8702         {
8703           if (attribute_flag[1] != 0)
8704             channel=(ChannelType) argument_list[1].integer_reference;
8705           if (attribute_flag[2] == 0)
8706             argument_list[2].real_reference=1.0;
8707           if (attribute_flag[3] == 0)
8708             argument_list[3].real_reference=1.0;
8709           if (attribute_flag[4] == 0)
8710             argument_list[4].real_reference=1.0;
8711           if (attribute_flag[0] == 0)
8712             {
8713               (void) FormatLocaleString(message,MaxTextExtent,
8714                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8715                 (double) argument_list[3].real_reference,
8716                 (double) argument_list[4].real_reference);
8717               argument_list[0].string_reference=message;
8718             }
8719           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8720             (void) GammaImage(image,argument_list[0].string_reference);
8721           else
8722             (void) GammaImageChannel(image,channel,InterpretLocaleValue(
8723               argument_list[0].string_reference,(char **) NULL));
8724           break;
8725         }
8726         case 41:  /* Map */
8727         {
8728           QuantizeInfo
8729             *quantize_info;
8730
8731           if (attribute_flag[0] == 0)
8732             {
8733               ThrowPerlException(exception,OptionError,"MapImageRequired",
8734                 PackageName);
8735               goto PerlException;
8736             }
8737           quantize_info=AcquireQuantizeInfo(info->image_info);
8738           if (attribute_flag[1] != 0)
8739             quantize_info->dither=(MagickBooleanType)
8740               argument_list[1].integer_reference;
8741           if (attribute_flag[2] != 0)
8742             quantize_info->dither_method=(DitherMethod)
8743               argument_list[2].integer_reference;
8744           (void) RemapImages(quantize_info,image,
8745             argument_list[0].image_reference);
8746           quantize_info=DestroyQuantizeInfo(quantize_info);
8747           break;
8748         }
8749         case 42:  /* MatteFloodfill */
8750         {
8751           DrawInfo
8752             *draw_info;
8753
8754           MagickBooleanType
8755             invert;
8756
8757           MagickPixelPacket
8758             target;
8759
8760           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8761             (DrawInfo *) NULL);
8762           if (attribute_flag[0] != 0)
8763           if (attribute_flag[0] != 0)
8764             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8765               &geometry,exception);
8766           if (attribute_flag[1] != 0)
8767             geometry.x=argument_list[1].integer_reference;
8768           if (attribute_flag[2] != 0)
8769             geometry.y=argument_list[2].integer_reference;
8770           if (image->matte == MagickFalse)
8771             (void) SetImageOpacity(image,OpaqueOpacity);
8772           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8773             exception);
8774           if (attribute_flag[4] != 0)
8775             QueryMagickColor(argument_list[4].string_reference,&target,
8776               exception);
8777           if (attribute_flag[3] != 0)
8778             target.opacity=SiPrefixToDouble(argument_list[3].string_reference,
8779               QuantumRange);
8780           if (attribute_flag[5] != 0)
8781             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8782               QuantumRange);
8783           invert=MagickFalse;
8784           if (attribute_flag[6] != 0)
8785             invert=(MagickBooleanType) argument_list[6].integer_reference;
8786           (void) FloodfillPaintImage(image,OpacityChannel,draw_info,&target,
8787             geometry.x,geometry.y,invert);
8788           draw_info=DestroyDrawInfo(draw_info);
8789           break;
8790         }
8791         case 43:  /* Modulate */
8792         {
8793           char
8794             modulate[MaxTextExtent];
8795
8796           geometry_info.rho=100.0;
8797           geometry_info.sigma=100.0;
8798           geometry_info.xi=100.0;
8799           if (attribute_flag[0] != 0)
8800             (void)ParseGeometry(argument_list[0].string_reference,
8801               &geometry_info);
8802           if (attribute_flag[1] != 0)
8803             geometry_info.xi=argument_list[1].real_reference;
8804           if (attribute_flag[2] != 0)
8805             geometry_info.sigma=argument_list[2].real_reference;
8806           if (attribute_flag[3] != 0)
8807             {
8808               geometry_info.sigma=argument_list[3].real_reference;
8809               SetImageArtifact(image,"modulate:colorspace","HWB");
8810             }
8811           if (attribute_flag[4] != 0)
8812             {
8813               geometry_info.rho=argument_list[4].real_reference;
8814               SetImageArtifact(image,"modulate:colorspace","HSB");
8815             }
8816           if (attribute_flag[5] != 0)
8817             {
8818               geometry_info.sigma=argument_list[5].real_reference;
8819               SetImageArtifact(image,"modulate:colorspace","HSL");
8820             }
8821           if (attribute_flag[6] != 0)
8822             {
8823               geometry_info.rho=argument_list[6].real_reference;
8824               SetImageArtifact(image,"modulate:colorspace","HWB");
8825             }
8826           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8827             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8828           (void) ModulateImage(image,modulate);
8829           break;
8830         }
8831         case 44:  /* Negate */
8832         {
8833           if (attribute_flag[0] == 0)
8834             argument_list[0].integer_reference=0;
8835           if (attribute_flag[1] != 0)
8836             channel=(ChannelType) argument_list[1].integer_reference;
8837           (void) NegateImageChannel(image,channel,
8838             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
8839           break;
8840         }
8841         case 45:  /* Normalize */
8842         {
8843           if (attribute_flag[0] != 0)
8844             channel=(ChannelType) argument_list[0].integer_reference;
8845           NormalizeImageChannel(image,channel);
8846           break;
8847         }
8848         case 46:  /* NumberColors */
8849           break;
8850         case 47:  /* Opaque */
8851         {
8852           MagickBooleanType
8853             invert;
8854
8855           MagickPixelPacket
8856             fill_color,
8857             target;
8858
8859           (void) QueryMagickColor("none",&target,exception);
8860           (void) QueryMagickColor("none",&fill_color,exception);
8861           if (attribute_flag[0] != 0)
8862             (void) QueryMagickColor(argument_list[0].string_reference,
8863               &target,exception);
8864           if (attribute_flag[1] != 0)
8865             (void) QueryMagickColor(argument_list[1].string_reference,
8866               &fill_color,exception);
8867           if (attribute_flag[2] != 0)
8868             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8869               QuantumRange);
8870           if (attribute_flag[3] != 0)
8871             channel=(ChannelType) argument_list[3].integer_reference;
8872           invert=MagickFalse;
8873           if (attribute_flag[4] != 0)
8874             invert=(MagickBooleanType) argument_list[4].integer_reference;
8875           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8876             invert);
8877           break;
8878         }
8879         case 48:  /* Quantize */
8880         {
8881           QuantizeInfo
8882             *quantize_info;
8883
8884           quantize_info=AcquireQuantizeInfo(info->image_info);
8885           if (attribute_flag[0] != 0)
8886             quantize_info->number_colors=(size_t)
8887               argument_list[0].integer_reference;
8888           if (attribute_flag[1] != 0)
8889             quantize_info->tree_depth=(size_t)
8890               argument_list[1].integer_reference;
8891           if (attribute_flag[2] != 0)
8892             quantize_info->colorspace=(ColorspaceType)
8893               argument_list[2].integer_reference;
8894           if (attribute_flag[3] != 0)
8895             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8896               MagickTrue : MagickFalse;
8897           if (attribute_flag[4] != 0)
8898             quantize_info->measure_error=
8899               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8900           if (attribute_flag[5] != 0)
8901             (void) QueryColorDatabase(argument_list[5].string_reference,
8902               &image->transparent_color,exception);
8903           if (attribute_flag[5] && argument_list[5].integer_reference)
8904             {
8905               (void) QuantizeImages(quantize_info,image);
8906               goto PerlException;
8907             }
8908           if (attribute_flag[6] != 0)
8909             quantize_info->dither_method=(DitherMethod)
8910               argument_list[6].integer_reference;
8911           if ((image->storage_class == DirectClass) ||
8912               (image->colors > quantize_info->number_colors) ||
8913               (quantize_info->colorspace == GRAYColorspace))
8914             (void) QuantizeImage(quantize_info,image);
8915           else
8916             CompressImageColormap(image);
8917           quantize_info=DestroyQuantizeInfo(quantize_info);
8918           break;
8919         }
8920         case 49:  /* Raise */
8921         {
8922           if (attribute_flag[0] != 0)
8923             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8924               &geometry,exception);
8925           if (attribute_flag[1] != 0)
8926             geometry.width=argument_list[1].integer_reference;
8927           if (attribute_flag[2] != 0)
8928             geometry.height=argument_list[2].integer_reference;
8929           if (attribute_flag[3] == 0)
8930             argument_list[3].integer_reference=1;
8931           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8932             0 ? MagickTrue : MagickFalse);
8933           break;
8934         }
8935         case 50:  /* Segment */
8936         {
8937           ColorspaceType
8938             colorspace;
8939
8940           double
8941             cluster_threshold,
8942             smoothing_threshold;
8943
8944           MagickBooleanType
8945             verbose;
8946
8947           cluster_threshold=1.0;
8948           smoothing_threshold=1.5;
8949           colorspace=RGBColorspace;
8950           verbose=MagickFalse;
8951           if (attribute_flag[0] != 0)
8952             {
8953               flags=ParseGeometry(argument_list[0].string_reference,
8954                 &geometry_info);
8955               cluster_threshold=geometry_info.rho;
8956               if (flags & SigmaValue)
8957                 smoothing_threshold=geometry_info.sigma;
8958             }
8959           if (attribute_flag[1] != 0)
8960             cluster_threshold=argument_list[1].real_reference;
8961           if (attribute_flag[2] != 0)
8962             smoothing_threshold=argument_list[2].real_reference;
8963           if (attribute_flag[3] != 0)
8964             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8965           if (attribute_flag[4] != 0)
8966             verbose=argument_list[4].integer_reference != 0 ?
8967               MagickTrue : MagickFalse;
8968           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8969             smoothing_threshold);
8970           break;
8971         }
8972         case 51:  /* Signature */
8973         {
8974           (void) SignatureImage(image);
8975           break;
8976         }
8977         case 52:  /* Solarize */
8978         {
8979           geometry_info.rho=QuantumRange/2.0;
8980           if (attribute_flag[0] != 0)
8981             flags=ParseGeometry(argument_list[0].string_reference,
8982               &geometry_info);
8983           if (attribute_flag[1] != 0)
8984             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8985              QuantumRange);
8986           (void) SolarizeImage(image,geometry_info.rho);
8987           break;
8988         }
8989         case 53:  /* Sync */
8990         {
8991           (void) SyncImage(image);
8992           break;
8993         }
8994         case 54:  /* Texture */
8995         {
8996           if (attribute_flag[0] == 0)
8997             break;
8998           TextureImage(image,argument_list[0].image_reference);
8999           break;
9000         }
9001         case 55:  /* Evalute */
9002         {
9003           MagickEvaluateOperator
9004             op;
9005
9006           op=SetEvaluateOperator;
9007           if (attribute_flag[0] == MagickFalse)
9008             argument_list[0].real_reference=0.0;
9009           if (attribute_flag[1] != MagickFalse)
9010             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9011           if (attribute_flag[2] != MagickFalse)
9012             channel=(ChannelType) argument_list[2].integer_reference;
9013           (void) EvaluateImageChannel(image,channel,op,
9014             argument_list[0].real_reference,exception);
9015           break;
9016         }
9017         case 56:  /* Transparent */
9018         {
9019           double
9020             opacity;
9021
9022           MagickBooleanType
9023             invert;
9024
9025           MagickPixelPacket
9026             target;
9027
9028           (void) QueryMagickColor("none",&target,exception);
9029           if (attribute_flag[0] != 0)
9030             (void) QueryMagickColor(argument_list[0].string_reference,&target,
9031               exception);
9032           opacity=TransparentOpacity;
9033           if (attribute_flag[1] != 0)
9034             opacity=SiPrefixToDouble(argument_list[1].string_reference,
9035               QuantumRange);
9036           if (attribute_flag[2] != 0)
9037             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9038               QuantumRange);
9039           if (attribute_flag[3] == 0)
9040             argument_list[3].integer_reference=0;
9041           invert=MagickFalse;
9042           if (attribute_flag[3] != 0)
9043             invert=(MagickBooleanType) argument_list[3].integer_reference;
9044           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9045             invert);
9046           break;
9047         }
9048         case 57:  /* Threshold */
9049         {
9050           double
9051             threshold;
9052
9053           if (attribute_flag[0] == 0)
9054             argument_list[0].string_reference="50%";
9055           if (attribute_flag[1] != 0)
9056             channel=(ChannelType) argument_list[1].integer_reference;
9057           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9058             QuantumRange);
9059           (void) BilevelImageChannel(image,channel,threshold);
9060           break;
9061         }
9062         case 58:  /* Charcoal */
9063         {
9064           if (attribute_flag[0] != 0)
9065             {
9066               flags=ParseGeometry(argument_list[0].string_reference,
9067                 &geometry_info);
9068               if ((flags & SigmaValue) == 0)
9069                 geometry_info.sigma=1.0;
9070             }
9071           if (attribute_flag[1] != 0)
9072             geometry_info.rho=argument_list[1].real_reference;
9073           if (attribute_flag[2] != 0)
9074             geometry_info.sigma=argument_list[2].real_reference;
9075           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9076             exception);
9077           break;
9078         }
9079         case 59:  /* Trim */
9080         {
9081           if (attribute_flag[0] != 0)
9082             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9083               QuantumRange);
9084           image=TrimImage(image,exception);
9085           break;
9086         }
9087         case 60:  /* Wave */
9088         {
9089           if (attribute_flag[0] != 0)
9090             {
9091               flags=ParseGeometry(argument_list[0].string_reference,
9092                 &geometry_info);
9093               if ((flags & SigmaValue) == 0)
9094                 geometry_info.sigma=1.0;
9095             }
9096           if (attribute_flag[1] != 0)
9097             geometry_info.rho=argument_list[1].real_reference;
9098           if (attribute_flag[2] != 0)
9099             geometry_info.sigma=argument_list[2].real_reference;
9100           if (attribute_flag[3] != 0)
9101             image->interpolate=(InterpolatePixelMethod)
9102               argument_list[3].integer_reference;
9103           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9104             exception);
9105           break;
9106         }
9107         case 61:  /* Separate */
9108         {
9109           if (attribute_flag[0] != 0)
9110             channel=(ChannelType) argument_list[0].integer_reference;
9111           (void) SeparateImageChannel(image,channel);
9112           break;
9113         }
9114         case 63:  /* Stereo */
9115         {
9116           if (attribute_flag[0] == 0)
9117             {
9118               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9119                 PackageName);
9120               goto PerlException;
9121             }
9122           if (attribute_flag[1] != 0)
9123             geometry.x=argument_list[1].integer_reference;
9124           if (attribute_flag[2] != 0)
9125             geometry.y=argument_list[2].integer_reference;
9126           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9127             geometry.x,geometry.y,exception);
9128           break;
9129         }
9130         case 64:  /* Stegano */
9131         {
9132           if (attribute_flag[0] == 0)
9133             {
9134               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9135                 PackageName);
9136               goto PerlException;
9137             }
9138           if (attribute_flag[1] == 0)
9139             argument_list[1].integer_reference=0;
9140           image->offset=argument_list[1].integer_reference;
9141           image=SteganoImage(image,argument_list[0].image_reference,exception);
9142           break;
9143         }
9144         case 65:  /* Deconstruct */
9145         {
9146           image=DeconstructImages(image,exception);
9147           break;
9148         }
9149         case 66:  /* GaussianBlur */
9150         {
9151           if (attribute_flag[0] != 0)
9152             {
9153               flags=ParseGeometry(argument_list[0].string_reference,
9154                 &geometry_info);
9155               if ((flags & SigmaValue) == 0)
9156                 geometry_info.sigma=1.0;
9157             }
9158           if (attribute_flag[1] != 0)
9159             geometry_info.rho=argument_list[1].real_reference;
9160           if (attribute_flag[2] != 0)
9161             geometry_info.sigma=argument_list[2].real_reference;
9162           if (attribute_flag[3] != 0)
9163             channel=(ChannelType) argument_list[3].integer_reference;
9164           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9165             geometry_info.sigma,exception);
9166           break;
9167         }
9168         case 67:  /* Convolve */
9169         {
9170           AV
9171             *av;
9172
9173           double
9174             *kernel;
9175
9176           size_t
9177             order;
9178
9179           if (attribute_flag[0] == 0)
9180             break;
9181           if (attribute_flag[1] != 0)
9182             channel=(ChannelType) argument_list[1].integer_reference;
9183           if (attribute_flag[2] != 0)
9184             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9185               QuantumRange);
9186           av=(AV *) argument_list[0].array_reference;
9187           order=(size_t) sqrt(av_len(av)+1);
9188           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9189           if (kernel == (double *) NULL)
9190             {
9191               ThrowPerlException(exception,ResourceLimitFatalError,
9192                 "MemoryAllocationFailed",PackageName);
9193               goto PerlException;
9194             }
9195           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9196             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9197           for ( ; j < (ssize_t) (order*order); j++)
9198             kernel[j]=0.0;
9199           image=ConvolveImageChannel(image,channel,order,kernel,exception);
9200           kernel=(double *) RelinquishMagickMemory(kernel);
9201           break;
9202         }
9203         case 68:  /* Profile */
9204         {
9205           const char
9206             *name;
9207
9208           Image
9209             *profile_image;
9210
9211           ImageInfo
9212             *profile_info;
9213
9214           StringInfo
9215             *profile;
9216
9217           name="*";
9218           if (attribute_flag[0] != 0)
9219             name=argument_list[0].string_reference;
9220           if (attribute_flag[2] != 0)
9221             image->rendering_intent=(RenderingIntent)
9222               argument_list[2].integer_reference;
9223           if (attribute_flag[3] != 0)
9224             image->black_point_compensation=
9225               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9226           if (attribute_flag[1] != 0)
9227             {
9228               if (argument_list[1].length == 0)
9229                 {
9230                   /*
9231                     Remove a profile from the image.
9232                   */
9233                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9234                     MagickTrue);
9235                   break;
9236                 }
9237               /*
9238                 Associate user supplied profile with the image.
9239               */
9240               profile=AcquireStringInfo(argument_list[1].length);
9241               SetStringInfoDatum(profile,(const unsigned char *)
9242                 argument_list[1].string_reference);
9243               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9244                 (size_t) GetStringInfoLength(profile),MagickFalse);
9245               profile=DestroyStringInfo(profile);
9246               break;
9247             }
9248           /*
9249             Associate a profile with the image.
9250           */
9251           profile_info=
9252             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9253           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9254           profile_image=ReadImages(profile_info,&image->exception);
9255           if (profile_image == (Image *) NULL)
9256             break;
9257           ResetImageProfileIterator(profile_image);
9258           name=GetNextImageProfile(profile_image);
9259           while (name != (const char *) NULL)
9260           {
9261             const StringInfo
9262               *profile;
9263
9264             profile=GetImageProfile(profile_image,name);
9265             if (profile != (const StringInfo *) NULL)
9266               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9267                 (size_t) GetStringInfoLength(profile),MagickFalse);
9268             name=GetNextImageProfile(profile_image);
9269           }
9270           profile_image=DestroyImage(profile_image);
9271           profile_info=DestroyImageInfo(profile_info);
9272           break;
9273         }
9274         case 69:  /* UnsharpMask */
9275         {
9276           if (attribute_flag[0] != 0)
9277             {
9278               flags=ParseGeometry(argument_list[0].string_reference,
9279                 &geometry_info);
9280               if ((flags & SigmaValue) == 0)
9281                 geometry_info.sigma=1.0;
9282               if ((flags & XiValue) == 0)
9283                 geometry_info.xi=1.0;
9284               if ((flags & PsiValue) == 0)
9285                 geometry_info.psi=0.5;
9286             }
9287           if (attribute_flag[1] != 0)
9288             geometry_info.rho=argument_list[1].real_reference;
9289           if (attribute_flag[2] != 0)
9290             geometry_info.sigma=argument_list[2].real_reference;
9291           if (attribute_flag[3] != 0)
9292             geometry_info.xi=argument_list[3].real_reference;
9293           if (attribute_flag[4] != 0)
9294             geometry_info.psi=argument_list[4].real_reference;
9295           if (attribute_flag[5] != 0)
9296             channel=(ChannelType) argument_list[5].integer_reference;
9297           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9298             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9299           break;
9300         }
9301         case 70:  /* MotionBlur */
9302         {
9303           if (attribute_flag[0] != 0)
9304             {
9305               flags=ParseGeometry(argument_list[0].string_reference,
9306                 &geometry_info);
9307               if ((flags & SigmaValue) == 0)
9308                 geometry_info.sigma=1.0;
9309               if ((flags & XiValue) == 0)
9310                 geometry_info.xi=1.0;
9311             }
9312           if (attribute_flag[1] != 0)
9313             geometry_info.rho=argument_list[1].real_reference;
9314           if (attribute_flag[2] != 0)
9315             geometry_info.sigma=argument_list[2].real_reference;
9316           if (attribute_flag[3] != 0)
9317             geometry_info.xi=argument_list[3].real_reference;
9318           if (attribute_flag[4] != 0)
9319             channel=(ChannelType) argument_list[4].integer_reference;
9320           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9321             geometry_info.sigma,geometry_info.xi,exception);
9322           break;
9323         }
9324         case 71:  /* OrderedDither */
9325         {
9326           if (attribute_flag[0] == 0)
9327             argument_list[0].string_reference="o8x8";
9328           if (attribute_flag[1] != 0)
9329             channel=(ChannelType) argument_list[1].integer_reference;
9330           (void) OrderedPosterizeImageChannel(image,channel,
9331             argument_list[0].string_reference,exception);
9332           break;
9333         }
9334         case 72:  /* Shave */
9335         {
9336           if (attribute_flag[0] != 0)
9337             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9338               &geometry,exception);
9339           if (attribute_flag[1] != 0)
9340             geometry.width=argument_list[1].integer_reference;
9341           if (attribute_flag[2] != 0)
9342             geometry.height=argument_list[2].integer_reference;
9343           image=ShaveImage(image,&geometry,exception);
9344           break;
9345         }
9346         case 73:  /* Level */
9347         {
9348           double
9349             black_point,
9350             gamma,
9351             white_point;
9352
9353           black_point=0.0;
9354           white_point=(MagickRealType) image->columns*image->rows;
9355           gamma=1.0;
9356           if (attribute_flag[0] != 0)
9357             {
9358               flags=ParseGeometry(argument_list[0].string_reference,
9359                 &geometry_info);
9360               black_point=geometry_info.rho;
9361               if ((flags & SigmaValue) != 0)
9362                 white_point=geometry_info.sigma;
9363               if ((flags & XiValue) != 0)
9364                 gamma=geometry_info.xi;
9365               if ((flags & PercentValue) != 0)
9366                 {
9367                   black_point*=(double) (QuantumRange/100.0);
9368                   white_point*=(double) (QuantumRange/100.0);
9369                 }
9370               if ((flags & SigmaValue) == 0)
9371                 white_point=(double) QuantumRange-black_point;
9372             }
9373           if (attribute_flag[1] != 0)
9374             black_point=argument_list[1].real_reference;
9375           if (attribute_flag[2] != 0)
9376             white_point=argument_list[2].real_reference;
9377           if (attribute_flag[3] != 0)
9378             gamma=argument_list[3].real_reference;
9379           if (attribute_flag[4] != 0)
9380             channel=(ChannelType) argument_list[4].integer_reference;
9381           if (attribute_flag[5] != 0)
9382             {
9383               argument_list[0].real_reference=argument_list[5].real_reference;
9384               attribute_flag[0]=attribute_flag[5];
9385             }
9386           (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9387           break;
9388         }
9389         case 74:  /* Clip */
9390         {
9391           if (attribute_flag[0] == 0)
9392             argument_list[0].string_reference="#1";
9393           if (attribute_flag[1] == 0)
9394             argument_list[1].integer_reference=MagickTrue;
9395           (void) ClipImagePath(image,argument_list[0].string_reference,
9396             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9397           break;
9398         }
9399         case 75:  /* AffineTransform */
9400         {
9401           DrawInfo
9402             *draw_info;
9403
9404           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9405             (DrawInfo *) NULL);
9406           if (attribute_flag[0] != 0)
9407             {
9408               AV
9409                 *av;
9410
9411               av=(AV *) argument_list[0].array_reference;
9412               if ((av_len(av) != 3) && (av_len(av) != 5))
9413                 {
9414                   ThrowPerlException(exception,OptionError,
9415                     "affine matrix must have 4 or 6 elements",PackageName);
9416                   goto PerlException;
9417                 }
9418               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9419               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9420               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9421               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9422               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9423                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9424                 {
9425                   ThrowPerlException(exception,OptionError,
9426                     "affine matrix is singular",PackageName);
9427                    goto PerlException;
9428                 }
9429               if (av_len(av) == 5)
9430                 {
9431                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9432                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9433                 }
9434             }
9435           for (j=1; j < 6; j++)
9436           {
9437             if (attribute_flag[j] == 0)
9438               continue;
9439             value=argument_list[j].string_reference;
9440             angle=argument_list[j].real_reference;
9441             current=draw_info->affine;
9442             GetAffineMatrix(&affine);
9443             switch (j)
9444             {
9445               case 1:
9446               {
9447                 /*
9448                   Translate.
9449                 */
9450                 flags=ParseGeometry(value,&geometry_info);
9451                 affine.tx=geometry_info.xi;
9452                 affine.ty=geometry_info.psi;
9453                 if ((flags & PsiValue) == 0)
9454                   affine.ty=affine.tx;
9455                 break;
9456               }
9457               case 2:
9458               {
9459                 /*
9460                   Scale.
9461                 */
9462                 flags=ParseGeometry(value,&geometry_info);
9463                 affine.sx=geometry_info.rho;
9464                 affine.sy=geometry_info.sigma;
9465                 if ((flags & SigmaValue) == 0)
9466                   affine.sy=affine.sx;
9467                 break;
9468               }
9469               case 3:
9470               {
9471                 /*
9472                   Rotate.
9473                 */
9474                 if (angle == 0.0)
9475                   break;
9476                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9477                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9478                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9479                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9480                 break;
9481               }
9482               case 4:
9483               {
9484                 /*
9485                   SkewX.
9486                 */
9487                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9488                 break;
9489               }
9490               case 5:
9491               {
9492                 /*
9493                   SkewY.
9494                 */
9495                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9496                 break;
9497               }
9498             }
9499             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9500             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9501             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9502             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9503             draw_info->affine.tx=
9504               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9505             draw_info->affine.ty=
9506               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9507           }
9508           if (attribute_flag[6] != 0)
9509             image->interpolate=(InterpolatePixelMethod)
9510               argument_list[6].integer_reference;
9511           if (attribute_flag[7] != 0)
9512             QueryColorDatabase(argument_list[7].string_reference,
9513               &image->background_color,exception);
9514           image=AffineTransformImage(image,&draw_info->affine,exception);
9515           draw_info=DestroyDrawInfo(draw_info);
9516           break;
9517         }
9518         case 76:  /* Difference */
9519         {
9520           if (attribute_flag[0] == 0)
9521             {
9522               ThrowPerlException(exception,OptionError,
9523                 "ReferenceImageRequired",PackageName);
9524               goto PerlException;
9525             }
9526           if (attribute_flag[1] != 0)
9527             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9528               QuantumRange);
9529           (void) IsImagesEqual(image,argument_list[0].image_reference);
9530           break;
9531         }
9532         case 77:  /* AdaptiveThreshold */
9533         {
9534           if (attribute_flag[0] != 0)
9535             {
9536               flags=ParseGeometry(argument_list[0].string_reference,
9537                 &geometry_info);
9538               if ((flags & PercentValue) != 0)
9539                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9540             }
9541           if (attribute_flag[1] != 0)
9542             geometry_info.rho=argument_list[1].integer_reference;
9543           if (attribute_flag[2] != 0)
9544             geometry_info.sigma=argument_list[2].integer_reference;
9545           if (attribute_flag[3] != 0)
9546             geometry_info.xi=argument_list[3].integer_reference;;
9547           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9548             (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9549             exception);
9550           break;
9551         }
9552         case 78:  /* Resample */
9553         {
9554           size_t
9555             height,
9556             width;
9557
9558           if (attribute_flag[0] != 0)
9559             {
9560               flags=ParseGeometry(argument_list[0].string_reference,
9561                 &geometry_info);
9562               if ((flags & SigmaValue) == 0)
9563                 geometry_info.sigma=geometry_info.rho;
9564             }
9565           if (attribute_flag[1] != 0)
9566             geometry_info.rho=argument_list[1].real_reference;
9567           if (attribute_flag[2] != 0)
9568             geometry_info.sigma=argument_list[2].real_reference;
9569           if (attribute_flag[3] == 0)
9570             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9571           if (attribute_flag[4] == 0)
9572             SetImageArtifact(image,"filter:support",
9573               argument_list[4].string_reference);
9574           if (attribute_flag[5] != 0)
9575             argument_list[5].real_reference=1.0;
9576           width=(size_t) (geometry_info.rho*image->columns/
9577             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9578           height=(size_t) (geometry_info.sigma*image->rows/
9579             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9580           image=ResizeImage(image,width,height,(FilterTypes)
9581             argument_list[3].integer_reference,argument_list[5].real_reference,
9582             exception);
9583           if (image != (Image *) NULL)
9584             {
9585               image->x_resolution=geometry_info.rho;
9586               image->y_resolution=geometry_info.sigma;
9587             }
9588           break;
9589         }
9590         case 79:  /* Describe */
9591         {
9592           if (attribute_flag[0] == 0)
9593             argument_list[0].file_reference=(FILE *) NULL;
9594           if (attribute_flag[1] != 0)
9595             (void) SetImageArtifact(image,"identify:features",
9596               argument_list[1].string_reference);
9597           (void) IdentifyImage(image,argument_list[0].file_reference,
9598             MagickTrue);
9599           break;
9600         }
9601         case 80:  /* BlackThreshold */
9602         {
9603           if (attribute_flag[0] == 0)
9604             argument_list[0].string_reference="50%";
9605           if (attribute_flag[2] != 0)
9606             channel=(ChannelType) argument_list[2].integer_reference;
9607           BlackThresholdImageChannel(image,channel,
9608             argument_list[0].string_reference,exception);
9609           break;
9610         }
9611         case 81:  /* WhiteThreshold */
9612         {
9613           if (attribute_flag[0] == 0)
9614             argument_list[0].string_reference="50%";
9615           if (attribute_flag[2] != 0)
9616             channel=(ChannelType) argument_list[2].integer_reference;
9617           WhiteThresholdImageChannel(image,channel,
9618             argument_list[0].string_reference,exception);
9619           break;
9620         }
9621         case 82:  /* RadialBlur */
9622         {
9623           if (attribute_flag[0] != 0)
9624             {
9625               flags=ParseGeometry(argument_list[0].string_reference,
9626                 &geometry_info);
9627               if ((flags & SigmaValue) == 0)
9628                 geometry_info.sigma=1.0;
9629             }
9630           if (attribute_flag[1] != 0)
9631             geometry_info.rho=argument_list[1].real_reference;
9632           if (attribute_flag[2] != 0)
9633             channel=(ChannelType) argument_list[2].integer_reference;
9634           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9635             exception);
9636           break;
9637         }
9638         case 83:  /* Thumbnail */
9639         {
9640           if (attribute_flag[0] != 0)
9641             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9642               &geometry,exception);
9643           if (attribute_flag[1] != 0)
9644             geometry.width=argument_list[1].integer_reference;
9645           if (attribute_flag[2] != 0)
9646             geometry.height=argument_list[2].integer_reference;
9647           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9648           break;
9649         }
9650         case 84:  /* Strip */
9651         {
9652           (void) StripImage(image);
9653           break;
9654         }
9655         case 85:  /* Tint */
9656         {
9657           PixelPacket
9658             target;
9659
9660           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9661           if (attribute_flag[0] != 0)
9662             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9663               exception);
9664           if (attribute_flag[1] == 0)
9665             argument_list[1].string_reference="100";
9666           image=TintImage(image,argument_list[1].string_reference,target,
9667             exception);
9668           break;
9669         }
9670         case 86:  /* Channel */
9671         {
9672           if (attribute_flag[0] != 0)
9673             channel=(ChannelType) argument_list[0].integer_reference;
9674           (void) SeparateImageChannel(image,channel);
9675           break;
9676         }
9677         case 87:  /* Splice */
9678         {
9679           if (attribute_flag[0] != 0)
9680             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9681               &geometry,exception);
9682           if (attribute_flag[1] != 0)
9683             geometry.width=argument_list[1].integer_reference;
9684           if (attribute_flag[2] != 0)
9685             geometry.height=argument_list[2].integer_reference;
9686           if (attribute_flag[3] != 0)
9687             geometry.x=argument_list[3].integer_reference;
9688           if (attribute_flag[4] != 0)
9689             geometry.y=argument_list[4].integer_reference;
9690           if (attribute_flag[5] != 0)
9691             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9692               QuantumRange);
9693           if (attribute_flag[6] != 0)
9694             (void) QueryColorDatabase(argument_list[6].string_reference,
9695               &image->background_color,exception);
9696           if (attribute_flag[7] != 0)
9697             image->gravity=(GravityType) argument_list[7].integer_reference;
9698           image=SpliceImage(image,&geometry,exception);
9699           break;
9700         }
9701         case 88:  /* Posterize */
9702         {
9703           if (attribute_flag[0] == 0)
9704             argument_list[0].integer_reference=3;
9705           if (attribute_flag[1] == 0)
9706             argument_list[1].integer_reference=0;
9707           (void) PosterizeImage(image,argument_list[0].integer_reference,
9708             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9709           break;
9710         }
9711         case 89:  /* Shadow */
9712         {
9713           if (attribute_flag[0] != 0)
9714             {
9715               flags=ParseGeometry(argument_list[0].string_reference,
9716                 &geometry_info);
9717               if ((flags & SigmaValue) == 0)
9718                 geometry_info.sigma=1.0;
9719               if ((flags & XiValue) == 0)
9720                 geometry_info.xi=4.0;
9721               if ((flags & PsiValue) == 0)
9722                 geometry_info.psi=4.0;
9723             }
9724           if (attribute_flag[1] != 0)
9725             geometry_info.rho=argument_list[1].real_reference;
9726           if (attribute_flag[2] != 0)
9727             geometry_info.sigma=argument_list[2].real_reference;
9728           if (attribute_flag[3] != 0)
9729             geometry_info.xi=argument_list[3].integer_reference;
9730           if (attribute_flag[4] != 0)
9731             geometry_info.psi=argument_list[4].integer_reference;
9732           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9733             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9734             0.5),exception);
9735           break;
9736         }
9737         case 90:  /* Identify */
9738         {
9739           if (attribute_flag[0] == 0)
9740             argument_list[0].file_reference=(FILE *) NULL;
9741           if (attribute_flag[1] != 0)
9742             (void) SetImageArtifact(image,"identify:features",
9743               argument_list[1].string_reference);
9744           if ((attribute_flag[2] != 0) &&
9745               (argument_list[2].integer_reference != 0))
9746             (void) SetImageArtifact(image,"identify:unique","true");
9747           (void) IdentifyImage(image,argument_list[0].file_reference,
9748             MagickTrue);
9749           break;
9750         }
9751         case 91:  /* SepiaTone */
9752         {
9753           if (attribute_flag[0] == 0)
9754             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9755           image=SepiaToneImage(image,argument_list[0].real_reference,
9756             exception);
9757           break;
9758         }
9759         case 92:  /* SigmoidalContrast */
9760         {
9761           MagickBooleanType
9762             sharpen;
9763
9764           if (attribute_flag[0] != 0)
9765             {
9766               flags=ParseGeometry(argument_list[0].string_reference,
9767                 &geometry_info);
9768               if ((flags & SigmaValue) == 0)
9769                 geometry_info.sigma=QuantumRange/2.0;
9770               if ((flags & PercentValue) != 0)
9771                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9772             }
9773           if (attribute_flag[1] != 0)
9774             geometry_info.rho=argument_list[1].real_reference;
9775           if (attribute_flag[2] != 0)
9776             geometry_info.sigma=argument_list[2].real_reference;
9777           if (attribute_flag[3] != 0)
9778             channel=(ChannelType) argument_list[3].integer_reference;
9779           sharpen=MagickTrue;
9780           if (attribute_flag[4] != 0)
9781             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9782               MagickFalse;
9783           (void) SigmoidalContrastImageChannel(image,channel,sharpen,
9784             geometry_info.rho,geometry_info.sigma);
9785           break;
9786         }
9787         case 93:  /* Extent */
9788         {
9789           if (attribute_flag[7] != 0)
9790             image->gravity=(GravityType) argument_list[7].integer_reference;
9791           if (attribute_flag[0] != 0)
9792             {
9793               int
9794                 flags;
9795
9796               flags=ParseGravityGeometry(image,
9797                 argument_list[0].string_reference,&geometry,exception);
9798               (void) flags;
9799               if (geometry.width == 0)
9800                 geometry.width=image->columns;
9801               if (geometry.height == 0)
9802                 geometry.height=image->rows;
9803             }
9804           if (attribute_flag[1] != 0)
9805             geometry.width=argument_list[1].integer_reference;
9806           if (attribute_flag[2] != 0)
9807             geometry.height=argument_list[2].integer_reference;
9808           if (attribute_flag[3] != 0)
9809             geometry.x=argument_list[3].integer_reference;
9810           if (attribute_flag[4] != 0)
9811             geometry.y=argument_list[4].integer_reference;
9812           if (attribute_flag[5] != 0)
9813             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9814               QuantumRange);
9815           if (attribute_flag[6] != 0)
9816             (void) QueryColorDatabase(argument_list[6].string_reference,
9817               &image->background_color,exception);
9818           image=ExtentImage(image,&geometry,exception);
9819           break;
9820         }
9821         case 94:  /* Vignette */
9822         {
9823           if (attribute_flag[0] != 0)
9824             {
9825               flags=ParseGeometry(argument_list[0].string_reference,
9826                 &geometry_info);
9827               if ((flags & SigmaValue) == 0)
9828                 geometry_info.sigma=1.0;
9829               if ((flags & XiValue) == 0)
9830                 geometry_info.xi=0.1*image->columns;
9831               if ((flags & PsiValue) == 0)
9832                 geometry_info.psi=0.1*image->rows;
9833             }
9834           if (attribute_flag[1] != 0)
9835             geometry_info.rho=argument_list[1].real_reference;
9836           if (attribute_flag[2] != 0)
9837             geometry_info.sigma=argument_list[2].real_reference;
9838           if (attribute_flag[3] != 0)
9839             geometry_info.xi=argument_list[3].integer_reference;
9840           if (attribute_flag[4] != 0)
9841             geometry_info.psi=argument_list[4].integer_reference;
9842           if (attribute_flag[5] != 0)
9843             (void) QueryColorDatabase(argument_list[5].string_reference,
9844               &image->background_color,exception);
9845           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9846             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9847             0.5),exception);
9848           break;
9849         }
9850         case 95:  /* ContrastStretch */
9851         {
9852           double
9853             black_point,
9854             white_point;
9855
9856           black_point=0.0;
9857           white_point=(MagickRealType) image->columns*image->rows;
9858           if (attribute_flag[0] != 0)
9859             {
9860               flags=ParseGeometry(argument_list[0].string_reference,
9861                 &geometry_info);
9862               black_point=geometry_info.rho;
9863               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9864                 black_point;
9865               if ((flags & PercentValue) != 0)
9866                 {
9867                   black_point*=(double) image->columns*image->rows/100.0;
9868                   white_point*=(double) image->columns*image->rows/100.0;
9869                 }
9870               white_point=(MagickRealType) image->columns*image->rows-
9871                 white_point;
9872             }
9873           if (attribute_flag[1] != 0)
9874             black_point=argument_list[1].real_reference;
9875           if (attribute_flag[2] != 0)
9876             white_point=argument_list[2].real_reference;
9877           if (attribute_flag[4] != 0)
9878             channel=(ChannelType) argument_list[4].integer_reference;
9879           (void) ContrastStretchImageChannel(image,channel,black_point,
9880             white_point);
9881           break;
9882         }
9883         case 96:  /* Sans0 */
9884         {
9885           break;
9886         }
9887         case 97:  /* Sans1 */
9888         {
9889           break;
9890         }
9891         case 98:  /* AdaptiveSharpen */
9892         {
9893           if (attribute_flag[0] != 0)
9894             {
9895               flags=ParseGeometry(argument_list[0].string_reference,
9896                 &geometry_info);
9897               if ((flags & SigmaValue) == 0)
9898                 geometry_info.sigma=1.0;
9899             }
9900           if (attribute_flag[1] != 0)
9901             geometry_info.rho=argument_list[1].real_reference;
9902           if (attribute_flag[2] != 0)
9903             geometry_info.sigma=argument_list[2].real_reference;
9904           if (attribute_flag[3] != 0)
9905             channel=(ChannelType) argument_list[3].integer_reference;
9906           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9907             geometry_info.sigma,exception);
9908           break;
9909         }
9910         case 99:  /* Transpose */
9911         {
9912           image=TransposeImage(image,exception);
9913           break;
9914         }
9915         case 100:  /* Tranverse */
9916         {
9917           image=TransverseImage(image,exception);
9918           break;
9919         }
9920         case 101:  /* AutoOrient */
9921         {
9922           switch (image->orientation)
9923           {
9924             case TopRightOrientation:
9925             {
9926               image=FlopImage(image,exception);
9927               break;
9928             }
9929             case BottomRightOrientation:
9930             {
9931               image=RotateImage(image,180.0,exception);
9932               break;
9933             }
9934             case BottomLeftOrientation:
9935             {
9936               image=FlipImage(image,exception);
9937               break;
9938             }
9939             case LeftTopOrientation:
9940             {
9941               image=TransposeImage(image,exception);
9942               break;
9943             }
9944             case RightTopOrientation:
9945             {
9946               image=RotateImage(image,90.0,exception);
9947               break;
9948             }
9949             case RightBottomOrientation:
9950             {
9951               image=TransverseImage(image,exception);
9952               break;
9953             }
9954             case LeftBottomOrientation:
9955             {
9956               image=RotateImage(image,270.0,exception);
9957               break;
9958             }
9959             default:
9960               break;
9961           }
9962           break;
9963         }
9964         case 102:  /* AdaptiveBlur */
9965         {
9966           if (attribute_flag[0] != 0)
9967             {
9968               flags=ParseGeometry(argument_list[0].string_reference,
9969                 &geometry_info);
9970               if ((flags & SigmaValue) == 0)
9971                 geometry_info.sigma=1.0;
9972             }
9973           if (attribute_flag[1] != 0)
9974             geometry_info.rho=argument_list[1].real_reference;
9975           if (attribute_flag[2] != 0)
9976             geometry_info.sigma=argument_list[2].real_reference;
9977           if (attribute_flag[3] != 0)
9978             channel=(ChannelType) argument_list[3].integer_reference;
9979           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
9980             geometry_info.sigma,exception);
9981           break;
9982         }
9983         case 103:  /* Sketch */
9984         {
9985           if (attribute_flag[0] != 0)
9986             {
9987               flags=ParseGeometry(argument_list[0].string_reference,
9988                 &geometry_info);
9989               if ((flags & SigmaValue) == 0)
9990                 geometry_info.sigma=1.0;
9991               if ((flags & XiValue) == 0)
9992                 geometry_info.xi=1.0;
9993             }
9994           if (attribute_flag[1] != 0)
9995             geometry_info.rho=argument_list[1].real_reference;
9996           if (attribute_flag[2] != 0)
9997             geometry_info.sigma=argument_list[2].real_reference;
9998           if (attribute_flag[3] != 0)
9999             geometry_info.xi=argument_list[3].real_reference;
10000           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10001             geometry_info.xi,exception);
10002           break;
10003         }
10004         case 104:  /* UniqueColors */
10005         {
10006           image=UniqueImageColors(image,exception);
10007           break;
10008         }
10009         case 105:  /* AdaptiveResize */
10010         {
10011           if (attribute_flag[0] != 0)
10012             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10013               &geometry,exception);
10014           if (attribute_flag[1] != 0)
10015             geometry.width=argument_list[1].integer_reference;
10016           if (attribute_flag[2] != 0)
10017             geometry.height=argument_list[2].integer_reference;
10018           if (attribute_flag[3] != 0)
10019             image->filter=(FilterTypes) argument_list[4].integer_reference;
10020           if (attribute_flag[4] != 0)
10021             SetImageArtifact(image,"filter:support",
10022               argument_list[4].string_reference);
10023           if (attribute_flag[5] != 0)
10024             image->blur=argument_list[5].real_reference;
10025           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10026             exception);
10027           break;
10028         }
10029         case 106:  /* ClipMask */
10030         {
10031           if (attribute_flag[0] == 0)
10032             {
10033               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10034                 PackageName);
10035               goto PerlException;
10036             }
10037           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10038             MagickTrue,exception);
10039           (void) NegateImage(image->clip_mask,MagickFalse);
10040           break;
10041         }
10042         case 107:  /* LinearStretch */
10043         {
10044            double
10045              black_point,
10046              white_point;
10047
10048            black_point=0.0;
10049            white_point=(MagickRealType) image->columns*image->rows;
10050            if (attribute_flag[0] != 0)
10051              {
10052                flags=ParseGeometry(argument_list[0].string_reference,
10053                  &geometry_info);
10054                if ((flags & SigmaValue) != 0)
10055                   white_point=geometry_info.sigma;
10056                if ((flags & PercentValue) != 0)
10057                  {
10058                    black_point*=(double) image->columns*image->rows/100.0;
10059                    white_point*=(double) image->columns*image->rows/100.0;
10060                  }
10061                if ((flags & SigmaValue) == 0)
10062                  white_point=(double) image->columns*image->rows-black_point;
10063              }
10064           if (attribute_flag[1] != 0)
10065             black_point=argument_list[1].real_reference;
10066           if (attribute_flag[2] != 0)
10067             white_point=argument_list[2].real_reference;
10068           (void) LinearStretchImage(image,black_point,white_point);
10069           break;
10070         }
10071         case 109:  /* Mask */
10072         {
10073           if (attribute_flag[0] == 0)
10074             {
10075               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10076                 PackageName);
10077               goto PerlException;
10078             }
10079           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10080             MagickTrue,exception);
10081           (void) NegateImage(image->mask,MagickFalse);
10082           break;
10083         }
10084         case 110:  /* Polaroid */
10085         {
10086           DrawInfo
10087             *draw_info;
10088
10089           double
10090             angle;
10091
10092           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10093             (DrawInfo *) NULL);
10094           if (attribute_flag[0] != 0)
10095             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10096               info ? info->image_info : (ImageInfo *) NULL,image,
10097               argument_list[0].string_reference));
10098           angle=0.0;
10099           if (attribute_flag[1] != 0)
10100             angle=argument_list[1].real_reference;
10101           if (attribute_flag[2] != 0)
10102             (void) CloneString(&draw_info->font,
10103               argument_list[2].string_reference);
10104           if (attribute_flag[3] != 0)
10105             (void) QueryColorDatabase(argument_list[3].string_reference,
10106               &draw_info->stroke,exception);
10107           if (attribute_flag[4] != 0)
10108             (void) QueryColorDatabase(argument_list[4].string_reference,
10109               &draw_info->fill,exception);
10110           if (attribute_flag[5] != 0)
10111             draw_info->stroke_width=argument_list[5].real_reference;
10112           if (attribute_flag[6] != 0)
10113             draw_info->pointsize=argument_list[6].real_reference;
10114           if (attribute_flag[7] != 0)
10115             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10116           if (attribute_flag[8] != 0)
10117             (void) QueryColorDatabase(argument_list[8].string_reference,
10118               &image->background_color,exception);
10119           image=PolaroidImage(image,draw_info,angle,exception);
10120           draw_info=DestroyDrawInfo(draw_info);
10121           break;
10122         }
10123         case 111:  /* FloodfillPaint */
10124         {
10125           DrawInfo
10126             *draw_info;
10127
10128           MagickBooleanType
10129             invert;
10130
10131           MagickPixelPacket
10132             target;
10133
10134           draw_info=CloneDrawInfo(info ? info->image_info :
10135             (ImageInfo *) NULL,(DrawInfo *) NULL);
10136           if (attribute_flag[0] != 0)
10137             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10138               &geometry,exception);
10139           if (attribute_flag[1] != 0)
10140             geometry.x=argument_list[1].integer_reference;
10141           if (attribute_flag[2] != 0)
10142             geometry.y=argument_list[2].integer_reference;
10143           if (attribute_flag[3] != 0)
10144             (void) QueryColorDatabase(argument_list[3].string_reference,
10145               &draw_info->fill,exception);
10146           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10147             exception);
10148           if (attribute_flag[4] != 0)
10149             QueryMagickColor(argument_list[4].string_reference,&target,
10150               exception);
10151           if (attribute_flag[5] != 0)
10152             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10153               QuantumRange);
10154           if (attribute_flag[6] != 0)
10155             channel=(ChannelType) argument_list[6].integer_reference;
10156           invert=MagickFalse;
10157           if (attribute_flag[7] != 0)
10158             invert=(MagickBooleanType) argument_list[7].integer_reference;
10159           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10160             geometry.y,invert);
10161           draw_info=DestroyDrawInfo(draw_info);
10162           break;
10163         }
10164         case 112:  /* Distort */
10165         {
10166           AV
10167             *av;
10168
10169           double
10170             *coordinates;
10171
10172           DistortImageMethod
10173             method;
10174
10175           size_t
10176             number_coordinates;
10177
10178           VirtualPixelMethod
10179             virtual_pixel;
10180
10181           if (attribute_flag[0] == 0)
10182             break;
10183           method=UndefinedDistortion;
10184           if (attribute_flag[1] != 0)
10185             method=(DistortImageMethod) argument_list[1].integer_reference;
10186           av=(AV *) argument_list[0].array_reference;
10187           number_coordinates=(size_t) av_len(av)+1;
10188           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10189             sizeof(*coordinates));
10190           if (coordinates == (double *) NULL)
10191             {
10192               ThrowPerlException(exception,ResourceLimitFatalError,
10193                 "MemoryAllocationFailed",PackageName);
10194               goto PerlException;
10195             }
10196           for (j=0; j < (ssize_t) number_coordinates; j++)
10197             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10198           virtual_pixel=UndefinedVirtualPixelMethod;
10199           if (attribute_flag[2] != 0)
10200             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10201               argument_list[2].integer_reference);
10202           image=DistortImage(image,method,number_coordinates,coordinates,
10203             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10204             exception);
10205           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10206             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10207           coordinates=(double *) RelinquishMagickMemory(coordinates);
10208           break;
10209         }
10210         case 113:  /* Clut */
10211         {
10212           if (attribute_flag[0] == 0)
10213             {
10214               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10215                 PackageName);
10216               goto PerlException;
10217             }
10218           if (attribute_flag[1] != 0)
10219             channel=(ChannelType) argument_list[1].integer_reference;
10220           (void) ClutImageChannel(image,channel,
10221             argument_list[0].image_reference);
10222           break;
10223         }
10224         case 114:  /* LiquidRescale */
10225         {
10226           if (attribute_flag[0] != 0)
10227             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10228               &geometry,exception);
10229           if (attribute_flag[1] != 0)
10230             geometry.width=argument_list[1].integer_reference;
10231           if (attribute_flag[2] != 0)
10232             geometry.height=argument_list[2].integer_reference;
10233           if (attribute_flag[3] == 0)
10234             argument_list[3].real_reference=1.0;
10235           if (attribute_flag[4] == 0)
10236             argument_list[4].real_reference=0.0;
10237           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10238             argument_list[3].real_reference,argument_list[4].real_reference,
10239             exception);
10240           break;
10241         }
10242         case 115:  /* EncipherImage */
10243         {
10244           (void) EncipherImage(image,argument_list[0].string_reference,
10245             exception);
10246           break;
10247         }
10248         case 116:  /* DecipherImage */
10249         {
10250           (void) DecipherImage(image,argument_list[0].string_reference,
10251             exception);
10252           break;
10253         }
10254         case 117:  /* Deskew */
10255         {
10256           geometry_info.rho=QuantumRange/2.0;
10257           if (attribute_flag[0] != 0)
10258             flags=ParseGeometry(argument_list[0].string_reference,
10259               &geometry_info);
10260           if (attribute_flag[1] != 0)
10261             geometry_info.rho=SiPrefixToDouble(
10262               argument_list[1].string_reference,QuantumRange);
10263           image=DeskewImage(image,geometry_info.rho,exception);
10264           break;
10265         }
10266         case 118:  /* Remap */
10267         {
10268           QuantizeInfo
10269             *quantize_info;
10270
10271           if (attribute_flag[0] == 0)
10272             {
10273               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10274                 PackageName);
10275               goto PerlException;
10276             }
10277           quantize_info=AcquireQuantizeInfo(info->image_info);
10278           if (attribute_flag[1] != 0)
10279             quantize_info->dither=(MagickBooleanType)
10280               argument_list[1].integer_reference;
10281           if (attribute_flag[2] != 0)
10282             quantize_info->dither_method=(DitherMethod)
10283               argument_list[2].integer_reference;
10284           (void) RemapImages(quantize_info,image,
10285             argument_list[0].image_reference);
10286           quantize_info=DestroyQuantizeInfo(quantize_info);
10287           break;
10288         }
10289         case 119:  /* SparseColor */
10290         {
10291           AV
10292             *av;
10293
10294           double
10295             *coordinates;
10296
10297           SparseColorMethod
10298             method;
10299
10300           size_t
10301             number_coordinates;
10302
10303           VirtualPixelMethod
10304             virtual_pixel;
10305
10306           if (attribute_flag[0] == 0)
10307             break;
10308           method=UndefinedColorInterpolate;
10309           if (attribute_flag[1] != 0)
10310             method=(SparseColorMethod) argument_list[1].integer_reference;
10311           av=(AV *) argument_list[0].array_reference;
10312           number_coordinates=(size_t) av_len(av)+1;
10313           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10314             sizeof(*coordinates));
10315           if (coordinates == (double *) NULL)
10316             {
10317               ThrowPerlException(exception,ResourceLimitFatalError,
10318                 "MemoryAllocationFailed",PackageName);
10319               goto PerlException;
10320             }
10321           for (j=0; j < (ssize_t) number_coordinates; j++)
10322             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10323           virtual_pixel=UndefinedVirtualPixelMethod;
10324           if (attribute_flag[2] != 0)
10325             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10326               argument_list[2].integer_reference);
10327           if (attribute_flag[3] != 0)
10328             channel=(ChannelType) argument_list[3].integer_reference;
10329           image=SparseColorImage(image,channel,method,number_coordinates,
10330             coordinates,exception);
10331           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10332             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10333           coordinates=(double *) RelinquishMagickMemory(coordinates);
10334           break;
10335         }
10336         case 120:  /* Function */
10337         {
10338           AV
10339             *av;
10340
10341           double
10342             *parameters;
10343
10344           MagickFunction
10345             function;
10346
10347           size_t
10348             number_parameters;
10349
10350           VirtualPixelMethod
10351             virtual_pixel;
10352
10353           if (attribute_flag[0] == 0)
10354             break;
10355           function=UndefinedFunction;
10356           if (attribute_flag[1] != 0)
10357             function=(MagickFunction) argument_list[1].integer_reference;
10358           av=(AV *) argument_list[0].array_reference;
10359           number_parameters=(size_t) av_len(av)+1;
10360           parameters=(double *) AcquireQuantumMemory(number_parameters,
10361             sizeof(*parameters));
10362           if (parameters == (double *) NULL)
10363             {
10364               ThrowPerlException(exception,ResourceLimitFatalError,
10365                 "MemoryAllocationFailed",PackageName);
10366               goto PerlException;
10367             }
10368           for (j=0; j < (ssize_t) number_parameters; j++)
10369             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10370           virtual_pixel=UndefinedVirtualPixelMethod;
10371           if (attribute_flag[2] != 0)
10372             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10373               argument_list[2].integer_reference);
10374           (void) FunctionImage(image,function,number_parameters,parameters,
10375             exception);
10376           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10377             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10378           parameters=(double *) RelinquishMagickMemory(parameters);
10379           break;
10380         }
10381         case 121:  /* SelectiveBlur */
10382         {
10383           if (attribute_flag[0] != 0)
10384             {
10385               flags=ParseGeometry(argument_list[0].string_reference,
10386                 &geometry_info);
10387               if ((flags & SigmaValue) == 0)
10388                 geometry_info.sigma=1.0;
10389               if ((flags & PercentValue) != 0)
10390                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10391             }
10392           if (attribute_flag[1] != 0)
10393             geometry_info.rho=argument_list[1].real_reference;
10394           if (attribute_flag[2] != 0)
10395             geometry_info.sigma=argument_list[2].real_reference;
10396           if (attribute_flag[3] != 0)
10397             geometry_info.xi=argument_list[3].integer_reference;;
10398           if (attribute_flag[4] != 0)
10399             channel=(ChannelType) argument_list[4].integer_reference;
10400           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10401             geometry_info.sigma,geometry_info.xi,exception);
10402           break;
10403         }
10404         case 122:  /* HaldClut */
10405         {
10406           if (attribute_flag[0] == 0)
10407             {
10408               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10409                 PackageName);
10410               goto PerlException;
10411             }
10412           if (attribute_flag[1] != 0)
10413             channel=(ChannelType) argument_list[1].integer_reference;
10414           (void) HaldClutImageChannel(image,channel,
10415             argument_list[0].image_reference);
10416           break;
10417         }
10418         case 123:  /* BlueShift */
10419         {
10420           if (attribute_flag[0] != 0)
10421             (void) ParseGeometry(argument_list[0].string_reference,
10422               &geometry_info);
10423           image=BlueShiftImage(image,geometry_info.rho,exception);
10424           break;
10425         }
10426         case 124:  /* ForwardFourierTransformImage */
10427         {
10428           image=ForwardFourierTransformImage(image,
10429             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10430             exception);
10431           break;
10432         }
10433         case 125:  /* InverseFourierTransformImage */
10434         {
10435           image=InverseFourierTransformImage(image,image->next,
10436             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10437             exception);
10438           break;
10439         }
10440         case 126:  /* ColorDecisionList */
10441         {
10442           if (attribute_flag[0] == 0)
10443             argument_list[0].string_reference=(char *) NULL;
10444           (void) ColorDecisionListImage(image,
10445             argument_list[0].string_reference);
10446           break;
10447         }
10448         case 127:  /* AutoGamma */
10449         {
10450           if (attribute_flag[0] != 0)
10451             channel=(ChannelType) argument_list[0].integer_reference;
10452           (void) AutoGammaImageChannel(image,channel);
10453           break;
10454         }
10455         case 128:  /* AutoLevel */
10456         {
10457           if (attribute_flag[0] != 0)
10458             channel=(ChannelType) argument_list[0].integer_reference;
10459           (void) AutoLevelImageChannel(image,channel);
10460           break;
10461         }
10462         case 129:  /* LevelColors */
10463         {
10464           MagickPixelPacket
10465             black_point,
10466             white_point;
10467
10468           (void) QueryMagickColor("#000000",&black_point,exception);
10469           (void) QueryMagickColor("#ffffff",&white_point,exception);
10470           if (attribute_flag[1] != 0)
10471              (void) QueryMagickColor(argument_list[1].string_reference,
10472                &black_point,exception);
10473           if (attribute_flag[2] != 0)
10474              (void) QueryMagickColor(argument_list[2].string_reference,
10475                &white_point,exception);
10476           if (attribute_flag[3] != 0)
10477             channel=(ChannelType) argument_list[3].integer_reference;
10478           (void) LevelColorsImageChannel(image,channel,&black_point,
10479             &white_point,argument_list[0].integer_reference != 0 ? MagickTrue :
10480             MagickFalse);
10481           break;
10482         }
10483         case 130:  /* Clamp */
10484         {
10485           if (attribute_flag[0] != 0)
10486             channel=(ChannelType) argument_list[0].integer_reference;
10487           (void) ClampImageChannel(image,channel);
10488           break;
10489         }
10490         case 131:  /* Filter */
10491         {
10492           KernelInfo
10493             *kernel;
10494
10495           if (attribute_flag[0] == 0)
10496             break;
10497           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10498           if (kernel == (KernelInfo *) NULL)
10499             break;
10500           if (attribute_flag[1] != 0)
10501             channel=(ChannelType) argument_list[1].integer_reference;
10502           if (attribute_flag[2] != 0)
10503             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10504               QuantumRange);
10505           image=FilterImageChannel(image,channel,kernel,exception);
10506           kernel=DestroyKernelInfo(kernel);
10507           break;
10508         }
10509         case 132:  /* BrightnessContrast */
10510         {
10511           double
10512             brightness,
10513             contrast;
10514
10515           brightness=0.0;
10516           contrast=0.0;
10517           if (attribute_flag[0] != 0)
10518             {
10519               flags=ParseGeometry(argument_list[0].string_reference,
10520                 &geometry_info);
10521               brightness=geometry_info.rho;
10522               if ((flags & SigmaValue) == 0)
10523                 contrast=geometry_info.sigma;
10524             }
10525           if (attribute_flag[1] != 0)
10526             brightness=argument_list[1].real_reference;
10527           if (attribute_flag[2] != 0)
10528             contrast=argument_list[2].real_reference;
10529           if (attribute_flag[4] != 0)
10530             channel=(ChannelType) argument_list[4].integer_reference;
10531           (void) BrightnessContrastImageChannel(image,channel,brightness,
10532             contrast);
10533           break;
10534         }
10535         case 133:  /* Morphology */
10536         {
10537           KernelInfo
10538             *kernel;
10539
10540           MorphologyMethod
10541             method;
10542
10543           ssize_t
10544             iterations;
10545
10546           if (attribute_flag[0] == 0)
10547             break;
10548           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10549           if (kernel == (KernelInfo *) NULL)
10550             break;
10551           if (attribute_flag[1] != 0)
10552             channel=(ChannelType) argument_list[1].integer_reference;
10553           method=UndefinedMorphology;
10554           if (attribute_flag[2] != 0)
10555             method=argument_list[2].integer_reference;
10556           iterations=1;
10557           if (attribute_flag[3] != 0)
10558             iterations=argument_list[4].integer_reference;
10559           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10560             exception);
10561           kernel=DestroyKernelInfo(kernel);
10562           break;
10563         }
10564         case 108:  /* Recolor */
10565         case 134:  /* ColorMatrix */
10566         {
10567           AV
10568             *av;
10569
10570           double
10571             *color_matrix;
10572
10573           KernelInfo
10574             *kernel_info;
10575
10576           size_t
10577             order;
10578
10579           if (attribute_flag[0] == 0)
10580             break;
10581           av=(AV *) argument_list[0].array_reference;
10582           order=(size_t) sqrt(av_len(av)+1);
10583           color_matrix=(double *) AcquireQuantumMemory(order,order*
10584             sizeof(*color_matrix));
10585           if (color_matrix == (double *) NULL)
10586             {
10587               ThrowPerlException(exception,ResourceLimitFatalError,
10588                 "MemoryAllocationFailed",PackageName);
10589               goto PerlException;
10590            }
10591           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10592             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10593           for ( ; j < (ssize_t) (order*order); j++)
10594             color_matrix[j]=0.0;
10595           kernel_info=AcquireKernelInfo("1");
10596           if (kernel_info == (KernelInfo *) NULL)
10597             break;
10598           kernel_info->width=order;
10599           kernel_info->height=order;
10600           kernel_info->values=color_matrix;
10601           image=ColorMatrixImage(image,kernel_info,exception);
10602           kernel_info->values=(double *) NULL;
10603           kernel_info=DestroyKernelInfo(kernel_info);
10604           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10605           break;
10606         }
10607         case 135:  /* Color */
10608         {
10609           MagickPixelPacket
10610             color;
10611
10612           (void) QueryMagickColor("none",&color,exception);
10613           if (attribute_flag[0] != 0)
10614             (void) QueryMagickColor(argument_list[0].string_reference,
10615               &color,exception);
10616           (void) SetImageColor(image,&color);
10617           break;
10618         }
10619         case 136:  /* Mode */
10620         {
10621           if (attribute_flag[0] != 0)
10622             {
10623               flags=ParseGeometry(argument_list[0].string_reference,
10624                 &geometry_info);
10625               if ((flags & SigmaValue) == 0)
10626                 geometry_info.sigma=1.0;
10627             }
10628           if (attribute_flag[1] != 0)
10629             geometry_info.rho=argument_list[1].real_reference;
10630           if (attribute_flag[2] != 0)
10631             geometry_info.sigma=argument_list[2].real_reference;
10632           if (attribute_flag[3] != 0)
10633             channel=(ChannelType) argument_list[3].integer_reference;
10634           image=StatisticImageChannel(image,channel,ModeStatistic,
10635             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10636           break;
10637         }
10638         case 137:  /* Statistic */
10639         {
10640           StatisticType
10641             statistic;
10642
10643           statistic=UndefinedStatistic;
10644           if (attribute_flag[0] != 0)
10645             {
10646               flags=ParseGeometry(argument_list[0].string_reference,
10647                 &geometry_info);
10648               if ((flags & SigmaValue) == 0)
10649                 geometry_info.sigma=1.0;
10650             }
10651           if (attribute_flag[1] != 0)
10652             geometry_info.rho=argument_list[1].real_reference;
10653           if (attribute_flag[2] != 0)
10654             geometry_info.sigma=argument_list[2].real_reference;
10655           if (attribute_flag[3] != 0)
10656             channel=(ChannelType) argument_list[3].integer_reference;
10657           if (attribute_flag[4] != 0)
10658             statistic=(StatisticType) argument_list[4].integer_reference;
10659           image=StatisticImageChannel(image,channel,statistic,
10660             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10661           break;
10662         }
10663       }
10664       if (next != (Image *) NULL)
10665         (void) CatchImageException(next);
10666       if (region_image != (Image *) NULL)
10667         {
10668           /*
10669             Composite region.
10670           */
10671           status=CompositeImage(region_image,CopyCompositeOp,image,
10672             region_info.x,region_info.y);
10673           (void) status;
10674           (void) CatchImageException(region_image);
10675           image=DestroyImage(image);
10676           image=region_image;
10677         }
10678       if (image != (Image *) NULL)
10679         {
10680           number_images++;
10681           if (next && (next != image))
10682             {
10683               image->next=next->next;
10684               DeleteImageFromRegistry(*pv,next);
10685             }
10686           sv_setiv(*pv,(IV) image);
10687           next=image;
10688         }
10689       if (*pv)
10690         pv++;
10691     }
10692
10693   PerlException:
10694     if (reference_vector)
10695       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10696     InheritPerlException(exception,perl_exception);
10697     exception=DestroyExceptionInfo(exception);
10698     sv_setiv(perl_exception,(IV) number_images);
10699     SvPOK_on(perl_exception);
10700     ST(0)=sv_2mortal(perl_exception);
10701     XSRETURN(1);
10702   }
10703 \f
10704 #
10705 ###############################################################################
10706 #                                                                             #
10707 #                                                                             #
10708 #                                                                             #
10709 #   M o n t a g e                                                             #
10710 #                                                                             #
10711 #                                                                             #
10712 #                                                                             #
10713 ###############################################################################
10714 #
10715 #
10716 void
10717 Montage(ref,...)
10718   Image::Magick ref=NO_INIT
10719   ALIAS:
10720     MontageImage  = 1
10721     montage       = 2
10722     montageimage  = 3
10723   PPCODE:
10724   {
10725     AV
10726       *av;
10727
10728     char
10729       *attribute;
10730
10731     ExceptionInfo
10732       *exception;
10733
10734     HV
10735       *hv;
10736
10737     Image
10738       *image,
10739       *next;
10740
10741     MagickPixelPacket
10742       transparent_color;
10743
10744     MontageInfo
10745       *montage_info;
10746
10747     register ssize_t
10748       i;
10749
10750     ssize_t
10751       sp;
10752
10753     struct PackageInfo
10754       *info;
10755
10756     SV
10757       *av_reference,
10758       *perl_exception,
10759       *reference,
10760       *rv,
10761       *sv;
10762
10763     PERL_UNUSED_VAR(ref);
10764     PERL_UNUSED_VAR(ix);
10765     exception=AcquireExceptionInfo();
10766     perl_exception=newSVpv("",0);
10767     sv=NULL;
10768     attribute=NULL;
10769     if (sv_isobject(ST(0)) == 0)
10770       {
10771         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10772           PackageName);
10773         goto PerlException;
10774       }
10775     reference=SvRV(ST(0));
10776     hv=SvSTASH(reference);
10777     av=newAV();
10778     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10779     SvREFCNT_dec(av);
10780     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10781     if (image == (Image *) NULL)
10782       {
10783         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10784           PackageName);
10785         goto PerlException;
10786       }
10787     /*
10788       Get options.
10789     */
10790     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10791     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10792     (void) QueryMagickColor("none",&transparent_color,exception);
10793     for (i=2; i < items; i+=2)
10794     {
10795       attribute=(char *) SvPV(ST(i-1),na);
10796       switch (*attribute)
10797       {
10798         case 'B':
10799         case 'b':
10800         {
10801           if (LocaleCompare(attribute,"background") == 0)
10802             {
10803               (void) QueryColorDatabase(SvPV(ST(i),na),
10804                 &montage_info->background_color,exception);
10805               for (next=image; next; next=next->next)
10806                 next->background_color=montage_info->background_color;
10807               break;
10808             }
10809           if (LocaleCompare(attribute,"border") == 0)
10810             {
10811               montage_info->border_width=SvIV(ST(i));
10812               break;
10813             }
10814           if (LocaleCompare(attribute,"bordercolor") == 0)
10815             {
10816               (void) QueryColorDatabase(SvPV(ST(i),na),
10817                 &montage_info->border_color,exception);
10818               for (next=image; next; next=next->next)
10819                 next->border_color=montage_info->border_color;
10820               break;
10821             }
10822           if (LocaleCompare(attribute,"borderwidth") == 0)
10823             {
10824               montage_info->border_width=SvIV(ST(i));
10825               break;
10826             }
10827           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10828             attribute);
10829           break;
10830         }
10831         case 'C':
10832         case 'c':
10833         {
10834           if (LocaleCompare(attribute,"compose") == 0)
10835             {
10836               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10837                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10838               if (sp < 0)
10839                 {
10840                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10841                     SvPV(ST(i),na));
10842                   break;
10843                 }
10844               for (next=image; next; next=next->next)
10845                 next->compose=(CompositeOperator) sp;
10846               break;
10847             }
10848           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10849             attribute);
10850           break;
10851         }
10852         case 'F':
10853         case 'f':
10854         {
10855           if (LocaleCompare(attribute,"fill") == 0)
10856             {
10857               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10858                 exception);
10859               break;
10860             }
10861           if (LocaleCompare(attribute,"font") == 0)
10862             {
10863               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10864               break;
10865             }
10866           if (LocaleCompare(attribute,"frame") == 0)
10867             {
10868               char
10869                 *p;
10870
10871               p=SvPV(ST(i),na);
10872               if (IsGeometry(p) == MagickFalse)
10873                 {
10874                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10875                     p);
10876                   break;
10877                 }
10878               (void) CloneString(&montage_info->frame,p);
10879               if (*p == '\0')
10880                 montage_info->frame=(char *) NULL;
10881               break;
10882             }
10883           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10884             attribute);
10885           break;
10886         }
10887         case 'G':
10888         case 'g':
10889         {
10890           if (LocaleCompare(attribute,"geometry") == 0)
10891             {
10892               char
10893                 *p;
10894
10895               p=SvPV(ST(i),na);
10896               if (IsGeometry(p) == MagickFalse)
10897                 {
10898                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10899                     p);
10900                   break;
10901                 }
10902              (void) CloneString(&montage_info->geometry,p);
10903              if (*p == '\0')
10904                montage_info->geometry=(char *) NULL;
10905              break;
10906            }
10907          if (LocaleCompare(attribute,"gravity") == 0)
10908            {
10909              ssize_t
10910                in;
10911
10912              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10913                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10914              if (in < 0)
10915                {
10916                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10917                    SvPV(ST(i),na));
10918                  return;
10919                }
10920              montage_info->gravity=(GravityType) in;
10921              for (next=image; next; next=next->next)
10922                next->gravity=(GravityType) in;
10923              break;
10924            }
10925           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10926             attribute);
10927           break;
10928         }
10929         case 'L':
10930         case 'l':
10931         {
10932           if (LocaleCompare(attribute,"label") == 0)
10933             {
10934               for (next=image; next; next=next->next)
10935                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10936                   info ? info->image_info : (ImageInfo *) NULL,next,
10937                   SvPV(ST(i),na)));
10938               break;
10939             }
10940           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10941             attribute);
10942           break;
10943         }
10944         case 'M':
10945         case 'm':
10946         {
10947           if (LocaleCompare(attribute,"mattecolor") == 0)
10948             {
10949               (void) QueryColorDatabase(SvPV(ST(i),na),
10950                 &montage_info->matte_color,exception);
10951               for (next=image; next; next=next->next)
10952                 next->matte_color=montage_info->matte_color;
10953               break;
10954             }
10955           if (LocaleCompare(attribute,"mode") == 0)
10956             {
10957               ssize_t
10958                 in;
10959
10960               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10961                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10962               switch (in)
10963               {
10964                 default:
10965                 {
10966                   ThrowPerlException(exception,OptionError,
10967                     "UnrecognizedModeType",SvPV(ST(i),na));
10968                   break;
10969                 }
10970                 case FrameMode:
10971                 {
10972                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10973                   montage_info->shadow=MagickTrue;
10974                   break;
10975                 }
10976                 case UnframeMode:
10977                 {
10978                   montage_info->frame=(char *) NULL;
10979                   montage_info->shadow=MagickFalse;
10980                   montage_info->border_width=0;
10981                   break;
10982                 }
10983                 case ConcatenateMode:
10984                 {
10985                   montage_info->frame=(char *) NULL;
10986                   montage_info->shadow=MagickFalse;
10987                   (void) CloneString(&montage_info->geometry,"+0+0");
10988                   montage_info->border_width=0;
10989                 }
10990               }
10991               break;
10992             }
10993           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10994             attribute);
10995           break;
10996         }
10997         case 'P':
10998         case 'p':
10999         {
11000           if (LocaleCompare(attribute,"pointsize") == 0)
11001             {
11002               montage_info->pointsize=SvIV(ST(i));
11003               break;
11004             }
11005           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11006             attribute);
11007           break;
11008         }
11009         case 'S':
11010         case 's':
11011         {
11012           if (LocaleCompare(attribute,"shadow") == 0)
11013             {
11014               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11015                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11016               if (sp < 0)
11017                 {
11018                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11019                     SvPV(ST(i),na));
11020                   break;
11021                 }
11022              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11023              break;
11024             }
11025           if (LocaleCompare(attribute,"stroke") == 0)
11026             {
11027               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11028                 exception);
11029               break;
11030             }
11031           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11032             attribute);
11033           break;
11034         }
11035         case 'T':
11036         case 't':
11037         {
11038           if (LocaleCompare(attribute,"texture") == 0)
11039             {
11040               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11041               break;
11042             }
11043           if (LocaleCompare(attribute,"tile") == 0)
11044             {
11045               char *p=SvPV(ST(i),na);
11046               if (IsGeometry(p) == MagickFalse)
11047                 {
11048                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11049                     p);
11050                   break;
11051                 }
11052               (void) CloneString(&montage_info->tile,p);
11053               if (*p == '\0')
11054                 montage_info->tile=(char *) NULL;
11055               break;
11056             }
11057           if (LocaleCompare(attribute,"title") == 0)
11058             {
11059               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11060               break;
11061             }
11062           if (LocaleCompare(attribute,"transparent") == 0)
11063             {
11064               MagickPixelPacket
11065                 transparent_color;
11066
11067               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11068               for (next=image; next; next=next->next)
11069                 (void) TransparentPaintImage(next,&transparent_color,
11070                   TransparentOpacity,MagickFalse);
11071               break;
11072             }
11073           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11074             attribute);
11075           break;
11076         }
11077         default:
11078         {
11079           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11080             attribute);
11081           break;
11082         }
11083       }
11084     }
11085     image=MontageImageList(info->image_info,montage_info,image,exception);
11086     montage_info=DestroyMontageInfo(montage_info);
11087     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11088       goto PerlException;
11089     if (transparent_color.opacity != TransparentOpacity)
11090       for (next=image; next; next=next->next)
11091         (void) TransparentPaintImage(next,&transparent_color,
11092           TransparentOpacity,MagickFalse);
11093     for (  ; image; image=image->next)
11094     {
11095       AddImageToRegistry(sv,image);
11096       rv=newRV(sv);
11097       av_push(av,sv_bless(rv,hv));
11098       SvREFCNT_dec(sv);
11099     }
11100     exception=DestroyExceptionInfo(exception);
11101     ST(0)=av_reference;
11102     SvREFCNT_dec(perl_exception);
11103     XSRETURN(1);
11104
11105   PerlException:
11106     InheritPerlException(exception,perl_exception);
11107     exception=DestroyExceptionInfo(exception);
11108     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11109     SvPOK_on(perl_exception);
11110     ST(0)=sv_2mortal(perl_exception);
11111     XSRETURN(1);
11112   }
11113 \f
11114 #
11115 ###############################################################################
11116 #                                                                             #
11117 #                                                                             #
11118 #                                                                             #
11119 #   M o r p h                                                                 #
11120 #                                                                             #
11121 #                                                                             #
11122 #                                                                             #
11123 ###############################################################################
11124 #
11125 #
11126 void
11127 Morph(ref,...)
11128   Image::Magick ref=NO_INIT
11129   ALIAS:
11130     MorphImage  = 1
11131     morph       = 2
11132     morphimage  = 3
11133   PPCODE:
11134   {
11135     AV
11136       *av;
11137
11138     char
11139       *attribute;
11140
11141     ExceptionInfo
11142       *exception;
11143
11144     HV
11145       *hv;
11146
11147     Image
11148       *image;
11149
11150     register ssize_t
11151       i;
11152
11153     ssize_t
11154       number_frames;
11155
11156     struct PackageInfo
11157       *info;
11158
11159     SV
11160       *av_reference,
11161       *perl_exception,
11162       *reference,
11163       *rv,
11164       *sv;
11165
11166     PERL_UNUSED_VAR(ref);
11167     PERL_UNUSED_VAR(ix);
11168     exception=AcquireExceptionInfo();
11169     perl_exception=newSVpv("",0);
11170     sv=NULL;
11171     av=NULL;
11172     attribute=NULL;
11173     if (sv_isobject(ST(0)) == 0)
11174       {
11175         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11176           PackageName);
11177         goto PerlException;
11178       }
11179     reference=SvRV(ST(0));
11180     hv=SvSTASH(reference);
11181     av=newAV();
11182     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11183     SvREFCNT_dec(av);
11184     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11185     if (image == (Image *) NULL)
11186       {
11187         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11188           PackageName);
11189         goto PerlException;
11190       }
11191     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11192     /*
11193       Get attribute.
11194     */
11195     number_frames=30;
11196     for (i=2; i < items; i+=2)
11197     {
11198       attribute=(char *) SvPV(ST(i-1),na);
11199       switch (*attribute)
11200       {
11201         case 'F':
11202         case 'f':
11203         {
11204           if (LocaleCompare(attribute,"frames") == 0)
11205             {
11206               number_frames=SvIV(ST(i));
11207               break;
11208             }
11209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11210             attribute);
11211           break;
11212         }
11213         default:
11214         {
11215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11216             attribute);
11217           break;
11218         }
11219       }
11220     }
11221     image=MorphImages(image,number_frames,exception);
11222     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11223       goto PerlException;
11224     for ( ; image; image=image->next)
11225     {
11226       AddImageToRegistry(sv,image);
11227       rv=newRV(sv);
11228       av_push(av,sv_bless(rv,hv));
11229       SvREFCNT_dec(sv);
11230     }
11231     exception=DestroyExceptionInfo(exception);
11232     ST(0)=av_reference;
11233     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11234     XSRETURN(1);
11235
11236   PerlException:
11237     InheritPerlException(exception,perl_exception);
11238     exception=DestroyExceptionInfo(exception);
11239     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11240     SvPOK_on(perl_exception);
11241     ST(0)=sv_2mortal(perl_exception);
11242     XSRETURN(1);
11243   }
11244 \f
11245 #
11246 ###############################################################################
11247 #                                                                             #
11248 #                                                                             #
11249 #                                                                             #
11250 #   M o s a i c                                                               #
11251 #                                                                             #
11252 #                                                                             #
11253 #                                                                             #
11254 ###############################################################################
11255 #
11256 #
11257 void
11258 Mosaic(ref)
11259   Image::Magick ref=NO_INIT
11260   ALIAS:
11261     MosaicImage   = 1
11262     mosaic        = 2
11263     mosaicimage   = 3
11264   PPCODE:
11265   {
11266     AV
11267       *av;
11268
11269     ExceptionInfo
11270       *exception;
11271
11272     HV
11273       *hv;
11274
11275     Image
11276       *image;
11277
11278     struct PackageInfo
11279       *info;
11280
11281     SV
11282       *perl_exception,
11283       *reference,
11284       *rv,
11285       *sv;
11286
11287     PERL_UNUSED_VAR(ref);
11288     PERL_UNUSED_VAR(ix);
11289     exception=AcquireExceptionInfo();
11290     perl_exception=newSVpv("",0);
11291     sv=NULL;
11292     if (sv_isobject(ST(0)) == 0)
11293       {
11294         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11295           PackageName);
11296         goto PerlException;
11297       }
11298     reference=SvRV(ST(0));
11299     hv=SvSTASH(reference);
11300     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11301     if (image == (Image *) NULL)
11302       {
11303         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11304           PackageName);
11305         goto PerlException;
11306       }
11307     image=MergeImageLayers(image,MosaicLayer,exception);
11308     /*
11309       Create blessed Perl array for the returned image.
11310     */
11311     av=newAV();
11312     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11313     SvREFCNT_dec(av);
11314     AddImageToRegistry(sv,image);
11315     rv=newRV(sv);
11316     av_push(av,sv_bless(rv,hv));
11317     SvREFCNT_dec(sv);
11318     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11319     (void) CopyMagickString(image->filename,info->image_info->filename,
11320       MaxTextExtent);
11321     SetImageInfo(info->image_info,0,&image->exception);
11322     exception=DestroyExceptionInfo(exception);
11323     SvREFCNT_dec(perl_exception);
11324     XSRETURN(1);
11325
11326   PerlException:
11327     InheritPerlException(exception,perl_exception);
11328     exception=DestroyExceptionInfo(exception);
11329     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11330     SvPOK_on(perl_exception);  /* return messages in string context */
11331     ST(0)=sv_2mortal(perl_exception);
11332     XSRETURN(1);
11333   }
11334 \f
11335 #
11336 ###############################################################################
11337 #                                                                             #
11338 #                                                                             #
11339 #                                                                             #
11340 #   P i n g                                                                   #
11341 #                                                                             #
11342 #                                                                             #
11343 #                                                                             #
11344 ###############################################################################
11345 #
11346 #
11347 void
11348 Ping(ref,...)
11349   Image::Magick ref=NO_INIT
11350   ALIAS:
11351     PingImage  = 1
11352     ping       = 2
11353     pingimage  = 3
11354   PPCODE:
11355   {
11356     AV
11357       *av;
11358
11359     char
11360       **keep,
11361       **list;
11362
11363     ExceptionInfo
11364       *exception;
11365
11366     Image
11367       *image,
11368       *next;
11369
11370     int
11371       n;
11372
11373     MagickBooleanType
11374       status;
11375
11376     register char
11377       **p;
11378
11379     register ssize_t
11380       i;
11381
11382     ssize_t
11383       ac;
11384
11385     STRLEN
11386       *length;
11387
11388     struct PackageInfo
11389       *info,
11390       *package_info;
11391
11392     SV
11393       *perl_exception,
11394       *reference;
11395
11396     size_t
11397       count;
11398
11399     PERL_UNUSED_VAR(ref);
11400     PERL_UNUSED_VAR(ix);
11401     exception=AcquireExceptionInfo();
11402     perl_exception=newSVpv("",0);
11403     package_info=(struct PackageInfo *) NULL;
11404     ac=(items < 2) ? 1 : items-1;
11405     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11406     keep=list;
11407     length=(STRLEN *) NULL;
11408     if (list == (char **) NULL)
11409       {
11410         ThrowPerlException(exception,ResourceLimitError,
11411           "MemoryAllocationFailed",PackageName);
11412         goto PerlException;
11413       }
11414     keep=list;
11415     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11416     if (length == (STRLEN *) NULL)
11417       {
11418         ThrowPerlException(exception,ResourceLimitError,
11419           "MemoryAllocationFailed",PackageName);
11420         goto PerlException;
11421       }
11422     if (sv_isobject(ST(0)) == 0)
11423       {
11424         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11425           PackageName);
11426         goto PerlException;
11427       }
11428     reference=SvRV(ST(0));
11429     if (SvTYPE(reference) != SVt_PVAV)
11430       {
11431         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11432           PackageName);
11433         goto PerlException;
11434       }
11435     av=(AV *) reference;
11436     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11437       exception);
11438     package_info=ClonePackageInfo(info,exception);
11439     n=1;
11440     if (items <= 1)
11441       *list=(char *) (*package_info->image_info->filename ?
11442         package_info->image_info->filename : "XC:black");
11443     else
11444       for (n=0, i=0; i < ac; i++)
11445       {
11446         list[n]=(char *) SvPV(ST(i+1),length[n]);
11447         if ((items >= 3) && strEQcase(list[n],"blob"))
11448           {
11449             void
11450               *blob;
11451
11452             i++;
11453             blob=(void *) (SvPV(ST(i+1),length[n]));
11454             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11455           }
11456         if ((items >= 3) && strEQcase(list[n],"filename"))
11457           continue;
11458         if ((items >= 3) && strEQcase(list[n],"file"))
11459           {
11460             FILE
11461               *file;
11462
11463             PerlIO
11464               *io_info;
11465
11466             i++;
11467             io_info=IoIFP(sv_2io(ST(i+1)));
11468             if (io_info == (PerlIO *) NULL)
11469               {
11470                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11471                   PackageName);
11472                 continue;
11473               }
11474             file=PerlIO_findFILE(io_info);
11475             if (file == (FILE *) NULL)
11476               {
11477                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11478                   PackageName);
11479                 continue;
11480               }
11481             SetImageInfoFile(package_info->image_info,file);
11482           }
11483         if ((items >= 3) && strEQcase(list[n],"magick"))
11484           continue;
11485         n++;
11486       }
11487     list[n]=(char *) NULL;
11488     keep=list;
11489     status=ExpandFilenames(&n,&list);
11490     if (status == MagickFalse)
11491       {
11492         ThrowPerlException(exception,ResourceLimitError,
11493           "MemoryAllocationFailed",PackageName);
11494         goto PerlException;
11495       }
11496     count=0;
11497     for (i=0; i < n; i++)
11498     {
11499       (void) CopyMagickString(package_info->image_info->filename,list[i],
11500         MaxTextExtent);
11501       image=PingImage(package_info->image_info,exception);
11502       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11503         break;
11504       if ((package_info->image_info->file != (FILE *) NULL) ||
11505           (package_info->image_info->blob != (void *) NULL))
11506         DisassociateImageStream(image);
11507       count+=GetImageListLength(image);
11508       EXTEND(sp,4*count);
11509       for (next=image; next; next=next->next)
11510       {
11511         PUSHs(sv_2mortal(newSViv(next->columns)));
11512         PUSHs(sv_2mortal(newSViv(next->rows)));
11513         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11514         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11515       }
11516       image=DestroyImageList(image);
11517     }
11518     /*
11519       Free resources.
11520     */
11521     for (i=0; i < n; i++)
11522       if (list[i] != (char *) NULL)
11523         for (p=keep; list[i] != *p++; )
11524           if (*p == NULL)
11525             {
11526               list[i]=(char *) RelinquishMagickMemory(list[i]);
11527               break;
11528             }
11529
11530   PerlException:
11531     if (package_info != (struct PackageInfo *) NULL)
11532       DestroyPackageInfo(package_info);
11533     if (list && (list != keep))
11534       list=(char **) RelinquishMagickMemory(list);
11535     if (keep)
11536       keep=(char **) RelinquishMagickMemory(keep);
11537     if (length)
11538       length=(STRLEN *) RelinquishMagickMemory(length);
11539     InheritPerlException(exception,perl_exception);
11540     exception=DestroyExceptionInfo(exception);
11541     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11542   }
11543 \f
11544 #
11545 ###############################################################################
11546 #                                                                             #
11547 #                                                                             #
11548 #                                                                             #
11549 #   P r e v i e w                                                             #
11550 #                                                                             #
11551 #                                                                             #
11552 #                                                                             #
11553 ###############################################################################
11554 #
11555 #
11556 void
11557 Preview(ref,...)
11558   Image::Magick ref=NO_INIT
11559   ALIAS:
11560     PreviewImage = 1
11561     preview      = 2
11562     previewimage = 3
11563   PPCODE:
11564   {
11565     AV
11566       *av;
11567
11568     ExceptionInfo
11569       *exception;
11570
11571     HV
11572       *hv;
11573
11574     Image
11575       *image,
11576       *preview_image;
11577
11578     PreviewType
11579       preview_type;
11580
11581     struct PackageInfo
11582       *info;
11583
11584     SV
11585       *av_reference,
11586       *perl_exception,
11587       *reference,
11588       *rv,
11589       *sv;
11590
11591     PERL_UNUSED_VAR(ref);
11592     PERL_UNUSED_VAR(ix);
11593     exception=AcquireExceptionInfo();
11594     perl_exception=newSVpv("",0);
11595     sv=NULL;
11596     av=NULL;
11597     if (sv_isobject(ST(0)) == 0)
11598       {
11599         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11600           PackageName);
11601         goto PerlException;
11602       }
11603     reference=SvRV(ST(0));
11604     hv=SvSTASH(reference);
11605     av=newAV();
11606     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11607     SvREFCNT_dec(av);
11608     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11609     if (image == (Image *) NULL)
11610       {
11611         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11612           PackageName);
11613         goto PerlException;
11614       }
11615     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11616     preview_type=GammaPreview;
11617     if (items > 1)
11618       preview_type=(PreviewType)
11619         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11620     for ( ; image; image=image->next)
11621     {
11622       preview_image=PreviewImage(image,preview_type,exception);
11623       if (preview_image == (Image *) NULL)
11624         goto PerlException;
11625       AddImageToRegistry(sv,preview_image);
11626       rv=newRV(sv);
11627       av_push(av,sv_bless(rv,hv));
11628       SvREFCNT_dec(sv);
11629     }
11630     exception=DestroyExceptionInfo(exception);
11631     ST(0)=av_reference;
11632     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11633     XSRETURN(1);
11634
11635   PerlException:
11636     InheritPerlException(exception,perl_exception);
11637     exception=DestroyExceptionInfo(exception);
11638     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11639     SvPOK_on(perl_exception);
11640     ST(0)=sv_2mortal(perl_exception);
11641     XSRETURN(1);
11642   }
11643 \f
11644 #
11645 ###############################################################################
11646 #                                                                             #
11647 #                                                                             #
11648 #                                                                             #
11649 #   Q u e r y C o l o r                                                       #
11650 #                                                                             #
11651 #                                                                             #
11652 #                                                                             #
11653 ###############################################################################
11654 #
11655 #
11656 void
11657 QueryColor(ref,...)
11658   Image::Magick ref=NO_INIT
11659   ALIAS:
11660     querycolor = 1
11661   PPCODE:
11662   {
11663     char
11664       *name;
11665
11666     ExceptionInfo
11667       *exception;
11668
11669     MagickPixelPacket
11670       color;
11671
11672     register ssize_t
11673       i;
11674
11675     SV
11676       *perl_exception;
11677
11678     PERL_UNUSED_VAR(ref);
11679     PERL_UNUSED_VAR(ix);
11680     exception=AcquireExceptionInfo();
11681     perl_exception=newSVpv("",0);
11682     if (items == 1)
11683       {
11684         const ColorInfo
11685           **colorlist;
11686
11687         size_t
11688           colors;
11689
11690         colorlist=GetColorInfoList("*",&colors,exception);
11691         EXTEND(sp,colors);
11692         for (i=0; i < (ssize_t) colors; i++)
11693         {
11694           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11695         }
11696         colorlist=(const ColorInfo **)
11697           RelinquishMagickMemory((ColorInfo **) colorlist);
11698         goto PerlException;
11699       }
11700     EXTEND(sp,5*items);
11701     for (i=1; i < items; i++)
11702     {
11703       name=(char *) SvPV(ST(i),na);
11704       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11705         {
11706           PUSHs(&sv_undef);
11707           continue;
11708         }
11709       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11710       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11711       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11712       if (color.matte != MagickFalse)
11713         PUSHs(sv_2mortal(newSViv((size_t) floor(color.opacity+0.5))));
11714       if (color.colorspace == CMYKColorspace)
11715         PUSHs(sv_2mortal(newSViv((size_t) floor(color.index+0.5))));
11716     }
11717
11718   PerlException:
11719     InheritPerlException(exception,perl_exception);
11720     exception=DestroyExceptionInfo(exception);
11721     SvREFCNT_dec(perl_exception);
11722   }
11723 \f
11724 #
11725 ###############################################################################
11726 #                                                                             #
11727 #                                                                             #
11728 #                                                                             #
11729 #   Q u e r y C o l o r N a m e                                               #
11730 #                                                                             #
11731 #                                                                             #
11732 #                                                                             #
11733 ###############################################################################
11734 #
11735 #
11736 void
11737 QueryColorname(ref,...)
11738   Image::Magick ref=NO_INIT
11739   ALIAS:
11740     querycolorname = 1
11741   PPCODE:
11742   {
11743     AV
11744       *av;
11745
11746     char
11747       message[MaxTextExtent];
11748
11749     ExceptionInfo
11750       *exception;
11751
11752     Image
11753       *image;
11754
11755     PixelPacket
11756       target_color;
11757
11758     register ssize_t
11759       i;
11760
11761     struct PackageInfo
11762       *info;
11763
11764     SV
11765       *perl_exception,
11766       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11767
11768     PERL_UNUSED_VAR(ref);
11769     PERL_UNUSED_VAR(ix);
11770     exception=AcquireExceptionInfo();
11771     perl_exception=newSVpv("",0);
11772     reference=SvRV(ST(0));
11773     av=(AV *) reference;
11774     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11775       exception);
11776     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11777     if (image == (Image *) NULL)
11778       {
11779         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11780           PackageName);
11781         goto PerlException;
11782       }
11783     EXTEND(sp,items);
11784     for (i=1; i < items; i++)
11785     {
11786       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11787       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11788         exception);
11789       PUSHs(sv_2mortal(newSVpv(message,0)));
11790     }
11791
11792   PerlException:
11793     InheritPerlException(exception,perl_exception);
11794     exception=DestroyExceptionInfo(exception);
11795     SvREFCNT_dec(perl_exception);
11796   }
11797 \f
11798 #
11799 ###############################################################################
11800 #                                                                             #
11801 #                                                                             #
11802 #                                                                             #
11803 #   Q u e r y F o n t                                                         #
11804 #                                                                             #
11805 #                                                                             #
11806 #                                                                             #
11807 ###############################################################################
11808 #
11809 #
11810 void
11811 QueryFont(ref,...)
11812   Image::Magick ref=NO_INIT
11813   ALIAS:
11814     queryfont = 1
11815   PPCODE:
11816   {
11817     char
11818       *name,
11819       message[MaxTextExtent];
11820
11821     ExceptionInfo
11822       *exception;
11823
11824     register ssize_t
11825       i;
11826
11827     SV
11828       *perl_exception;
11829
11830     volatile const TypeInfo
11831       *type_info;
11832
11833     PERL_UNUSED_VAR(ref);
11834     PERL_UNUSED_VAR(ix);
11835     exception=AcquireExceptionInfo();
11836     perl_exception=newSVpv("",0);
11837     if (items == 1)
11838       {
11839         const TypeInfo
11840           **typelist;
11841
11842         size_t
11843           types;
11844
11845         typelist=GetTypeInfoList("*",&types,exception);
11846         EXTEND(sp,types);
11847         for (i=0; i < (ssize_t) types; i++)
11848         {
11849           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11850         }
11851         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11852           typelist);
11853         goto PerlException;
11854       }
11855     EXTEND(sp,10*items);
11856     for (i=1; i < items; i++)
11857     {
11858       name=(char *) SvPV(ST(i),na);
11859       type_info=GetTypeInfo(name,exception);
11860       if (type_info == (TypeInfo *) NULL)
11861         {
11862           PUSHs(&sv_undef);
11863           continue;
11864         }
11865       if (type_info->name == (char *) NULL)
11866         PUSHs(&sv_undef);
11867       else
11868         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11869       if (type_info->description == (char *) NULL)
11870         PUSHs(&sv_undef);
11871       else
11872         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11873       if (type_info->family == (char *) NULL)
11874         PUSHs(&sv_undef);
11875       else
11876         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11877       if (type_info->style == UndefinedStyle)
11878         PUSHs(&sv_undef);
11879       else
11880         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11881           type_info->style),0)));
11882       if (type_info->stretch == UndefinedStretch)
11883         PUSHs(&sv_undef);
11884       else
11885         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11886           type_info->stretch),0)));
11887       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11888         type_info->weight);
11889       PUSHs(sv_2mortal(newSVpv(message,0)));
11890       if (type_info->encoding == (char *) NULL)
11891         PUSHs(&sv_undef);
11892       else
11893         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11894       if (type_info->foundry == (char *) NULL)
11895         PUSHs(&sv_undef);
11896       else
11897         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11898       if (type_info->format == (char *) NULL)
11899         PUSHs(&sv_undef);
11900       else
11901         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11902       if (type_info->metrics == (char *) NULL)
11903         PUSHs(&sv_undef);
11904       else
11905         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11906       if (type_info->glyphs == (char *) NULL)
11907         PUSHs(&sv_undef);
11908       else
11909         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11910     }
11911
11912   PerlException:
11913     InheritPerlException(exception,perl_exception);
11914     exception=DestroyExceptionInfo(exception);
11915     SvREFCNT_dec(perl_exception);
11916   }
11917 \f
11918 #
11919 ###############################################################################
11920 #                                                                             #
11921 #                                                                             #
11922 #                                                                             #
11923 #   Q u e r y F o n t M e t r i c s                                           #
11924 #                                                                             #
11925 #                                                                             #
11926 #                                                                             #
11927 ###############################################################################
11928 #
11929 #
11930 void
11931 QueryFontMetrics(ref,...)
11932   Image::Magick ref=NO_INIT
11933   ALIAS:
11934     queryfontmetrics = 1
11935   PPCODE:
11936   {
11937     AffineMatrix
11938       affine,
11939       current;
11940
11941     AV
11942       *av;
11943
11944     char
11945       *attribute;
11946
11947     double
11948       x,
11949       y;
11950
11951     DrawInfo
11952       *draw_info;
11953
11954     ExceptionInfo
11955       *exception;
11956
11957     GeometryInfo
11958       geometry_info;
11959
11960     Image
11961       *image;
11962
11963     MagickBooleanType
11964       status;
11965
11966     MagickStatusType
11967       flags;
11968
11969     register ssize_t
11970       i;
11971
11972     ssize_t
11973       type;
11974
11975     struct PackageInfo
11976       *info,
11977       *package_info;
11978
11979     SV
11980       *perl_exception,
11981       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11982
11983     TypeMetric
11984       metrics;
11985
11986     PERL_UNUSED_VAR(ref);
11987     PERL_UNUSED_VAR(ix);
11988     exception=AcquireExceptionInfo();
11989     package_info=(struct PackageInfo *) NULL;
11990     perl_exception=newSVpv("",0);
11991     reference=SvRV(ST(0));
11992     av=(AV *) reference;
11993     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11994       exception);
11995     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11996     if (image == (Image *) NULL)
11997       {
11998         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11999           PackageName);
12000         goto PerlException;
12001       }
12002     package_info=ClonePackageInfo(info,exception);
12003     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12004     CloneString(&draw_info->text,"");
12005     current=draw_info->affine;
12006     GetAffineMatrix(&affine);
12007     x=0.0;
12008     y=0.0;
12009     EXTEND(sp,7*items);
12010     for (i=2; i < items; i+=2)
12011     {
12012       attribute=(char *) SvPV(ST(i-1),na);
12013       switch (*attribute)
12014       {
12015         case 'A':
12016         case 'a':
12017         {
12018           if (LocaleCompare(attribute,"antialias") == 0)
12019             {
12020               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12021                 SvPV(ST(i),na));
12022               if (type < 0)
12023                 {
12024                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12025                     SvPV(ST(i),na));
12026                   break;
12027                 }
12028               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12029               break;
12030             }
12031           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12032             attribute);
12033           break;
12034         }
12035         case 'd':
12036         case 'D':
12037         {
12038           if (LocaleCompare(attribute,"density") == 0)
12039             {
12040               CloneString(&draw_info->density,SvPV(ST(i),na));
12041               break;
12042             }
12043           if (LocaleCompare(attribute,"direction") == 0)
12044             {
12045               draw_info->direction=(DirectionType) ParseCommandOption(
12046                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12047               break;
12048             }
12049           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12050             attribute);
12051           break;
12052         }
12053         case 'e':
12054         case 'E':
12055         {
12056           if (LocaleCompare(attribute,"encoding") == 0)
12057             {
12058               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12059               break;
12060             }
12061           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12062             attribute);
12063           break;
12064         }
12065         case 'f':
12066         case 'F':
12067         {
12068           if (LocaleCompare(attribute,"family") == 0)
12069             {
12070               CloneString(&draw_info->family,SvPV(ST(i),na));
12071               break;
12072             }
12073           if (LocaleCompare(attribute,"fill") == 0)
12074             {
12075               if (info)
12076                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12077                   &image->exception);
12078               break;
12079             }
12080           if (LocaleCompare(attribute,"font") == 0)
12081             {
12082               CloneString(&draw_info->font,SvPV(ST(i),na));
12083               break;
12084             }
12085           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12086             attribute);
12087           break;
12088         }
12089         case 'g':
12090         case 'G':
12091         {
12092           if (LocaleCompare(attribute,"geometry") == 0)
12093             {
12094               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12095               break;
12096             }
12097           if (LocaleCompare(attribute,"gravity") == 0)
12098             {
12099               draw_info->gravity=(GravityType) ParseCommandOption(
12100                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12101               break;
12102             }
12103           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12104             attribute);
12105           break;
12106         }
12107         case 'i':
12108         case 'I':
12109         {
12110           if (LocaleCompare(attribute,"interline-spacing") == 0)
12111             {
12112               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12113               draw_info->interline_spacing=geometry_info.rho;
12114               break;
12115             }
12116           if (LocaleCompare(attribute,"interword-spacing") == 0)
12117             {
12118               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12119               draw_info->interword_spacing=geometry_info.rho;
12120               break;
12121             }
12122           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12123             attribute);
12124           break;
12125         }
12126         case 'k':
12127         case 'K':
12128         {
12129           if (LocaleCompare(attribute,"kerning") == 0)
12130             {
12131               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12132               draw_info->kerning=geometry_info.rho;
12133               break;
12134             }
12135           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12136             attribute);
12137           break;
12138         }
12139         case 'p':
12140         case 'P':
12141         {
12142           if (LocaleCompare(attribute,"pointsize") == 0)
12143             {
12144               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12145               draw_info->pointsize=geometry_info.rho;
12146               break;
12147             }
12148           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12149             attribute);
12150           break;
12151         }
12152         case 'r':
12153         case 'R':
12154         {
12155           if (LocaleCompare(attribute,"rotate") == 0)
12156             {
12157               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12158               affine.rx=geometry_info.rho;
12159               affine.ry=geometry_info.sigma;
12160               if ((flags & SigmaValue) == 0)
12161                 affine.ry=affine.rx;
12162               break;
12163             }
12164           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12165             attribute);
12166           break;
12167         }
12168         case 's':
12169         case 'S':
12170         {
12171           if (LocaleCompare(attribute,"scale") == 0)
12172             {
12173               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12174               affine.sx=geometry_info.rho;
12175               affine.sy=geometry_info.sigma;
12176               if ((flags & SigmaValue) == 0)
12177                 affine.sy=affine.sx;
12178               break;
12179             }
12180           if (LocaleCompare(attribute,"skew") == 0)
12181             {
12182               double
12183                 x_angle,
12184                 y_angle;
12185
12186               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12187               x_angle=geometry_info.rho;
12188               y_angle=geometry_info.sigma;
12189               if ((flags & SigmaValue) == 0)
12190                 y_angle=x_angle;
12191               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12192               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12193               break;
12194             }
12195           if (LocaleCompare(attribute,"stroke") == 0)
12196             {
12197               if (info)
12198                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12199                   &image->exception);
12200               break;
12201             }
12202           if (LocaleCompare(attribute,"style") == 0)
12203             {
12204               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12205                 SvPV(ST(i),na));
12206               if (type < 0)
12207                 {
12208                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12209                     SvPV(ST(i),na));
12210                   break;
12211                 }
12212               draw_info->style=(StyleType) type;
12213               break;
12214             }
12215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12216             attribute);
12217           break;
12218         }
12219         case 't':
12220         case 'T':
12221         {
12222           if (LocaleCompare(attribute,"text") == 0)
12223             {
12224               CloneString(&draw_info->text,SvPV(ST(i),na));
12225               break;
12226             }
12227           if (LocaleCompare(attribute,"translate") == 0)
12228             {
12229               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12230               affine.tx=geometry_info.rho;
12231               affine.ty=geometry_info.sigma;
12232               if ((flags & SigmaValue) == 0)
12233                 affine.ty=affine.tx;
12234               break;
12235             }
12236           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12237             attribute);
12238           break;
12239         }
12240         case 'w':
12241         case 'W':
12242         {
12243           if (LocaleCompare(attribute,"weight") == 0)
12244             {
12245               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12246               draw_info->weight=(size_t) geometry_info.rho;
12247               break;
12248             }
12249           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12250             attribute);
12251           break;
12252         }
12253         case 'x':
12254         case 'X':
12255         {
12256           if (LocaleCompare(attribute,"x") == 0)
12257             {
12258               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12259               x=geometry_info.rho;
12260               break;
12261             }
12262           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12263             attribute);
12264           break;
12265         }
12266         case 'y':
12267         case 'Y':
12268         {
12269           if (LocaleCompare(attribute,"y") == 0)
12270             {
12271               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12272               y=geometry_info.rho;
12273               break;
12274             }
12275           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12276             attribute);
12277           break;
12278         }
12279         default:
12280         {
12281           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12282             attribute);
12283           break;
12284         }
12285       }
12286     }
12287     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12288     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12289     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12290     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12291     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12292     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12293     if (draw_info->geometry == (char *) NULL)
12294       {
12295         draw_info->geometry=AcquireString((char *) NULL);
12296         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12297           "%.15g,%.15g",x,y);
12298       }
12299     status=GetTypeMetrics(image,draw_info,&metrics);
12300     (void) CatchImageException(image);
12301     if (status == MagickFalse)
12302       PUSHs(&sv_undef);
12303     else
12304       {
12305         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12306         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12307         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12308         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12309         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12310         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12311         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12312         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12313         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12314         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12315         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12316         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12317         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12318       }
12319     draw_info=DestroyDrawInfo(draw_info);
12320
12321   PerlException:
12322     if (package_info != (struct PackageInfo *) NULL)
12323       DestroyPackageInfo(package_info);
12324     InheritPerlException(exception,perl_exception);
12325     exception=DestroyExceptionInfo(exception);
12326     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12327   }
12328 \f
12329 #
12330 ###############################################################################
12331 #                                                                             #
12332 #                                                                             #
12333 #                                                                             #
12334 #   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                         #
12335 #                                                                             #
12336 #                                                                             #
12337 #                                                                             #
12338 ###############################################################################
12339 #
12340 #
12341 void
12342 QueryMultilineFontMetrics(ref,...)
12343   Image::Magick ref=NO_INIT
12344   ALIAS:
12345     querymultilinefontmetrics = 1
12346   PPCODE:
12347   {
12348     AffineMatrix
12349       affine,
12350       current;
12351
12352     AV
12353       *av;
12354
12355     char
12356       *attribute;
12357
12358     double
12359       x,
12360       y;
12361
12362     DrawInfo
12363       *draw_info;
12364
12365     ExceptionInfo
12366       *exception;
12367
12368     GeometryInfo
12369       geometry_info;
12370
12371     Image
12372       *image;
12373
12374     MagickBooleanType
12375       status;
12376
12377     MagickStatusType
12378       flags;
12379
12380     register ssize_t
12381       i;
12382
12383     ssize_t
12384       type;
12385
12386     struct PackageInfo
12387       *info,
12388       *package_info;
12389
12390     SV
12391       *perl_exception,
12392       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12393
12394     TypeMetric
12395       metrics;
12396
12397     PERL_UNUSED_VAR(ref);
12398     PERL_UNUSED_VAR(ix);
12399     exception=AcquireExceptionInfo();
12400     package_info=(struct PackageInfo *) NULL;
12401     perl_exception=newSVpv("",0);
12402     reference=SvRV(ST(0));
12403     av=(AV *) reference;
12404     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12405       exception);
12406     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12407     if (image == (Image *) NULL)
12408       {
12409         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12410           PackageName);
12411         goto PerlException;
12412       }
12413     package_info=ClonePackageInfo(info,exception);
12414     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12415     CloneString(&draw_info->text,"");
12416     current=draw_info->affine;
12417     GetAffineMatrix(&affine);
12418     x=0.0;
12419     y=0.0;
12420     EXTEND(sp,7*items);
12421     for (i=2; i < items; i+=2)
12422     {
12423       attribute=(char *) SvPV(ST(i-1),na);
12424       switch (*attribute)
12425       {
12426         case 'A':
12427         case 'a':
12428         {
12429           if (LocaleCompare(attribute,"antialias") == 0)
12430             {
12431               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12432                 SvPV(ST(i),na));
12433               if (type < 0)
12434                 {
12435                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12436                     SvPV(ST(i),na));
12437                   break;
12438                 }
12439               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12440               break;
12441             }
12442           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12443             attribute);
12444           break;
12445         }
12446         case 'd':
12447         case 'D':
12448         {
12449           if (LocaleCompare(attribute,"density") == 0)
12450             {
12451               CloneString(&draw_info->density,SvPV(ST(i),na));
12452               break;
12453             }
12454           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12455             attribute);
12456           break;
12457         }
12458         case 'e':
12459         case 'E':
12460         {
12461           if (LocaleCompare(attribute,"encoding") == 0)
12462             {
12463               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12464               break;
12465             }
12466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12467             attribute);
12468           break;
12469         }
12470         case 'f':
12471         case 'F':
12472         {
12473           if (LocaleCompare(attribute,"family") == 0)
12474             {
12475               CloneString(&draw_info->family,SvPV(ST(i),na));
12476               break;
12477             }
12478           if (LocaleCompare(attribute,"fill") == 0)
12479             {
12480               if (info)
12481                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12482                   &image->exception);
12483               break;
12484             }
12485           if (LocaleCompare(attribute,"font") == 0)
12486             {
12487               CloneString(&draw_info->font,SvPV(ST(i),na));
12488               break;
12489             }
12490           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12491             attribute);
12492           break;
12493         }
12494         case 'g':
12495         case 'G':
12496         {
12497           if (LocaleCompare(attribute,"geometry") == 0)
12498             {
12499               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12500               break;
12501             }
12502           if (LocaleCompare(attribute,"gravity") == 0)
12503             {
12504               draw_info->gravity=(GravityType) ParseCommandOption(
12505                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12506               break;
12507             }
12508           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12509             attribute);
12510           break;
12511         }
12512         case 'p':
12513         case 'P':
12514         {
12515           if (LocaleCompare(attribute,"pointsize") == 0)
12516             {
12517               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12518               draw_info->pointsize=geometry_info.rho;
12519               break;
12520             }
12521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12522             attribute);
12523           break;
12524         }
12525         case 'r':
12526         case 'R':
12527         {
12528           if (LocaleCompare(attribute,"rotate") == 0)
12529             {
12530               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12531               affine.rx=geometry_info.rho;
12532               affine.ry=geometry_info.sigma;
12533               if ((flags & SigmaValue) == 0)
12534                 affine.ry=affine.rx;
12535               break;
12536             }
12537           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12538             attribute);
12539           break;
12540         }
12541         case 's':
12542         case 'S':
12543         {
12544           if (LocaleCompare(attribute,"scale") == 0)
12545             {
12546               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12547               affine.sx=geometry_info.rho;
12548               affine.sy=geometry_info.sigma;
12549               if ((flags & SigmaValue) == 0)
12550                 affine.sy=affine.sx;
12551               break;
12552             }
12553           if (LocaleCompare(attribute,"skew") == 0)
12554             {
12555               double
12556                 x_angle,
12557                 y_angle;
12558
12559               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12560               x_angle=geometry_info.rho;
12561               y_angle=geometry_info.sigma;
12562               if ((flags & SigmaValue) == 0)
12563                 y_angle=x_angle;
12564               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12565               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12566               break;
12567             }
12568           if (LocaleCompare(attribute,"stroke") == 0)
12569             {
12570               if (info)
12571                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12572                   &image->exception);
12573               break;
12574             }
12575           if (LocaleCompare(attribute,"style") == 0)
12576             {
12577               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12578                 SvPV(ST(i),na));
12579               if (type < 0)
12580                 {
12581                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12582                     SvPV(ST(i),na));
12583                   break;
12584                 }
12585               draw_info->style=(StyleType) type;
12586               break;
12587             }
12588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12589             attribute);
12590           break;
12591         }
12592         case 't':
12593         case 'T':
12594         {
12595           if (LocaleCompare(attribute,"text") == 0)
12596             {
12597               CloneString(&draw_info->text,SvPV(ST(i),na));
12598               break;
12599             }
12600           if (LocaleCompare(attribute,"translate") == 0)
12601             {
12602               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12603               affine.tx=geometry_info.rho;
12604               affine.ty=geometry_info.sigma;
12605               if ((flags & SigmaValue) == 0)
12606                 affine.ty=affine.tx;
12607               break;
12608             }
12609           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12610             attribute);
12611           break;
12612         }
12613         case 'w':
12614         case 'W':
12615         {
12616           if (LocaleCompare(attribute,"weight") == 0)
12617             {
12618               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12619               draw_info->weight=(size_t) geometry_info.rho;
12620               break;
12621             }
12622           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12623             attribute);
12624           break;
12625         }
12626         case 'x':
12627         case 'X':
12628         {
12629           if (LocaleCompare(attribute,"x") == 0)
12630             {
12631               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12632               x=geometry_info.rho;
12633               break;
12634             }
12635           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12636             attribute);
12637           break;
12638         }
12639         case 'y':
12640         case 'Y':
12641         {
12642           if (LocaleCompare(attribute,"y") == 0)
12643             {
12644               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12645               y=geometry_info.rho;
12646               break;
12647             }
12648           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12649             attribute);
12650           break;
12651         }
12652         default:
12653         {
12654           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12655             attribute);
12656           break;
12657         }
12658       }
12659     }
12660     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12661     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12662     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12663     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12664     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12665     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12666     if (draw_info->geometry == (char *) NULL)
12667       {
12668         draw_info->geometry=AcquireString((char *) NULL);
12669         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12670           "%.15g,%.15g",x,y);
12671       }
12672     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12673     (void) CatchImageException(image);
12674     if (status == MagickFalse)
12675       PUSHs(&sv_undef);
12676     else
12677       {
12678         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12679         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12680         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12681         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12682         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12683         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12684         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12685         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12686         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12687         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12688         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12689         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12690         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12691       }
12692     draw_info=DestroyDrawInfo(draw_info);
12693
12694   PerlException:
12695     if (package_info != (struct PackageInfo *) NULL)
12696       DestroyPackageInfo(package_info);
12697     InheritPerlException(exception,perl_exception);
12698     exception=DestroyExceptionInfo(exception);
12699     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12700   }
12701 \f
12702 #
12703 ###############################################################################
12704 #                                                                             #
12705 #                                                                             #
12706 #                                                                             #
12707 #   Q u e r y F o r m a t                                                     #
12708 #                                                                             #
12709 #                                                                             #
12710 #                                                                             #
12711 ###############################################################################
12712 #
12713 #
12714 void
12715 QueryFormat(ref,...)
12716   Image::Magick ref=NO_INIT
12717   ALIAS:
12718     queryformat = 1
12719   PPCODE:
12720   {
12721     char
12722       *name;
12723
12724     ExceptionInfo
12725       *exception;
12726
12727     register ssize_t
12728       i;
12729
12730     SV
12731       *perl_exception;
12732
12733     volatile const MagickInfo
12734       *magick_info;
12735
12736     PERL_UNUSED_VAR(ref);
12737     PERL_UNUSED_VAR(ix);
12738     exception=AcquireExceptionInfo();
12739     perl_exception=newSVpv("",0);
12740     if (items == 1)
12741       {
12742         char
12743           format[MaxTextExtent];
12744
12745         const MagickInfo
12746           **format_list;
12747
12748         size_t
12749           types;
12750
12751         format_list=GetMagickInfoList("*",&types,exception);
12752         EXTEND(sp,types);
12753         for (i=0; i < (ssize_t) types; i++)
12754         {
12755           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12756           LocaleLower(format);
12757           PUSHs(sv_2mortal(newSVpv(format,0)));
12758         }
12759         format_list=(const MagickInfo **)
12760           RelinquishMagickMemory((MagickInfo *) format_list);
12761         goto PerlException;
12762       }
12763     EXTEND(sp,8*items);
12764     for (i=1; i < items; i++)
12765     {
12766       name=(char *) SvPV(ST(i),na);
12767       magick_info=GetMagickInfo(name,exception);
12768       if (magick_info == (const MagickInfo *) NULL)
12769         {
12770           PUSHs(&sv_undef);
12771           continue;
12772         }
12773       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12774       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12775       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12776       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12777       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12778       if (magick_info->description == (char *) NULL)
12779         PUSHs(&sv_undef);
12780       else
12781         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12782       if (magick_info->module == (char *) NULL)
12783         PUSHs(&sv_undef);
12784       else
12785         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12786     }
12787
12788   PerlException:
12789     InheritPerlException(exception,perl_exception);
12790     exception=DestroyExceptionInfo(exception);
12791     SvREFCNT_dec(perl_exception);
12792   }
12793 \f
12794 #
12795 ###############################################################################
12796 #                                                                             #
12797 #                                                                             #
12798 #                                                                             #
12799 #   Q u e r y O p t i o n                                                     #
12800 #                                                                             #
12801 #                                                                             #
12802 #                                                                             #
12803 ###############################################################################
12804 #
12805 #
12806 void
12807 QueryOption(ref,...)
12808   Image::Magick ref=NO_INIT
12809   ALIAS:
12810     queryoption = 1
12811   PPCODE:
12812   {
12813     char
12814       **options;
12815
12816     ExceptionInfo
12817       *exception;
12818
12819     register ssize_t
12820       i;
12821
12822     ssize_t
12823       j,
12824       option;
12825
12826     SV
12827       *perl_exception;
12828
12829     PERL_UNUSED_VAR(ref);
12830     PERL_UNUSED_VAR(ix);
12831     exception=AcquireExceptionInfo();
12832     perl_exception=newSVpv("",0);
12833     EXTEND(sp,8*items);
12834     for (i=1; i < items; i++)
12835     {
12836       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12837         SvPV(ST(i),na));
12838       options=GetCommandOptions((CommandOption) option);
12839       if (options == (char **) NULL)
12840         PUSHs(&sv_undef);
12841       else
12842         {
12843           for (j=0; options[j] != (char *) NULL; j++)
12844             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12845           options=DestroyStringList(options);
12846         }
12847     }
12848
12849     InheritPerlException(exception,perl_exception);
12850     exception=DestroyExceptionInfo(exception);
12851     SvREFCNT_dec(perl_exception);
12852   }
12853 \f
12854 #
12855 ###############################################################################
12856 #                                                                             #
12857 #                                                                             #
12858 #                                                                             #
12859 #   R e a d                                                                   #
12860 #                                                                             #
12861 #                                                                             #
12862 #                                                                             #
12863 ###############################################################################
12864 #
12865 #
12866 void
12867 Read(ref,...)
12868   Image::Magick ref=NO_INIT
12869   ALIAS:
12870     ReadImage  = 1
12871     read       = 2
12872     readimage  = 3
12873   PPCODE:
12874   {
12875     AV
12876       *av;
12877
12878     char
12879       **keep,
12880       **list;
12881
12882     ExceptionInfo
12883       *exception;
12884
12885     HV
12886       *hv;
12887
12888     Image
12889       *image;
12890
12891     int
12892       n;
12893
12894     MagickBooleanType
12895       status;
12896
12897     register char
12898       **p;
12899
12900     register ssize_t
12901       i;
12902
12903     ssize_t
12904       ac,
12905       number_images;
12906
12907     STRLEN
12908       *length;
12909
12910     struct PackageInfo
12911       *info,
12912       *package_info;
12913
12914     SV
12915       *perl_exception,  /* Perl variable for storing messages */
12916       *reference,
12917       *rv,
12918       *sv;
12919
12920     PERL_UNUSED_VAR(ref);
12921     PERL_UNUSED_VAR(ix);
12922     exception=AcquireExceptionInfo();
12923     perl_exception=newSVpv("",0);
12924     sv=NULL;
12925     package_info=(struct PackageInfo *) NULL;
12926     number_images=0;
12927     ac=(items < 2) ? 1 : items-1;
12928     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12929     keep=list;
12930     length=(STRLEN *) NULL;
12931     if (list == (char **) NULL)
12932       {
12933         ThrowPerlException(exception,ResourceLimitError,
12934           "MemoryAllocationFailed",PackageName);
12935         goto PerlException;
12936       }
12937     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12938     if (length == (STRLEN *) NULL)
12939       {
12940         ThrowPerlException(exception,ResourceLimitError,
12941           "MemoryAllocationFailed",PackageName);
12942         goto PerlException;
12943       }
12944     if (sv_isobject(ST(0)) == 0)
12945       {
12946         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12947           PackageName);
12948         goto PerlException;
12949       }
12950     reference=SvRV(ST(0));
12951     hv=SvSTASH(reference);
12952     if (SvTYPE(reference) != SVt_PVAV)
12953       {
12954         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12955           PackageName);
12956         goto PerlException;
12957       }
12958     av=(AV *) reference;
12959     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12960       exception);
12961     package_info=ClonePackageInfo(info,exception);
12962     n=1;
12963     if (items <= 1)
12964       *list=(char *) (*package_info->image_info->filename ?
12965         package_info->image_info->filename : "XC:black");
12966     else
12967       for (n=0, i=0; i < ac; i++)
12968       {
12969         list[n]=(char *) SvPV(ST(i+1),length[n]);
12970         if ((items >= 3) && strEQcase(list[n],"blob"))
12971           {
12972             void
12973               *blob;
12974
12975             i++;
12976             blob=(void *) (SvPV(ST(i+1),length[n]));
12977             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12978           }
12979         if ((items >= 3) && strEQcase(list[n],"filename"))
12980           continue;
12981         if ((items >= 3) && strEQcase(list[n],"file"))
12982           {
12983             FILE
12984               *file;
12985
12986             PerlIO
12987               *io_info;
12988
12989             i++;
12990             io_info=IoIFP(sv_2io(ST(i+1)));
12991             if (io_info == (PerlIO *) NULL)
12992               {
12993                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12994                   PackageName);
12995                 continue;
12996               }
12997             file=PerlIO_findFILE(io_info);
12998             if (file == (FILE *) NULL)
12999               {
13000                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13001                   PackageName);
13002                 continue;
13003               }
13004             SetImageInfoFile(package_info->image_info,file);
13005           }
13006         if ((items >= 3) && strEQcase(list[n],"magick"))
13007           continue;
13008         n++;
13009       }
13010     list[n]=(char *) NULL;
13011     keep=list;
13012     status=ExpandFilenames(&n,&list);
13013     if (status == MagickFalse)
13014       {
13015         ThrowPerlException(exception,ResourceLimitError,
13016           "MemoryAllocationFailed",PackageName);
13017         goto PerlException;
13018       }
13019     number_images=0;
13020     for (i=0; i < n; i++)
13021     {
13022       if ((package_info->image_info->file != (FILE *) NULL) ||
13023           (package_info->image_info->blob != (void *) NULL))
13024         {
13025           image=ReadImages(package_info->image_info,exception);
13026           if (image != (Image *) NULL)
13027             DisassociateImageStream(image);
13028         }
13029       else
13030         {
13031           (void) CopyMagickString(package_info->image_info->filename,list[i],
13032             MaxTextExtent);
13033           image=ReadImages(package_info->image_info,exception);
13034         }
13035       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13036         break;
13037       for ( ; image; image=image->next)
13038       {
13039         AddImageToRegistry(sv,image);
13040         rv=newRV(sv);
13041         av_push(av,sv_bless(rv,hv));
13042         SvREFCNT_dec(sv);
13043         number_images++;
13044       }
13045     }
13046     /*
13047       Free resources.
13048     */
13049     for (i=0; i < n; i++)
13050       if (list[i] != (char *) NULL)
13051         for (p=keep; list[i] != *p++; )
13052           if (*p == (char *) NULL)
13053             {
13054               list[i]=(char *) RelinquishMagickMemory(list[i]);
13055               break;
13056             }
13057
13058   PerlException:
13059     if (package_info != (struct PackageInfo *) NULL)
13060       DestroyPackageInfo(package_info);
13061     if (list && (list != keep))
13062       list=(char **) RelinquishMagickMemory(list);
13063     if (keep)
13064       keep=(char **) RelinquishMagickMemory(keep);
13065     if (length)
13066       length=(STRLEN *) RelinquishMagickMemory(length);
13067     InheritPerlException(exception,perl_exception);
13068     exception=DestroyExceptionInfo(exception);
13069     sv_setiv(perl_exception,(IV) number_images);
13070     SvPOK_on(perl_exception);
13071     ST(0)=sv_2mortal(perl_exception);
13072     XSRETURN(1);
13073   }
13074 \f
13075 #
13076 ###############################################################################
13077 #                                                                             #
13078 #                                                                             #
13079 #                                                                             #
13080 #   R e m o t e                                                               #
13081 #                                                                             #
13082 #                                                                             #
13083 #                                                                             #
13084 ###############################################################################
13085 #
13086 #
13087 void
13088 Remote(ref,...)
13089   Image::Magick ref=NO_INIT
13090   ALIAS:
13091     RemoteCommand  = 1
13092     remote         = 2
13093     remoteCommand  = 3
13094   PPCODE:
13095   {
13096     AV
13097       *av;
13098
13099     ExceptionInfo
13100       *exception;
13101
13102     register ssize_t
13103       i;
13104
13105     SV
13106       *perl_exception,
13107       *reference;
13108
13109     struct PackageInfo
13110       *info;
13111
13112     PERL_UNUSED_VAR(ref);
13113     PERL_UNUSED_VAR(ix);
13114     exception=AcquireExceptionInfo();
13115     perl_exception=newSVpv("",0);
13116     reference=SvRV(ST(0));
13117     av=(AV *) reference;
13118     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13119       exception);
13120     for (i=1; i < items; i++)
13121       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13122         SvPV(ST(i),na),exception);
13123     InheritPerlException(exception,perl_exception);
13124     exception=DestroyExceptionInfo(exception);
13125     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13126   }
13127 \f
13128 #
13129 ###############################################################################
13130 #                                                                             #
13131 #                                                                             #
13132 #                                                                             #
13133 #   S e t                                                                     #
13134 #                                                                             #
13135 #                                                                             #
13136 #                                                                             #
13137 ###############################################################################
13138 #
13139 #
13140 void
13141 Set(ref,...)
13142   Image::Magick ref=NO_INIT
13143   ALIAS:
13144     SetAttributes  = 1
13145     SetAttribute   = 2
13146     set            = 3
13147     setattributes  = 4
13148     setattribute   = 5
13149   PPCODE:
13150   {
13151     ExceptionInfo
13152       *exception;
13153
13154     Image
13155       *image;
13156
13157     register ssize_t
13158       i;
13159
13160     struct PackageInfo
13161       *info;
13162
13163     SV
13164       *perl_exception,
13165       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13166
13167     PERL_UNUSED_VAR(ref);
13168     PERL_UNUSED_VAR(ix);
13169     exception=AcquireExceptionInfo();
13170     perl_exception=newSVpv("",0);
13171     if (sv_isobject(ST(0)) == 0)
13172       {
13173         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13174           PackageName);
13175         goto PerlException;
13176       }
13177     reference=SvRV(ST(0));
13178     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13179     if (items == 2)
13180       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13181     else
13182       for (i=2; i < items; i+=2)
13183         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13184
13185   PerlException:
13186     InheritPerlException(exception,perl_exception);
13187     exception=DestroyExceptionInfo(exception);
13188     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13189     SvPOK_on(perl_exception);
13190     ST(0)=sv_2mortal(perl_exception);
13191     XSRETURN(1);
13192   }
13193 \f
13194 #
13195 ###############################################################################
13196 #                                                                             #
13197 #                                                                             #
13198 #                                                                             #
13199 #   S e t P i x e l                                                           #
13200 #                                                                             #
13201 #                                                                             #
13202 #                                                                             #
13203 ###############################################################################
13204 #
13205 #
13206 void
13207 SetPixel(ref,...)
13208   Image::Magick ref=NO_INIT
13209   ALIAS:
13210     setpixel = 1
13211     setPixel = 2
13212   PPCODE:
13213   {
13214     AV
13215       *av;
13216
13217     char
13218       *attribute;
13219
13220     ChannelType
13221       channel;
13222
13223     ExceptionInfo
13224       *exception;
13225
13226     Image
13227       *image;
13228
13229     MagickBooleanType
13230       normalize;
13231
13232     RectangleInfo
13233       region;
13234
13235     register IndexPacket
13236       *indexes;
13237
13238     register ssize_t
13239       i;
13240
13241     register PixelPacket
13242       *q;
13243
13244     ssize_t
13245       option;
13246
13247     struct PackageInfo
13248       *info;
13249
13250     SV
13251       *perl_exception,
13252       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13253
13254     PERL_UNUSED_VAR(ref);
13255     PERL_UNUSED_VAR(ix);
13256     exception=AcquireExceptionInfo();
13257     perl_exception=newSVpv("",0);
13258     reference=SvRV(ST(0));
13259     av=(AV *) reference;
13260     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13261       exception);
13262     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13263     if (image == (Image *) NULL)
13264       {
13265         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13266           PackageName);
13267         goto PerlException;
13268       }
13269     av=(AV *) NULL;
13270     channel=DefaultChannels;
13271     normalize=MagickTrue;
13272     region.x=0;
13273     region.y=0;
13274     region.width=image->columns;
13275     region.height=1;
13276     if (items == 1)
13277       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13278     for (i=2; i < items; i+=2)
13279     {
13280       attribute=(char *) SvPV(ST(i-1),na);
13281       switch (*attribute)
13282       {
13283         case 'C':
13284         case 'c':
13285         {
13286           if (LocaleCompare(attribute,"channel") == 0)
13287             {
13288               ssize_t
13289                 option;
13290
13291               option=ParseChannelOption(SvPV(ST(i),na));
13292               if (option < 0)
13293                 {
13294                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13295                     SvPV(ST(i),na));
13296                   return;
13297                 }
13298                channel=(ChannelType) option;
13299               break;
13300             }
13301           if (LocaleCompare(attribute,"color") == 0)
13302             {
13303               if (SvTYPE(ST(i)) != SVt_RV)
13304                 {
13305                   char
13306                     message[MaxTextExtent];
13307
13308                   (void) FormatLocaleString(message,MaxTextExtent,
13309                     "invalid %.60s value",attribute);
13310                   ThrowPerlException(exception,OptionError,message,
13311                     SvPV(ST(i),na));
13312                 }
13313               av=(AV *) SvRV(ST(i));
13314               break;
13315             }
13316           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13317             attribute);
13318           break;
13319         }
13320         case 'g':
13321         case 'G':
13322         {
13323           if (LocaleCompare(attribute,"geometry") == 0)
13324             {
13325               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13326               break;
13327             }
13328           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13329             attribute);
13330           break;
13331         }
13332         case 'N':
13333         case 'n':
13334         {
13335           if (LocaleCompare(attribute,"normalize") == 0)
13336             {
13337               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13338                 SvPV(ST(i),na));
13339               if (option < 0)
13340                 {
13341                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13342                     SvPV(ST(i),na));
13343                   break;
13344                 }
13345              normalize=option != 0 ? MagickTrue : MagickFalse;
13346              break;
13347             }
13348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13349             attribute);
13350           break;
13351         }
13352         case 'x':
13353         case 'X':
13354         {
13355           if (LocaleCompare(attribute,"x") == 0)
13356             {
13357               region.x=SvIV(ST(i));
13358               break;
13359             }
13360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13361             attribute);
13362           break;
13363         }
13364         case 'y':
13365         case 'Y':
13366         {
13367           if (LocaleCompare(attribute,"y") == 0)
13368             {
13369               region.y=SvIV(ST(i));
13370               break;
13371             }
13372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13373             attribute);
13374           break;
13375         }
13376         default:
13377         {
13378           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13379             attribute);
13380           break;
13381         }
13382       }
13383     }
13384     (void) SetImageStorageClass(image,DirectClass);
13385     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13386     if ((q == (PixelPacket *) NULL) || (av == (AV *) NULL) ||
13387         (SvTYPE(av) != SVt_PVAV))
13388       PUSHs(&sv_undef);
13389     else
13390       {
13391         double
13392           scale;
13393
13394         register ssize_t
13395           i;
13396
13397         i=0;
13398         indexes=GetAuthenticIndexQueue(image);
13399         scale=1.0;
13400         if (normalize != MagickFalse)
13401           scale=QuantumRange;
13402         if (((channel & RedChannel) != 0) && (i <= av_len(av)))
13403           {
13404             SetRedPixelComponent(q,ClampToQuantum(scale*SvNV(*(
13405               av_fetch(av,i,0)))));
13406             i++;
13407           }
13408         if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
13409           {
13410             SetGreenPixelComponent(q,ClampToQuantum(scale*SvNV(*(
13411               av_fetch(av,i,0)))));
13412             i++;
13413           }
13414         if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
13415           {
13416             SetBluePixelComponent(q,ClampToQuantum(scale*SvNV(*(
13417               av_fetch(av,i,0)))));
13418             i++;
13419           }
13420         if ((((channel & IndexChannel) != 0) &&
13421             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13422           {
13423             SetIndexPixelComponent(indexes,ClampToQuantum(scale*
13424               SvNV(*(av_fetch(av,i,0)))));
13425             i++;
13426           }
13427         if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
13428           {
13429             SetOpacityPixelComponent(q,ClampToQuantum(scale*
13430               SvNV(*(av_fetch(av,i,0)))));
13431             i++;
13432           }
13433         (void) SyncAuthenticPixels(image,exception);
13434       }
13435
13436   PerlException:
13437     InheritPerlException(exception,perl_exception);
13438     exception=DestroyExceptionInfo(exception);
13439     SvREFCNT_dec(perl_exception);
13440   }
13441 \f
13442 #
13443 ###############################################################################
13444 #                                                                             #
13445 #                                                                             #
13446 #                                                                             #
13447 #   S m u s h                                                                 #
13448 #                                                                             #
13449 #                                                                             #
13450 #                                                                             #
13451 ###############################################################################
13452 #
13453 #
13454 void
13455 Smush(ref,...)
13456   Image::Magick ref=NO_INIT
13457   ALIAS:
13458     SmushImage  = 1
13459     smush       = 2
13460     smushimage  = 3
13461   PPCODE:
13462   {
13463     AV
13464       *av;
13465
13466     char
13467       *attribute;
13468
13469     ExceptionInfo
13470       *exception;
13471
13472     HV
13473       *hv;
13474
13475     Image
13476       *image;
13477
13478     register ssize_t
13479       i;
13480
13481     ssize_t
13482       offset,
13483       stack;
13484
13485     struct PackageInfo
13486       *info;
13487
13488     SV
13489       *av_reference,
13490       *perl_exception,
13491       *reference,
13492       *rv,
13493       *sv;
13494
13495     PERL_UNUSED_VAR(ref);
13496     PERL_UNUSED_VAR(ix);
13497     exception=AcquireExceptionInfo();
13498     perl_exception=newSVpv("",0);
13499     sv=NULL;
13500     attribute=NULL;
13501     av=NULL;
13502     if (sv_isobject(ST(0)) == 0)
13503       {
13504         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13505           PackageName);
13506         goto PerlException;
13507       }
13508     reference=SvRV(ST(0));
13509     hv=SvSTASH(reference);
13510     av=newAV();
13511     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13512     SvREFCNT_dec(av);
13513     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13514     if (image == (Image *) NULL)
13515       {
13516         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13517           PackageName);
13518         goto PerlException;
13519       }
13520     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13521     /*
13522       Get options.
13523     */
13524     offset=0;
13525     stack=MagickTrue;
13526     for (i=2; i < items; i+=2)
13527     {
13528       attribute=(char *) SvPV(ST(i-1),na);
13529       switch (*attribute)
13530       {
13531         case 'O':
13532         case 'o':
13533         {
13534           if (LocaleCompare(attribute,"offset") == 0)
13535             {
13536               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13537               break;
13538             }
13539           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13540             attribute);
13541           break;
13542         }
13543         case 'S':
13544         case 's':
13545         {
13546           if (LocaleCompare(attribute,"stack") == 0)
13547             {
13548               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13549                 SvPV(ST(i),na));
13550               if (stack < 0)
13551                 {
13552                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13553                     SvPV(ST(i),na));
13554                   return;
13555                 }
13556               break;
13557             }
13558           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13559             attribute);
13560           break;
13561         }
13562         default:
13563         {
13564           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13565             attribute);
13566           break;
13567         }
13568       }
13569     }
13570     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13571       exception);
13572     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13573       goto PerlException;
13574     for ( ; image; image=image->next)
13575     {
13576       AddImageToRegistry(sv,image);
13577       rv=newRV(sv);
13578       av_push(av,sv_bless(rv,hv));
13579       SvREFCNT_dec(sv);
13580     }
13581     exception=DestroyExceptionInfo(exception);
13582     ST(0)=av_reference;
13583     SvREFCNT_dec(perl_exception);
13584     XSRETURN(1);
13585
13586   PerlException:
13587     InheritPerlException(exception,perl_exception);
13588     exception=DestroyExceptionInfo(exception);
13589     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13590     SvPOK_on(perl_exception);
13591     ST(0)=sv_2mortal(perl_exception);
13592     XSRETURN(1);
13593   }
13594 \f
13595 #
13596 ###############################################################################
13597 #                                                                             #
13598 #                                                                             #
13599 #                                                                             #
13600 #   S t a t i s t i c s                                                       #
13601 #                                                                             #
13602 #                                                                             #
13603 #                                                                             #
13604 ###############################################################################
13605 #
13606 #
13607 void
13608 Statistics(ref,...)
13609   Image::Magick ref=NO_INIT
13610   ALIAS:
13611     StatisticsImage = 1
13612     statistics      = 2
13613     statisticsimage = 3
13614   PPCODE:
13615   {
13616 #define ChannelStatistics(channel) \
13617 { \
13618   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13619     (double) channel_statistics[channel].depth); \
13620   PUSHs(sv_2mortal(newSVpv(message,0))); \
13621   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13622     channel_statistics[channel].minima/scale); \
13623   PUSHs(sv_2mortal(newSVpv(message,0))); \
13624   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13625     channel_statistics[channel].maxima/scale); \
13626   PUSHs(sv_2mortal(newSVpv(message,0))); \
13627   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13628     channel_statistics[channel].mean/scale); \
13629   PUSHs(sv_2mortal(newSVpv(message,0))); \
13630   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13631     channel_statistics[channel].standard_deviation/scale); \
13632   PUSHs(sv_2mortal(newSVpv(message,0))); \
13633   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13634     channel_statistics[channel].kurtosis); \
13635   PUSHs(sv_2mortal(newSVpv(message,0))); \
13636   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13637     channel_statistics[channel].skewness); \
13638   PUSHs(sv_2mortal(newSVpv(message,0))); \
13639 }
13640
13641     AV
13642       *av;
13643
13644     char
13645       message[MaxTextExtent];
13646
13647     ChannelStatistics
13648       *channel_statistics;
13649
13650     double
13651       scale;
13652
13653     ExceptionInfo
13654       *exception;
13655
13656     Image
13657       *image;
13658
13659     ssize_t
13660       count;
13661
13662     struct PackageInfo
13663       *info;
13664
13665     SV
13666       *perl_exception,
13667       *reference;
13668
13669     PERL_UNUSED_VAR(ref);
13670     PERL_UNUSED_VAR(ix);
13671     exception=AcquireExceptionInfo();
13672     perl_exception=newSVpv("",0);
13673     av=NULL;
13674     if (sv_isobject(ST(0)) == 0)
13675       {
13676         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13677           PackageName);
13678         goto PerlException;
13679       }
13680     reference=SvRV(ST(0));
13681     av=newAV();
13682     SvREFCNT_dec(av);
13683     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13684     if (image == (Image *) NULL)
13685       {
13686         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13687           PackageName);
13688         goto PerlException;
13689       }
13690     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13691     count=0;
13692     for ( ; image; image=image->next)
13693     {
13694       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13695       if (channel_statistics == (ChannelStatistics *) NULL)
13696         continue;
13697       count++;
13698       EXTEND(sp,35*count);
13699       scale=(double) QuantumRange;
13700       ChannelStatistics(RedChannel);
13701       ChannelStatistics(GreenChannel);
13702       ChannelStatistics(BlueChannel);
13703       if (image->colorspace == CMYKColorspace)
13704         ChannelStatistics(IndexChannel);
13705       if (image->matte != MagickFalse)
13706         ChannelStatistics(OpacityChannel);
13707       channel_statistics=(ChannelStatistics *)
13708         RelinquishMagickMemory(channel_statistics);
13709     }
13710
13711   PerlException:
13712     InheritPerlException(exception,perl_exception);
13713     exception=DestroyExceptionInfo(exception);
13714     SvREFCNT_dec(perl_exception);
13715   }
13716 \f
13717 #
13718 ###############################################################################
13719 #                                                                             #
13720 #                                                                             #
13721 #                                                                             #
13722 #   S y n c A u t h e n t i c P i x e l s                                     #
13723 #                                                                             #
13724 #                                                                             #
13725 #                                                                             #
13726 ###############################################################################
13727 #
13728 #
13729 void
13730 SyncAuthenticPixels(ref,...)
13731   Image::Magick ref = NO_INIT
13732   ALIAS:
13733     Syncauthenticpixels = 1
13734     SyncImagePixels = 2
13735     syncimagepixels = 3
13736   CODE:
13737   {
13738     ExceptionInfo
13739       *exception;
13740
13741     Image
13742       *image;
13743
13744     MagickBooleanType
13745       status;
13746
13747     struct PackageInfo
13748       *info;
13749
13750     SV
13751       *perl_exception,
13752       *reference;
13753
13754     PERL_UNUSED_VAR(ref);
13755     PERL_UNUSED_VAR(ix);
13756     exception=AcquireExceptionInfo();
13757     perl_exception=newSVpv("",0);
13758     if (sv_isobject(ST(0)) == 0)
13759       {
13760         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13761           PackageName);
13762         goto PerlException;
13763       }
13764
13765     reference=SvRV(ST(0));
13766     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13767     if (image == (Image *) NULL)
13768       {
13769         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13770           PackageName);
13771         goto PerlException;
13772       }
13773
13774     status=SyncAuthenticPixels(image,exception);
13775     if (status != MagickFalse)
13776       return;
13777     InheritException(exception,&image->exception);
13778
13779   PerlException:
13780     InheritPerlException(exception,perl_exception);
13781     exception=DestroyExceptionInfo(exception);
13782     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13783   }
13784 \f
13785 #
13786 ###############################################################################
13787 #                                                                             #
13788 #                                                                             #
13789 #                                                                             #
13790 #   T r a n s f o r m                                                         #
13791 #                                                                             #
13792 #                                                                             #
13793 #                                                                             #
13794 ###############################################################################
13795 #
13796 #
13797 void
13798 Transform(ref,...)
13799   Image::Magick ref=NO_INIT
13800   ALIAS:
13801     TransformImage = 1
13802     transform      = 2
13803     transformimage = 3
13804   PPCODE:
13805   {
13806     AV
13807       *av;
13808
13809     char
13810       *attribute,
13811       *crop_geometry,
13812       *geometry;
13813
13814     ExceptionInfo
13815       *exception;
13816
13817     HV
13818       *hv;
13819
13820     Image
13821       *clone,
13822       *image;
13823
13824     register ssize_t
13825       i;
13826
13827     struct PackageInfo
13828       *info;
13829
13830     SV
13831       *av_reference,
13832       *perl_exception,
13833       *reference,
13834       *rv,
13835       *sv;
13836
13837     PERL_UNUSED_VAR(ref);
13838     PERL_UNUSED_VAR(ix);
13839     exception=AcquireExceptionInfo();
13840     perl_exception=newSVpv("",0);
13841     sv=NULL;
13842     av=NULL;
13843     attribute=NULL;
13844     if (sv_isobject(ST(0)) == 0)
13845       {
13846         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13847           PackageName);
13848         goto PerlException;
13849       }
13850     reference=SvRV(ST(0));
13851     hv=SvSTASH(reference);
13852     av=newAV();
13853     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13854     SvREFCNT_dec(av);
13855     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13856     if (image == (Image *) NULL)
13857       {
13858         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13859           PackageName);
13860         goto PerlException;
13861       }
13862     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13863     /*
13864       Get attribute.
13865     */
13866     crop_geometry=(char *) NULL;
13867     geometry=(char *) NULL;
13868     for (i=2; i < items; i+=2)
13869     {
13870       attribute=(char *) SvPV(ST(i-1),na);
13871       switch (*attribute)
13872       {
13873         case 'c':
13874         case 'C':
13875         {
13876           if (LocaleCompare(attribute,"crop") == 0)
13877             {
13878               crop_geometry=SvPV(ST(i),na);
13879               break;
13880             }
13881           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13882             attribute);
13883           break;
13884         }
13885         case 'g':
13886         case 'G':
13887         {
13888           if (LocaleCompare(attribute,"geometry") == 0)
13889             {
13890               geometry=SvPV(ST(i),na);
13891               break;
13892             }
13893          if (LocaleCompare(attribute,"gravity") == 0)
13894            {
13895              Image
13896                *next;
13897
13898              ssize_t
13899                in;
13900
13901              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13902                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13903              if (in < 0)
13904                {
13905                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13906                    SvPV(ST(i),na));
13907                  return;
13908                }
13909              for (next=image; next; next=next->next)
13910                next->gravity=(GravityType) in;
13911              break;
13912            }
13913           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13914             attribute);
13915           break;
13916         }
13917         default:
13918         {
13919           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13920             attribute);
13921           break;
13922         }
13923       }
13924     }
13925     for ( ; image; image=image->next)
13926     {
13927       clone=CloneImage(image,0,0,MagickTrue,exception);
13928       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13929         goto PerlException;
13930       TransformImage(&clone,crop_geometry,geometry);
13931       for ( ; clone; clone=clone->next)
13932       {
13933         AddImageToRegistry(sv,clone);
13934         rv=newRV(sv);
13935         av_push(av,sv_bless(rv,hv));
13936         SvREFCNT_dec(sv);
13937       }
13938     }
13939     exception=DestroyExceptionInfo(exception);
13940     ST(0)=av_reference;
13941     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13942     XSRETURN(1);
13943
13944   PerlException:
13945     InheritPerlException(exception,perl_exception);
13946     exception=DestroyExceptionInfo(exception);
13947     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13948     SvPOK_on(perl_exception);
13949     ST(0)=sv_2mortal(perl_exception);
13950     XSRETURN(1);
13951   }
13952 \f
13953 #
13954 ###############################################################################
13955 #                                                                             #
13956 #                                                                             #
13957 #                                                                             #
13958 #   W r i t e                                                                 #
13959 #                                                                             #
13960 #                                                                             #
13961 #                                                                             #
13962 ###############################################################################
13963 #
13964 #
13965 void
13966 Write(ref,...)
13967   Image::Magick ref=NO_INIT
13968   ALIAS:
13969     WriteImage    = 1
13970     write         = 2
13971     writeimage    = 3
13972   PPCODE:
13973   {
13974     char
13975       filename[MaxTextExtent];
13976
13977     ExceptionInfo
13978       *exception;
13979
13980     Image
13981       *image,
13982       *next;
13983
13984     register ssize_t
13985       i;
13986
13987     ssize_t
13988       number_images,
13989       scene;
13990
13991     struct PackageInfo
13992       *info,
13993       *package_info;
13994
13995     SV
13996       *perl_exception,
13997       *reference;
13998
13999     PERL_UNUSED_VAR(ref);
14000     PERL_UNUSED_VAR(ix);
14001     exception=AcquireExceptionInfo();
14002     perl_exception=newSVpv("",0);
14003     number_images=0;
14004     package_info=(struct PackageInfo *) NULL;
14005     if (sv_isobject(ST(0)) == 0)
14006       {
14007         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14008           PackageName);
14009         goto PerlException;
14010       }
14011     reference=SvRV(ST(0));
14012     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14013     if (image == (Image *) NULL)
14014       {
14015         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14016           PackageName);
14017         goto PerlException;
14018       }
14019     package_info=ClonePackageInfo(info,exception);
14020     if (items == 2)
14021       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14022     else
14023       if (items > 2)
14024         for (i=2; i < items; i+=2)
14025           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14026             exception);
14027     (void) CopyMagickString(filename,package_info->image_info->filename,
14028       MaxTextExtent);
14029     scene=0;
14030     for (next=image; next; next=next->next)
14031     {
14032       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14033       next->scene=scene++;
14034     }
14035     SetImageInfo(package_info->image_info,(unsigned int)
14036       GetImageListLength(image),&image->exception);
14037     for (next=image; next; next=next->next)
14038     {
14039       (void) WriteImage(package_info->image_info,next);
14040       if (next->exception.severity >= ErrorException)
14041         InheritException(exception,&next->exception);
14042       GetImageException(next,exception);
14043       number_images++;
14044       if (package_info->image_info->adjoin)
14045         break;
14046     }
14047
14048   PerlException:
14049     if (package_info != (struct PackageInfo *) NULL)
14050       DestroyPackageInfo(package_info);
14051     InheritPerlException(exception,perl_exception);
14052     exception=DestroyExceptionInfo(exception);
14053     sv_setiv(perl_exception,(IV) number_images);
14054     SvPOK_on(perl_exception);
14055     ST(0)=sv_2mortal(perl_exception);
14056     XSRETURN(1);
14057   }