]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
85be652880d424ecb18c89a8a52a23a4e170a2ff
[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-2010 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  32
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(image) \
98 { \
99   if (magick_registry != (SplayTreeInfo *) NULL) \
100     { \
101       (void) AddValueToSplayTree(magick_registry,image,image); \
102       sv=newSViv((IV) image); \
103     } \
104 }
105
106 #define DeleteImageFromRegistry(reference,image) \
107 { \
108   if (magick_registry != (SplayTreeInfo *) NULL) \
109     { \
110       if (GetImageReferenceCount(image) == 1) \
111        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
112       image=DestroyImage(image); \
113       sv_setiv(reference,0); \
114     } \
115 }
116
117 #define InheritPerlException(exception,perl_exception) \
118 { \
119   char \
120     message[MaxTextExtent]; \
121  \
122   if ((exception)->severity != UndefinedException) \
123     { \
124       (void) FormatMagickString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
125         (exception)->severity, (exception)->reason ? \
126         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
127         "Unknown", (exception)->description ? " (" : "", \
128         (exception)->description ? GetLocaleExceptionMessage( \
129         (exception)->severity,(exception)->description) : "", \
130         (exception)->description ? ")" : ""); \
131       if ((perl_exception) != (SV *) NULL) \
132         { \
133           if (SvCUR(perl_exception)) \
134             sv_catpv(perl_exception,"\n"); \
135           sv_catpv(perl_exception,message); \
136         } \
137     } \
138 }
139
140 #define ThrowPerlException(exception,severity,tag,reason) \
141   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
142     tag,"`%s'",reason); \
143 \f
144 /*
145   Typedef and structure declarations.
146 */
147 typedef enum
148 {
149   ArrayReference = (~0),
150   RealReference = (~0)-1,
151   FileReference = (~0)-2,
152   ImageReference = (~0)-3,
153   IntegerReference = (~0)-4,
154   StringReference = (~0)-5
155 } MagickReference;
156
157 typedef struct _Arguments
158 {
159   const char
160     *method;
161
162   long
163     type;
164 } Arguments;
165
166 struct ArgumentList
167 {
168   long
169     long_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", { {"radius", RealReference} } },
245     { "Minify", },
246     { "OilPaint", { {"radius", RealReference} } },
247     { "ReduceNoise", { {"radius", RealReference} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
251       {"color", StringReference}, {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference} } },
264     { "Swirl", { {"degrees", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
267       {"height", IntegerReference}, {"filter", MagickFilterOptions},
268       {"support", StringReference }, {"blur", RealReference } } },
269     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", RealReference }, {"blur", RealReference } } },
272     { "Annotate", { {"text", StringReference}, {"font", StringReference},
273       {"pointsize", RealReference}, {"density", StringReference},
274       {"undercolor", StringReference}, {"stroke", StringReference},
275       {"fill", StringReference}, {"geometry", StringReference},
276       {"pen", StringReference}, {"x", RealReference},
277       {"y", RealReference}, {"gravity", MagickGravityOptions},
278       {"translate", StringReference}, {"scale", StringReference},
279       {"rotate", RealReference}, {"skewX", RealReference},
280       {"skewY", RealReference}, {"strokewidth", RealReference},
281       {"antialias", MagickBooleanOptions}, {"family", StringReference},
282       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
283       {"weight", IntegerReference}, {"align", MagickAlignOptions},
284       {"encoding", StringReference}, {"affine", ArrayReference},
285       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
286       {"tile", ImageReference}, {"kerning", RealReference},
287       {"interline-spacing", RealReference},
288       {"interword-spacing", RealReference},
289       {"direction", MagickDirectionOptions} } },
290     { "ColorFloodfill", { {"geometry", StringReference},
291       {"x", IntegerReference}, {"y", IntegerReference},
292       {"fill", StringReference}, {"bordercolor", StringReference},
293       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
294     { "Composite", { {"image", ImageReference},
295       {"compose", MagickComposeOptions}, {"geometry", StringReference},
296       {"x", IntegerReference}, {"y", IntegerReference},
297       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
298       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
299       {"color", StringReference}, {"mask", ImageReference},
300       {"channel", MagickChannelOptions},
301       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
302       {"blend", StringReference} } },
303     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
304     { "CycleColormap", { {"display", IntegerReference} } },
305     { "Draw", { {"primitive", MagickPrimitiveOptions},
306       {"points", StringReference}, {"method", MagickMethodOptions},
307       {"stroke", StringReference}, {"fill", StringReference},
308       {"strokewidth", RealReference}, {"font", StringReference},
309       {"bordercolor", StringReference}, {"x", RealReference},
310       {"y", RealReference}, {"translate", StringReference},
311       {"scale", StringReference}, {"rotate", RealReference},
312       {"skewX", RealReference}, {"skewY", RealReference},
313       {"tile", ImageReference}, {"pointsize", RealReference},
314       {"antialias", MagickBooleanOptions}, {"density", StringReference},
315       {"linewidth", RealReference}, {"affine", ArrayReference},
316       {"stroke-dashoffset", RealReference},
317       {"stroke-dasharray", ArrayReference},
318       {"interpolate", MagickInterpolateOptions},
319       {"origin", StringReference}, {"text", StringReference},
320       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
321       {"vector-graphics", StringReference}, {"kerning", RealReference},
322       {"interline-spacing", RealReference},
323       {"interword-spacing", RealReference} } },
324     { "Equalize", { {"channel", MagickChannelOptions} } },
325     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
326       {"red", RealReference}, {"green", RealReference},
327       {"blue", RealReference} } },
328     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
329       {"dither-method", MagickDitherOptions} } },
330     { "MatteFloodfill", { {"geometry", StringReference},
331       {"x", IntegerReference}, {"y", IntegerReference},
332       {"opacity", StringReference}, {"bordercolor", StringReference},
333       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
334     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
335       {"saturation", RealReference}, {"whiteness", RealReference},
336       {"brightness", RealReference}, {"lightness", RealReference},
337       {"blackness", RealReference} } },
338     { "Negate", { {"gray", MagickBooleanOptions},
339       {"channel", MagickChannelOptions} } },
340     { "Normalize", { {"channel", MagickChannelOptions} } },
341     { "NumberColors", },
342     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
343       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
344       {"invert", MagickBooleanOptions} } },
345     { "Quantize", { {"colors", IntegerReference},
346       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
347       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
348       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
349       {"dither-method", MagickDitherOptions} } },
350     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
351       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
352     { "Segment", { {"geometry", StringReference},
353       {"cluster-threshold", RealReference},
354       {"smoothing-threshold", RealReference},
355       {"colorspace", MagickColorspaceOptions},
356       {"verbose", MagickBooleanOptions} } },
357     { "Signature", },
358     { "Solarize", { {"geometry", StringReference},
359       {"threshold", StringReference} } },
360     { "Sync", },
361     { "Texture", { {"texture", ImageReference} } },
362     { "Evaluate", { {"value", RealReference},
363       {"operator", MagickEvaluateOptions},
364       {"channel", MagickChannelOptions} } },
365     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
366       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
367     { "Threshold", { {"threshold", StringReference},
368       {"channel", MagickChannelOptions} } },
369     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
370       {"sigma", RealReference} } },
371     { "Trim", { {"fuzz", StringReference} } },
372     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
373       {"wavelength", RealReference},
374       {"interpolate", MagickInterpolateOptions} } },
375     { "Separate", { {"channel", MagickChannelOptions} } },
376     { "Condense", },
377     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
378       {"y", IntegerReference} } },
379     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
380     { "Deconstruct", },
381     { "GaussianBlur", { {"geometry", StringReference},
382       {"radius", RealReference}, {"sigma", RealReference},
383       {"channel", MagickChannelOptions} } },
384     { "Convolve", { {"coefficients", ArrayReference},
385       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
386     { "Profile", { {"name", StringReference}, {"profile", StringReference},
387       { "rendering-intent", MagickIntentOptions},
388       { "black-point-compensation", MagickBooleanOptions} } },
389     { "UnsharpMask", { {"geometry", StringReference},
390       {"radius", RealReference}, {"sigma", RealReference},
391       {"amount", RealReference}, {"threshold", RealReference},
392       {"channel", MagickChannelOptions} } },
393     { "MotionBlur", { {"geometry", StringReference},
394       {"radius", RealReference}, {"sigma", RealReference},
395       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
396     { "OrderedDither", { {"threshold", StringReference},
397       {"channel", MagickChannelOptions} } },
398     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
399       {"height", IntegerReference} } },
400     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
401       {"white-point", RealReference}, {"gamma", RealReference},
402       {"channel", MagickChannelOptions}, {"level", StringReference} } },
403     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
404     { "AffineTransform", { {"affine", ArrayReference},
405       {"translate", StringReference}, {"scale", StringReference},
406       {"rotate", RealReference}, {"skewX", RealReference},
407       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
408       {"background", StringReference} } },
409     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
410     { "AdaptiveThreshold", { {"geometry", StringReference},
411       {"width", IntegerReference}, {"height", IntegerReference},
412       {"offset", IntegerReference} } },
413     { "Resample", { {"density", StringReference}, {"x", RealReference},
414       {"y", RealReference}, {"filter", MagickFilterOptions},
415       {"support", RealReference }, {"blur", RealReference } } },
416     { "Describe", { {"file", FileReference} } },
417     { "BlackThreshold", { {"threshold", StringReference},
418       {"channel", MagickChannelOptions} } },
419     { "WhiteThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
422       {"channel", MagickChannelOptions} } },
423     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
424       {"height", IntegerReference} } },
425     { "Strip", },
426     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
427     { "Channel", { {"channel", MagickChannelOptions} } },
428     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference}, {"x", IntegerReference},
430       {"y", IntegerReference}, {"fuzz", StringReference},
431       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
432     { "Posterize", { {"levels", IntegerReference},
433       {"dither", MagickBooleanOptions} } },
434     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
435       {"sigma", RealReference}, {"x", IntegerReference},
436       {"y", IntegerReference} } },
437     { "Identify", { {"file", FileReference}, {"features", StringReference},
438       {"unique", MagickBooleanOptions} } },
439     { "SepiaTone", { {"threshold", RealReference} } },
440     { "SigmoidalContrast", { {"geometry", StringReference},
441       {"contrast", RealReference}, {"mid-point", RealReference},
442       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
443     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
444       {"height", IntegerReference}, {"x", IntegerReference},
445       {"y", IntegerReference}, {"fuzz", StringReference},
446       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
447     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
448       {"sigma", RealReference}, {"x", IntegerReference},
449       {"y", IntegerReference}, {"background", StringReference} } },
450     { "ContrastStretch", { {"levels", StringReference},
451       {"black-point", RealReference},{"white-point", RealReference},
452       {"channel", MagickChannelOptions} } },
453     { "Sans0", },
454     { "Sans1", },
455     { "AdaptiveSharpen", { {"geometry", StringReference},
456       {"radius", RealReference}, {"sigma", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Transpose", },
459     { "Transverse", },
460     { "AutoOrient", },
461     { "AdaptiveBlur", { {"geometry", StringReference},
462       {"radius", RealReference}, {"sigma", RealReference},
463       {"channel", MagickChannelOptions} } },
464     { "Sketch", { {"geometry", StringReference},
465       {"radius", RealReference}, {"sigma", RealReference},
466       {"angle", RealReference} } },
467     { "UniqueColors", },
468     { "AdaptiveResize", { {"geometry", StringReference},
469       {"width", IntegerReference}, {"height", IntegerReference},
470       {"filter", MagickFilterOptions}, {"support", StringReference },
471       {"blur", RealReference } } },
472     { "ClipMask", { {"mask", ImageReference} } },
473     { "LinearStretch", { {"levels", StringReference},
474       {"black-point", RealReference},{"white-point", RealReference} } },
475     { "Recolor", { {"matrix", ArrayReference} } },
476     { "Mask", { {"mask", ImageReference} } },
477     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
478       {"font", StringReference}, {"stroke", StringReference},
479       {"fill", StringReference}, {"strokewidth", RealReference},
480       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
481       {"background", StringReference} } },
482     { "FloodfillPaint", { {"geometry", StringReference},
483       {"x", IntegerReference}, {"y", IntegerReference},
484       {"fill", StringReference}, {"bordercolor", StringReference},
485       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
486       {"invert", MagickBooleanOptions} } },
487     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
488       {"virtual-pixel", MagickVirtualPixelOptions},
489       {"best-fit", MagickBooleanOptions} } },
490     { "Clut", { {"image", ImageReference},
491       {"channel", MagickChannelOptions} } },
492     { "LiquidRescale", { {"geometry", StringReference},
493       {"width", IntegerReference}, {"height", IntegerReference},
494       {"delta-x", RealReference}, {"rigidity", RealReference } } },
495     { "Encipher", { {"passphrase", StringReference} } },
496     { "Decipher", { {"passphrase", StringReference} } },
497     { "Deskew", { {"geometry", StringReference},
498       {"threshold", StringReference} } },
499     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
500       {"dither-method", MagickDitherOptions} } },
501     { "SparseColor", { {"points", ArrayReference},
502       {"method", MagickSparseColorOptions},
503       {"virtual-pixel", MagickVirtualPixelOptions},
504       {"channel", MagickChannelOptions} } },
505     { "Function", { {"parameters", ArrayReference},
506       {"function", MagickFunctionOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions} } },
508     { "SelectiveBlur", { {"geometry", StringReference},
509       {"radius", RealReference}, {"sigma", RealReference},
510       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
511     { "HaldClut", { {"image", ImageReference},
512       {"channel", MagickChannelOptions} } },
513     { "BlueShift", { {"factor", StringReference} } },
514     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
515     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
516     { "ColorDecisionList", {
517       {"color-correction-collection", StringReference} } },
518     { "AutoGamma", { {"channel", MagickChannelOptions} } },
519     { "AutoLevel", { {"channel", MagickChannelOptions} } },
520     { "LevelColors", { {"invert", MagickBooleanOptions},
521       {"black-point", RealReference}, {"white-point", RealReference},
522       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
523     { "Clamp", { {"channel", MagickChannelOptions} } },
524     { "Filter", { {"kernel", StringReference},
525       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
526     { "BrightnessContrast", { {"levels", StringReference},
527       {"brightness", RealReference},{"contrast", RealReference},
528       {"channel", MagickChannelOptions} } },
529     { "Morphology", { {"kernel", StringReference},
530       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
531       {"iterations", IntegerReference} } },
532     { "ColorMatrix", { {"matrix", ArrayReference} } },
533   };
534
535 static SplayTreeInfo
536   *magick_registry = (SplayTreeInfo *) NULL;
537 \f
538 /*
539   Forward declarations.
540 */
541 static Image
542   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
543
544 static long
545   strEQcase(const char *,const char *);
546 \f
547 /*
548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549 %                                                                             %
550 %                                                                             %
551 %                                                                             %
552 %   C l o n e P a c k a g e I n f o                                           %
553 %                                                                             %
554 %                                                                             %
555 %                                                                             %
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 %
558 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
559 %  a new one.
560 %
561 %  The format of the ClonePackageInfo routine is:
562 %
563 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
564 %        exception)
565 %
566 %  A description of each parameter follows:
567 %
568 %    o info: a structure of type info.
569 %
570 %    o exception: Return any errors or warnings in this structure.
571 %
572 */
573 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
574   ExceptionInfo *exception)
575 {
576   struct PackageInfo
577     *clone_info;
578
579   clone_info=(struct PackageInfo *) AcquireAlignedMemory(1,sizeof(*clone_info));
580   if (clone_info == (struct PackageInfo *) NULL)
581     {
582       ThrowPerlException(exception,ResourceLimitError,
583         "UnableToClonePackageInfo",PackageName);
584       return((struct PackageInfo *) NULL);
585     }
586   if (info == (struct PackageInfo *) NULL)
587     {
588       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
589       return(clone_info);
590     }
591   *clone_info=(*info);
592   clone_info->image_info=CloneImageInfo(info->image_info);
593   return(clone_info);
594 }
595 \f
596 /*
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 %                                                                             %
599 %                                                                             %
600 %                                                                             %
601 %   c o n s t a n t                                                           %
602 %                                                                             %
603 %                                                                             %
604 %                                                                             %
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 %
607 %  constant() returns a double value for the specified name.
608 %
609 %  The format of the constant routine is:
610 %
611 %      double constant(char *name,long sans)
612 %
613 %  A description of each parameter follows:
614 %
615 %    o value: Method constant returns a double value for the specified name.
616 %
617 %    o name: The name of the constant.
618 %
619 %    o sans: This integer value is not used.
620 %
621 */
622 static double constant(char *name,long sans)
623 {
624   (void) sans;
625   errno=0;
626   switch (*name)
627   {
628     case 'B':
629     {
630       if (strEQ(name,"BlobError"))
631         return(BlobError);
632       if (strEQ(name,"BlobWarning"))
633         return(BlobWarning);
634       break;
635     }
636     case 'C':
637     {
638       if (strEQ(name,"CacheError"))
639         return(CacheError);
640       if (strEQ(name,"CacheWarning"))
641         return(CacheWarning);
642       if (strEQ(name,"CoderError"))
643         return(CoderError);
644       if (strEQ(name,"CoderWarning"))
645         return(CoderWarning);
646       if (strEQ(name,"ConfigureError"))
647         return(ConfigureError);
648       if (strEQ(name,"ConfigureWarning"))
649         return(ConfigureWarning);
650       if (strEQ(name,"CorruptImageError"))
651         return(CorruptImageError);
652       if (strEQ(name,"CorruptImageWarning"))
653         return(CorruptImageWarning);
654       break;
655     }
656     case 'D':
657     {
658       if (strEQ(name,"DelegateError"))
659         return(DelegateError);
660       if (strEQ(name,"DelegateWarning"))
661         return(DelegateWarning);
662       if (strEQ(name,"DrawError"))
663         return(DrawError);
664       if (strEQ(name,"DrawWarning"))
665         return(DrawWarning);
666       break;
667     }
668     case 'E':
669     {
670       if (strEQ(name,"ErrorException"))
671         return(ErrorException);
672       if (strEQ(name,"ExceptionError"))
673         return(CoderError);
674       if (strEQ(name,"ExceptionWarning"))
675         return(CoderWarning);
676       break;
677     }
678     case 'F':
679     {
680       if (strEQ(name,"FatalErrorException"))
681         return(FatalErrorException);
682       if (strEQ(name,"FileOpenError"))
683         return(FileOpenError);
684       if (strEQ(name,"FileOpenWarning"))
685         return(FileOpenWarning);
686       break;
687     }
688     case 'I':
689     {
690       if (strEQ(name,"ImageError"))
691         return(ImageError);
692       if (strEQ(name,"ImageWarning"))
693         return(ImageWarning);
694       break;
695     }
696     case 'M':
697     {
698       if (strEQ(name,"MaxRGB"))
699         return(QuantumRange);
700       if (strEQ(name,"MissingDelegateError"))
701         return(MissingDelegateError);
702       if (strEQ(name,"MissingDelegateWarning"))
703         return(MissingDelegateWarning);
704       if (strEQ(name,"ModuleError"))
705         return(ModuleError);
706       if (strEQ(name,"ModuleWarning"))
707         return(ModuleWarning);
708       break;
709     }
710     case 'O':
711     {
712       if (strEQ(name,"Opaque"))
713         return(OpaqueOpacity);
714       if (strEQ(name,"OptionError"))
715         return(OptionError);
716       if (strEQ(name,"OptionWarning"))
717         return(OptionWarning);
718       break;
719     }
720     case 'Q':
721     {
722       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
723         return(MAGICKCORE_QUANTUM_DEPTH);
724       if (strEQ(name,"QuantumDepth"))
725         return(QuantumDepth);
726       if (strEQ(name,"QuantumRange"))
727         return(QuantumRange);
728       break;
729     }
730     case 'R':
731     {
732       if (strEQ(name,"ResourceLimitError"))
733         return(ResourceLimitError);
734       if (strEQ(name,"ResourceLimitWarning"))
735         return(ResourceLimitWarning);
736       if (strEQ(name,"RegistryError"))
737         return(RegistryError);
738       if (strEQ(name,"RegistryWarning"))
739         return(RegistryWarning);
740       break;
741     }
742     case 'S':
743     {
744       if (strEQ(name,"StreamError"))
745         return(StreamError);
746       if (strEQ(name,"StreamWarning"))
747         return(StreamWarning);
748       if (strEQ(name,"Success"))
749         return(0);
750       break;
751     }
752     case 'T':
753     {
754       if (strEQ(name,"Transparent"))
755         return(TransparentOpacity);
756       if (strEQ(name,"TypeError"))
757         return(TypeError);
758       if (strEQ(name,"TypeWarning"))
759         return(TypeWarning);
760       break;
761     }
762     case 'W':
763     {
764       if (strEQ(name,"WarningException"))
765         return(WarningException);
766       break;
767     }
768     case 'X':
769     {
770       if (strEQ(name,"XServerError"))
771         return(XServerError);
772       if (strEQ(name,"XServerWarning"))
773         return(XServerWarning);
774       break;
775     }
776   }
777   errno=EINVAL;
778   return(0);
779 }
780 \f
781 /*
782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
783 %                                                                             %
784 %                                                                             %
785 %                                                                             %
786 %   D e s t r o y P a c k a g e I n f o                                       %
787 %                                                                             %
788 %                                                                             %
789 %                                                                             %
790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791 %
792 %  Method DestroyPackageInfo frees a previously created info structure.
793 %
794 %  The format of the DestroyPackageInfo routine is:
795 %
796 %      DestroyPackageInfo(struct PackageInfo *info)
797 %
798 %  A description of each parameter follows:
799 %
800 %    o info: a structure of type info.
801 %
802 */
803 static void DestroyPackageInfo(struct PackageInfo *info)
804 {
805   info->image_info=DestroyImageInfo(info->image_info);
806   info=(struct PackageInfo *) RelinquishMagickMemory(info);
807 }
808 \f
809 /*
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811 %                                                                             %
812 %                                                                             %
813 %                                                                             %
814 %   G e t L i s t                                                             %
815 %                                                                             %
816 %                                                                             %
817 %                                                                             %
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 %
820 %  Method GetList is recursively called by SetupList to traverse the
821 %  Image__Magick reference.  If building an reference_vector (see SetupList),
822 %  *current is the current position in *reference_vector and *last is the final
823 %  entry in *reference_vector.
824 %
825 %  The format of the GetList routine is:
826 %
827 %      GetList(info)
828 %
829 %  A description of each parameter follows:
830 %
831 %    o info: a structure of type info.
832 %
833 */
834 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,long *current,
835   long *last,ExceptionInfo *exception)
836 {
837   Image
838     *image;
839
840   if (reference == (SV *) NULL)
841     return(NULL);
842   switch (SvTYPE(reference))
843   {
844     case SVt_PVAV:
845     {
846       AV
847         *av;
848
849       Image
850         *head,
851         *previous;
852
853       long
854         n;
855
856       register long
857         i;
858
859       /*
860         Array of images.
861       */
862       previous=(Image *) NULL;
863       head=(Image *) NULL;
864       av=(AV *) reference;
865       n=av_len(av);
866       for (i=0; i <= n; i++)
867       {
868         SV
869           **rv;
870
871         rv=av_fetch(av,i,0);
872         if (rv && *rv && sv_isobject(*rv))
873           {
874             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
875               exception);
876             if (image == (Image *) NULL)
877               continue;
878             if (image == previous)
879               {
880                 image=CloneImage(image,0,0,MagickTrue,exception);
881                 if (image == (Image *) NULL)
882                   return(NULL);
883               }
884             image->previous=previous;
885             *(previous ? &previous->next : &head)=image;
886             for (previous=image; previous->next; previous=previous->next) ;
887           }
888       }
889       return(head);
890     }
891     case SVt_PVMG:
892     {
893       /*
894         Blessed scalar, one image.
895       */
896       image=(Image *) SvIV(reference);
897       if (image == (Image *) NULL)
898         return(NULL);
899       image->previous=(Image *) NULL;
900       image->next=(Image *) NULL;
901       if (reference_vector)
902         {
903           if (*current == *last)
904             {
905               *last+=256;
906               if (*reference_vector == (SV **) NULL)
907                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
908                   sizeof(*reference_vector));
909               else
910                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
911                   *last,sizeof(*reference_vector));
912             }
913           if (*reference_vector == (SV **) NULL)
914             {
915               ThrowPerlException(exception,ResourceLimitError,
916                 "MemoryAllocationFailed",PackageName);
917               return((Image *) NULL);
918             }
919           (*reference_vector)[*current]=reference;
920           (*reference_vector)[++(*current)]=NULL;
921         }
922       return(image);
923     }
924     default:
925       break;
926   }
927   (void) fprintf(stderr,"GetList: UnrecognizedType %ld\n",
928     (long) SvTYPE(reference));
929   return((Image *) NULL);
930 }
931 \f
932 /*
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 %                                                                             %
935 %                                                                             %
936 %                                                                             %
937 %   G e t P a c k a g e I n f o                                               %
938 %                                                                             %
939 %                                                                             %
940 %                                                                             %
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 %
943 %  Method GetPackageInfo looks up or creates an info structure for the given
944 %  Image__Magick reference.  If it does create a new one, the information in
945 %  package_info is used to initialize it.
946 %
947 %  The format of the GetPackageInfo routine is:
948 %
949 %      struct PackageInfo *GetPackageInfo(void *reference,
950 %        struct PackageInfo *package_info,ExceptionInfo *exception)
951 %
952 %  A description of each parameter follows:
953 %
954 %    o info: a structure of type info.
955 %
956 %    o exception: Return any errors or warnings in this structure.
957 %
958 */
959 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
960   struct PackageInfo *package_info,ExceptionInfo *exception)
961 {
962   char
963     message[MaxTextExtent];
964
965   struct PackageInfo
966     *clone_info;
967
968   SV
969     *sv;
970
971   (void) FormatMagickString(message,MaxTextExtent,"%s::package%s%lx",
972     PackageName,XS_VERSION,(long) reference);
973   sv=perl_get_sv(message,(TRUE | 0x02));
974   if (sv == (SV *) NULL)
975     {
976       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
977         message);
978       return(package_info);
979     }
980   if (SvREFCNT(sv) == 0)
981     (void) SvREFCNT_inc(sv);
982   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
983     return(clone_info);
984   clone_info=ClonePackageInfo(package_info,exception);
985   sv_setiv(sv,(IV) clone_info);
986   return(clone_info);
987 }
988 \f
989 /*
990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 %                                                                             %
992 %                                                                             %
993 %                                                                             %
994 %   S e t A t t r i b u t e                                                   %
995 %                                                                             %
996 %                                                                             %
997 %                                                                             %
998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999 %
1000 %  SetAttribute() sets the attribute to the value in sval.  This can change
1001 %  either or both of image or info.
1002 %
1003 %  The format of the SetAttribute routine is:
1004 %
1005 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1006 %        SV *sval,ExceptionInfo *exception)
1007 %
1008 %  A description of each parameter follows:
1009 %
1010 %    o list: a list of strings.
1011 %
1012 %    o string: a character string.
1013 %
1014 */
1015
1016 static inline double SiPrefixToDouble(const char *string,const double interval)
1017 {
1018   char
1019     *q;
1020
1021   double
1022     scale,
1023     value;
1024
1025   value=strtod(string,&q);
1026   scale=1000.0;
1027   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1028     scale=1024.0;
1029   switch (tolower((int) ((unsigned char) *q)))
1030   {
1031     case '%': value*=pow(scale,0)*interval/100.0; break;
1032     case 'k': value*=pow(scale,1); break;
1033     case 'm': value*=pow(scale,2); break;
1034     case 'g': value*=pow(scale,3); break;
1035     case 't': value*=pow(scale,4); break;
1036     case 'p': value*=pow(scale,5); break;
1037     case 'e': value*=pow(scale,6); break;
1038     case 'z': value*=pow(scale,7); break;
1039     case 'y': value*=pow(scale,8); break;
1040     default:  break;
1041   }
1042   return(value);
1043 }
1044
1045 static inline double StringToDouble(const char *value)
1046 {
1047   return(strtod(value,(char **) NULL));
1048 }
1049
1050 static inline long StringToLong(const char *value)
1051 {
1052   return(strtol(value,(char **) NULL,10));
1053 }
1054
1055 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1056   const char *attribute,SV *sval,ExceptionInfo *exception)
1057 {
1058   GeometryInfo
1059     geometry_info;
1060
1061   long
1062     sp;
1063
1064   long
1065     x,
1066     y;
1067
1068   MagickPixelPacket
1069     pixel;
1070
1071   MagickStatusType
1072     flags;
1073
1074   PixelPacket
1075     *color,
1076     target_color;
1077
1078   switch (*attribute)
1079   {
1080     case 'A':
1081     case 'a':
1082     {
1083       if (LocaleCompare(attribute,"adjoin") == 0)
1084         {
1085           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1086             SvPV(sval,na)) : SvIV(sval);
1087           if (sp < 0)
1088             {
1089               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1090                 SvPV(sval,na));
1091               break;
1092             }
1093           if (info)
1094             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1095           break;
1096         }
1097       if (LocaleCompare(attribute,"alpha") == 0)
1098         {
1099           sp=SvPOK(sval) ? ParseMagickOption(MagickAlphaOptions,MagickFalse,
1100             SvPV(sval,na)) : SvIV(sval);
1101           if (sp < 0)
1102             {
1103               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1104                 SvPV(sval,na));
1105               break;
1106             }
1107           for ( ; image; image=image->next)
1108             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1109           break;
1110         }
1111       if (LocaleCompare(attribute,"antialias") == 0)
1112         {
1113           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1114             SvPV(sval,na)) : SvIV(sval);
1115           if (sp < 0)
1116             {
1117               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1118                 SvPV(sval,na));
1119               break;
1120             }
1121           if (info)
1122             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1123           break;
1124         }
1125       if (LocaleCompare(attribute,"area-limit") == 0)
1126         {
1127           MagickSizeType
1128             limit;
1129
1130           limit=MagickResourceInfinity;
1131           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1132             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1133           (void) SetMagickResourceLimit(AreaResource,limit);
1134           break;
1135         }
1136       if (LocaleCompare(attribute,"attenuate") == 0)
1137         {
1138           if (info)
1139             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"authenticate") == 0)
1143         {
1144           if (info)
1145             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1146           break;
1147         }
1148       if (info)
1149         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1150       for ( ; image; image=image->next)
1151         SetImageProperty(image,attribute,SvPV(sval,na));
1152       break;
1153     }
1154     case 'B':
1155     case 'b':
1156     {
1157       if (LocaleCompare(attribute,"background") == 0)
1158         {
1159           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1160           if (info)
1161             info->image_info->background_color=target_color;
1162           for ( ; image; image=image->next)
1163             image->background_color=target_color;
1164           break;
1165         }
1166       if (LocaleCompare(attribute,"bias") == 0)
1167         {
1168           for ( ; image; image=image->next)
1169             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1170           break;
1171         }
1172       if (LocaleCompare(attribute,"blue-primary") == 0)
1173         {
1174           for ( ; image; image=image->next)
1175           {
1176             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1177             image->chromaticity.blue_primary.x=geometry_info.rho;
1178             image->chromaticity.blue_primary.y=geometry_info.sigma;
1179             if ((flags & SigmaValue) == 0)
1180               image->chromaticity.blue_primary.y=
1181                 image->chromaticity.blue_primary.x;
1182           }
1183           break;
1184         }
1185       if (LocaleCompare(attribute,"bordercolor") == 0)
1186         {
1187           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1188           if (info)
1189             info->image_info->border_color=target_color;
1190           for ( ; image; image=image->next)
1191             image->border_color=target_color;
1192           break;
1193         }
1194       if (info)
1195         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1196       for ( ; image; image=image->next)
1197         SetImageProperty(image,attribute,SvPV(sval,na));
1198       break;
1199     }
1200     case 'C':
1201     case 'c':
1202     {
1203       if (LocaleCompare(attribute,"cache-threshold") == 0)
1204         {
1205           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1206             SiPrefixToDouble(SvPV(sval,na),100.0));
1207           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1208             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1209           break;
1210         }
1211       if (LocaleCompare(attribute,"clip-mask") == 0)
1212         {
1213           Image
1214             *clip_mask;
1215
1216           clip_mask=(Image *) NULL;
1217           if (SvPOK(sval))
1218             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1219           for ( ; image; image=image->next)
1220             SetImageClipMask(image,clip_mask);
1221           break;
1222         }
1223       if (LocaleNCompare(attribute,"colormap",8) == 0)
1224         {
1225           for ( ; image; image=image->next)
1226           {
1227             int
1228               items;
1229
1230             long
1231               i;
1232
1233             if (image->storage_class == DirectClass)
1234               continue;
1235             i=0;
1236             items=sscanf(attribute,"%*[^[][%ld",&i);
1237             if (i > (long) image->colors)
1238               i%=image->colors;
1239             if ((strchr(SvPV(sval,na),',') == 0) ||
1240                 (strchr(SvPV(sval,na),')') != 0))
1241               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1242             else
1243               {
1244                 color=image->colormap+i;
1245                 pixel.red=color->red;
1246                 pixel.green=color->green;
1247                 pixel.blue=color->blue;
1248                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1249                 pixel.red=geometry_info.rho;
1250                 pixel.green=geometry_info.sigma;
1251                 pixel.blue=geometry_info.xi;
1252                 color->red=ClampToQuantum(pixel.red);
1253                 color->green=ClampToQuantum(pixel.green);
1254                 color->blue=ClampToQuantum(pixel.blue);
1255               }
1256           }
1257           break;
1258         }
1259       if (LocaleCompare(attribute,"colorspace") == 0)
1260         {
1261           sp=SvPOK(sval) ? ParseMagickOption(MagickColorspaceOptions,
1262             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1263           if (sp < 0)
1264             {
1265               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1266                 SvPV(sval,na));
1267               break;
1268             }
1269           for ( ; image; image=image->next)
1270             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1271           break;
1272         }
1273       if (LocaleCompare(attribute,"comment") == 0)
1274         {
1275           for ( ; image; image=image->next)
1276             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1277               info ? info->image_info : (ImageInfo *) NULL,image,
1278               SvPV(sval,na)));
1279           break;
1280         }
1281       if (LocaleCompare(attribute,"compression") == 0)
1282         {
1283           sp=SvPOK(sval) ? ParseMagickOption(MagickCompressOptions,
1284             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1285           if (sp < 0)
1286             {
1287               ThrowPerlException(exception,OptionError,
1288                 "UnrecognizedImageCompression",SvPV(sval,na));
1289               break;
1290             }
1291           if (info)
1292             info->image_info->compression=(CompressionType) sp;
1293           for ( ; image; image=image->next)
1294             image->compression=(CompressionType) sp;
1295           break;
1296         }
1297       if (info)
1298         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1299       for ( ; image; image=image->next)
1300         SetImageProperty(image,attribute,SvPV(sval,na));
1301       break;
1302     }
1303     case 'D':
1304     case 'd':
1305     {
1306       if (LocaleCompare(attribute,"debug") == 0)
1307         {
1308           SetLogEventMask(SvPV(sval,na));
1309           break;
1310         }
1311       if (LocaleCompare(attribute,"delay") == 0)
1312         {
1313           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1314           for ( ; image; image=image->next)
1315           {
1316             image->delay=(unsigned long) floor(geometry_info.rho+0.5);
1317             if ((flags & SigmaValue) != 0)
1318               image->ticks_per_second=(unsigned long)
1319                 floor(geometry_info.sigma+0.5);
1320           }
1321           break;
1322         }
1323       if (LocaleCompare(attribute,"disk-limit") == 0)
1324         {
1325           MagickSizeType
1326             limit;
1327
1328           limit=MagickResourceInfinity;
1329           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1330             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1331           (void) SetMagickResourceLimit(DiskResource,limit);
1332           break;
1333         }
1334       if (LocaleCompare(attribute,"density") == 0)
1335         {
1336           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1337             {
1338               ThrowPerlException(exception,OptionError,"MissingGeometry",
1339                 SvPV(sval,na));
1340               break;
1341             }
1342           if (info)
1343             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1344           for ( ; image; image=image->next)
1345           {
1346             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1347             image->x_resolution=geometry_info.rho;
1348             image->y_resolution=geometry_info.sigma;
1349             if ((flags & SigmaValue) == 0)
1350               image->y_resolution=image->x_resolution;
1351           }
1352           break;
1353         }
1354       if (LocaleCompare(attribute,"depth") == 0)
1355         {
1356           if (info)
1357             info->image_info->depth=SvIV(sval);
1358           for ( ; image; image=image->next)
1359             (void) SetImageDepth(image,SvIV(sval));
1360           break;
1361         }
1362       if (LocaleCompare(attribute,"dispose") == 0)
1363         {
1364           sp=SvPOK(sval) ? ParseMagickOption(MagickDisposeOptions,MagickFalse,
1365             SvPV(sval,na)) : SvIV(sval);
1366           if (sp < 0)
1367             {
1368               ThrowPerlException(exception,OptionError,
1369                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1370               break;
1371             }
1372           for ( ; image; image=image->next)
1373             image->dispose=(DisposeType) sp;
1374           break;
1375         }
1376       if (LocaleCompare(attribute,"dither") == 0)
1377         {
1378           if (info)
1379             {
1380               sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,
1381                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1382               if (sp < 0)
1383                 {
1384                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1385                     SvPV(sval,na));
1386                   break;
1387                 }
1388               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1389             }
1390           break;
1391         }
1392       if (LocaleCompare(attribute,"display") == 0)
1393         {
1394           display:
1395           if (info)
1396             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1397           break;
1398         }
1399       if (info)
1400         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1401       for ( ; image; image=image->next)
1402         SetImageProperty(image,attribute,SvPV(sval,na));
1403       break;
1404     }
1405     case 'E':
1406     case 'e':
1407     {
1408       if (LocaleCompare(attribute,"endian") == 0)
1409         {
1410           sp=SvPOK(sval) ? ParseMagickOption(MagickEndianOptions,MagickFalse,
1411             SvPV(sval,na)) : SvIV(sval);
1412           if (sp < 0)
1413             {
1414               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1415                 SvPV(sval,na));
1416               break;
1417             }
1418           if (info)
1419             info->image_info->endian=(EndianType) sp;
1420           for ( ; image; image=image->next)
1421             image->endian=(EndianType) sp;
1422           break;
1423         }
1424       if (LocaleCompare(attribute,"extract") == 0)
1425         {
1426           /*
1427             Set image extract geometry.
1428           */
1429           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1430           break;
1431         }
1432       if (info)
1433         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1434       for ( ; image; image=image->next)
1435         SetImageProperty(image,attribute,SvPV(sval,na));
1436       break;
1437     }
1438     case 'F':
1439     case 'f':
1440     {
1441       if (LocaleCompare(attribute,"filename") == 0)
1442         {
1443           if (info)
1444             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1445               MaxTextExtent);
1446           for ( ; image; image=image->next)
1447             (void) CopyMagickString(image->filename,SvPV(sval,na),
1448               MaxTextExtent);
1449           break;
1450         }
1451       if (LocaleCompare(attribute,"file") == 0)
1452         {
1453           FILE
1454             *file;
1455
1456           PerlIO
1457             *io_info;
1458
1459           if (info == (struct PackageInfo *) NULL)
1460             break;
1461           io_info=IoIFP(sv_2io(sval));
1462           if (io_info == (PerlIO *) NULL)
1463             {
1464               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1465                 PackageName);
1466               break;
1467             }
1468           file=PerlIO_findFILE(io_info);
1469           if (file == (FILE *) NULL)
1470             {
1471               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1472                 PackageName);
1473               break;
1474             }
1475           SetImageInfoFile(info->image_info,file);
1476           break;
1477         }
1478       if (LocaleCompare(attribute,"fill") == 0)
1479         {
1480           if (info)
1481             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1482           break;
1483         }
1484       if (LocaleCompare(attribute,"font") == 0)
1485         {
1486           if (info)
1487             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"foreground") == 0)
1491         break;
1492       if (LocaleCompare(attribute,"fuzz") == 0)
1493         {
1494           if (info)
1495             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1496           for ( ; image; image=image->next)
1497             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1498           break;
1499         }
1500       if (info)
1501         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1502       for ( ; image; image=image->next)
1503         SetImageProperty(image,attribute,SvPV(sval,na));
1504       break;
1505     }
1506     case 'G':
1507     case 'g':
1508     {
1509       if (LocaleCompare(attribute,"gamma") == 0)
1510         {
1511           for ( ; image; image=image->next)
1512             image->gamma=SvNV(sval);
1513           break;
1514         }
1515       if (LocaleCompare(attribute,"gravity") == 0)
1516         {
1517           sp=SvPOK(sval) ? ParseMagickOption(MagickGravityOptions,MagickFalse,
1518             SvPV(sval,na)) : SvIV(sval);
1519           if (sp < 0)
1520             {
1521               ThrowPerlException(exception,OptionError,
1522                 "UnrecognizedGravityType",SvPV(sval,na));
1523               break;
1524             }
1525           for ( ; image; image=image->next)
1526             image->gravity=(GravityType) sp;
1527           break;
1528         }
1529       if (LocaleCompare(attribute,"green-primary") == 0)
1530         {
1531           for ( ; image; image=image->next)
1532           {
1533             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1534             image->chromaticity.green_primary.x=geometry_info.rho;
1535             image->chromaticity.green_primary.y=geometry_info.sigma;
1536             if ((flags & SigmaValue) == 0)
1537               image->chromaticity.green_primary.y=
1538                 image->chromaticity.green_primary.x;
1539           }
1540           break;
1541         }
1542       if (info)
1543         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1544       for ( ; image; image=image->next)
1545         SetImageProperty(image,attribute,SvPV(sval,na));
1546       break;
1547     }
1548     case 'I':
1549     case 'i':
1550     {
1551       if (LocaleNCompare(attribute,"index",5) == 0)
1552         {
1553           IndexPacket
1554             *indexes;
1555
1556           int
1557             items;
1558
1559           long
1560             index;
1561
1562           register PixelPacket
1563             *p;
1564
1565           CacheView
1566             *image_view;
1567
1568           for ( ; image; image=image->next)
1569           {
1570             if (image->storage_class != PseudoClass)
1571               continue;
1572             x=0;
1573             y=0;
1574             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1575             image_view=AcquireCacheView(image);
1576             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1577             if (p != (PixelPacket *) NULL)
1578               {
1579                 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1580                 items=sscanf(SvPV(sval,na),"%ld",&index);
1581                 if ((index >= 0) && (index < (long) image->colors))
1582                   *indexes=(IndexPacket) index;
1583                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1584               }
1585             image_view=DestroyCacheView(image_view);
1586           }
1587           break;
1588         }
1589       if (LocaleCompare(attribute,"iterations") == 0)
1590         {
1591   iterations:
1592           for ( ; image; image=image->next)
1593             image->iterations=SvIV(sval);
1594           break;
1595         }
1596       if (LocaleCompare(attribute,"interlace") == 0)
1597         {
1598           sp=SvPOK(sval) ? ParseMagickOption(MagickInterlaceOptions,MagickFalse,
1599             SvPV(sval,na)) : SvIV(sval);
1600           if (sp < 0)
1601             {
1602               ThrowPerlException(exception,OptionError,
1603                 "UnrecognizedInterlaceType",SvPV(sval,na));
1604               break;
1605             }
1606           if (info)
1607             info->image_info->interlace=(InterlaceType) sp;
1608           for ( ; image; image=image->next)
1609             image->interlace=(InterlaceType) sp;
1610           break;
1611         }
1612       if (info)
1613         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1614       for ( ; image; image=image->next)
1615         SetImageProperty(image,attribute,SvPV(sval,na));
1616       break;
1617     }
1618     case 'L':
1619     case 'l':
1620     {
1621       if (LocaleCompare(attribute,"label") == 0)
1622         {
1623           for ( ; image; image=image->next)
1624             (void) SetImageProperty(image,"label",InterpretImageProperties(
1625               info ? info->image_info : (ImageInfo *) NULL,image,
1626               SvPV(sval,na)));
1627           break;
1628         }
1629       if (LocaleCompare(attribute,"loop") == 0)
1630         goto iterations;
1631       if (info)
1632         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1633       for ( ; image; image=image->next)
1634         SetImageProperty(image,attribute,SvPV(sval,na));
1635       break;
1636     }
1637     case 'M':
1638     case 'm':
1639     {
1640       if (LocaleCompare(attribute,"magick") == 0)
1641         {
1642           if (info)
1643             (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
1644               "%.1024s:",SvPV(sval,na));
1645           for ( ; image; image=image->next)
1646             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1647           break;
1648         }
1649       if (LocaleCompare(attribute,"map-limit") == 0)
1650         {
1651           MagickSizeType
1652             limit;
1653
1654           limit=MagickResourceInfinity;
1655           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1656             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1657           (void) SetMagickResourceLimit(MapResource,limit);
1658           break;
1659         }
1660       if (LocaleCompare(attribute,"mask") == 0)
1661         {
1662           Image
1663             *mask;
1664
1665           mask=(Image *) NULL;
1666           if (SvPOK(sval))
1667             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1668           for ( ; image; image=image->next)
1669             SetImageMask(image,mask);
1670           break;
1671         }
1672       if (LocaleCompare(attribute,"mattecolor") == 0)
1673         {
1674           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1675           if (info)
1676             info->image_info->matte_color=target_color;
1677           for ( ; image; image=image->next)
1678             image->matte_color=target_color;
1679           break;
1680         }
1681       if (LocaleCompare(attribute,"matte") == 0)
1682         {
1683           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1684             SvPV(sval,na)) : SvIV(sval);
1685           if (sp < 0)
1686             {
1687               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1688                 SvPV(sval,na));
1689               break;
1690             }
1691           for ( ; image; image=image->next)
1692             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1693           break;
1694         }
1695       if (LocaleCompare(attribute,"memory-limit") == 0)
1696         {
1697           MagickSizeType
1698             limit;
1699
1700           limit=MagickResourceInfinity;
1701           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1702             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1703           (void) SetMagickResourceLimit(MemoryResource,limit);
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"monochrome") == 0)
1707         {
1708           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1709             SvPV(sval,na)) : SvIV(sval);
1710           if (sp < 0)
1711             {
1712               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1713                 SvPV(sval,na));
1714               break;
1715             }
1716           if (info)
1717             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1718           for ( ; image; image=image->next)
1719             (void) SetImageType(image,BilevelType);
1720           break;
1721         }
1722       if (info)
1723         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1724       for ( ; image; image=image->next)
1725         SetImageProperty(image,attribute,SvPV(sval,na));
1726       break;
1727     }
1728     case 'O':
1729     case 'o':
1730     {
1731       if (LocaleCompare(attribute,"option") == 0)
1732         {
1733           if (info)
1734             DefineImageOption(info->image_info,SvPV(sval,na));
1735           break;
1736         }
1737       if (LocaleCompare(attribute,"orientation") == 0)
1738         {
1739           sp=SvPOK(sval) ? ParseMagickOption(MagickOrientationOptions,
1740             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1741           if (sp < 0)
1742             {
1743               ThrowPerlException(exception,OptionError,
1744                 "UnrecognizedOrientationType",SvPV(sval,na));
1745               break;
1746             }
1747           if (info)
1748             info->image_info->orientation=(OrientationType) sp;
1749           for ( ; image; image=image->next)
1750             image->orientation=(OrientationType) sp;
1751           break;
1752         }
1753       if (info)
1754         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1755       for ( ; image; image=image->next)
1756         SetImageProperty(image,attribute,SvPV(sval,na));
1757       break;
1758     }
1759     case 'P':
1760     case 'p':
1761     {
1762       if (LocaleCompare(attribute,"page") == 0)
1763         {
1764           char
1765             *geometry;
1766
1767           geometry=GetPageGeometry(SvPV(sval,na));
1768           if (info)
1769             (void) CloneString(&info->image_info->page,geometry);
1770           for ( ; image; image=image->next)
1771             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1772           geometry=(char *) RelinquishMagickMemory(geometry);
1773           break;
1774         }
1775       if (LocaleCompare(attribute,"pen") == 0)
1776         {
1777           if (info)
1778             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1779           break;
1780         }
1781       if (LocaleNCompare(attribute,"pixel",5) == 0)
1782         {
1783           int
1784             items;
1785
1786           MagickPixelPacket
1787             pixel;
1788
1789           register IndexPacket
1790             *indexes;
1791
1792           register PixelPacket
1793             *p;
1794
1795           CacheView
1796             *image_view;
1797
1798           for ( ; image; image=image->next)
1799           {
1800             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1801               break;
1802             x=0;
1803             y=0;
1804             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1805             image_view=AcquireCacheView(image);
1806             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1807             indexes=GetCacheViewAuthenticIndexQueue(image_view);
1808             if (p != (PixelPacket *) NULL)
1809               {
1810                 if ((strchr(SvPV(sval,na),',') == 0) ||
1811                     (strchr(SvPV(sval,na),')') != 0))
1812                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1813                 else
1814                   {
1815                     GetMagickPixelPacket(image,&pixel);
1816                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1817                     pixel.red=geometry_info.rho;
1818                     if ((flags & SigmaValue) != 0)
1819                       pixel.green=geometry_info.sigma;
1820                     if ((flags & XiValue) != 0)
1821                       pixel.blue=geometry_info.xi;
1822                     if ((flags & PsiValue) != 0)
1823                       pixel.opacity=geometry_info.psi;
1824                     if ((flags & ChiValue) != 0)
1825                       pixel.index=geometry_info.chi;
1826                   }
1827                 p->red=ClampToQuantum(pixel.red);
1828                 p->green=ClampToQuantum(pixel.green);
1829                 p->blue=ClampToQuantum(pixel.blue);
1830                 p->opacity=ClampToQuantum(pixel.opacity);
1831                 if (((image->colorspace == CMYKColorspace) ||
1832                      (image->storage_class == PseudoClass)) &&
1833                     (indexes != (IndexPacket *) NULL))
1834                   *indexes=ClampToQuantum(pixel.index);
1835                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1836               }
1837             image_view=DestroyCacheView(image_view);
1838           }
1839           break;
1840         }
1841       if (LocaleCompare(attribute,"pointsize") == 0)
1842         {
1843           if (info)
1844             {
1845               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1846               info->image_info->pointsize=geometry_info.rho;
1847             }
1848           break;
1849         }
1850       if (LocaleCompare(attribute,"preview") == 0)
1851         {
1852           sp=SvPOK(sval) ? ParseMagickOption(MagickPreviewOptions,MagickFalse,
1853             SvPV(sval,na)) : SvIV(sval);
1854           if (sp < 0)
1855             {
1856               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1857                 SvPV(sval,na));
1858               break;
1859             }
1860           if (info)
1861             info->image_info->preview_type=(PreviewType) sp;
1862           break;
1863         }
1864       if (info)
1865         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1866       for ( ; image; image=image->next)
1867         SetImageProperty(image,attribute,SvPV(sval,na));
1868       break;
1869     }
1870     case 'Q':
1871     case 'q':
1872     {
1873       if (LocaleCompare(attribute,"quality") == 0)
1874         {
1875           if (info)
1876             info->image_info->quality=SvIV(sval);
1877           for ( ; image; image=image->next)
1878             image->quality=SvIV(sval);
1879           break;
1880         }
1881       if (info)
1882         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1883       for ( ; image; image=image->next)
1884         SetImageProperty(image,attribute,SvPV(sval,na));
1885       break;
1886     }
1887     case 'R':
1888     case 'r':
1889     {
1890       if (LocaleCompare(attribute,"red-primary") == 0)
1891         {
1892           for ( ; image; image=image->next)
1893           {
1894             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1895             image->chromaticity.red_primary.x=geometry_info.rho;
1896             image->chromaticity.red_primary.y=geometry_info.sigma;
1897             if ((flags & SigmaValue) == 0)
1898               image->chromaticity.red_primary.y=
1899                 image->chromaticity.red_primary.x;
1900           }
1901           break;
1902         }
1903       if (LocaleCompare(attribute,"render") == 0)
1904         {
1905           sp=SvPOK(sval) ? ParseMagickOption(MagickIntentOptions,MagickFalse,
1906             SvPV(sval,na)) : SvIV(sval);
1907           if (sp < 0)
1908             {
1909               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1910                 SvPV(sval,na));
1911               break;
1912             }
1913          for ( ; image; image=image->next)
1914            image->rendering_intent=(RenderingIntent) sp;
1915          break;
1916        }
1917       if (LocaleCompare(attribute,"repage") == 0)
1918         {
1919           RectangleInfo
1920             geometry;
1921
1922           for ( ; image; image=image->next)
1923           {
1924             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1925             if ((flags & WidthValue) != 0)
1926               {
1927                 if ((flags & HeightValue) == 0)
1928                   geometry.height=geometry.width;
1929                 image->page.width=geometry.width;
1930                 image->page.height=geometry.height;
1931               }
1932             if ((flags & AspectValue) != 0)
1933               {
1934                 if ((flags & XValue) != 0)
1935                   image->page.x+=geometry.x;
1936                 if ((flags & YValue) != 0)
1937                   image->page.y+=geometry.y;
1938               }
1939             else
1940               {
1941                 if ((flags & XValue) != 0)
1942                   {
1943                     image->page.x=geometry.x;
1944                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1945                       image->page.width=image->columns+geometry.x;
1946                   }
1947                 if ((flags & YValue) != 0)
1948                   {
1949                     image->page.y=geometry.y;
1950                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1951                       image->page.height=image->rows+geometry.y;
1952                   }
1953               }
1954           }
1955           break;
1956         }
1957       if (info)
1958         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1959       for ( ; image; image=image->next)
1960         SetImageProperty(image,attribute,SvPV(sval,na));
1961       break;
1962     }
1963     case 'S':
1964     case 's':
1965     {
1966       if (LocaleCompare(attribute,"sampling-factor") == 0)
1967         {
1968           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1969             {
1970               ThrowPerlException(exception,OptionError,"MissingGeometry",
1971                 SvPV(sval,na));
1972               break;
1973             }
1974           if (info)
1975             (void) CloneString(&info->image_info->sampling_factor,
1976               SvPV(sval,na));
1977           break;
1978         }
1979       if (LocaleCompare(attribute,"scene") == 0)
1980         {
1981           for ( ; image; image=image->next)
1982             image->scene=SvIV(sval);
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"subimage") == 0)
1986         {
1987           if (info)
1988             info->image_info->subimage=SvIV(sval);
1989           break;
1990         }
1991       if (LocaleCompare(attribute,"subrange") == 0)
1992         {
1993           if (info)
1994             info->image_info->subrange=SvIV(sval);
1995           break;
1996         }
1997       if (LocaleCompare(attribute,"server") == 0)
1998         goto display;
1999       if (LocaleCompare(attribute,"size") == 0)
2000         {
2001           if (info)
2002             {
2003               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2004                 {
2005                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2006                     SvPV(sval,na));
2007                   break;
2008                 }
2009               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2010             }
2011           break;
2012         }
2013       if (LocaleCompare(attribute,"stroke") == 0)
2014         {
2015           if (info)
2016             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2017           break;
2018         }
2019       if (info)
2020         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2021       for ( ; image; image=image->next)
2022         SetImageProperty(image,attribute,SvPV(sval,na));
2023       break;
2024     }
2025     case 'T':
2026     case 't':
2027     {
2028       if (LocaleCompare(attribute,"tile") == 0)
2029         {
2030           if (info)
2031             (void) CloneString(&info->image_info->tile,SvPV(sval,na));
2032           break;
2033         }
2034       if (LocaleCompare(attribute,"texture") == 0)
2035         {
2036           if (info)
2037             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2038           break;
2039         }
2040       if (LocaleCompare(attribute,"tile-offset") == 0)
2041         {
2042           char
2043             *geometry;
2044
2045           geometry=GetPageGeometry(SvPV(sval,na));
2046           if (info)
2047             (void) CloneString(&info->image_info->page,geometry);
2048           for ( ; image; image=image->next)
2049             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2050               exception);
2051           geometry=(char *) RelinquishMagickMemory(geometry);
2052           break;
2053         }
2054       if (LocaleCompare(attribute,"time-limit") == 0)
2055         {
2056           MagickSizeType
2057             limit;
2058
2059           limit=MagickResourceInfinity;
2060           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2061             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2062           (void) SetMagickResourceLimit(TimeResource,limit);
2063           break;
2064         }
2065       if (LocaleCompare(attribute,"transparent-color") == 0)
2066         {
2067           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2068           if (info)
2069             info->image_info->transparent_color=target_color;
2070           for ( ; image; image=image->next)
2071             image->transparent_color=target_color;
2072           break;
2073         }
2074       if (LocaleCompare(attribute,"type") == 0)
2075         {
2076           sp=SvPOK(sval) ? ParseMagickOption(MagickTypeOptions,MagickFalse,
2077             SvPV(sval,na)) : SvIV(sval);
2078           if (sp < 0)
2079             {
2080               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2081                 SvPV(sval,na));
2082               break;
2083             }
2084           if (info)
2085             info->image_info->type=(ImageType) sp;
2086           for ( ; image; image=image->next)
2087             SetImageType(image,(ImageType) sp);
2088           break;
2089         }
2090       if (info)
2091         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2092       for ( ; image; image=image->next)
2093         SetImageProperty(image,attribute,SvPV(sval,na));
2094       break;
2095     }
2096     case 'U':
2097     case 'u':
2098     {
2099       if (LocaleCompare(attribute,"units") == 0)
2100         {
2101           sp=SvPOK(sval) ? ParseMagickOption(MagickResolutionOptions,
2102             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2103           if (sp < 0)
2104             {
2105               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2106                 SvPV(sval,na));
2107               break;
2108             }
2109           if (info)
2110             info->image_info->units=(ResolutionType) sp;
2111           for ( ; image; image=image->next)
2112           {
2113             ResolutionType
2114               units;
2115
2116             units=(ResolutionType) sp;
2117             if (image->units != units)
2118               switch (image->units)
2119               {
2120                 case UndefinedResolution:
2121                 case PixelsPerInchResolution:
2122                 {
2123                   if (units == PixelsPerCentimeterResolution)
2124                     {
2125                       image->x_resolution*=2.54;
2126                       image->y_resolution*=2.54;
2127                     }
2128                   break;
2129                 }
2130                 case PixelsPerCentimeterResolution:
2131                 {
2132                   if (units == PixelsPerInchResolution)
2133                     {
2134                       image->x_resolution/=2.54;
2135                       image->y_resolution/=2.54;
2136                     }
2137                   break;
2138                 }
2139               }
2140             image->units=units;
2141           }
2142           break;
2143         }
2144       if (info)
2145         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2146       for ( ; image; image=image->next)
2147         SetImageProperty(image,attribute,SvPV(sval,na));
2148       break;
2149     }
2150     case 'V':
2151     case 'v':
2152     {
2153       if (LocaleCompare(attribute,"verbose") == 0)
2154         {
2155           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
2156             SvPV(sval,na)) : SvIV(sval);
2157           if (sp < 0)
2158             {
2159               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2160                 SvPV(sval,na));
2161               break;
2162             }
2163           if (info)
2164             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2165           break;
2166         }
2167       if (LocaleCompare(attribute,"view") == 0)
2168         {
2169           if (info)
2170             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2171           break;
2172         }
2173       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2174         {
2175           sp=SvPOK(sval) ? ParseMagickOption(MagickVirtualPixelOptions,
2176             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2177           if (sp < 0)
2178             {
2179               ThrowPerlException(exception,OptionError,
2180                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2181               break;
2182             }
2183           if (info)
2184             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2185           for ( ; image; image=image->next)
2186             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2187           break;
2188         }
2189       if (info)
2190         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2191       for ( ; image; image=image->next)
2192         SetImageProperty(image,attribute,SvPV(sval,na));
2193       break;
2194     }
2195     case 'W':
2196     case 'w':
2197     {
2198       if (LocaleCompare(attribute,"white-point") == 0)
2199         {
2200           for ( ; image; image=image->next)
2201           {
2202             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2203             image->chromaticity.white_point.x=geometry_info.rho;
2204             image->chromaticity.white_point.y=geometry_info.sigma;
2205             if ((flags & SigmaValue) == 0)
2206               image->chromaticity.white_point.y=
2207                 image->chromaticity.white_point.x;
2208           }
2209           break;
2210         }
2211       if (info)
2212         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2213       for ( ; image; image=image->next)
2214         SetImageProperty(image,attribute,SvPV(sval,na));
2215       break;
2216     }
2217     default:
2218     {
2219       if (info)
2220         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2221       for ( ; image; image=image->next)
2222         SetImageProperty(image,attribute,SvPV(sval,na));
2223       break;
2224     }
2225   }
2226 }
2227 \f
2228 /*
2229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %   S e t u p L i s t                                                         %
2234 %                                                                             %
2235 %                                                                             %
2236 %                                                                             %
2237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2238 %
2239 %  Method SetupList returns the list of all the images linked by their
2240 %  image->next and image->previous link lists for use with ImageMagick.  If
2241 %  info is non-NULL, an info structure is returned in *info.  If
2242 %  reference_vector is non-NULL,an array of SV* are returned in
2243 %  *reference_vector.  Reference_vector is used when the images are going to be
2244 %  replaced with new Image*'s.
2245 %
2246 %  The format of the SetupList routine is:
2247 %
2248 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2249 %        SV ***reference_vector,ExceptionInfo *exception)
2250 %
2251 %  A description of each parameter follows:
2252 %
2253 %    o list: a list of strings.
2254 %
2255 %    o string: a character string.
2256 %
2257 %    o exception: Return any errors or warnings in this structure.
2258 %
2259 */
2260 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2261   SV ***reference_vector,ExceptionInfo *exception)
2262 {
2263   Image
2264     *image;
2265
2266   long
2267     current,
2268     last;
2269
2270   if (reference_vector)
2271     *reference_vector=NULL;
2272   if (info)
2273     *info=NULL;
2274   current=0;
2275   last=0;
2276   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2277   if (info && (SvTYPE(reference) == SVt_PVAV))
2278     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2279       exception);
2280   return(image);
2281 }
2282 \f
2283 /*
2284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2285 %                                                                             %
2286 %                                                                             %
2287 %                                                                             %
2288 %   s t r E Q c a s e                                                         %
2289 %                                                                             %
2290 %                                                                             %
2291 %                                                                             %
2292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2293 %
2294 %  strEQcase() compares two strings and returns 0 if they are the
2295 %  same or if the second string runs out first.  The comparison is case
2296 %  insensitive.
2297 %
2298 %  The format of the strEQcase routine is:
2299 %
2300 %      long strEQcase(const char *p,const char *q)
2301 %
2302 %  A description of each parameter follows:
2303 %
2304 %    o p: a character string.
2305 %
2306 %    o q: a character string.
2307 %
2308 %
2309 */
2310 static long strEQcase(const char *p,const char *q)
2311 {
2312   char
2313     c;
2314
2315   register long
2316     i;
2317
2318   for (i=0 ; (c=(*q)) != 0; i++)
2319   {
2320     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2321         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2322       return(0);
2323     p++;
2324     q++;
2325   }
2326   return(((*q == 0) && (*p == 0)) ? i : 0);
2327 }
2328 \f
2329 /*
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %   I m a g e : : M a g i c k                                                 %
2335 %                                                                             %
2336 %                                                                             %
2337 %                                                                             %
2338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 %
2340 %
2341 */
2342 MODULE = Image::Magick PACKAGE = Image::Magick
2343
2344 PROTOTYPES: ENABLE
2345
2346 BOOT:
2347   MagickCoreGenesis("PerlMagick",MagickFalse);
2348   SetWarningHandler(NULL);
2349   SetErrorHandler(NULL);
2350   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2351     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2352
2353 void
2354 UNLOAD()
2355   PPCODE:
2356   {
2357     if (magick_registry != (SplayTreeInfo *) NULL)
2358       magick_registry=DestroySplayTree(magick_registry);
2359     MagickCoreTerminus();
2360   }
2361
2362 double
2363 constant(name,argument)
2364   char *name
2365   long argument
2366 \f
2367 #
2368 ###############################################################################
2369 #                                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 #   A n i m a t e                                                             #
2373 #                                                                             #
2374 #                                                                             #
2375 #                                                                             #
2376 ###############################################################################
2377 #
2378 #
2379 void
2380 Animate(ref,...)
2381   Image::Magick ref=NO_INIT
2382   ALIAS:
2383     AnimateImage  = 1
2384     animate       = 2
2385     animateimage  = 3
2386   PPCODE:
2387   {
2388     ExceptionInfo
2389       *exception;
2390
2391     Image
2392       *image;
2393
2394     register long
2395       i;
2396
2397     struct PackageInfo
2398       *info,
2399       *package_info;
2400
2401     SV
2402       *perl_exception,
2403       *reference;
2404
2405     exception=AcquireExceptionInfo();
2406     perl_exception=newSVpv("",0);
2407     package_info=(struct PackageInfo *) NULL;
2408     if (sv_isobject(ST(0)) == 0)
2409       {
2410         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2411           PackageName);
2412         goto PerlException;
2413       }
2414     reference=SvRV(ST(0));
2415     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2416     if (image == (Image *) NULL)
2417       {
2418         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2419           PackageName);
2420         goto PerlException;
2421       }
2422     package_info=ClonePackageInfo(info,exception);
2423     if (items == 2)
2424       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2425     else
2426       if (items > 2)
2427         for (i=2; i < items; i+=2)
2428           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2429             exception);
2430     (void) AnimateImages(package_info->image_info,image);
2431     (void) CatchImageException(image);
2432     InheritException(exception,&image->exception);
2433
2434   PerlException:
2435     if (package_info != (struct PackageInfo *) NULL)
2436       DestroyPackageInfo(package_info);
2437     InheritPerlException(exception,perl_exception);
2438     exception=DestroyExceptionInfo(exception);
2439     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2440     SvPOK_on(perl_exception);
2441     ST(0)=sv_2mortal(perl_exception);
2442     XSRETURN(1);
2443   }
2444 \f
2445 #
2446 ###############################################################################
2447 #                                                                             #
2448 #                                                                             #
2449 #                                                                             #
2450 #   A p p e n d                                                               #
2451 #                                                                             #
2452 #                                                                             #
2453 #                                                                             #
2454 ###############################################################################
2455 #
2456 #
2457 void
2458 Append(ref,...)
2459   Image::Magick ref=NO_INIT
2460   ALIAS:
2461     AppendImage  = 1
2462     append       = 2
2463     appendimage  = 3
2464   PPCODE:
2465   {
2466     AV
2467       *av;
2468
2469     char
2470       *attribute;
2471
2472     ExceptionInfo
2473       *exception;
2474
2475     HV
2476       *hv;
2477
2478     Image
2479       *image;
2480
2481     long
2482       stack;
2483
2484     register long
2485       i;
2486
2487     struct PackageInfo
2488       *info;
2489
2490     SV
2491       *av_reference,
2492       *perl_exception,
2493       *reference,
2494       *rv,
2495       *sv;
2496
2497     exception=AcquireExceptionInfo();
2498     perl_exception=newSVpv("",0);
2499     attribute=NULL;
2500     av=NULL;
2501     if (sv_isobject(ST(0)) == 0)
2502       {
2503         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2504           PackageName);
2505         goto PerlException;
2506       }
2507     reference=SvRV(ST(0));
2508     hv=SvSTASH(reference);
2509     av=newAV();
2510     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2511     SvREFCNT_dec(av);
2512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2513     if (image == (Image *) NULL)
2514       {
2515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2516           PackageName);
2517         goto PerlException;
2518       }
2519     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2520     /*
2521       Get options.
2522     */
2523     stack=MagickTrue;
2524     for (i=2; i < items; i+=2)
2525     {
2526       attribute=(char *) SvPV(ST(i-1),na);
2527       switch (*attribute)
2528       {
2529         case 'S':
2530         case 's':
2531         {
2532           if (LocaleCompare(attribute,"stack") == 0)
2533             {
2534               stack=ParseMagickOption(MagickBooleanOptions,MagickFalse,
2535                 SvPV(ST(i),na));
2536               if (stack < 0)
2537                 {
2538                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2539                     SvPV(ST(i),na));
2540                   return;
2541                 }
2542               break;
2543             }
2544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2545             attribute);
2546           break;
2547         }
2548         default:
2549         {
2550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2551             attribute);
2552           break;
2553         }
2554       }
2555     }
2556     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2557     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2558       goto PerlException;
2559     for ( ; image; image=image->next)
2560     {
2561       AddImageToRegistry(image);
2562       rv=newRV(sv);
2563       av_push(av,sv_bless(rv,hv));
2564       SvREFCNT_dec(sv);
2565     }
2566     exception=DestroyExceptionInfo(exception);
2567     ST(0)=av_reference;
2568     SvREFCNT_dec(perl_exception);
2569     XSRETURN(1);
2570
2571   PerlException:
2572     InheritPerlException(exception,perl_exception);
2573     exception=DestroyExceptionInfo(exception);
2574     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2575     SvPOK_on(perl_exception);
2576     ST(0)=sv_2mortal(perl_exception);
2577     XSRETURN(1);
2578   }
2579 \f
2580 #
2581 ###############################################################################
2582 #                                                                             #
2583 #                                                                             #
2584 #                                                                             #
2585 #   A v e r a g e                                                             #
2586 #                                                                             #
2587 #                                                                             #
2588 #                                                                             #
2589 ###############################################################################
2590 #
2591 #
2592 void
2593 Average(ref)
2594   Image::Magick ref=NO_INIT
2595   ALIAS:
2596     AverageImage   = 1
2597     average        = 2
2598     averageimage   = 3
2599   PPCODE:
2600   {
2601     AV
2602       *av;
2603
2604     char
2605       *p;
2606
2607     ExceptionInfo
2608       *exception;
2609
2610     HV
2611       *hv;
2612
2613     Image
2614       *image;
2615
2616     struct PackageInfo
2617       *info;
2618
2619     SV
2620       *perl_exception,
2621       *reference,
2622       *rv,
2623       *sv;
2624
2625     exception=AcquireExceptionInfo();
2626     perl_exception=newSVpv("",0);
2627     if (sv_isobject(ST(0)) == 0)
2628       {
2629         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2630           PackageName);
2631         goto PerlException;
2632       }
2633     reference=SvRV(ST(0));
2634     hv=SvSTASH(reference);
2635     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2636     if (image == (Image *) NULL)
2637       {
2638         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2639           PackageName);
2640         goto PerlException;
2641       }
2642     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2643     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2644       goto PerlException;
2645     /*
2646       Create blessed Perl array for the returned image.
2647     */
2648     av=newAV();
2649     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2650     SvREFCNT_dec(av);
2651     AddImageToRegistry(image);
2652     rv=newRV(sv);
2653     av_push(av,sv_bless(rv,hv));
2654     SvREFCNT_dec(sv);
2655     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2656     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
2657       "average-%.*s",(int) (MaxTextExtent-9),
2658       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2659     (void) CopyMagickString(image->filename,info->image_info->filename,
2660       MaxTextExtent);
2661     SetImageInfo(info->image_info,0,exception);
2662     exception=DestroyExceptionInfo(exception);
2663     SvREFCNT_dec(perl_exception);
2664     XSRETURN(1);
2665
2666   PerlException:
2667     InheritPerlException(exception,perl_exception);
2668     exception=DestroyExceptionInfo(exception);
2669     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2670     SvPOK_on(perl_exception);
2671     ST(0)=sv_2mortal(perl_exception);
2672     XSRETURN(1);
2673   }
2674 \f
2675 #
2676 ###############################################################################
2677 #                                                                             #
2678 #                                                                             #
2679 #                                                                             #
2680 #   B l o b T o I m a g e                                                     #
2681 #                                                                             #
2682 #                                                                             #
2683 #                                                                             #
2684 ###############################################################################
2685 #
2686 #
2687 void
2688 BlobToImage(ref,...)
2689   Image::Magick ref=NO_INIT
2690   ALIAS:
2691     BlobToImage  = 1
2692     blobtoimage  = 2
2693     blobto       = 3
2694   PPCODE:
2695   {
2696     AV
2697       *av;
2698
2699     char
2700       **keep,
2701       **list;
2702
2703     ExceptionInfo
2704       *exception;
2705
2706     HV
2707       *hv;
2708
2709     Image
2710       *image;
2711
2712     long
2713       ac,
2714       n,
2715       number_images;
2716
2717     register char
2718       **p;
2719
2720     register long
2721       i;
2722
2723     STRLEN
2724       *length;
2725
2726     struct PackageInfo
2727       *info;
2728
2729     SV
2730       *perl_exception,
2731       *reference,
2732       *rv,
2733       *sv;
2734
2735     exception=AcquireExceptionInfo();
2736     perl_exception=newSVpv("",0);
2737     number_images=0;
2738     ac=(items < 2) ? 1 : items-1;
2739     length=(STRLEN *) NULL;
2740     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2741     if (list == (char **) NULL)
2742       {
2743         ThrowPerlException(exception,ResourceLimitError,
2744           "MemoryAllocationFailed",PackageName);
2745         goto PerlException;
2746       }
2747     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2748     if (length == (STRLEN *) NULL)
2749       {
2750         ThrowPerlException(exception,ResourceLimitError,
2751           "MemoryAllocationFailed",PackageName);
2752         goto PerlException;
2753       }
2754     if (sv_isobject(ST(0)) == 0)
2755       {
2756         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2757           PackageName);
2758         goto PerlException;
2759       }
2760     reference=SvRV(ST(0));
2761     hv=SvSTASH(reference);
2762     if (SvTYPE(reference) != SVt_PVAV)
2763       {
2764         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2765           PackageName);
2766         goto PerlException;
2767       }
2768     av=(AV *) reference;
2769     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2770       exception);
2771     n=1;
2772     if (items <= 1)
2773       {
2774         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2775         goto PerlException;
2776       }
2777     for (n=0, i=0; i < ac; i++)
2778     {
2779       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2780       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2781         {
2782           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2783           continue;
2784         }
2785       n++;
2786     }
2787     list[n]=(char *) NULL;
2788     keep=list;
2789     for (i=number_images=0; i < n; i++)
2790     {
2791       image=BlobToImage(info->image_info,list[i],length[i],exception);
2792       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2793         break;
2794       for ( ; image; image=image->next)
2795       {
2796         AddImageToRegistry(image);
2797         rv=newRV(sv);
2798         av_push(av,sv_bless(rv,hv));
2799         SvREFCNT_dec(sv);
2800         number_images++;
2801       }
2802     }
2803     /*
2804       Free resources.
2805     */
2806     for (i=0; i < n; i++)
2807       if (list[i] != (char *) NULL)
2808         for (p=keep; list[i] != *p++; )
2809           if (*p == (char *) NULL)
2810             {
2811               list[i]=(char *) RelinquishMagickMemory(list[i]);
2812               break;
2813             }
2814
2815   PerlException:
2816     if (list)
2817       list=(char **) RelinquishMagickMemory(list);
2818     if (length)
2819       length=(STRLEN *) RelinquishMagickMemory(length);
2820     InheritPerlException(exception,perl_exception);
2821     exception=DestroyExceptionInfo(exception);
2822     sv_setiv(perl_exception,(IV) number_images);
2823     SvPOK_on(perl_exception);
2824     ST(0)=sv_2mortal(perl_exception);
2825     XSRETURN(1);
2826   }
2827 \f
2828 #
2829 ###############################################################################
2830 #                                                                             #
2831 #                                                                             #
2832 #                                                                             #
2833 #   C l o n e                                                                 #
2834 #                                                                             #
2835 #                                                                             #
2836 #                                                                             #
2837 ###############################################################################
2838 #
2839 #
2840 void
2841 Clone(ref)
2842   Image::Magick ref=NO_INIT
2843   ALIAS:
2844     CopyImage   = 1
2845     copy        = 2
2846     copyimage   = 3
2847     CloneImage  = 4
2848     clone       = 5
2849     cloneimage  = 6
2850     Clone       = 7
2851   PPCODE:
2852   {
2853     AV
2854       *av;
2855
2856     ExceptionInfo
2857       *exception;
2858
2859     HV
2860       *hv;
2861
2862     Image
2863       *clone,
2864       *image;
2865
2866     struct PackageInfo
2867       *info;
2868
2869     SV
2870       *perl_exception,
2871       *reference,
2872       *rv,
2873       *sv;
2874
2875     exception=AcquireExceptionInfo();
2876     perl_exception=newSVpv("",0);
2877     if (sv_isobject(ST(0)) == 0)
2878       {
2879         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2880           PackageName);
2881         goto PerlException;
2882       }
2883     reference=SvRV(ST(0));
2884     hv=SvSTASH(reference);
2885     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2886     if (image == (Image *) NULL)
2887       {
2888         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2889           PackageName);
2890         goto PerlException;
2891       }
2892     /*
2893       Create blessed Perl array for the returned image.
2894     */
2895     av=newAV();
2896     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2897     SvREFCNT_dec(av);
2898     for ( ; image; image=image->next)
2899     {
2900       clone=CloneImage(image,0,0,MagickTrue,exception);
2901       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2902         break;
2903       AddImageToRegistry(clone);
2904       rv=newRV(sv);
2905       av_push(av,sv_bless(rv,hv));
2906       SvREFCNT_dec(sv);
2907     }
2908     exception=DestroyExceptionInfo(exception);
2909     SvREFCNT_dec(perl_exception);
2910     XSRETURN(1);
2911
2912   PerlException:
2913     InheritPerlException(exception,perl_exception);
2914     exception=DestroyExceptionInfo(exception);
2915     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2916     SvPOK_on(perl_exception);
2917     ST(0)=sv_2mortal(perl_exception);
2918     XSRETURN(1);
2919   }
2920 \f
2921 #
2922 ###############################################################################
2923 #                                                                             #
2924 #                                                                             #
2925 #                                                                             #
2926 #   C L O N E                                                                 #
2927 #                                                                             #
2928 #                                                                             #
2929 #                                                                             #
2930 ###############################################################################
2931 #
2932 #
2933 void
2934 CLONE(ref,...)
2935   SV *ref;
2936   CODE:
2937   {
2938     if (magick_registry != (SplayTreeInfo *) NULL)
2939       {
2940         register Image
2941           *p;
2942
2943         ResetSplayTreeIterator(magick_registry);
2944         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2945         while (p != (Image *) NULL)
2946         {
2947           ReferenceImage(p);
2948           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2949         }
2950       }
2951   }
2952 \f
2953 #
2954 ###############################################################################
2955 #                                                                             #
2956 #                                                                             #
2957 #                                                                             #
2958 #   C o a l e s c e                                                           #
2959 #                                                                             #
2960 #                                                                             #
2961 #                                                                             #
2962 ###############################################################################
2963 #
2964 #
2965 void
2966 Coalesce(ref)
2967   Image::Magick ref=NO_INIT
2968   ALIAS:
2969     CoalesceImage   = 1
2970     coalesce        = 2
2971     coalesceimage   = 3
2972   PPCODE:
2973   {
2974     AV
2975       *av;
2976
2977     ExceptionInfo
2978       *exception;
2979
2980     HV
2981       *hv;
2982
2983     Image
2984       *image;
2985
2986     struct PackageInfo
2987       *info;
2988
2989     SV
2990       *av_reference,
2991       *perl_exception,
2992       *reference,
2993       *rv,
2994       *sv;
2995
2996     exception=AcquireExceptionInfo();
2997     perl_exception=newSVpv("",0);
2998     if (sv_isobject(ST(0)) == 0)
2999       {
3000         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3001           PackageName);
3002         goto PerlException;
3003       }
3004     reference=SvRV(ST(0));
3005     hv=SvSTASH(reference);
3006     av=newAV();
3007     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3008     SvREFCNT_dec(av);
3009     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3010     if (image == (Image *) NULL)
3011       {
3012         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3013           PackageName);
3014         goto PerlException;
3015       }
3016     image=CoalesceImages(image,exception);
3017     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3018       goto PerlException;
3019     for ( ; image; image=image->next)
3020     {
3021       AddImageToRegistry(image);
3022       rv=newRV(sv);
3023       av_push(av,sv_bless(rv,hv));
3024       SvREFCNT_dec(sv);
3025     }
3026     exception=DestroyExceptionInfo(exception);
3027     ST(0)=av_reference;
3028     SvREFCNT_dec(perl_exception);
3029     XSRETURN(1);
3030
3031   PerlException:
3032     InheritPerlException(exception,perl_exception);
3033     exception=DestroyExceptionInfo(exception);
3034     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3035     SvPOK_on(perl_exception);
3036     ST(0)=sv_2mortal(perl_exception);
3037     XSRETURN(1);
3038   }
3039 \f
3040 #
3041 ###############################################################################
3042 #                                                                             #
3043 #                                                                             #
3044 #                                                                             #
3045 #   C o m p a r e                                                             #
3046 #                                                                             #
3047 #                                                                             #
3048 #                                                                             #
3049 ###############################################################################
3050 #
3051 #
3052 void
3053 Compare(ref,...)
3054   Image::Magick ref=NO_INIT
3055   ALIAS:
3056     CompareImage = 1
3057     compare      = 2
3058     compareimage = 3
3059   PPCODE:
3060   {
3061     AV
3062       *av;
3063
3064     char
3065       *attribute;
3066
3067     ChannelType
3068       channel;
3069
3070     double
3071       distortion;
3072
3073     ExceptionInfo
3074       *exception;
3075
3076     HV
3077       *hv;
3078
3079     Image
3080       *difference_image,
3081       *image,
3082       *reconstruct_image;
3083
3084     long
3085       option;
3086
3087     MetricType
3088       metric;
3089
3090     register long
3091       i;
3092
3093     struct PackageInfo
3094       *info;
3095
3096     SV
3097       *av_reference,
3098       *perl_exception,
3099       *reference,
3100       *rv,
3101       *sv;
3102
3103     exception=AcquireExceptionInfo();
3104     perl_exception=newSVpv("",0);
3105     av=NULL;
3106     attribute=NULL;
3107     if (sv_isobject(ST(0)) == 0)
3108       {
3109         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3110           PackageName);
3111         goto PerlException;
3112       }
3113     reference=SvRV(ST(0));
3114     hv=SvSTASH(reference);
3115     av=newAV();
3116     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3117     SvREFCNT_dec(av);
3118     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3119     if (image == (Image *) NULL)
3120       {
3121         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3122           PackageName);
3123         goto PerlException;
3124       }
3125     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3126     /*
3127       Get attribute.
3128     */
3129     channel=DefaultChannels;
3130     reconstruct_image=image;
3131     metric=RootMeanSquaredErrorMetric;
3132     for (i=2; i < items; i+=2)
3133     {
3134       attribute=(char *) SvPV(ST(i-1),na);
3135       switch (*attribute)
3136       {
3137         case 'C':
3138         case 'c':
3139         {
3140           if (LocaleCompare(attribute,"channel") == 0)
3141             {
3142               long
3143                 option;
3144
3145               option=ParseChannelOption(SvPV(ST(i),na));
3146               if (option < 0)
3147                 {
3148                   ThrowPerlException(exception,OptionError,
3149                     "UnrecognizedType",SvPV(ST(i),na));
3150                   return;
3151                 }
3152               channel=(ChannelType) option;
3153               break;
3154             }
3155           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3156             attribute);
3157           break;
3158         }
3159         case 'F':
3160         case 'f':
3161         {
3162           if (LocaleCompare(attribute,"fuzz") == 0)
3163             {
3164               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3165               break;
3166             }
3167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3168             attribute);
3169           break;
3170         }
3171         case 'I':
3172         case 'i':
3173         {
3174           if (LocaleCompare(attribute,"image") == 0)
3175             {
3176               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3177                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3178             }
3179           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3180             attribute);
3181           break;
3182         }
3183         case 'M':
3184         case 'm':
3185         {
3186           if (LocaleCompare(attribute,"metric") == 0)
3187             {
3188               option=ParseMagickOption(MagickMetricOptions,MagickFalse,
3189                 SvPV(ST(i),na));
3190               if (option < 0)
3191                 {
3192                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3193                     SvPV(ST(i),na));
3194                   break;
3195                 }
3196                metric=(MetricType) option;
3197               break;
3198             }
3199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3200             attribute);
3201           break;
3202         }
3203         default:
3204         {
3205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3206             attribute);
3207           break;
3208         }
3209       }
3210     }
3211     difference_image=CompareImageChannels(image,reconstruct_image,channel,
3212       metric,&distortion,exception);
3213     if (difference_image != (Image *) NULL)
3214       {
3215         difference_image->error.mean_error_per_pixel=distortion;
3216         AddImageToRegistry(difference_image);
3217         rv=newRV(sv);
3218         av_push(av,sv_bless(rv,hv));
3219         SvREFCNT_dec(sv);
3220       }
3221     exception=DestroyExceptionInfo(exception);
3222     ST(0)=av_reference;
3223     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3224     XSRETURN(1);
3225
3226   PerlException:
3227     InheritPerlException(exception,perl_exception);
3228     exception=DestroyExceptionInfo(exception);
3229     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3230     SvPOK_on(perl_exception);
3231     ST(0)=sv_2mortal(perl_exception);
3232     XSRETURN(1);
3233   }
3234 \f
3235 #
3236 ###############################################################################
3237 #                                                                             #
3238 #                                                                             #
3239 #                                                                             #
3240 #   C o m p a r e L a y e r s                                                 #
3241 #                                                                             #
3242 #                                                                             #
3243 #                                                                             #
3244 ###############################################################################
3245 #
3246 #
3247 void
3248 CompareLayers(ref)
3249   Image::Magick ref=NO_INIT
3250   ALIAS:
3251     CompareImageLayers   = 1
3252     comparelayers        = 2
3253     compareimagelayers   = 3
3254   PPCODE:
3255   {
3256     AV
3257       *av;
3258
3259     char
3260       *attribute;
3261
3262     ExceptionInfo
3263       *exception;
3264
3265     HV
3266       *hv;
3267
3268     Image
3269       *image;
3270
3271     long
3272       option;
3273
3274     ImageLayerMethod
3275       method;
3276
3277     register long
3278       i;
3279
3280     struct PackageInfo
3281       *info;
3282
3283     SV
3284       *av_reference,
3285       *perl_exception,
3286       *reference,
3287       *rv,
3288       *sv;
3289
3290     exception=AcquireExceptionInfo();
3291     perl_exception=newSVpv("",0);
3292     if (sv_isobject(ST(0)) == 0)
3293       {
3294         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3295           PackageName);
3296         goto PerlException;
3297       }
3298     reference=SvRV(ST(0));
3299     hv=SvSTASH(reference);
3300     av=newAV();
3301     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3302     SvREFCNT_dec(av);
3303     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3304     if (image == (Image *) NULL)
3305       {
3306         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3307           PackageName);
3308         goto PerlException;
3309       }
3310     method=CompareAnyLayer;
3311     for (i=2; i < items; i+=2)
3312     {
3313       attribute=(char *) SvPV(ST(i-1),na);
3314       switch (*attribute)
3315       {
3316         case 'M':
3317         case 'm':
3318         {
3319           if (LocaleCompare(attribute,"method") == 0)
3320             {
3321               option=ParseMagickOption(MagickLayerOptions,MagickFalse,
3322                 SvPV(ST(i),na));
3323               if (option < 0)
3324                 {
3325                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3326                     SvPV(ST(i),na));
3327                   break;
3328                 }
3329                method=(ImageLayerMethod) option;
3330               break;
3331             }
3332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3333             attribute);
3334           break;
3335         }
3336         default:
3337         {
3338           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3339             attribute);
3340           break;
3341         }
3342       }
3343     }
3344     image=CompareImageLayers(image,method,exception);
3345     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3346       goto PerlException;
3347     for ( ; image; image=image->next)
3348     {
3349       AddImageToRegistry(image);
3350       rv=newRV(sv);
3351       av_push(av,sv_bless(rv,hv));
3352       SvREFCNT_dec(sv);
3353     }
3354     exception=DestroyExceptionInfo(exception);
3355     ST(0)=av_reference;
3356     SvREFCNT_dec(perl_exception);
3357     XSRETURN(1);
3358
3359   PerlException:
3360     InheritPerlException(exception,perl_exception);
3361     exception=DestroyExceptionInfo(exception);
3362     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3363     SvPOK_on(perl_exception);
3364     ST(0)=sv_2mortal(perl_exception);
3365     XSRETURN(1);
3366   }
3367 \f
3368 #
3369 ###############################################################################
3370 #                                                                             #
3371 #                                                                             #
3372 #                                                                             #
3373 #   D e s t r o y                                                             #
3374 #                                                                             #
3375 #                                                                             #
3376 #                                                                             #
3377 ###############################################################################
3378 #
3379 #
3380 void
3381 DESTROY(ref)
3382   Image::Magick ref=NO_INIT
3383   PPCODE:
3384   {
3385     SV
3386       *reference;
3387
3388     if (sv_isobject(ST(0)) == 0)
3389       croak("ReferenceIsNotMyType");
3390     reference=SvRV(ST(0));
3391     switch (SvTYPE(reference))
3392     {
3393       case SVt_PVAV:
3394       {
3395         char
3396           message[MaxTextExtent];
3397
3398         struct PackageInfo
3399           *info;
3400
3401         HV
3402           *hv;
3403
3404         GV
3405           **gvp;
3406
3407         SV
3408           *sv;
3409
3410         /*
3411           Array (AV *) reference
3412         */
3413         (void) FormatMagickString(message,MaxTextExtent,"package%s%lx",
3414           XS_VERSION,(long) reference);
3415         hv=gv_stashpv(PackageName, FALSE);
3416         if (!hv)
3417           break;
3418         gvp=(GV **) hv_fetch(hv,message,strlen(message),FALSE);
3419         if (!gvp)
3420           break;
3421         sv=GvSV(*gvp);
3422         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3423           {
3424             info=(struct PackageInfo *) SvIV(sv);
3425             DestroyPackageInfo(info);
3426           }
3427         hv_delete(hv,message,strlen(message),G_DISCARD);
3428         break;
3429       }
3430       case SVt_PVMG:
3431       {
3432         Image
3433           *image;
3434
3435         /*
3436           Blessed scalar = (Image *) SvIV(reference)
3437         */
3438         image=(Image *) SvIV(reference);
3439         if (image != (Image *) NULL)
3440           DeleteImageFromRegistry(reference,image);
3441         break;
3442       }
3443       default:
3444         break;
3445     }
3446   }
3447 \f
3448 #
3449 ###############################################################################
3450 #                                                                             #
3451 #                                                                             #
3452 #                                                                             #
3453 #   D i s p l a y                                                             #
3454 #                                                                             #
3455 #                                                                             #
3456 #                                                                             #
3457 ###############################################################################
3458 #
3459 #
3460 void
3461 Display(ref,...)
3462   Image::Magick ref=NO_INIT
3463   ALIAS:
3464     DisplayImage  = 1
3465     display       = 2
3466     displayimage  = 3
3467   PPCODE:
3468   {
3469     ExceptionInfo
3470       *exception;
3471
3472     Image
3473       *image;
3474
3475     register long
3476       i;
3477
3478     struct PackageInfo
3479       *info,
3480       *package_info;
3481
3482     SV
3483       *perl_exception,
3484       *reference;
3485
3486     exception=AcquireExceptionInfo();
3487     perl_exception=newSVpv("",0);
3488     package_info=(struct PackageInfo *) NULL;
3489     if (sv_isobject(ST(0)) == 0)
3490       {
3491         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3492           PackageName);
3493         goto PerlException;
3494       }
3495     reference=SvRV(ST(0));
3496     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3497     if (image == (Image *) NULL)
3498       {
3499         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3500           PackageName);
3501         goto PerlException;
3502       }
3503     package_info=ClonePackageInfo(info,exception);
3504     if (items == 2)
3505       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3506     else
3507       if (items > 2)
3508         for (i=2; i < items; i+=2)
3509           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3510             exception);
3511     (void) DisplayImages(package_info->image_info,image);
3512     (void) CatchImageException(image);
3513     InheritException(exception,&image->exception);
3514
3515   PerlException:
3516     if (package_info != (struct PackageInfo *) NULL)
3517       DestroyPackageInfo(package_info);
3518     InheritPerlException(exception,perl_exception);
3519     exception=DestroyExceptionInfo(exception);
3520     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3521     SvPOK_on(perl_exception);
3522     ST(0)=sv_2mortal(perl_exception);
3523     XSRETURN(1);
3524   }
3525 \f
3526 #
3527 ###############################################################################
3528 #                                                                             #
3529 #                                                                             #
3530 #                                                                             #
3531 #   E v a l u a t e I m a g e s                                               #
3532 #                                                                             #
3533 #                                                                             #
3534 #                                                                             #
3535 ###############################################################################
3536 #
3537 #
3538 void
3539 EvaluateImages(ref)
3540   Image::Magick ref=NO_INIT
3541   ALIAS:
3542     EvaluateImages   = 1
3543     evaluateimages   = 2
3544   PPCODE:
3545   {
3546     AV
3547       *av;
3548
3549     char
3550       *attribute,
3551       *p;
3552
3553     ExceptionInfo
3554       *exception;
3555
3556     HV
3557       *hv;
3558
3559     Image
3560       *image;
3561
3562     MagickEvaluateOperator
3563       op;
3564
3565     register long
3566       i;
3567
3568     struct PackageInfo
3569       *info;
3570
3571     SV
3572       *perl_exception,
3573       *reference,
3574       *rv,
3575       *sv;
3576
3577     exception=AcquireExceptionInfo();
3578     perl_exception=newSVpv("",0);
3579     if (sv_isobject(ST(0)) == 0)
3580       {
3581         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3582           PackageName);
3583         goto PerlException;
3584       }
3585     reference=SvRV(ST(0));
3586     hv=SvSTASH(reference);
3587     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3588     if (image == (Image *) NULL)
3589       {
3590         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3591           PackageName);
3592         goto PerlException;
3593       }
3594     op=MeanEvaluateOperator;
3595     if (items == 2)
3596       {
3597         long
3598           in;
3599
3600         in=ParseMagickOption(MagickEvaluateOptions,MagickFalse,(char *)
3601           SvPV(ST(1),na));
3602         if (in < 0)
3603           {
3604             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3605               SvPV(ST(1),na));
3606             return;
3607           }
3608         op=(MagickEvaluateOperator) in;
3609       }
3610     else
3611       for (i=2; i < items; i+=2)
3612       {
3613         attribute=(char *) SvPV(ST(i-1),na);
3614         switch (*attribute)
3615         {
3616           case 'O':
3617           case 'o':
3618           {
3619             if (LocaleCompare(attribute,"operator") == 0)
3620               {
3621                 long
3622                   in;
3623
3624                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
3625                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3626                 if (in < 0)
3627                   {
3628                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3629                       SvPV(ST(i),na));
3630                     return;
3631                   }
3632                 op=(MagickEvaluateOperator) in;
3633                 break;
3634               }
3635             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3636               attribute);
3637             break;
3638           }
3639           default:
3640           {
3641             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3642               attribute);
3643             break;
3644           }
3645         }
3646       }
3647     image=EvaluateImages(image,op,exception);
3648     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3649       goto PerlException;
3650     /*
3651       Create blessed Perl array for the returned image.
3652     */
3653     av=newAV();
3654     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3655     SvREFCNT_dec(av);
3656     AddImageToRegistry(image);
3657     rv=newRV(sv);
3658     av_push(av,sv_bless(rv,hv));
3659     SvREFCNT_dec(sv);
3660     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3661     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
3662       "evaluate-%.*s",(int) (MaxTextExtent-9),
3663       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3664     (void) CopyMagickString(image->filename,info->image_info->filename,
3665       MaxTextExtent);
3666     SetImageInfo(info->image_info,0,exception);
3667     exception=DestroyExceptionInfo(exception);
3668     SvREFCNT_dec(perl_exception);
3669     XSRETURN(1);
3670
3671   PerlException:
3672     InheritPerlException(exception,perl_exception);
3673     exception=DestroyExceptionInfo(exception);
3674     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3675     SvPOK_on(perl_exception);
3676     ST(0)=sv_2mortal(perl_exception);
3677     XSRETURN(1);
3678   }
3679 \f
3680 #
3681 ###############################################################################
3682 #                                                                             #
3683 #                                                                             #
3684 #                                                                             #
3685 #   F e a t u r e s                                                           #
3686 #                                                                             #
3687 #                                                                             #
3688 #                                                                             #
3689 ###############################################################################
3690 #
3691 #
3692 void
3693 Features(ref,...)
3694   Image::Magick ref=NO_INIT
3695   ALIAS:
3696     FeaturesImage = 1
3697     features      = 2
3698     featuresimage = 3
3699   PPCODE:
3700   {
3701 #define ChannelFeatures(channel,direction) \
3702 { \
3703   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3704     channel_features[channel].angular_second_moment[direction]); \
3705   PUSHs(sv_2mortal(newSVpv(message,0))); \
3706   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3707     channel_features[channel].contrast[direction]); \
3708   PUSHs(sv_2mortal(newSVpv(message,0))); \
3709   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3710     channel_features[channel].contrast[direction]); \
3711   PUSHs(sv_2mortal(newSVpv(message,0))); \
3712   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3713     channel_features[channel].variance_sum_of_squares[direction]); \
3714   PUSHs(sv_2mortal(newSVpv(message,0))); \
3715   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3716     channel_features[channel].inverse_difference_moment[direction]); \
3717   PUSHs(sv_2mortal(newSVpv(message,0))); \
3718   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3719     channel_features[channel].sum_average[direction]); \
3720   PUSHs(sv_2mortal(newSVpv(message,0))); \
3721   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3722     channel_features[channel].sum_variance[direction]); \
3723   PUSHs(sv_2mortal(newSVpv(message,0))); \
3724   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3725     channel_features[channel].sum_entropy[direction]); \
3726   PUSHs(sv_2mortal(newSVpv(message,0))); \
3727   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3728     channel_features[channel].entropy[direction]); \
3729   PUSHs(sv_2mortal(newSVpv(message,0))); \
3730   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3731     channel_features[channel].difference_variance[direction]); \
3732   PUSHs(sv_2mortal(newSVpv(message,0))); \
3733   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3734     channel_features[channel].difference_entropy[direction]); \
3735   PUSHs(sv_2mortal(newSVpv(message,0))); \
3736   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3737     channel_features[channel].measure_of_correlation_1[direction]); \
3738   PUSHs(sv_2mortal(newSVpv(message,0))); \
3739   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3740     channel_features[channel].measure_of_correlation_2[direction]); \
3741   PUSHs(sv_2mortal(newSVpv(message,0))); \
3742   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3743     channel_features[channel].maximum_correlation_coefficient[direction]); \
3744   PUSHs(sv_2mortal(newSVpv(message,0))); \
3745 }
3746
3747     AV
3748       *av;
3749
3750     char
3751       *attribute,
3752       message[MaxTextExtent];
3753
3754     ChannelFeatures
3755       *channel_features;
3756
3757     double
3758       distance;
3759
3760     ExceptionInfo
3761       *exception;
3762
3763     HV
3764       *hv;
3765
3766     Image
3767       *image;
3768
3769     register long
3770       i;
3771
3772     ssize_t
3773       count;
3774
3775     struct PackageInfo
3776       *info;
3777
3778     SV
3779       *av_reference,
3780       *perl_exception,
3781       *reference;
3782
3783     exception=AcquireExceptionInfo();
3784     perl_exception=newSVpv("",0);
3785     av=NULL;
3786     if (sv_isobject(ST(0)) == 0)
3787       {
3788         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3789           PackageName);
3790         goto PerlException;
3791       }
3792     reference=SvRV(ST(0));
3793     hv=SvSTASH(reference);
3794     av=newAV();
3795     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3796     SvREFCNT_dec(av);
3797     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3798     if (image == (Image *) NULL)
3799       {
3800         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3801           PackageName);
3802         goto PerlException;
3803       }
3804     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3805     distance=1;
3806     for (i=2; i < items; i+=2)
3807     {
3808       attribute=(char *) SvPV(ST(i-1),na);
3809       switch (*attribute)
3810       {
3811         case 'D':
3812         case 'd':
3813         {
3814           if (LocaleCompare(attribute,"distance") == 0)
3815             {
3816               distance=StringToLong((char *) SvPV(ST(1),na));
3817               break;
3818             }
3819           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3820             attribute);
3821           break;
3822         }
3823         default:
3824         {
3825           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3826             attribute);
3827           break;
3828         }
3829       }
3830     }
3831     count=0;
3832     for ( ; image; image=image->next)
3833     {
3834       channel_features=GetImageChannelFeatures(image,distance,
3835         &image->exception);
3836       if (channel_features == (ChannelFeatures *) NULL)
3837         continue;
3838       count++;
3839       EXTEND(sp,75*count);
3840       for (i=0; i < 4; i++)
3841       {
3842         ChannelFeatures(RedChannel,i);
3843         ChannelFeatures(GreenChannel,i);
3844         ChannelFeatures(BlueChannel,i);
3845         if (image->colorspace == CMYKColorspace)
3846           ChannelFeatures(IndexChannel,i);
3847         if (image->matte != MagickFalse)
3848           ChannelFeatures(OpacityChannel,i);
3849       }
3850       channel_features=(ChannelFeatures *)
3851         RelinquishMagickMemory(channel_features);
3852     }
3853
3854   PerlException:
3855     InheritPerlException(exception,perl_exception);
3856     exception=DestroyExceptionInfo(exception);
3857     SvREFCNT_dec(perl_exception);
3858   }
3859 \f
3860 #
3861 ###############################################################################
3862 #                                                                             #
3863 #                                                                             #
3864 #                                                                             #
3865 #   F l a t t e n                                                             #
3866 #                                                                             #
3867 #                                                                             #
3868 #                                                                             #
3869 ###############################################################################
3870 #
3871 #
3872 void
3873 Flatten(ref)
3874   Image::Magick ref=NO_INIT
3875   ALIAS:
3876     FlattenImage   = 1
3877     flatten        = 2
3878     flattenimage   = 3
3879   PPCODE:
3880   {
3881     AV
3882       *av;
3883
3884     char
3885       *attribute,
3886       *p;
3887
3888     ExceptionInfo
3889       *exception;
3890
3891     HV
3892       *hv;
3893
3894     Image
3895       *image;
3896
3897     PixelPacket
3898       background_color;
3899
3900     register long
3901       i;
3902
3903     struct PackageInfo
3904       *info;
3905
3906     SV
3907       *perl_exception,
3908       *reference,
3909       *rv,
3910       *sv;
3911
3912     exception=AcquireExceptionInfo();
3913     perl_exception=newSVpv("",0);
3914     if (sv_isobject(ST(0)) == 0)
3915       {
3916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3917           PackageName);
3918         goto PerlException;
3919       }
3920     reference=SvRV(ST(0));
3921     hv=SvSTASH(reference);
3922     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3923     if (image == (Image *) NULL)
3924       {
3925         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3926           PackageName);
3927         goto PerlException;
3928       }
3929     background_color=image->background_color;
3930     if (items == 2)
3931       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3932         exception);
3933     else
3934       for (i=2; i < items; i+=2)
3935       {
3936         attribute=(char *) SvPV(ST(i-1),na);
3937         switch (*attribute)
3938         {
3939           case 'B':
3940           case 'b':
3941           {
3942             if (LocaleCompare(attribute,"background") == 0)
3943               {
3944                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3945                   &background_color,exception);
3946                 break;
3947               }
3948             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3949               attribute);
3950             break;
3951           }
3952           default:
3953           {
3954             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3955               attribute);
3956             break;
3957           }
3958         }
3959       }
3960     image->background_color=background_color;
3961     image=MergeImageLayers(image,FlattenLayer,exception);
3962     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3963       goto PerlException;
3964     /*
3965       Create blessed Perl array for the returned image.
3966     */
3967     av=newAV();
3968     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3969     SvREFCNT_dec(av);
3970     AddImageToRegistry(image);
3971     rv=newRV(sv);
3972     av_push(av,sv_bless(rv,hv));
3973     SvREFCNT_dec(sv);
3974     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3975     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
3976       "flatten-%.*s",(int) (MaxTextExtent-9),
3977       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3978     (void) CopyMagickString(image->filename,info->image_info->filename,
3979       MaxTextExtent);
3980     SetImageInfo(info->image_info,0,exception);
3981     exception=DestroyExceptionInfo(exception);
3982     SvREFCNT_dec(perl_exception);
3983     XSRETURN(1);
3984
3985   PerlException:
3986     InheritPerlException(exception,perl_exception);
3987     exception=DestroyExceptionInfo(exception);
3988     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3989     SvPOK_on(perl_exception);  /* return messages in string context */
3990     ST(0)=sv_2mortal(perl_exception);
3991     XSRETURN(1);
3992   }
3993 \f
3994 #
3995 ###############################################################################
3996 #                                                                             #
3997 #                                                                             #
3998 #                                                                             #
3999 #   F x                                                                       #
4000 #                                                                             #
4001 #                                                                             #
4002 #                                                                             #
4003 ###############################################################################
4004 #
4005 #
4006 void
4007 Fx(ref,...)
4008   Image::Magick ref=NO_INIT
4009   ALIAS:
4010     FxImage  = 1
4011     fx       = 2
4012     fximage  = 3
4013   PPCODE:
4014   {
4015     AV
4016       *av;
4017
4018     char
4019       *attribute,
4020       expression[MaxTextExtent];
4021
4022     ChannelType
4023       channel;
4024
4025     ExceptionInfo
4026       *exception;
4027
4028     HV
4029       *hv;
4030
4031     Image
4032       *image;
4033
4034     register long
4035       i;
4036
4037     struct PackageInfo
4038       *info;
4039
4040     SV
4041       *av_reference,
4042       *perl_exception,
4043       *reference,
4044       *rv,
4045       *sv;
4046
4047     exception=AcquireExceptionInfo();
4048     perl_exception=newSVpv("",0);
4049     attribute=NULL;
4050     av=NULL;
4051     if (sv_isobject(ST(0)) == 0)
4052       {
4053         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4054           PackageName);
4055         goto PerlException;
4056       }
4057     reference=SvRV(ST(0));
4058     hv=SvSTASH(reference);
4059     av=newAV();
4060     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4061     SvREFCNT_dec(av);
4062     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4063     if (image == (Image *) NULL)
4064       {
4065         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4066           PackageName);
4067         goto PerlException;
4068       }
4069     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4070     /*
4071       Get options.
4072     */
4073     channel=DefaultChannels;
4074     (void) CopyMagickString(expression,"u",MaxTextExtent);
4075     if (items == 2)
4076       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4077     else
4078       for (i=2; i < items; i+=2)
4079       {
4080         attribute=(char *) SvPV(ST(i-1),na);
4081         switch (*attribute)
4082         {
4083           case 'C':
4084           case 'c':
4085           {
4086             if (LocaleCompare(attribute,"channel") == 0)
4087               {
4088                 long
4089                   option;
4090
4091                 option=ParseChannelOption(SvPV(ST(i),na));
4092                 if (option < 0)
4093                   {
4094                     ThrowPerlException(exception,OptionError,
4095                       "UnrecognizedType",SvPV(ST(i),na));
4096                     return;
4097                   }
4098                 channel=(ChannelType) option;
4099                 break;
4100               }
4101             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4102               attribute);
4103             break;
4104           }
4105           case 'E':
4106           case 'e':
4107           {
4108             if (LocaleCompare(attribute,"expression") == 0)
4109               {
4110                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4111                   MaxTextExtent);
4112                 break;
4113               }
4114             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4115               attribute);
4116             break;
4117           }
4118           default:
4119           {
4120             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4121               attribute);
4122             break;
4123           }
4124         }
4125       }
4126     image=FxImageChannel(image,channel,expression,exception);
4127     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4128       goto PerlException;
4129     for ( ; image; image=image->next)
4130     {
4131       AddImageToRegistry(image);
4132       rv=newRV(sv);
4133       av_push(av,sv_bless(rv,hv));
4134       SvREFCNT_dec(sv);
4135     }
4136     exception=DestroyExceptionInfo(exception);
4137     ST(0)=av_reference;
4138     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4139     XSRETURN(1);
4140
4141   PerlException:
4142     InheritPerlException(exception,perl_exception);
4143     exception=DestroyExceptionInfo(exception);
4144     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4145     SvPOK_on(perl_exception);
4146     ST(0)=sv_2mortal(perl_exception);
4147     XSRETURN(1);
4148   }
4149 \f
4150 #
4151 ###############################################################################
4152 #                                                                             #
4153 #                                                                             #
4154 #                                                                             #
4155 #   G e t                                                                     #
4156 #                                                                             #
4157 #                                                                             #
4158 #                                                                             #
4159 ###############################################################################
4160 #
4161 #
4162 void
4163 Get(ref,...)
4164   Image::Magick ref=NO_INIT
4165   ALIAS:
4166     GetAttributes = 1
4167     GetAttribute  = 2
4168     get           = 3
4169     getattributes = 4
4170     getattribute  = 5
4171   PPCODE:
4172   {
4173     char
4174       *attribute,
4175       color[MaxTextExtent];
4176
4177     const char
4178       *value;
4179
4180     ExceptionInfo
4181       *exception;
4182
4183     Image
4184       *image;
4185
4186     long
4187       j;
4188
4189     register long
4190       i;
4191
4192     struct PackageInfo
4193       *info;
4194
4195     SV
4196       *perl_exception,
4197       *reference,
4198       *s;
4199
4200     exception=AcquireExceptionInfo();
4201     perl_exception=newSVpv("",0);
4202     if (sv_isobject(ST(0)) == 0)
4203       {
4204         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4205           PackageName);
4206         XSRETURN_EMPTY;
4207       }
4208     reference=SvRV(ST(0));
4209     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4210     if (image == (Image *) NULL && !info)
4211       XSRETURN_EMPTY;
4212     EXTEND(sp,items);
4213     for (i=1; i < items; i++)
4214     {
4215       attribute=(char *) SvPV(ST(i),na);
4216       s=NULL;
4217       switch (*attribute)
4218       {
4219         case 'A':
4220         case 'a':
4221         {
4222           if (LocaleCompare(attribute,"adjoin") == 0)
4223             {
4224               if (info)
4225                 s=newSViv((long) info->image_info->adjoin);
4226               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4227               continue;
4228             }
4229           if (LocaleCompare(attribute,"antialias") == 0)
4230             {
4231               if (info)
4232                 s=newSViv((long) info->image_info->antialias);
4233               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4234               continue;
4235             }
4236           if (LocaleCompare(attribute,"area") == 0)
4237             {
4238               s=newSViv(GetMagickResource(AreaResource));
4239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4240               continue;
4241             }
4242           if (LocaleCompare(attribute,"attenuate") == 0)
4243             {
4244               const char
4245                 *value;
4246
4247               value=GetImageProperty(image,attribute);
4248               if (value != (const char *) NULL)
4249                 s=newSVpv(value,0);
4250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4251               continue;
4252             }
4253           if (LocaleCompare(attribute,"authenticate") == 0)
4254             {
4255               if (info)
4256                 s=newSVpv(info->image_info->authenticate,0);
4257               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4258               continue;
4259             }
4260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4261             attribute);
4262           break;
4263         }
4264         case 'B':
4265         case 'b':
4266         {
4267           if (LocaleCompare(attribute,"background") == 0)
4268             {
4269               if (image == (Image *) NULL)
4270                 break;
4271               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4272                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4273                 image->background_color.red,image->background_color.green,
4274                 image->background_color.blue,image->background_color.opacity);
4275               s=newSVpv(color,0);
4276               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4277               continue;
4278             }
4279           if (LocaleCompare(attribute,"base-columns") == 0)
4280             {
4281               if (image != (Image *) NULL)
4282                 s=newSViv((long) image->magick_columns);
4283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4284               continue;
4285             }
4286           if (LocaleCompare(attribute,"base-filename") == 0)
4287             {
4288               if (image != (Image *) NULL)
4289                 s=newSVpv(image->magick_filename,0);
4290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4291               continue;
4292             }
4293           if (LocaleCompare(attribute,"base-height") == 0)
4294             {
4295               if (image != (Image *) NULL)
4296                 s=newSViv((long) image->magick_rows);
4297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4298               continue;
4299             }
4300           if (LocaleCompare(attribute,"base-rows") == 0)
4301             {
4302               if (image != (Image *) NULL)
4303                 s=newSViv((long) image->magick_rows);
4304               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4305               continue;
4306             }
4307           if (LocaleCompare(attribute,"base-width") == 0)
4308             {
4309               if (image != (Image *) NULL)
4310                 s=newSViv((long) image->magick_columns);
4311               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4312               continue;
4313             }
4314           if (LocaleCompare(attribute,"bias") == 0)
4315             {
4316               if (image != (Image *) NULL)
4317                 s=newSVnv(image->bias);
4318               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4319               continue;
4320             }
4321           if (LocaleCompare(attribute,"blue-primary") == 0)
4322             {
4323               if (image == (Image *) NULL)
4324                 break;
4325               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4326                 image->chromaticity.blue_primary.x,
4327                 image->chromaticity.blue_primary.y);
4328               s=newSVpv(color,0);
4329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4330               continue;
4331             }
4332           if (LocaleCompare(attribute,"bordercolor") == 0)
4333             {
4334               if (image == (Image *) NULL)
4335                 break;
4336               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4337                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4338                 image->border_color.red,image->border_color.green,
4339                 image->border_color.blue,image->border_color.opacity);
4340               s=newSVpv(color,0);
4341               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4342               continue;
4343             }
4344           if (LocaleCompare(attribute,"bounding-box") == 0)
4345             {
4346               char
4347                 geometry[MaxTextExtent];
4348
4349               RectangleInfo
4350                 page;
4351
4352               if (image == (Image *) NULL)
4353                 break;
4354               page=GetImageBoundingBox(image,&image->exception);
4355               (void) FormatMagickString(geometry,MaxTextExtent,
4356                 "%lux%lu%+ld%+ld",page.width,page.height,page.x,page.y);
4357               s=newSVpv(geometry,0);
4358               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4359               continue;
4360             }
4361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4362             attribute);
4363           break;
4364         }
4365         case 'C':
4366         case 'c':
4367         {
4368           if (LocaleCompare(attribute,"class") == 0)
4369             {
4370               if (image == (Image *) NULL)
4371                 break;
4372               s=newSViv(image->storage_class);
4373               (void) sv_setpv(s,MagickOptionToMnemonic(MagickClassOptions,
4374                 image->storage_class));
4375               SvIOK_on(s);
4376               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4377               continue;
4378             }
4379           if (LocaleCompare(attribute,"clip-mask") == 0)
4380             {
4381               if (image != (Image *) NULL)
4382                 {
4383                   SV
4384                     *sv;
4385
4386                   if (image->mask == (Image *) NULL)
4387                     ClipImage(image);
4388                   if (image->mask != (Image *) NULL)
4389                     {
4390                       AddImageToRegistry(image->mask);
4391                       s=sv_bless(newRV(sv),SvSTASH(reference));
4392                     }
4393                 }
4394               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4395               continue;
4396             }
4397           if (LocaleCompare(attribute,"clip-path") == 0)
4398             {
4399               if (image != (Image *) NULL)
4400                 {
4401                   SV
4402                     *sv;
4403
4404                   if (image->clip_mask == (Image *) NULL)
4405                     ClipImage(image);
4406                   if (image->clip_mask != (Image *) NULL)
4407                     {
4408                       AddImageToRegistry(image->clip_mask);
4409                       s=sv_bless(newRV(sv),SvSTASH(reference));
4410                     }
4411                 }
4412               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4413               continue;
4414             }
4415           if (LocaleCompare(attribute,"compression") == 0)
4416             {
4417               j=info ? info->image_info->compression : image->compression;
4418               if (info)
4419                 if (info->image_info->compression == UndefinedCompression)
4420                   j=image->compression;
4421               s=newSViv(j);
4422               (void) sv_setpv(s,MagickOptionToMnemonic(MagickCompressOptions,
4423                 j));
4424               SvIOK_on(s);
4425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4426               continue;
4427             }
4428           if (LocaleCompare(attribute,"colorspace") == 0)
4429             {
4430               j=image ? image->colorspace : RGBColorspace;
4431               s=newSViv(j);
4432               (void) sv_setpv(s,MagickOptionToMnemonic(MagickColorspaceOptions,
4433                 j));
4434               SvIOK_on(s);
4435               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4436               continue;
4437             }
4438           if (LocaleCompare(attribute,"colors") == 0)
4439             {
4440               if (image != (Image *) NULL)
4441                 s=newSViv((long) GetNumberColors(image,(FILE *) NULL,
4442                   &image->exception));
4443               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4444               continue;
4445             }
4446           if (LocaleNCompare(attribute,"colormap",8) == 0)
4447             {
4448               int
4449                 items;
4450
4451               if (image == (Image *) NULL || !image->colormap)
4452                 break;
4453               j=0;
4454               items=sscanf(attribute,"%*[^[][%ld",&j);
4455               if (j > (long) image->colors)
4456                 j%=image->colors;
4457               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4458                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4459                 image->colormap[j].red,image->colormap[j].green,
4460                 image->colormap[j].blue,image->colormap[j].opacity);
4461               s=newSVpv(color,0);
4462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4463               continue;
4464             }
4465           if (LocaleCompare(attribute,"columns") == 0)
4466             {
4467               if (image != (Image *) NULL)
4468                 s=newSViv((long) image->columns);
4469               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4470               continue;
4471             }
4472           if (LocaleCompare(attribute,"comment") == 0)
4473             {
4474               const char
4475                 *value;
4476
4477               value=GetImageProperty(image,attribute);
4478               if (value != (const char *) NULL)
4479                 s=newSVpv(value,0);
4480               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4481               continue;
4482             }
4483           if (LocaleCompare(attribute,"copyright") == 0)
4484             {
4485               s=newSVpv(GetMagickCopyright(),0);
4486               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4487               continue;
4488             }
4489           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4490             attribute);
4491           break;
4492         }
4493         case 'D':
4494         case 'd':
4495         {
4496           if (LocaleCompare(attribute,"density") == 0)
4497             {
4498               char
4499                 geometry[MaxTextExtent];
4500
4501               if (image == (Image *) NULL)
4502                 break;
4503               (void) FormatMagickString(geometry,MaxTextExtent,"%.15gx%.15g",
4504                 image->x_resolution,image->y_resolution);
4505               s=newSVpv(geometry,0);
4506               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4507               continue;
4508             }
4509           if (LocaleCompare(attribute,"delay") == 0)
4510             {
4511               if (image != (Image *) NULL)
4512                 s=newSViv((long) image->delay);
4513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4514               continue;
4515             }
4516           if (LocaleCompare(attribute,"depth") == 0)
4517             {
4518               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4519               if (image != (Image *) NULL)
4520                 s=newSViv((long) GetImageDepth(image,&image->exception));
4521               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4522               continue;
4523             }
4524           if (LocaleCompare(attribute,"directory") == 0)
4525             {
4526               if (image && image->directory)
4527                 s=newSVpv(image->directory,0);
4528               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4529               continue;
4530             }
4531           if (LocaleCompare(attribute,"dispose") == 0)
4532             {
4533               if (image == (Image *) NULL)
4534                 break;
4535
4536               s=newSViv(image->dispose);
4537               (void) sv_setpv(s,
4538                 MagickOptionToMnemonic(MagickDisposeOptions,image->dispose));
4539               SvIOK_on(s);
4540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4541               continue;
4542             }
4543           if (LocaleCompare(attribute,"disk") == 0)
4544             {
4545               s=newSViv(GetMagickResource(DiskResource));
4546               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4547               continue;
4548             }
4549           if (LocaleCompare(attribute,"dither") == 0)
4550             {
4551               if (info)
4552                 s=newSViv((long) info->image_info->dither);
4553               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4554               continue;
4555             }
4556           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4557             {
4558               if (info && info->image_info->server_name)
4559                 s=newSVpv(info->image_info->server_name,0);
4560               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4561               continue;
4562             }
4563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4564             attribute);
4565           break;
4566         }
4567         case 'E':
4568         case 'e':
4569         {
4570           if (LocaleCompare(attribute,"elapsed-time") == 0)
4571             {
4572               if (image != (Image *) NULL)
4573                 s=newSVnv(GetElapsedTime(&image->timer));
4574               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4575               continue;
4576             }
4577           if (LocaleCompare(attribute,"endian") == 0)
4578             {
4579               j=info ? info->image_info->endian : image->endian;
4580               s=newSViv(j);
4581               (void) sv_setpv(s,MagickOptionToMnemonic(MagickEndianOptions,j));
4582               SvIOK_on(s);
4583               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4584               continue;
4585             }
4586           if (LocaleCompare(attribute,"error") == 0)
4587             {
4588               if (image != (Image *) NULL)
4589                 s=newSVnv(image->error.mean_error_per_pixel);
4590               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4591               continue;
4592             }
4593           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4594             attribute);
4595           break;
4596         }
4597         case 'F':
4598         case 'f':
4599         {
4600           if (LocaleCompare(attribute,"filesize") == 0)
4601             {
4602               if (image != (Image *) NULL)
4603                 s=newSViv((long) GetBlobSize(image));
4604               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4605               continue;
4606             }
4607           if (LocaleCompare(attribute,"filename") == 0)
4608             {
4609               if (info && info->image_info->filename &&
4610                   *info->image_info->filename)
4611                 s=newSVpv(info->image_info->filename,0);
4612               if (image != (Image *) NULL)
4613                 s=newSVpv(image->filename,0);
4614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4615               continue;
4616             }
4617           if (LocaleCompare(attribute,"filter") == 0)
4618             {
4619               s=newSViv(image->filter);
4620               (void) sv_setpv(s,MagickOptionToMnemonic(MagickFilterOptions,
4621                 image->filter));
4622               SvIOK_on(s);
4623               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4624               continue;
4625             }
4626           if (LocaleCompare(attribute,"font") == 0)
4627             {
4628               if (info && info->image_info->font)
4629                 s=newSVpv(info->image_info->font,0);
4630               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4631               continue;
4632             }
4633           if (LocaleCompare(attribute,"foreground") == 0)
4634             continue;
4635           if (LocaleCompare(attribute,"format") == 0)
4636             {
4637               const MagickInfo
4638                 *magick_info;
4639
4640               magick_info=(const MagickInfo *) NULL;
4641               if (info && (*info->image_info->magick != '\0'))
4642                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4643               if (image != (Image *) NULL)
4644                 magick_info=GetMagickInfo(image->magick,&image->exception);
4645               if ((magick_info != (const MagickInfo *) NULL) &&
4646                   (*magick_info->description != '\0'))
4647                 s=newSVpv((char *) magick_info->description,0);
4648               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4649               continue;
4650             }
4651           if (LocaleCompare(attribute,"fuzz") == 0)
4652             {
4653               if (info)
4654                 s=newSVnv(info->image_info->fuzz);
4655               if (image != (Image *) NULL)
4656                 s=newSVnv(image->fuzz);
4657               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4658               continue;
4659             }
4660           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4661             attribute);
4662           break;
4663         }
4664         case 'G':
4665         case 'g':
4666         {
4667           if (LocaleCompare(attribute,"gamma") == 0)
4668             {
4669               if (image != (Image *) NULL)
4670                 s=newSVnv(image->gamma);
4671               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4672               continue;
4673             }
4674           if (LocaleCompare(attribute,"geometry") == 0)
4675             {
4676               if (image && image->geometry)
4677                 s=newSVpv(image->geometry,0);
4678               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4679               continue;
4680             }
4681           if (LocaleCompare(attribute,"gravity") == 0)
4682             {
4683               s=newSViv(image->gravity);
4684               (void) sv_setpv(s,
4685                 MagickOptionToMnemonic(MagickGravityOptions,image->gravity));
4686               SvIOK_on(s);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           if (LocaleCompare(attribute,"green-primary") == 0)
4691             {
4692               if (image == (Image *) NULL)
4693                 break;
4694               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4695                 image->chromaticity.green_primary.x,
4696                 image->chromaticity.green_primary.y);
4697               s=newSVpv(color,0);
4698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699               continue;
4700             }
4701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4702             attribute);
4703           break;
4704         }
4705         case 'H':
4706         case 'h':
4707         {
4708           if (LocaleCompare(attribute,"height") == 0)
4709             {
4710               if (image != (Image *) NULL)
4711                 s=newSViv((long) image->rows);
4712               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4713               continue;
4714             }
4715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4716             attribute);
4717           break;
4718         }
4719         case 'I':
4720         case 'i':
4721         {
4722           if (LocaleCompare(attribute,"icc") == 0)
4723             {
4724               if (image != (Image *) NULL)
4725                 {
4726                   const StringInfo
4727                     *profile;
4728
4729                   profile=GetImageProfile(image,"icc");
4730                   if (profile != (StringInfo *) NULL)
4731                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4732                       GetStringInfoLength(profile));
4733                 }
4734               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4735               continue;
4736             }
4737           if (LocaleCompare(attribute,"icm") == 0)
4738             {
4739               if (image != (Image *) NULL)
4740                 {
4741                   const StringInfo
4742                     *profile;
4743
4744                   profile=GetImageProfile(image,"icm");
4745                   if (profile != (const StringInfo *) NULL)
4746                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4747                       GetStringInfoLength(profile));
4748                 }
4749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4750               continue;
4751             }
4752           if (LocaleCompare(attribute,"id") == 0)
4753             {
4754               if (image != (Image *) NULL)
4755                 {
4756                   char
4757                     key[MaxTextExtent];
4758
4759                   MagickBooleanType
4760                     status;
4761
4762                   static long
4763                     id = 0;
4764
4765                   (void) FormatMagickString(key,MaxTextExtent,"%ld\n",id);
4766                   status=SetImageRegistry(ImageRegistryType,key,image,
4767                     &image->exception);
4768                   s=newSViv(id++);
4769                 }
4770               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4771               continue;
4772             }
4773           if (LocaleNCompare(attribute,"index",5) == 0)
4774             {
4775               char
4776                 name[MaxTextExtent];
4777
4778               int
4779                 items;
4780
4781               long
4782                 x,
4783                 y;
4784
4785               register const IndexPacket
4786                 *indexes;
4787
4788               register const PixelPacket
4789                 *p;
4790
4791               CacheView
4792                 *image_view;
4793
4794               if (image == (Image *) NULL)
4795                 break;
4796               if (image->storage_class != PseudoClass)
4797                 break;
4798               x=0;
4799               y=0;
4800               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4801               image_view=AcquireCacheView(image);
4802               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4803               if (p != (const PixelPacket *) NULL)
4804                 {
4805                   indexes=GetCacheViewVirtualIndexQueue(image_view);
4806                   (void) FormatMagickString(name,MaxTextExtent,QuantumFormat,
4807                     *indexes);
4808                   s=newSVpv(name,0);
4809                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4810                 }
4811               image_view=DestroyCacheView(image_view);
4812               continue;
4813             }
4814           if (LocaleCompare(attribute,"iptc") == 0)
4815             {
4816               if (image != (Image *) NULL)
4817                 {
4818                   const StringInfo
4819                     *profile;
4820
4821                   profile=GetImageProfile(image,"iptc");
4822                   if (profile != (const StringInfo *) NULL)
4823                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4824                       GetStringInfoLength(profile));
4825                 }
4826               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4827               continue;
4828             }
4829           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4830             {
4831               if (image != (Image *) NULL)
4832                 s=newSViv((long) image->iterations);
4833               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4834               continue;
4835             }
4836           if (LocaleCompare(attribute,"interlace") == 0)
4837             {
4838               j=info ? info->image_info->interlace : image->interlace;
4839               s=newSViv(j);
4840               (void) sv_setpv(s,MagickOptionToMnemonic(MagickInterlaceOptions,
4841                 j));
4842               SvIOK_on(s);
4843               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844               continue;
4845             }
4846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4847             attribute);
4848           break;
4849         }
4850         case 'L':
4851         case 'l':
4852         {
4853           if (LocaleCompare(attribute,"label") == 0)
4854             {
4855               const char
4856                 *value;
4857
4858               if (image == (Image *) NULL)
4859                 break;
4860               value=GetImageProperty(image,"Label");
4861               if (value != (const char *) NULL)
4862                 s=newSVpv(value,0);
4863               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4864               continue;
4865             }
4866           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4867             {
4868               if (image != (Image *) NULL)
4869                 s=newSViv((long) image->iterations);
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4874             attribute);
4875           break;
4876         }
4877         case 'M':
4878         case 'm':
4879         {
4880           if (LocaleCompare(attribute,"magick") == 0)
4881             {
4882               if (info && *info->image_info->magick)
4883                 s=newSVpv(info->image_info->magick,0);
4884               if (image != (Image *) NULL)
4885                 s=newSVpv(image->magick,0);
4886               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4887               continue;
4888             }
4889           if (LocaleCompare(attribute,"map") == 0)
4890             {
4891               s=newSViv(GetMagickResource(MapResource));
4892               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4893               continue;
4894             }
4895           if (LocaleCompare(attribute,"maximum-error") == 0)
4896             {
4897               if (image != (Image *) NULL)
4898                 s=newSVnv(image->error.normalized_maximum_error);
4899               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4900               continue;
4901             }
4902           if (LocaleCompare(attribute,"memory") == 0)
4903             {
4904               s=newSViv(GetMagickResource(MemoryResource));
4905               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4906               continue;
4907             }
4908           if (LocaleCompare(attribute,"mean-error") == 0)
4909             {
4910               if (image != (Image *) NULL)
4911                 s=newSVnv(image->error.normalized_mean_error);
4912               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4913               continue;
4914             }
4915           if (LocaleCompare(attribute,"mime") == 0)
4916             {
4917               if (info && *info->image_info->magick)
4918                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4919               if (image != (Image *) NULL)
4920                 s=newSVpv(MagickToMime(image->magick),0);
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           if (LocaleCompare(attribute,"mattecolor") == 0)
4925             {
4926               if (image == (Image *) NULL)
4927                 break;
4928               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4929                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4930                 image->matte_color.red,image->matte_color.green,
4931                 image->matte_color.blue,image->matte_color.opacity);
4932               s=newSVpv(color,0);
4933               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4934               continue;
4935             }
4936           if (LocaleCompare(attribute,"matte") == 0)
4937             {
4938               if (image != (Image *) NULL)
4939                 s=newSViv((long) image->matte);
4940               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4941               continue;
4942             }
4943           if (LocaleCompare(attribute,"mime") == 0)
4944             {
4945               const char
4946                 *magick;
4947
4948               magick=NULL;
4949               if (info && *info->image_info->magick)
4950                 magick=info->image_info->magick;
4951               if (image != (Image *) NULL)
4952                 magick=image->magick;
4953               if (magick)
4954                 {
4955                   char
4956                     *mime;
4957
4958                   mime=MagickToMime(magick);
4959                   s=newSVpv(mime,0);
4960                   mime=(char *) RelinquishMagickMemory(mime);
4961                 }
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           if (LocaleCompare(attribute,"monochrome") == 0)
4966             {
4967               if (image == (Image *) NULL)
4968                 continue;
4969               j=info ? info->image_info->monochrome :
4970                 IsMonochromeImage(image,&image->exception);
4971               s=newSViv(j);
4972               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4973               continue;
4974             }
4975           if (LocaleCompare(attribute,"montage") == 0)
4976             {
4977               if (image && image->montage)
4978                 s=newSVpv(image->montage,0);
4979               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4980               continue;
4981             }
4982           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4983             attribute);
4984           break;
4985         }
4986         case 'O':
4987         case 'o':
4988         {
4989           if (LocaleCompare(attribute,"orientation") == 0)
4990             {
4991               j=info ? info->image_info->orientation : image->orientation;
4992               s=newSViv(j);
4993               (void) sv_setpv(s,MagickOptionToMnemonic(MagickOrientationOptions,
4994                 j));
4995               SvIOK_on(s);
4996               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4997               continue;
4998             }
4999           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5000             attribute);
5001           break;
5002         }
5003         case 'P':
5004         case 'p':
5005         {
5006           if (LocaleCompare(attribute,"page") == 0)
5007             {
5008               if (info && info->image_info->page)
5009                 s=newSVpv(info->image_info->page,0);
5010               if (image != (Image *) NULL)
5011                 {
5012                   char
5013                     geometry[MaxTextExtent];
5014
5015                   (void) FormatMagickString(geometry,MaxTextExtent,
5016                     "%lux%lu%+ld%+ld",image->page.width,image->page.height,
5017                     image->page.x,image->page.y);
5018                   s=newSVpv(geometry,0);
5019                 }
5020               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5021               continue;
5022             }
5023           if (LocaleCompare(attribute,"page.x") == 0)
5024             {
5025               if (image != (Image *) NULL)
5026                 s=newSViv((long) image->page.x);
5027               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5028               continue;
5029             }
5030           if (LocaleCompare(attribute,"page.y") == 0)
5031             {
5032               if (image != (Image *) NULL)
5033                 s=newSViv((long) image->page.y);
5034               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5035               continue;
5036             }
5037           if (LocaleNCompare(attribute,"pixel",5) == 0)
5038             {
5039               char
5040                 tuple[MaxTextExtent];
5041
5042               int
5043                 items;
5044
5045               long
5046                 x,
5047                 y;
5048
5049               register const PixelPacket
5050                 *p;
5051
5052               register const IndexPacket
5053                 *indexes;
5054
5055               if (image == (Image *) NULL)
5056                 break;
5057               x=0;
5058               y=0;
5059               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5060               p=GetVirtualPixels(image,x,y,1,1,exception);
5061               indexes=GetVirtualIndexQueue(image);
5062               if (image->colorspace != CMYKColorspace)
5063                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
5064                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5065                   p->red,p->green,p->blue,p->opacity);
5066               else
5067                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
5068                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5069                   QuantumFormat,p->red,p->green,p->blue,*indexes,p->opacity);
5070               s=newSVpv(tuple,0);
5071               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5072               continue;
5073             }
5074           if (LocaleCompare(attribute,"pointsize") == 0)
5075             {
5076               if (info)
5077                 s=newSViv((long) info->image_info->pointsize);
5078               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5079               continue;
5080             }
5081           if (LocaleCompare(attribute,"preview") == 0)
5082             {
5083               s=newSViv(info->image_info->preview_type);
5084               (void) sv_setpv(s,MagickOptionToMnemonic(MagickPreviewOptions,
5085                 info->image_info->preview_type));
5086               SvIOK_on(s);
5087               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5088               continue;
5089             }
5090           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5091             attribute);
5092           break;
5093         }
5094         case 'Q':
5095         case 'q':
5096         {
5097           if (LocaleCompare(attribute,"quality") == 0)
5098             {
5099               if (info)
5100                 s=newSViv((long) info->image_info->quality);
5101               if (image != (Image *) NULL)
5102                 s=newSViv((long) image->quality);
5103               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104               continue;
5105             }
5106           if (LocaleCompare(attribute,"quantum") == 0)
5107             {
5108               if (info)
5109                 s=newSViv((long) MAGICKCORE_QUANTUM_DEPTH);
5110               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111               continue;
5112             }
5113           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5114             attribute);
5115           break;
5116         }
5117         case 'R':
5118         case 'r':
5119         {
5120           if (LocaleCompare(attribute,"rendering-intent") == 0)
5121             {
5122               s=newSViv(image->rendering_intent);
5123               (void) sv_setpv(s,MagickOptionToMnemonic(MagickIntentOptions,
5124                 image->rendering_intent));
5125               SvIOK_on(s);
5126               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5127               continue;
5128             }
5129           if (LocaleCompare(attribute,"red-primary") == 0)
5130             {
5131               if (image == (Image *) NULL)
5132                 break;
5133               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
5134                 image->chromaticity.red_primary.x,
5135                 image->chromaticity.red_primary.y);
5136               s=newSVpv(color,0);
5137               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5138               continue;
5139             }
5140           if (LocaleCompare(attribute,"rows") == 0)
5141             {
5142               if (image != (Image *) NULL)
5143                 s=newSViv((long) image->rows);
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5148             attribute);
5149           break;
5150         }
5151         case 'S':
5152         case 's':
5153         {
5154           if (LocaleCompare(attribute,"sampling-factor") == 0)
5155             {
5156               if (info && info->image_info->sampling_factor)
5157                 s=newSVpv(info->image_info->sampling_factor,0);
5158               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5159               continue;
5160             }
5161           if (LocaleCompare(attribute,"subimage") == 0)
5162             {
5163               if (info)
5164                 s=newSViv((long) info->image_info->subimage);
5165               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5166               continue;
5167             }
5168           if (LocaleCompare(attribute,"subrange") == 0)
5169             {
5170               if (info)
5171                 s=newSViv((long) info->image_info->subrange);
5172               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5173               continue;
5174             }
5175           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5176             {
5177               if (info && info->image_info->server_name)
5178                 s=newSVpv(info->image_info->server_name,0);
5179               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5180               continue;
5181             }
5182           if (LocaleCompare(attribute,"size") == 0)
5183             {
5184               if (info && info->image_info->size)
5185                 s=newSVpv(info->image_info->size,0);
5186               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5187               continue;
5188             }
5189           if (LocaleCompare(attribute,"scene") == 0)
5190             {
5191               if (image != (Image *) NULL)
5192                 s=newSViv((long) image->scene);
5193               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5194               continue;
5195             }
5196           if (LocaleCompare(attribute,"scenes") == 0)
5197             {
5198               if (image != (Image *) NULL)
5199                 s=newSViv((long) info->image_info->number_scenes);
5200               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5201               continue;
5202             }
5203           if (LocaleCompare(attribute,"signature") == 0)
5204             {
5205               const char
5206                 *value;
5207
5208               if (image == (Image *) NULL)
5209                 break;
5210               (void) SignatureImage(image);
5211               value=GetImageProperty(image,"Signature");
5212               if (value != (const char *) NULL)
5213                 s=newSVpv(value,0);
5214               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5215               continue;
5216             }
5217           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5218             attribute);
5219           break;
5220         }
5221         case 'T':
5222         case 't':
5223         {
5224           if (LocaleCompare(attribute,"taint") == 0)
5225             {
5226               if (image != (Image *) NULL)
5227                 s=newSViv((long) IsTaintImage(image));
5228               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5229               continue;
5230             }
5231           if (LocaleCompare(attribute,"tile") == 0)
5232             {
5233               if (info && info->image_info->tile)
5234                 s=newSVpv(info->image_info->tile,0);
5235               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5236               continue;
5237             }
5238           if (LocaleCompare(attribute,"texture") == 0)
5239             {
5240               if (info && info->image_info->texture)
5241                 s=newSVpv(info->image_info->texture,0);
5242               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5243               continue;
5244             }
5245           if (LocaleCompare(attribute,"total-ink-density") == 0)
5246             {
5247               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5248               if (image != (Image *) NULL)
5249                 s=newSVnv(GetImageTotalInkDensity(image));
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleCompare(attribute,"transparent-color") == 0)
5254             {
5255               if (image == (Image *) NULL)
5256                 break;
5257               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
5258                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5259                 image->transparent_color.red,image->transparent_color.green,
5260                 image->transparent_color.blue,image->transparent_color.opacity);
5261               s=newSVpv(color,0);
5262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263               continue;
5264             }
5265           if (LocaleCompare(attribute,"type") == 0)
5266             {
5267               if (image == (Image *) NULL)
5268                 break;
5269               j=(long) GetImageType(image,&image->exception);
5270               s=newSViv(j);
5271               (void) sv_setpv(s,MagickOptionToMnemonic(MagickTypeOptions,j));
5272               SvIOK_on(s);
5273               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5274               continue;
5275             }
5276           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5277             attribute);
5278           break;
5279         }
5280         case 'U':
5281         case 'u':
5282         {
5283           if (LocaleCompare(attribute,"units") == 0)
5284             {
5285               j=info ? info->image_info->units : image->units;
5286               if (info)
5287                 if (info->image_info->units == UndefinedResolution)
5288                   j=image->units;
5289               if (j == UndefinedResolution)
5290                 s=newSVpv("undefined units",0);
5291               else
5292                 if (j == PixelsPerInchResolution)
5293                   s=newSVpv("pixels / inch",0);
5294                 else
5295                   s=newSVpv("pixels / centimeter",0);
5296               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5297               continue;
5298             }
5299           if (LocaleCompare(attribute,"user-time") == 0)
5300             {
5301               if (image != (Image *) NULL)
5302                 s=newSVnv(GetUserTime(&image->timer));
5303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304               continue;
5305             }
5306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5307             attribute);
5308           break;
5309         }
5310         case 'V':
5311         case 'v':
5312         {
5313           if (LocaleCompare(attribute,"verbose") == 0)
5314             {
5315               if (info)
5316                 s=newSViv((long) info->image_info->verbose);
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           if (LocaleCompare(attribute,"version") == 0)
5321             {
5322               s=newSVpv(GetMagickVersion((unsigned long *) NULL),0);
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           if (LocaleCompare(attribute,"view") == 0)
5327             {
5328               if (info && info->image_info->view)
5329                 s=newSVpv(info->image_info->view,0);
5330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5331               continue;
5332             }
5333           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5334             {
5335               if (image == (Image *) NULL)
5336                 break;
5337               j=(long) GetImageVirtualPixelMethod(image);
5338               s=newSViv(j);
5339               (void) sv_setpv(s,MagickOptionToMnemonic(
5340                 MagickVirtualPixelOptions,j));
5341               SvIOK_on(s);
5342               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343               continue;
5344             }
5345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5346             attribute);
5347           break;
5348         }
5349         case 'W':
5350         case 'w':
5351         {
5352           if (LocaleCompare(attribute,"white-point") == 0)
5353             {
5354               if (image == (Image *) NULL)
5355                 break;
5356               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
5357                 image->chromaticity.white_point.x,
5358                 image->chromaticity.white_point.y);
5359               s=newSVpv(color,0);
5360               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5361               continue;
5362             }
5363           if (LocaleCompare(attribute,"width") == 0)
5364             {
5365               if (image != (Image *) NULL)
5366                 s=newSViv((long) image->columns);
5367               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5368               continue;
5369             }
5370           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5371              attribute);
5372           break;
5373         }
5374         case 'X':
5375         case 'x':
5376         {
5377           if (LocaleCompare(attribute,"x-resolution") == 0)
5378             {
5379               if (image != (Image *) NULL)
5380                 s=newSVnv(image->x_resolution);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5385             attribute);
5386           break;
5387         }
5388         case 'Y':
5389         case 'y':
5390         {
5391           if (LocaleCompare(attribute,"y-resolution") == 0)
5392             {
5393               if (image != (Image *) NULL)
5394                 s=newSVnv(image->y_resolution);
5395               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5396               continue;
5397             }
5398           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5399             attribute);
5400           break;
5401         }
5402         default:
5403           break;
5404       }
5405       if (image == (Image *) NULL)
5406         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5407           attribute)
5408       else
5409         {
5410           value=GetImageProperty(image,attribute);
5411           if (value != (const char *) NULL)
5412             {
5413               s=newSVpv(value,0);
5414               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415             }
5416           else
5417             if (*attribute != '%')
5418               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419                 attribute)
5420             else
5421               {
5422                  char
5423                    *meta;
5424
5425                  meta=InterpretImageProperties(info ? info->image_info :
5426                    (ImageInfo *) NULL,image,attribute);
5427                  s=newSVpv(meta,0);
5428                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5429                  meta=(char *) RelinquishMagickMemory(meta);
5430               }
5431         }
5432     }
5433     exception=DestroyExceptionInfo(exception);
5434     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5435   }
5436 \f
5437 #
5438 ###############################################################################
5439 #                                                                             #
5440 #                                                                             #
5441 #                                                                             #
5442 #   G e t A u t h e n t i c P i x e l s                                       #
5443 #                                                                             #
5444 #                                                                             #
5445 #                                                                             #
5446 ###############################################################################
5447 #
5448 #
5449 void *
5450 GetAuthenticPixels(ref,...)
5451   Image::Magick ref = NO_INIT
5452   ALIAS:
5453     getauthenticpixels = 1
5454     GetImagePixels = 2
5455     getimagepixels = 3
5456   CODE:
5457   {
5458     char
5459       *attribute;
5460
5461     ExceptionInfo
5462       *exception;
5463
5464     Image
5465       *image;
5466
5467     long
5468       i;
5469
5470     RectangleInfo
5471       region;
5472
5473     struct PackageInfo
5474       *info;
5475
5476     SV
5477       *perl_exception,
5478       *reference;
5479
5480     void
5481       *blob = NULL;
5482
5483     exception=AcquireExceptionInfo();
5484     perl_exception=newSVpv("",0);
5485     if (sv_isobject(ST(0)) == 0)
5486       {
5487         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5488           PackageName);
5489         goto PerlException;
5490       }
5491     reference=SvRV(ST(0));
5492
5493     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5494     if (image == (Image *) NULL)
5495       {
5496         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5497           PackageName);
5498         goto PerlException;
5499       }
5500
5501     region.x=0;
5502     region.y=0;
5503     region.width=image->columns;
5504     region.height=1;
5505     if (items == 1)
5506       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5507     for (i=2; i < items; i+=2)
5508     {
5509       attribute=(char *) SvPV(ST(i-1),na);
5510       switch (*attribute)
5511       {
5512         case 'g':
5513         case 'G':
5514         {
5515           if (LocaleCompare(attribute,"geometry") == 0)
5516             {
5517               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5518               break;
5519             }
5520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5521             attribute);
5522           break;
5523         }
5524         case 'H':
5525         case 'h':
5526         {
5527           if (LocaleCompare(attribute,"height") == 0)
5528             {
5529               region.height=SvIV(ST(i));
5530               continue;
5531             }
5532           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5533             attribute);
5534           break;
5535         }
5536         case 'X':
5537         case 'x':
5538         {
5539           if (LocaleCompare(attribute,"x") == 0)
5540             {
5541               region.x=SvIV(ST(i));
5542               continue;
5543             }
5544           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5545             attribute);
5546           break;
5547         }
5548         case 'Y':
5549         case 'y':
5550         {
5551           if (LocaleCompare(attribute,"y") == 0)
5552             {
5553               region.y=SvIV(ST(i));
5554               continue;
5555             }
5556           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5557             attribute);
5558           break;
5559         }
5560         case 'W':
5561         case 'w':
5562         {
5563           if (LocaleCompare(attribute,"width") == 0)
5564             {
5565               region.width=SvIV(ST(i));
5566               continue;
5567             }
5568           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5569             attribute);
5570           break;
5571         }
5572       }
5573     }
5574     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5575       region.height,exception);
5576     if (blob != (void *) NULL)
5577       goto PerlEnd;
5578
5579   PerlException:
5580     InheritPerlException(exception,perl_exception);
5581     exception=DestroyExceptionInfo(exception);
5582     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5583
5584   PerlEnd:
5585     RETVAL = blob;
5586   }
5587   OUTPUT:
5588     RETVAL
5589 \f
5590 #
5591 ###############################################################################
5592 #                                                                             #
5593 #                                                                             #
5594 #                                                                             #
5595 #   G e t V i r t u a l P i x e l s                                           #
5596 #                                                                             #
5597 #                                                                             #
5598 #                                                                             #
5599 ###############################################################################
5600 #
5601 #
5602 void *
5603 GetVirtualPixels(ref,...)
5604   Image::Magick ref = NO_INIT
5605   ALIAS:
5606     getvirtualpixels = 1
5607     AcquireImagePixels = 2
5608     acquireimagepixels = 3
5609   CODE:
5610   {
5611     char
5612       *attribute;
5613
5614     const void
5615       *blob = NULL;
5616
5617     ExceptionInfo
5618       *exception;
5619
5620     Image
5621       *image;
5622
5623     long
5624       i;
5625
5626     RectangleInfo
5627       region;
5628
5629     struct PackageInfo
5630       *info;
5631
5632     SV
5633       *perl_exception,
5634       *reference;
5635
5636     exception=AcquireExceptionInfo();
5637     perl_exception=newSVpv("",0);
5638     if (sv_isobject(ST(0)) == 0)
5639       {
5640         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5641           PackageName);
5642         goto PerlException;
5643       }
5644     reference=SvRV(ST(0));
5645
5646     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5647     if (image == (Image *) NULL)
5648       {
5649         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5650           PackageName);
5651         goto PerlException;
5652       }
5653
5654     region.x=0;
5655     region.y=0;
5656     region.width=image->columns;
5657     region.height=1;
5658     if (items == 1)
5659       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5660     for (i=2; i < items; i+=2)
5661     {
5662       attribute=(char *) SvPV(ST(i-1),na);
5663       switch (*attribute)
5664       {
5665         case 'g':
5666         case 'G':
5667         {
5668           if (LocaleCompare(attribute,"geometry") == 0)
5669             {
5670               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5671               break;
5672             }
5673           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5674             attribute);
5675           break;
5676         }
5677         case 'H':
5678         case 'h':
5679         {
5680           if (LocaleCompare(attribute,"height") == 0)
5681             {
5682               region.height=SvIV(ST(i));
5683               continue;
5684             }
5685           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5686             attribute);
5687           break;
5688         }
5689         case 'X':
5690         case 'x':
5691         {
5692           if (LocaleCompare(attribute,"x") == 0)
5693             {
5694               region.x=SvIV(ST(i));
5695               continue;
5696             }
5697           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5698             attribute);
5699           break;
5700         }
5701         case 'Y':
5702         case 'y':
5703         {
5704           if (LocaleCompare(attribute,"y") == 0)
5705             {
5706               region.y=SvIV(ST(i));
5707               continue;
5708             }
5709           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5710             attribute);
5711           break;
5712         }
5713         case 'W':
5714         case 'w':
5715         {
5716           if (LocaleCompare(attribute,"width") == 0)
5717             {
5718               region.width=SvIV(ST(i));
5719               continue;
5720             }
5721           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5722             attribute);
5723           break;
5724         }
5725       }
5726     }
5727     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5728       region.height,exception);
5729     if (blob != (void *) NULL)
5730       goto PerlEnd;
5731
5732   PerlException:
5733     InheritPerlException(exception,perl_exception);
5734     exception=DestroyExceptionInfo(exception);
5735     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5736
5737   PerlEnd:
5738     RETVAL = (void *) blob;
5739   }
5740   OUTPUT:
5741     RETVAL
5742 \f
5743 #
5744 ###############################################################################
5745 #                                                                             #
5746 #                                                                             #
5747 #                                                                             #
5748 #   G e t A u t h e n t i c I n d e x Q u e u e                               #
5749 #                                                                             #
5750 #                                                                             #
5751 #                                                                             #
5752 ###############################################################################
5753 #
5754 #
5755 void *
5756 GetAuthenticIndexQueue(ref,...)
5757   Image::Magick ref = NO_INIT
5758   ALIAS:
5759     getauthenticindexqueue = 1
5760     GetIndexes = 2
5761     getindexes = 3
5762   CODE:
5763   {
5764     ExceptionInfo
5765       *exception;
5766
5767     Image
5768       *image;
5769
5770     struct PackageInfo
5771       *info;
5772
5773     SV
5774       *perl_exception,
5775       *reference;
5776
5777     void
5778       *blob = NULL;
5779
5780     exception=AcquireExceptionInfo();
5781     perl_exception=newSVpv("",0);
5782     if (sv_isobject(ST(0)) == 0)
5783       {
5784         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5785           PackageName);
5786         goto PerlException;
5787       }
5788     reference=SvRV(ST(0));
5789
5790     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5791     if (image == (Image *) NULL)
5792       {
5793         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5794           PackageName);
5795         goto PerlException;
5796       }
5797
5798     blob=(void *) GetAuthenticIndexQueue(image);
5799     if (blob != (void *) NULL)
5800       goto PerlEnd;
5801
5802   PerlException:
5803     InheritPerlException(exception,perl_exception);
5804     exception=DestroyExceptionInfo(exception);
5805     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5806
5807   PerlEnd:
5808     RETVAL = blob;
5809   }
5810   OUTPUT:
5811     RETVAL
5812 \f
5813 #
5814 ###############################################################################
5815 #                                                                             #
5816 #                                                                             #
5817 #                                                                             #
5818 #   G e t V i r t u a l I n d e x Q u e u e                                   #
5819 #                                                                             #
5820 #                                                                             #
5821 #                                                                             #
5822 ###############################################################################
5823 #
5824 #
5825 void *
5826 GetVirtualIndexQueue(ref,...)
5827   Image::Magick ref = NO_INIT
5828   ALIAS:
5829     getvirtualindexqueue = 1
5830   CODE:
5831   {
5832     ExceptionInfo
5833       *exception;
5834
5835     Image
5836       *image;
5837
5838     struct PackageInfo
5839       *info;
5840
5841     SV
5842       *perl_exception,
5843       *reference;
5844
5845     void
5846       *blob = NULL;
5847
5848     exception=AcquireExceptionInfo();
5849     perl_exception=newSVpv("",0);
5850     if (sv_isobject(ST(0)) == 0)
5851       {
5852         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5853           PackageName);
5854         goto PerlException;
5855       }
5856     reference=SvRV(ST(0));
5857
5858     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5859     if (image == (Image *) NULL)
5860       {
5861         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5862           PackageName);
5863         goto PerlException;
5864       }
5865
5866     blob=(void *) GetVirtualIndexQueue(image);
5867     if (blob != (void *) NULL)
5868       goto PerlEnd;
5869
5870   PerlException:
5871     InheritPerlException(exception,perl_exception);
5872     exception=DestroyExceptionInfo(exception);
5873     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5874
5875   PerlEnd:
5876     RETVAL = blob;
5877   }
5878   OUTPUT:
5879     RETVAL
5880 \f
5881 #
5882 ###############################################################################
5883 #                                                                             #
5884 #                                                                             #
5885 #                                                                             #
5886 #   H i s t o g r a m                                                         #
5887 #                                                                             #
5888 #                                                                             #
5889 #                                                                             #
5890 ###############################################################################
5891 #
5892 #
5893 void
5894 Histogram(ref,...)
5895   Image::Magick ref=NO_INIT
5896   ALIAS:
5897     HistogramImage = 1
5898     histogram      = 2
5899     histogramimage = 3
5900   PPCODE:
5901   {
5902     AV
5903       *av;
5904
5905     char
5906       message[MaxTextExtent];
5907
5908     ColorPacket
5909       *histogram;
5910
5911     ExceptionInfo
5912       *exception;
5913
5914     HV
5915       *hv;
5916
5917     Image
5918       *image;
5919
5920     register long
5921       i;
5922
5923     ssize_t
5924       count;
5925
5926     struct PackageInfo
5927       *info;
5928
5929     SV
5930       *av_reference,
5931       *perl_exception,
5932       *reference;
5933
5934     unsigned long
5935       number_colors;
5936
5937     exception=AcquireExceptionInfo();
5938     perl_exception=newSVpv("",0);
5939     av=NULL;
5940     if (sv_isobject(ST(0)) == 0)
5941       {
5942         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5943           PackageName);
5944         goto PerlException;
5945       }
5946     reference=SvRV(ST(0));
5947     hv=SvSTASH(reference);
5948     av=newAV();
5949     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
5950     SvREFCNT_dec(av);
5951     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5952     if (image == (Image *) NULL)
5953       {
5954         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5955           PackageName);
5956         goto PerlException;
5957       }
5958     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5959     count=0;
5960     for ( ; image; image=image->next)
5961     {
5962       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5963       if (histogram == (ColorPacket *) NULL)
5964         continue;
5965       count+=number_colors;
5966       EXTEND(sp,6*count);
5967       for (i=0; i < (long) number_colors; i++)
5968       {
5969         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5970           histogram[i].pixel.red);
5971         PUSHs(sv_2mortal(newSVpv(message,0)));
5972         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5973           histogram[i].pixel.green);
5974         PUSHs(sv_2mortal(newSVpv(message,0)));
5975         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5976           histogram[i].pixel.blue);
5977         PUSHs(sv_2mortal(newSVpv(message,0)));
5978         if (image->colorspace == CMYKColorspace)
5979           {
5980             (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5981               histogram[i].index);
5982             PUSHs(sv_2mortal(newSVpv(message,0)));
5983           }
5984         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5985           histogram[i].pixel.opacity);
5986         PUSHs(sv_2mortal(newSVpv(message,0)));
5987         (void) FormatMagickString(message,MaxTextExtent,"%lu",
5988            (unsigned long) histogram[i].count);
5989         PUSHs(sv_2mortal(newSVpv(message,0)));
5990       }
5991       histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
5992     }
5993
5994   PerlException:
5995     InheritPerlException(exception,perl_exception);
5996     exception=DestroyExceptionInfo(exception);
5997     SvREFCNT_dec(perl_exception);
5998   }
5999 \f
6000 #
6001 ###############################################################################
6002 #                                                                             #
6003 #                                                                             #
6004 #                                                                             #
6005 #   G e t P i x e l                                                           #
6006 #                                                                             #
6007 #                                                                             #
6008 #                                                                             #
6009 ###############################################################################
6010 #
6011 #
6012 void
6013 GetPixel(ref,...)
6014   Image::Magick ref=NO_INIT
6015   ALIAS:
6016     getpixel = 1
6017     getPixel = 2
6018   PPCODE:
6019   {
6020     AV
6021       *av;
6022
6023     char
6024       *attribute;
6025
6026     ChannelType
6027       channel;
6028
6029     ExceptionInfo
6030       *exception;
6031
6032     Image
6033       *image;
6034
6035     long
6036       option;
6037
6038     MagickBooleanType
6039       normalize;
6040
6041     RectangleInfo
6042       region;
6043
6044     register const IndexPacket
6045       *indexes;
6046
6047     register const PixelPacket
6048       *p;
6049
6050     register long
6051       i;
6052
6053     struct PackageInfo
6054       *info;
6055
6056     SV
6057       *perl_exception,
6058       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6059
6060     exception=AcquireExceptionInfo();
6061     perl_exception=newSVpv("",0);
6062     reference=SvRV(ST(0));
6063     av=(AV *) reference;
6064     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6065       exception);
6066     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6067     if (image == (Image *) NULL)
6068       {
6069         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6070           PackageName);
6071         goto PerlException;
6072       }
6073     channel=DefaultChannels;
6074     normalize=MagickTrue;
6075     region.x=0;
6076     region.y=0;
6077     region.width=image->columns;
6078     region.height=1;
6079     if (items == 1)
6080       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6081     for (i=2; i < items; i+=2)
6082     {
6083       attribute=(char *) SvPV(ST(i-1),na);
6084       switch (*attribute)
6085       {
6086         case 'C':
6087         case 'c':
6088         {
6089           if (LocaleCompare(attribute,"channel") == 0)
6090             {
6091               long
6092                 option;
6093
6094               option=ParseChannelOption(SvPV(ST(i),na));
6095               if (option < 0)
6096                 {
6097                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6098                     SvPV(ST(i),na));
6099                   return;
6100                 }
6101                channel=(ChannelType) option;
6102               break;
6103             }
6104           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6105             attribute);
6106           break;
6107         }
6108         case 'g':
6109         case 'G':
6110         {
6111           if (LocaleCompare(attribute,"geometry") == 0)
6112             {
6113               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6114               break;
6115             }
6116           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6117             attribute);
6118           break;
6119         }
6120         case 'N':
6121         case 'n':
6122         {
6123           if (LocaleCompare(attribute,"normalize") == 0)
6124             {
6125               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
6126                 SvPV(ST(i),na));
6127               if (option < 0)
6128                 {
6129                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6130                     SvPV(ST(i),na));
6131                   break;
6132                 }
6133              normalize=option != 0 ? MagickTrue : MagickFalse;
6134              break;
6135             }
6136           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6137             attribute);
6138           break;
6139         }
6140         case 'x':
6141         case 'X':
6142         {
6143           if (LocaleCompare(attribute,"x") == 0)
6144             {
6145               region.x=SvIV(ST(i));
6146               break;
6147             }
6148           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6149             attribute);
6150           break;
6151         }
6152         case 'y':
6153         case 'Y':
6154         {
6155           if (LocaleCompare(attribute,"y") == 0)
6156             {
6157               region.y=SvIV(ST(i));
6158               break;
6159             }
6160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6161             attribute);
6162           break;
6163         }
6164         default:
6165         {
6166           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6167             attribute);
6168           break;
6169         }
6170       }
6171     }
6172     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6173     if (p == (const PixelPacket *) NULL)
6174       PUSHs(&sv_undef);
6175     else
6176       {
6177         double
6178           scale;
6179
6180         indexes=GetVirtualIndexQueue(image);
6181         scale=1.0;
6182         if (normalize != MagickFalse)
6183           scale=1.0/QuantumRange;
6184         if ((channel & RedChannel) != 0)
6185           PUSHs(sv_2mortal(newSVnv(scale*p->red)));
6186         if ((channel & GreenChannel) != 0)
6187           PUSHs(sv_2mortal(newSVnv(scale*p->green)));
6188         if ((channel & BlueChannel) != 0)
6189           PUSHs(sv_2mortal(newSVnv(scale*p->blue)));
6190         if (((channel & IndexChannel) != 0) &&
6191             (image->colorspace == CMYKColorspace))
6192           PUSHs(sv_2mortal(newSVnv(scale*(*indexes))));
6193         if ((channel & OpacityChannel) != 0)
6194           PUSHs(sv_2mortal(newSVnv(scale*p->opacity)));
6195       }
6196
6197   PerlException:
6198     InheritPerlException(exception,perl_exception);
6199     exception=DestroyExceptionInfo(exception);
6200     SvREFCNT_dec(perl_exception);
6201   }
6202 \f
6203 #
6204 ###############################################################################
6205 #                                                                             #
6206 #                                                                             #
6207 #                                                                             #
6208 #   G e t P i x e l s                                                         #
6209 #                                                                             #
6210 #                                                                             #
6211 #                                                                             #
6212 ###############################################################################
6213 #
6214 #
6215 void
6216 GetPixels(ref,...)
6217   Image::Magick ref=NO_INIT
6218   ALIAS:
6219     getpixels = 1
6220     getPixels = 2
6221   PPCODE:
6222   {
6223     AV
6224       *av;
6225
6226     char
6227       *attribute;
6228
6229     const char
6230       *map;
6231
6232     ExceptionInfo
6233       *exception;
6234
6235     Image
6236       *image;
6237
6238     long
6239       option;
6240
6241     MagickBooleanType
6242       normalize,
6243       status;
6244
6245     RectangleInfo
6246       region;
6247
6248     register long
6249       i;
6250
6251     struct PackageInfo
6252       *info;
6253
6254     SV
6255       *perl_exception,
6256       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6257
6258     exception=AcquireExceptionInfo();
6259     perl_exception=newSVpv("",0);
6260     reference=SvRV(ST(0));
6261     av=(AV *) reference;
6262     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6263       exception);
6264     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6265     if (image == (Image *) NULL)
6266       {
6267         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6268           PackageName);
6269         goto PerlException;
6270       }
6271     map="RGB";
6272     if (image->matte != MagickFalse)
6273       map="RGBA";
6274     if (image->colorspace == CMYKColorspace)
6275       {
6276         map="CMYK";
6277         if (image->matte != MagickFalse)
6278           map="CMYKA";
6279       }
6280     normalize=MagickFalse;
6281     region.x=0;
6282     region.y=0;
6283     region.width=image->columns;
6284     region.height=1;
6285     if (items == 1)
6286       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6287     for (i=2; i < items; i+=2)
6288     {
6289       attribute=(char *) SvPV(ST(i-1),na);
6290       switch (*attribute)
6291       {
6292         case 'g':
6293         case 'G':
6294         {
6295           if (LocaleCompare(attribute,"geometry") == 0)
6296             {
6297               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6298               break;
6299             }
6300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6301             attribute);
6302           break;
6303         }
6304         case 'H':
6305         case 'h':
6306         {
6307           if (LocaleCompare(attribute,"height") == 0)
6308             {
6309               region.height=SvIV(ST(i));
6310               break;
6311             }
6312           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6313             attribute);
6314           break;
6315         }
6316         case 'M':
6317         case 'm':
6318         {
6319           if (LocaleCompare(attribute,"map") == 0)
6320             {
6321               map=SvPV(ST(i),na);
6322               break;
6323             }
6324           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6325             attribute);
6326           break;
6327         }
6328         case 'N':
6329         case 'n':
6330         {
6331           if (LocaleCompare(attribute,"normalize") == 0)
6332             {
6333               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
6334                 SvPV(ST(i),na));
6335               if (option < 0)
6336                 {
6337                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6338                     SvPV(ST(i),na));
6339                   break;
6340                 }
6341              normalize=option != 0 ? MagickTrue : MagickFalse;
6342              break;
6343             }
6344           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6345             attribute);
6346           break;
6347         }
6348         case 'W':
6349         case 'w':
6350         {
6351           if (LocaleCompare(attribute,"width") == 0)
6352             {
6353               region.width=SvIV(ST(i));
6354               break;
6355             }
6356           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6357             attribute);
6358           break;
6359         }
6360         case 'x':
6361         case 'X':
6362         {
6363           if (LocaleCompare(attribute,"x") == 0)
6364             {
6365               region.x=SvIV(ST(i));
6366               break;
6367             }
6368           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6369             attribute);
6370           break;
6371         }
6372         case 'y':
6373         case 'Y':
6374         {
6375           if (LocaleCompare(attribute,"y") == 0)
6376             {
6377               region.y=SvIV(ST(i));
6378               break;
6379             }
6380           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6381             attribute);
6382           break;
6383         }
6384         default:
6385         {
6386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6387             attribute);
6388           break;
6389         }
6390       }
6391     }
6392     if (normalize != MagickFalse)
6393       {
6394         float
6395           *pixels;
6396
6397         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6398           region.height*sizeof(*pixels));
6399         if (pixels == (float *) NULL)
6400           {
6401             ThrowPerlException(exception,ResourceLimitError,
6402               "MemoryAllocationFailed",PackageName);
6403             goto PerlException;
6404           }
6405         status=ExportImagePixels(image,region.x,region.y,region.width,
6406           region.height,map,FloatPixel,pixels,exception);
6407         if (status == MagickFalse)
6408           PUSHs(&sv_undef);
6409         else
6410           {
6411             EXTEND(sp,strlen(map)*region.width*region.height);
6412             for (i=0; i < (long) (strlen(map)*region.width*region.height); i++)
6413               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6414           }
6415         pixels=(float *) RelinquishMagickMemory(pixels);
6416       }
6417     else
6418       {
6419         Quantum
6420           *pixels;
6421
6422         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6423           region.height*sizeof(*pixels));
6424         if (pixels == (Quantum *) NULL)
6425           {
6426             ThrowPerlException(exception,ResourceLimitError,
6427               "MemoryAllocationFailed",PackageName);
6428             goto PerlException;
6429           }
6430         status=ExportImagePixels(image,region.x,region.y,region.width,
6431           region.height,map,QuantumPixel,pixels,exception);
6432         if (status == MagickFalse)
6433           PUSHs(&sv_undef);
6434         else
6435           {
6436             EXTEND(sp,strlen(map)*region.width*region.height);
6437             for (i=0; i < (long) (strlen(map)*region.width*region.height); i++)
6438               PUSHs(sv_2mortal(newSViv(pixels[i])));
6439           }
6440         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6441       }
6442
6443   PerlException:
6444     InheritPerlException(exception,perl_exception);
6445     exception=DestroyExceptionInfo(exception);
6446     SvREFCNT_dec(perl_exception);
6447   }
6448 \f
6449 #
6450 ###############################################################################
6451 #                                                                             #
6452 #                                                                             #
6453 #                                                                             #
6454 #   I m a g e T o B l o b                                                     #
6455 #                                                                             #
6456 #                                                                             #
6457 #                                                                             #
6458 ###############################################################################
6459 #
6460 #
6461 void
6462 ImageToBlob(ref,...)
6463   Image::Magick ref=NO_INIT
6464   ALIAS:
6465     ImageToBlob  = 1
6466     imagetoblob  = 2
6467     toblob       = 3
6468     blob         = 4
6469   PPCODE:
6470   {
6471     char
6472       filename[MaxTextExtent];
6473
6474     ExceptionInfo
6475       *exception;
6476
6477     Image
6478       *image,
6479       *next;
6480
6481     long
6482       scene;
6483
6484     register long
6485       i;
6486
6487     struct PackageInfo
6488       *info,
6489       *package_info;
6490
6491     size_t
6492       length;
6493
6494     SV
6495       *perl_exception,
6496       *reference;
6497
6498     void
6499       *blob;
6500
6501     exception=AcquireExceptionInfo();
6502     perl_exception=newSVpv("",0);
6503     package_info=(struct PackageInfo *) NULL;
6504     if (sv_isobject(ST(0)) == 0)
6505       {
6506         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6507           PackageName);
6508         goto PerlException;
6509       }
6510     reference=SvRV(ST(0));
6511     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6512     if (image == (Image *) NULL)
6513       {
6514         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6515           PackageName);
6516         goto PerlException;
6517       }
6518     package_info=ClonePackageInfo(info,exception);
6519     for (i=2; i < items; i+=2)
6520       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6521     (void) CopyMagickString(filename,package_info->image_info->filename,
6522       MaxTextExtent);
6523     scene=0;
6524     for (next=image; next; next=next->next)
6525     {
6526       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6527       next->scene=scene++;
6528     }
6529     SetImageInfo(package_info->image_info,(unsigned int)
6530       GetImageListLength(image),&image->exception);
6531     EXTEND(sp,(long) GetImageListLength(image));
6532     for ( ; image; image=image->next)
6533     {
6534       length=0;
6535       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6536       if (blob != (char *) NULL)
6537         {
6538           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6539           blob=(unsigned char *) RelinquishMagickMemory(blob);
6540         }
6541       if (package_info->image_info->adjoin)
6542         break;
6543     }
6544
6545   PerlException:
6546     if (package_info != (struct PackageInfo *) NULL)
6547       DestroyPackageInfo(package_info);
6548     InheritPerlException(exception,perl_exception);
6549     exception=DestroyExceptionInfo(exception);
6550     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6551   }
6552 \f
6553 #
6554 ###############################################################################
6555 #                                                                             #
6556 #                                                                             #
6557 #                                                                             #
6558 #   L a y e r s                                                               #
6559 #                                                                             #
6560 #                                                                             #
6561 #                                                                             #
6562 ###############################################################################
6563 #
6564 #
6565 void
6566 Layers(ref,...)
6567   Image::Magick ref=NO_INIT
6568   ALIAS:
6569     Layers                = 1
6570     layers           = 2
6571     OptimizeImageLayers   = 3
6572     optimizelayers        = 4
6573     optimizeimagelayers   = 5
6574   PPCODE:
6575   {
6576     AV
6577       *av;
6578
6579     char
6580       *attribute;
6581
6582     CompositeOperator
6583       compose;
6584
6585     ExceptionInfo
6586       *exception;
6587
6588     HV
6589       *hv;
6590
6591     Image
6592       *image,
6593       *layers;
6594
6595     long
6596       option,
6597       sp;
6598
6599     MagickBooleanType
6600       dither;
6601
6602     ImageLayerMethod
6603       method;
6604
6605     register long
6606       i;
6607
6608     struct PackageInfo
6609       *info;
6610
6611     SV
6612       *av_reference,
6613       *perl_exception,
6614       *reference,
6615       *rv,
6616       *sv;
6617
6618     exception=AcquireExceptionInfo();
6619     perl_exception=newSVpv("",0);
6620     if (sv_isobject(ST(0)) == 0)
6621       {
6622         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6623           PackageName);
6624         goto PerlException;
6625       }
6626     reference=SvRV(ST(0));
6627     hv=SvSTASH(reference);
6628     av=newAV();
6629     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6630     SvREFCNT_dec(av);
6631     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6632     if (image == (Image *) NULL)
6633       {
6634         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6635           PackageName);
6636         goto PerlException;
6637       }
6638     compose=image->compose;
6639     dither=MagickFalse;
6640     method=OptimizeLayer;
6641     for (i=2; i < items; i+=2)
6642     {
6643       attribute=(char *) SvPV(ST(i-1),na);
6644       switch (*attribute)
6645       {
6646         case 'C':
6647         case 'c':
6648         {
6649           if (LocaleCompare(attribute,"compose") == 0)
6650             {
6651               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
6652                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6653               if (sp < 0)
6654                 {
6655                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6656                     SvPV(ST(i),na));
6657                   break;
6658                 }
6659               compose=(CompositeOperator) sp;
6660               break;
6661             }
6662           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6663             attribute);
6664           break;
6665         }
6666         case 'D':
6667         case 'd':
6668         {
6669           if (LocaleCompare(attribute,"dither") == 0)
6670             {
6671               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
6672                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
6673               if (sp < 0)
6674                 {
6675                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6676                     SvPV(ST(i),na));
6677                   break;
6678                 }
6679               dither=(MagickBooleanType) sp;
6680               break;
6681             }
6682           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6683             attribute);
6684           break;
6685         }
6686         case 'M':
6687         case 'm':
6688         {
6689           if (LocaleCompare(attribute,"method") == 0)
6690             {
6691               option=ParseMagickOption(MagickLayerOptions,MagickFalse,
6692                 SvPV(ST(i),na));
6693               if (option < 0)
6694                 {
6695                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6696                     SvPV(ST(i),na));
6697                   break;
6698                 }
6699               method=(ImageLayerMethod) option;
6700               break;
6701             }
6702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6703             attribute);
6704           break;
6705         }
6706         default:
6707         {
6708           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6709             attribute);
6710           break;
6711         }
6712       }
6713     }
6714     layers=(Image *) NULL;
6715     switch (method)
6716     {
6717       case CompareAnyLayer:
6718       case CompareClearLayer:
6719       case CompareOverlayLayer:
6720       default:
6721       {
6722         layers=CompareImageLayers(image,method,exception);
6723         break;
6724       }
6725       case MergeLayer:
6726       case FlattenLayer:
6727       case MosaicLayer:
6728       {
6729         layers=MergeImageLayers(image,method,exception);
6730         break;
6731       }
6732       case DisposeLayer:
6733       {
6734         layers=DisposeImages(image,exception);
6735         break;
6736       }
6737       case OptimizeImageLayer:
6738       {
6739         layers=OptimizeImageLayers(image,exception);
6740         break;
6741       }
6742       case OptimizePlusLayer:
6743       {
6744         layers=OptimizePlusImageLayers(image,exception);
6745         break;
6746       }
6747       case OptimizeTransLayer:
6748       {
6749         OptimizeImageTransparency(image,exception);
6750         InheritException(&(image->exception),exception);
6751         break;
6752       }
6753       case RemoveDupsLayer:
6754       {
6755         RemoveDuplicateLayers(&image,exception);
6756         InheritException(&(image->exception),exception);
6757         break;
6758       }
6759       case RemoveZeroLayer:
6760       {
6761         RemoveZeroDelayLayers(&image,exception);
6762         InheritException(&(image->exception),exception);
6763         break;
6764       }
6765       case OptimizeLayer:
6766       {
6767         QuantizeInfo
6768           *quantize_info;
6769
6770         /*
6771           General Purpose, GIF Animation Optimizer.
6772         */
6773         layers=CoalesceImages(image,exception);
6774         if (layers == (Image *) NULL)
6775           break;
6776         InheritException(&(layers->exception),exception);
6777         image=layers;
6778         layers=OptimizeImageLayers(image,exception);
6779         if (layers == (Image *) NULL)
6780           break;
6781         InheritException(&(layers->exception),exception);
6782         image=DestroyImageList(image);
6783         image=layers;
6784         layers=(Image *) NULL;
6785         OptimizeImageTransparency(image,exception);
6786         InheritException(&(image->exception),exception);
6787         quantize_info=AcquireQuantizeInfo(info->image_info);
6788         (void) RemapImages(quantize_info,image,(Image *) NULL);
6789         quantize_info=DestroyQuantizeInfo(quantize_info);
6790         break;
6791       }
6792       case CompositeLayer:
6793       {
6794         Image
6795           *source;
6796
6797         RectangleInfo
6798           geometry;
6799
6800         /*
6801           Split image sequence at the first 'NULL:' image.
6802         */
6803         source=image;
6804         while (source != (Image *) NULL)
6805         {
6806           source=GetNextImageInList(source);
6807           if ((source != (Image *) NULL) &&
6808               (LocaleCompare(source->magick,"NULL") == 0))
6809             break;
6810         }
6811         if (source != (Image *) NULL)
6812           {
6813             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6814                 (GetNextImageInList(source) == (Image *) NULL))
6815               source=(Image *) NULL;
6816             else
6817               {
6818                 /*
6819                   Separate the two lists, junk the null: image.
6820                 */
6821                 source=SplitImageList(source->previous);
6822                 DeleteImageFromList(&source);
6823               }
6824           }
6825         if (source == (Image *) NULL)
6826           {
6827             (void) ThrowMagickException(exception,GetMagickModule(),
6828               OptionError,"MissingNullSeparator","layers Composite");
6829             break;
6830           }
6831         /*
6832           Adjust offset with gravity and virtual canvas.
6833         */
6834         SetGeometry(image,&geometry);
6835         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6836         geometry.width=source->page.width != 0 ? source->page.width :
6837           source->columns;
6838         geometry.height=source->page.height != 0 ? source->page.height :
6839           source->rows;
6840         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6841           image->columns,image->page.height != 0 ? image->page.height :
6842           image->rows,image->gravity,&geometry);
6843         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6844         source=DestroyImageList(source);
6845         InheritException(&(image->exception),exception);
6846         break;
6847       }
6848     }
6849     if (layers != (Image *) NULL)
6850       {
6851         InheritException(&(layers->exception),exception);
6852         image=layers;
6853       }
6854     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6855       goto PerlException;
6856     for ( ; image; image=image->next)
6857     {
6858       AddImageToRegistry(image);
6859       rv=newRV(sv);
6860       av_push(av,sv_bless(rv,hv));
6861       SvREFCNT_dec(sv);
6862     }
6863     exception=DestroyExceptionInfo(exception);
6864     ST(0)=av_reference;
6865     SvREFCNT_dec(perl_exception);
6866     XSRETURN(1);
6867
6868   PerlException:
6869     InheritPerlException(exception,perl_exception);
6870     exception=DestroyExceptionInfo(exception);
6871     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6872     SvPOK_on(perl_exception);
6873     ST(0)=sv_2mortal(perl_exception);
6874     XSRETURN(1);
6875   }
6876 \f
6877 #
6878 ###############################################################################
6879 #                                                                             #
6880 #                                                                             #
6881 #                                                                             #
6882 #   M a g i c k T o M i m e                                                   #
6883 #                                                                             #
6884 #                                                                             #
6885 #                                                                             #
6886 ###############################################################################
6887 #
6888 #
6889 SV *
6890 MagickToMime(ref,name)
6891   Image::Magick ref=NO_INIT
6892   char *name
6893   ALIAS:
6894     magicktomime = 1
6895   CODE:
6896   {
6897     char
6898       *mime;
6899
6900     mime=MagickToMime(name);
6901     RETVAL=newSVpv(mime,0);
6902     mime=(char *) RelinquishMagickMemory(mime);
6903   }
6904   OUTPUT:
6905     RETVAL
6906 \f
6907 #
6908 ###############################################################################
6909 #                                                                             #
6910 #                                                                             #
6911 #                                                                             #
6912 #   M o g r i f y                                                             #
6913 #                                                                             #
6914 #                                                                             #
6915 #                                                                             #
6916 ###############################################################################
6917 #
6918 #
6919 void
6920 Mogrify(ref,...)
6921   Image::Magick ref=NO_INIT
6922   ALIAS:
6923     Comment            =   1
6924     CommentImage       =   2
6925     Label              =   3
6926     LabelImage         =   4
6927     AddNoise           =   5
6928     AddNoiseImage      =   6
6929     Colorize           =   7
6930     ColorizeImage      =   8
6931     Border             =   9
6932     BorderImage        =  10
6933     Blur               =  11
6934     BlurImage          =  12
6935     Chop               =  13
6936     ChopImage          =  14
6937     Crop               =  15
6938     CropImage          =  16
6939     Despeckle          =  17
6940     DespeckleImage     =  18
6941     Edge               =  19
6942     EdgeImage          =  20
6943     Emboss             =  21
6944     EmbossImage        =  22
6945     Enhance            =  23
6946     EnhanceImage       =  24
6947     Flip               =  25
6948     FlipImage          =  26
6949     Flop               =  27
6950     FlopImage          =  28
6951     Frame              =  29
6952     FrameImage         =  30
6953     Implode            =  31
6954     ImplodeImage       =  32
6955     Magnify            =  33
6956     MagnifyImage       =  34
6957     MedianFilter       =  35
6958     MedianFilterImage  =  36
6959     Minify             =  37
6960     MinifyImage        =  38
6961     OilPaint           =  39
6962     OilPaintImage      =  40
6963     ReduceNoise        =  41
6964     ReduceNoiseImage   =  42
6965     Roll               =  43
6966     RollImage          =  44
6967     Rotate             =  45
6968     RotateImage        =  46
6969     Sample             =  47
6970     SampleImage        =  48
6971     Scale              =  49
6972     ScaleImage         =  50
6973     Shade              =  51
6974     ShadeImage         =  52
6975     Sharpen            =  53
6976     SharpenImage       =  54
6977     Shear              =  55
6978     ShearImage         =  56
6979     Spread             =  57
6980     SpreadImage        =  58
6981     Swirl              =  59
6982     SwirlImage         =  60
6983     Resize             =  61
6984     ResizeImage        =  62
6985     Zoom               =  63
6986     ZoomImage          =  64
6987     Annotate           =  65
6988     AnnotateImage      =  66
6989     ColorFloodfill     =  67
6990     ColorFloodfillImage=  68
6991     Composite          =  69
6992     CompositeImage     =  70
6993     Contrast           =  71
6994     ContrastImage      =  72
6995     CycleColormap      =  73
6996     CycleColormapImage =  74
6997     Draw               =  75
6998     DrawImage          =  76
6999     Equalize           =  77
7000     EqualizeImage      =  78
7001     Gamma              =  79
7002     GammaImage         =  80
7003     Map                =  81
7004     MapImage           =  82
7005     MatteFloodfill     =  83
7006     MatteFloodfillImage=  84
7007     Modulate           =  85
7008     ModulateImage      =  86
7009     Negate             =  87
7010     NegateImage        =  88
7011     Normalize          =  89
7012     NormalizeImage     =  90
7013     NumberColors       =  91
7014     NumberColorsImage  =  92
7015     Opaque             =  93
7016     OpaqueImage        =  94
7017     Quantize           =  95
7018     QuantizeImage      =  96
7019     Raise              =  97
7020     RaiseImage         =  98
7021     Segment            =  99
7022     SegmentImage       = 100
7023     Signature          = 101
7024     SignatureImage     = 102
7025     Solarize           = 103
7026     SolarizeImage      = 104
7027     Sync               = 105
7028     SyncImage          = 106
7029     Texture            = 107
7030     TextureImage       = 108
7031     Evaluate           = 109
7032     EvaluateImage      = 110
7033     Transparent        = 111
7034     TransparentImage   = 112
7035     Threshold          = 113
7036     ThresholdImage     = 114
7037     Charcoal           = 115
7038     CharcoalImage      = 116
7039     Trim               = 117
7040     TrimImage          = 118
7041     Wave               = 119
7042     WaveImage          = 120
7043     Separate           = 121
7044     SeparateImage      = 122
7045     Stereo             = 125
7046     StereoImage        = 126
7047     Stegano            = 127
7048     SteganoImage       = 128
7049     Deconstruct        = 129
7050     DeconstructImage   = 130
7051     GaussianBlur       = 131
7052     GaussianBlurImage  = 132
7053     Convolve           = 133
7054     ConvolveImage      = 134
7055     Profile            = 135
7056     ProfileImage       = 136
7057     UnsharpMask        = 137
7058     UnsharpMaskImage   = 138
7059     MotionBlur         = 139
7060     MotionBlurImage    = 140
7061     OrderedDither      = 141
7062     OrderedDitherImage = 142
7063     Shave              = 143
7064     ShaveImage         = 144
7065     Level              = 145
7066     LevelImage         = 146
7067     Clip               = 147
7068     ClipImage          = 148
7069     AffineTransform    = 149
7070     AffineTransformImage = 150
7071     Difference         = 151
7072     DifferenceImage    = 152
7073     AdaptiveThreshold  = 153
7074     AdaptiveThresholdImage = 154
7075     Resample           = 155
7076     ResampleImage      = 156
7077     Describe           = 157
7078     DescribeImage      = 158
7079     BlackThreshold     = 159
7080     BlackThresholdImage= 160
7081     WhiteThreshold     = 161
7082     WhiteThresholdImage= 162
7083     RadialBlur         = 163
7084     RadialBlurImage    = 164
7085     Thumbnail          = 165
7086     ThumbnailImage     = 166
7087     Strip              = 167
7088     StripImage         = 168
7089     Tint               = 169
7090     TintImage          = 170
7091     Channel            = 171
7092     ChannelImage       = 172
7093     Splice             = 173
7094     SpliceImage        = 174
7095     Posterize          = 175
7096     PosterizeImage     = 176
7097     Shadow             = 177
7098     ShadowImage        = 178
7099     Identify           = 179
7100     IdentifyImage      = 180
7101     SepiaTone          = 181
7102     SepiaToneImage     = 182
7103     SigmoidalContrast  = 183
7104     SigmoidalContrastImage = 184
7105     Extent             = 185
7106     ExtentImage        = 186
7107     Vignette           = 187
7108     VignetteImage      = 188
7109     ContrastStretch    = 189
7110     ContrastStretchImage = 190
7111     Sans0              = 191
7112     Sans0Image         = 192
7113     Sans1              = 193
7114     Sans1Image         = 194
7115     AdaptiveSharpen    = 195
7116     AdaptiveSharpenImage = 196
7117     Transpose          = 197
7118     TransposeImage     = 198
7119     Transverse         = 199
7120     TransverseImage    = 200
7121     AutoOrient         = 201
7122     AutoOrientImage    = 202
7123     AdaptiveBlur       = 203
7124     AdaptiveBlurImage  = 204
7125     Sketch             = 205
7126     SketchImage        = 206
7127     UniqueColors       = 207
7128     UniqueColorsImage  = 208
7129     AdaptiveResize     = 209
7130     AdaptiveResizeImage= 210
7131     ClipMask           = 211
7132     ClipMaskImage      = 212
7133     LinearStretch      = 213
7134     LinearStretchImage = 214
7135     RecolorImage       = 215
7136     Recolor            = 216
7137     Mask               = 217
7138     MaskImage          = 218
7139     Polaroid           = 219
7140     PolaroidImage      = 220
7141     FloodfillPaint     = 221
7142     FloodfillPaintImage= 222
7143     Distort            = 223
7144     DistortImage       = 224
7145     Clut               = 225
7146     ClutImage          = 226
7147     LiquidRescale      = 227
7148     LiquidRescaleImage = 228
7149     Encipher           = 229
7150     EncipherImage      = 230
7151     Decipher           = 231
7152     DecipherImage      = 232
7153     Deskew             = 233
7154     DeskewImage        = 234
7155     Remap              = 235
7156     RemapImage         = 236
7157     SparseColor        = 237
7158     SparseColorImage   = 238
7159     Function           = 239
7160     FunctionImage      = 240
7161     SelectiveBlur      = 241
7162     SelectiveBlurImage = 242
7163     HaldClut           = 243
7164     HaldClutImage      = 244
7165     BlueShift          = 245
7166     BlueShiftImage     = 246
7167     ForwardFourierTransform  = 247
7168     ForwardFourierTransformImage = 248
7169     InverseFourierTransform = 249
7170     InverseFourierTransformImage = 250
7171     ColorDecisionList  = 251
7172     ColorDecisionListImage = 252
7173     AutoGamma          = 253
7174     AutoGammaImage     = 254
7175     AutoLevel          = 255
7176     AutoLevelImage     = 256
7177     LevelColors        = 257
7178     LevelColorsImage   = 258
7179     Clamp              = 259
7180     ClampImage         = 260
7181     Filter             = 261
7182     FilterImage        = 262
7183     BrightnessContrast = 263
7184     BrightnessContrastImage = 264
7185     Morphology         = 265
7186     MorphologyImage    = 266
7187     ColorMatrix        = 267
7188     ColorMatrixImage   = 268
7189     MogrifyRegion      = 666
7190   PPCODE:
7191   {
7192     AffineMatrix
7193       affine,
7194       current;
7195
7196     char
7197       attribute_flag[MaxArguments],
7198       message[MaxTextExtent];
7199
7200     ChannelType
7201       channel;
7202
7203     CompositeOperator
7204       compose;
7205
7206     const char
7207       *attribute,
7208       *value;
7209
7210     double
7211       angle;
7212
7213     ExceptionInfo
7214       *exception;
7215
7216     GeometryInfo
7217       geometry_info;
7218
7219     Image
7220       *image,
7221       *next,
7222       *region_image;
7223
7224     long
7225       base,
7226       j,
7227       number_images;
7228
7229     MagickBooleanType
7230       status;
7231
7232     MagickStatusType
7233       flags;
7234
7235     PixelPacket
7236       fill_color;
7237
7238     RectangleInfo
7239       geometry,
7240       region_info;
7241
7242     register long
7243       i;
7244
7245     struct PackageInfo
7246       *info;
7247
7248     struct Methods
7249       *rp;
7250
7251     SV
7252       *perl_exception,
7253       **pv,
7254       *reference,
7255       **reference_vector;
7256
7257     struct ArgumentList
7258       argument_list[MaxArguments];
7259
7260     exception=AcquireExceptionInfo();
7261     perl_exception=newSVpv("",0);
7262     reference_vector=NULL;
7263     region_image=NULL;
7264     number_images=0;
7265     base=2;
7266     if (sv_isobject(ST(0)) == 0)
7267       {
7268         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7269           PackageName);
7270         goto PerlException;
7271       }
7272     reference=SvRV(ST(0));
7273     region_info.width=0;
7274     region_info.height=0;
7275     region_info.x=0;
7276     region_info.y=0;
7277     region_image=(Image *) NULL;
7278     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7279     if (ix && (ix != 666))
7280       {
7281         /*
7282           Called as Method(...)
7283         */
7284         ix=(ix+1)/2;
7285         rp=(&Methods[ix-1]);
7286         attribute=rp->name;
7287       }
7288     else
7289       {
7290         /*
7291           Called as Mogrify("Method",...)
7292         */
7293         attribute=(char *) SvPV(ST(1),na);
7294         if (ix)
7295           {
7296             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7297             attribute=(char *) SvPV(ST(2),na);
7298             base++;
7299           }
7300         for (rp=Methods; ; rp++)
7301         {
7302           if (rp >= EndOf(Methods))
7303             {
7304               ThrowPerlException(exception,OptionError,
7305                 "UnrecognizedPerlMagickMethod",attribute);
7306               goto PerlException;
7307             }
7308           if (strEQcase(attribute,rp->name))
7309             break;
7310         }
7311         ix=rp-Methods+1;
7312         base++;
7313       }
7314     if (image == (Image *) NULL)
7315       {
7316         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7317         goto PerlException;
7318       }
7319     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7320     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7321     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7322     {
7323       long
7324         longest;
7325
7326       Arguments
7327         *pp,
7328         *qq;
7329
7330       struct ArgumentList
7331         *al;
7332
7333       SV
7334         *sv;
7335
7336       longest=0;
7337       pp=(Arguments *) NULL;
7338       qq=rp->arguments;
7339       if (i == items)
7340         {
7341           pp=rp->arguments,
7342           sv=ST(i-1);
7343         }
7344       else
7345         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7346         {
7347           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7348             break;
7349           if (strEQcase(attribute,qq->method) > longest)
7350             {
7351               pp=qq;
7352               longest=strEQcase(attribute,qq->method);
7353             }
7354         }
7355       if (pp == (Arguments *) NULL)
7356         {
7357           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7358             attribute);
7359           goto continue_outer_loop;
7360         }
7361       al=(&argument_list[pp-rp->arguments]);
7362       switch (pp->type)
7363       {
7364         case ArrayReference:
7365         {
7366           if (SvTYPE(sv) != SVt_RV)
7367             {
7368               (void) FormatMagickString(message,MaxTextExtent,
7369                 "invalid %.60s value",pp->method);
7370               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7371               goto continue_outer_loop;
7372             }
7373           al->array_reference=SvRV(sv);
7374           break;
7375         }
7376         case RealReference:
7377         {
7378           al->real_reference=SvNV(sv);
7379           break;
7380         }
7381         case FileReference:
7382         {
7383           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7384           break;
7385         }
7386         case ImageReference:
7387         {
7388           if (!sv_isobject(sv) ||
7389               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7390                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7391             {
7392               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7393                 PackageName);
7394               goto PerlException;
7395             }
7396           break;
7397         }
7398         case IntegerReference:
7399         {
7400           al->long_reference=SvIV(sv);
7401           break;
7402         }
7403         case StringReference:
7404         {
7405           al->string_reference=(char *) SvPV(sv,al->length);
7406           if (sv_isobject(sv))
7407             al->image_reference=SetupList(aTHX_ SvRV(sv),
7408               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7409           break;
7410         }
7411         default:
7412         {
7413           /*
7414             Is a string; look up name.
7415           */
7416           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7417             {
7418               al->string_reference=(char *) SvPV(sv,al->length);
7419               al->long_reference=(-1);
7420               break;
7421             }
7422           al->long_reference=ParseMagickOption((MagickOption) pp->type,
7423             MagickFalse,SvPV(sv,na));
7424           if (pp->type == MagickChannelOptions)
7425             al->long_reference=ParseChannelOption(SvPV(sv,na));
7426           if ((al->long_reference < 0) && ((al->long_reference=SvIV(sv)) <= 0))
7427             {
7428               (void) FormatMagickString(message,MaxTextExtent,
7429                 "invalid %.60s value",pp->method);
7430               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7431               goto continue_outer_loop;
7432             }
7433           break;
7434         }
7435       }
7436       attribute_flag[pp-rp->arguments]++;
7437       continue_outer_loop: ;
7438     }
7439     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7440     pv=reference_vector;
7441     SetGeometryInfo(&geometry_info);
7442     channel=DefaultChannels;
7443     for (next=image; next; next=next->next)
7444     {
7445       image=next;
7446       SetGeometry(image,&geometry);
7447       if ((region_info.width*region_info.height) != 0)
7448         {
7449           region_image=image;
7450           image=CropImage(image,&region_info,exception);
7451         }
7452       switch (ix)
7453       {
7454         default:
7455         {
7456           (void) FormatMagickString(message,MaxTextExtent,"%ld",(long) ix);
7457           ThrowPerlException(exception,OptionError,
7458             "UnrecognizedPerlMagickMethod",message);
7459           goto PerlException;
7460         }
7461         case 1:  /* Comment */
7462         {
7463           if (attribute_flag[0] == 0)
7464             argument_list[0].string_reference=(char *) NULL;
7465           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7466             info ? info->image_info : (ImageInfo *) NULL,image,
7467             argument_list[0].string_reference));
7468           break;
7469         }
7470         case 2:  /* Label */
7471         {
7472           if (attribute_flag[0] == 0)
7473             argument_list[0].string_reference=(char *) NULL;
7474           (void) SetImageProperty(image,"label",InterpretImageProperties(
7475             info ? info->image_info : (ImageInfo *) NULL,image,
7476             argument_list[0].string_reference));
7477           break;
7478         }
7479         case 3:  /* AddNoise */
7480         {
7481           if (attribute_flag[0] == 0)
7482             argument_list[0].long_reference=UniformNoise;
7483           if (attribute_flag[1] != 0)
7484             channel=(ChannelType) argument_list[1].long_reference;
7485           image=AddNoiseImageChannel(image,channel,(NoiseType)
7486             argument_list[0].long_reference,exception);
7487           break;
7488         }
7489         case 4:  /* Colorize */
7490         {
7491           PixelPacket
7492             target;
7493
7494           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7495           if (attribute_flag[0] != 0)
7496             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7497               exception);
7498           if (attribute_flag[1] == 0)
7499             argument_list[1].string_reference="100%";
7500           image=ColorizeImage(image,argument_list[1].string_reference,target,
7501             exception);
7502           break;
7503         }
7504         case 5:  /* Border */
7505         {
7506           geometry.width=0;
7507           geometry.height=0;
7508           if (attribute_flag[0] != 0)
7509             {
7510               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7511                 &geometry,exception);
7512               if ((flags & HeightValue) == 0)
7513                 geometry.height=geometry.width;
7514             }
7515           if (attribute_flag[1] != 0)
7516             geometry.width=argument_list[1].long_reference;
7517           if (attribute_flag[2] != 0)
7518             geometry.height=argument_list[2].long_reference;
7519           if (attribute_flag[3] != 0)
7520             QueryColorDatabase(argument_list[3].string_reference,
7521               &image->border_color,exception);
7522           if (attribute_flag[4] != 0)
7523             QueryColorDatabase(argument_list[4].string_reference,
7524               &image->border_color,exception);
7525           if (attribute_flag[5] != 0)
7526             QueryColorDatabase(argument_list[5].string_reference,
7527               &image->border_color,exception);
7528           if (attribute_flag[6] != 0)
7529             image->compose=(CompositeOperator) argument_list[6].long_reference;
7530           image=BorderImage(image,&geometry,exception);
7531           break;
7532         }
7533         case 6:  /* Blur */
7534         {
7535           if (attribute_flag[0] != 0)
7536             {
7537               flags=ParseGeometry(argument_list[0].string_reference,
7538                 &geometry_info);
7539               if ((flags & SigmaValue) == 0)
7540                 geometry_info.sigma=1.0;
7541             }
7542           if (attribute_flag[1] != 0)
7543             geometry_info.rho=argument_list[1].real_reference;
7544           if (attribute_flag[2] != 0)
7545             geometry_info.sigma=argument_list[2].real_reference;
7546           if (attribute_flag[3] != 0)
7547             channel=(ChannelType) argument_list[3].long_reference;
7548           image=BlurImageChannel(image,channel,geometry_info.rho,
7549             geometry_info.sigma,exception);
7550           break;
7551         }
7552         case 7:  /* Chop */
7553         {
7554           if (attribute_flag[0] != 0)
7555             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7556               &geometry,exception);
7557           if (attribute_flag[1] != 0)
7558             geometry.width=argument_list[1].long_reference;
7559           if (attribute_flag[2] != 0)
7560             geometry.height=argument_list[2].long_reference;
7561           if (attribute_flag[3] != 0)
7562             geometry.x=argument_list[3].long_reference;
7563           if (attribute_flag[4] != 0)
7564             geometry.y=argument_list[4].long_reference;
7565           image=ChopImage(image,&geometry,exception);
7566           break;
7567         }
7568         case 8:  /* Crop */
7569         {
7570           if (attribute_flag[6] != 0)
7571             image->gravity=(GravityType) argument_list[6].long_reference;
7572           if (attribute_flag[0] != 0)
7573             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7574               &geometry,exception);
7575           if (attribute_flag[1] != 0)
7576             geometry.width=argument_list[1].long_reference;
7577           if (attribute_flag[2] != 0)
7578             geometry.height=argument_list[2].long_reference;
7579           if (attribute_flag[3] != 0)
7580             geometry.x=argument_list[3].long_reference;
7581           if (attribute_flag[4] != 0)
7582             geometry.y=argument_list[4].long_reference;
7583           if (attribute_flag[5] != 0)
7584             image->fuzz=
7585               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7586           image=CropImage(image,&geometry,exception);
7587           break;
7588         }
7589         case 9:  /* Despeckle */
7590         {
7591           image=DespeckleImage(image,exception);
7592           break;
7593         }
7594         case 10:  /* Edge */
7595         {
7596           if (attribute_flag[0] != 0)
7597             geometry_info.rho=argument_list[0].real_reference;
7598           image=EdgeImage(image,geometry_info.rho,exception);
7599           break;
7600         }
7601         case 11:  /* Emboss */
7602         {
7603           if (attribute_flag[0] != 0)
7604             {
7605               flags=ParseGeometry(argument_list[0].string_reference,
7606                 &geometry_info);
7607               if ((flags & SigmaValue) == 0)
7608                 geometry_info.sigma=1.0;
7609             }
7610           if (attribute_flag[1] != 0)
7611             geometry_info.rho=argument_list[1].real_reference;
7612           if (attribute_flag[2] != 0)
7613             geometry_info.sigma=argument_list[2].real_reference;
7614           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7615             exception);
7616           break;
7617         }
7618         case 12:  /* Enhance */
7619         {
7620           image=EnhanceImage(image,exception);
7621           break;
7622         }
7623         case 13:  /* Flip */
7624         {
7625           image=FlipImage(image,exception);
7626           break;
7627         }
7628         case 14:  /* Flop */
7629         {
7630           image=FlopImage(image,exception);
7631           break;
7632         }
7633         case 15:  /* Frame */
7634         {
7635           FrameInfo
7636             frame_info;
7637
7638           if (attribute_flag[0] != 0)
7639             {
7640               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7641                 &geometry,exception);
7642               if ((flags & HeightValue) == 0)
7643                 geometry.height=geometry.width;
7644               frame_info.width=geometry.width;
7645               frame_info.height=geometry.height;
7646               frame_info.outer_bevel=geometry.x;
7647               frame_info.inner_bevel=geometry.y;
7648             }
7649           if (attribute_flag[1] != 0)
7650             frame_info.width=argument_list[1].long_reference;
7651           if (attribute_flag[2] != 0)
7652             frame_info.height=argument_list[2].long_reference;
7653           if (attribute_flag[3] != 0)
7654             frame_info.inner_bevel=argument_list[3].long_reference;
7655           if (attribute_flag[4] != 0)
7656             frame_info.outer_bevel=argument_list[4].long_reference;
7657           if (attribute_flag[5] != 0)
7658             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7659               exception);
7660           if (attribute_flag[6] != 0)
7661             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7662               exception);
7663           frame_info.x=(long) frame_info.width;
7664           frame_info.y=(long) frame_info.height;
7665           frame_info.width=image->columns+2*frame_info.x;
7666           frame_info.height=image->rows+2*frame_info.y;
7667           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7668             image->matte_color=fill_color;
7669           if (attribute_flag[7] != 0)
7670             image->compose=(CompositeOperator) argument_list[7].long_reference;
7671           image=FrameImage(image,&frame_info,exception);
7672           break;
7673         }
7674         case 16:  /* Implode */
7675         {
7676           if (attribute_flag[0] == 0)
7677             argument_list[0].real_reference=0.5;
7678           if (attribute_flag[1] != 0)
7679             image->interpolate=(InterpolatePixelMethod)
7680               argument_list[1].long_reference;
7681           image=ImplodeImage(image,argument_list[0].real_reference,
7682             exception);
7683           break;
7684         }
7685         case 17:  /* Magnify */
7686         {
7687           image=MagnifyImage(image,exception);
7688           break;
7689         }
7690         case 18:  /* MedianFilter */
7691         {
7692           if (attribute_flag[0] == 0)
7693             argument_list[0].real_reference=0.0;
7694           image=MedianFilterImage(image,argument_list[0].real_reference,
7695             exception);
7696           break;
7697         }
7698         case 19:  /* Minify */
7699         {
7700           image=MinifyImage(image,exception);
7701           break;
7702         }
7703         case 20:  /* OilPaint */
7704         {
7705           if (attribute_flag[0] == 0)
7706             argument_list[0].real_reference=0.0;
7707           image=OilPaintImage(image,argument_list[0].real_reference,
7708             exception);
7709           break;
7710         }
7711         case 21:  /* ReduceNoise */
7712         {
7713           if (attribute_flag[0] == 0)
7714             argument_list[0].real_reference=0.0;
7715           image=ReduceNoiseImage(image,argument_list[0].real_reference,
7716             exception);
7717           break;
7718         }
7719         case 22:  /* Roll */
7720         {
7721           if (attribute_flag[0] != 0)
7722             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7723               &geometry,exception);
7724           if (attribute_flag[1] != 0)
7725             geometry.x=argument_list[1].long_reference;
7726           if (attribute_flag[2] != 0)
7727             geometry.y=argument_list[2].long_reference;
7728           image=RollImage(image,geometry.x,geometry.y,exception);
7729           break;
7730         }
7731         case 23:  /* Rotate */
7732         {
7733           if (attribute_flag[0] == 0)
7734             argument_list[0].real_reference=90.0;
7735           if (attribute_flag[1] != 0)
7736             QueryColorDatabase(argument_list[1].string_reference,
7737               &image->background_color,exception);
7738           if (attribute_flag[2] != 0)
7739             QueryColorDatabase(argument_list[2].string_reference,
7740               &image->background_color,exception);
7741           if (attribute_flag[3] != 0)
7742             QueryColorDatabase(argument_list[3].string_reference,
7743               &image->background_color,exception);
7744           image=RotateImage(image,argument_list[0].real_reference,exception);
7745           break;
7746         }
7747         case 24:  /* Sample */
7748         {
7749           if (attribute_flag[0] != 0)
7750             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7751               &geometry,exception);
7752           if (attribute_flag[1] != 0)
7753             geometry.width=argument_list[1].long_reference;
7754           if (attribute_flag[2] != 0)
7755             geometry.height=argument_list[2].long_reference;
7756           image=SampleImage(image,geometry.width,geometry.height,exception);
7757           break;
7758         }
7759         case 25:  /* Scale */
7760         {
7761           if (attribute_flag[0] != 0)
7762             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7763               &geometry,exception);
7764           if (attribute_flag[1] != 0)
7765             geometry.width=argument_list[1].long_reference;
7766           if (attribute_flag[2] != 0)
7767             geometry.height=argument_list[2].long_reference;
7768           image=ScaleImage(image,geometry.width,geometry.height,exception);
7769           break;
7770         }
7771         case 26:  /* Shade */
7772         {
7773           if (attribute_flag[0] != 0)
7774             {
7775               flags=ParseGeometry(argument_list[0].string_reference,
7776                 &geometry_info);
7777               if ((flags & SigmaValue) == 0)
7778                 geometry_info.sigma=0.0;
7779             }
7780           if (attribute_flag[1] != 0)
7781             geometry_info.rho=argument_list[1].real_reference;
7782           if (attribute_flag[2] != 0)
7783             geometry_info.sigma=argument_list[2].real_reference;
7784           image=ShadeImage(image,
7785             argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse,
7786             geometry_info.rho,geometry_info.sigma,exception);
7787           break;
7788         }
7789         case 27:  /* Sharpen */
7790         {
7791           if (attribute_flag[0] != 0)
7792             {
7793               flags=ParseGeometry(argument_list[0].string_reference,
7794                 &geometry_info);
7795               if ((flags & SigmaValue) == 0)
7796                 geometry_info.sigma=1.0;
7797             }
7798           if (attribute_flag[1] != 0)
7799             geometry_info.rho=argument_list[1].real_reference;
7800           if (attribute_flag[2] != 0)
7801             geometry_info.sigma=argument_list[2].real_reference;
7802           if (attribute_flag[3] != 0)
7803             channel=(ChannelType) argument_list[3].long_reference;
7804           image=SharpenImageChannel(image,channel,geometry_info.rho,
7805             geometry_info.sigma,exception);
7806           break;
7807         }
7808         case 28:  /* Shear */
7809         {
7810           if (attribute_flag[0] != 0)
7811             {
7812               flags=ParseGeometry(argument_list[0].string_reference,
7813                 &geometry_info);
7814               if ((flags & SigmaValue) == 0)
7815                 geometry_info.sigma=geometry_info.rho;
7816             }
7817           if (attribute_flag[1] != 0)
7818             geometry_info.rho=argument_list[1].real_reference;
7819           if (attribute_flag[2] != 0)
7820             geometry_info.sigma=argument_list[2].real_reference;
7821           if (attribute_flag[3] != 0)
7822             QueryColorDatabase(argument_list[3].string_reference,
7823               &image->background_color,exception);
7824           if (attribute_flag[4] != 0)
7825             QueryColorDatabase(argument_list[4].string_reference,
7826               &image->background_color,exception);
7827           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7828             exception);
7829           break;
7830         }
7831         case 29:  /* Spread */
7832         {
7833           if (attribute_flag[0] == 0)
7834             argument_list[0].real_reference=1.0;
7835           image=SpreadImage(image,argument_list[0].real_reference,exception);
7836           break;
7837         }
7838         case 30:  /* Swirl */
7839         {
7840           if (attribute_flag[0] == 0)
7841             argument_list[0].real_reference=50.0;
7842           if (attribute_flag[1] != 0)
7843             image->interpolate=(InterpolatePixelMethod)
7844               argument_list[1].long_reference;
7845           image=SwirlImage(image,argument_list[0].real_reference,exception);
7846           break;
7847         }
7848         case 31:  /* Resize */
7849         case 32:  /* Zoom */
7850         {
7851           if (attribute_flag[0] != 0)
7852             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7853               &geometry,exception);
7854           if (attribute_flag[1] != 0)
7855             geometry.width=argument_list[1].long_reference;
7856           if (attribute_flag[2] != 0)
7857             geometry.height=argument_list[2].long_reference;
7858           if (attribute_flag[3] == 0)
7859             argument_list[3].long_reference=(long) UndefinedFilter;
7860           if (attribute_flag[4] != 0)
7861             SetImageArtifact(image,"filter:support",
7862               argument_list[4].string_reference);
7863           if (attribute_flag[5] == 0)
7864             argument_list[5].real_reference=1.0;
7865           image=ResizeImage(image,geometry.width,geometry.height,
7866             (FilterTypes) argument_list[3].long_reference,
7867             argument_list[5].real_reference,exception);
7868           break;
7869         }
7870         case 33:  /* Annotate */
7871         {
7872           DrawInfo
7873             *draw_info;
7874
7875           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7876             (DrawInfo *) NULL);
7877           if (attribute_flag[0] != 0)
7878             {
7879               char
7880                 *text;
7881
7882               text=InterpretImageProperties(info ? info->image_info :
7883                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7884               (void) CloneString(&draw_info->text,text);
7885               text=DestroyString(text);
7886             }
7887           if (attribute_flag[1] != 0)
7888             (void) CloneString(&draw_info->font,
7889               argument_list[1].string_reference);
7890           if (attribute_flag[2] != 0)
7891             draw_info->pointsize=argument_list[2].real_reference;
7892           if (attribute_flag[3] != 0)
7893             (void) CloneString(&draw_info->density,
7894               argument_list[3].string_reference);
7895           if (attribute_flag[4] != 0)
7896             (void) QueryColorDatabase(argument_list[4].string_reference,
7897               &draw_info->undercolor,exception);
7898           if (attribute_flag[5] != 0)
7899             {
7900               (void) QueryColorDatabase(argument_list[5].string_reference,
7901                 &draw_info->stroke,exception);
7902               if (argument_list[5].image_reference != (Image *) NULL)
7903                 draw_info->stroke_pattern=CloneImage(
7904                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7905             }
7906           if (attribute_flag[6] != 0)
7907             {
7908               (void) QueryColorDatabase(argument_list[6].string_reference,
7909                 &draw_info->fill,exception);
7910               if (argument_list[6].image_reference != (Image *) NULL)
7911                 draw_info->fill_pattern=CloneImage(
7912                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7913             }
7914           if (attribute_flag[7] != 0)
7915             {
7916               (void) CloneString(&draw_info->geometry,
7917                 argument_list[7].string_reference);
7918               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7919                 &geometry,exception);
7920               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7921                 geometry_info.sigma=geometry_info.xi;
7922             }
7923           if (attribute_flag[8] != 0)
7924             (void) QueryColorDatabase(argument_list[8].string_reference,
7925               &draw_info->fill,exception);
7926           if (attribute_flag[11] != 0)
7927             draw_info->gravity=(GravityType) argument_list[11].long_reference;
7928           if (attribute_flag[25] != 0)
7929             {
7930               AV
7931                 *av;
7932
7933               av=(AV *) argument_list[25].array_reference;
7934               if ((av_len(av) != 3) && (av_len(av) != 5))
7935                 {
7936                   ThrowPerlException(exception,OptionError,
7937                     "affine matrix must have 4 or 6 elements",PackageName);
7938                   goto PerlException;
7939                 }
7940               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7941               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7942               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7943               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7944               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7945                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7946                 {
7947                   ThrowPerlException(exception,OptionError,
7948                     "affine matrix is singular",PackageName);
7949                    goto PerlException;
7950                 }
7951               if (av_len(av) == 5)
7952                 {
7953                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7954                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
7955                 }
7956             }
7957           for (j=12; j < 17; j++)
7958           {
7959             if (attribute_flag[j] == 0)
7960               continue;
7961             value=argument_list[j].string_reference;
7962             angle=argument_list[j].real_reference;
7963             current=draw_info->affine;
7964             GetAffineMatrix(&affine);
7965             switch (j)
7966             {
7967               case 12:
7968               {
7969                 /*
7970                   Translate.
7971                 */
7972                 flags=ParseGeometry(value,&geometry_info);
7973                 affine.tx=geometry_info.xi;
7974                 affine.ty=geometry_info.psi;
7975                 if ((flags & PsiValue) == 0)
7976                   affine.ty=affine.tx;
7977                 break;
7978               }
7979               case 13:
7980               {
7981                 /*
7982                   Scale.
7983                 */
7984                 flags=ParseGeometry(value,&geometry_info);
7985                 affine.sx=geometry_info.rho;
7986                 affine.sy=geometry_info.sigma;
7987                 if ((flags & SigmaValue) == 0)
7988                   affine.sy=affine.sx;
7989                 break;
7990               }
7991               case 14:
7992               {
7993                 /*
7994                   Rotate.
7995                 */
7996                 if (angle == 0.0)
7997                   break;
7998                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
7999                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8000                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8001                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8002                 break;
8003               }
8004               case 15:
8005               {
8006                 /*
8007                   SkewX.
8008                 */
8009                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8010                 break;
8011               }
8012               case 16:
8013               {
8014                 /*
8015                   SkewY.
8016                 */
8017                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8018                 break;
8019               }
8020             }
8021             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8022             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8023             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8024             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8025             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8026               current.tx;
8027             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8028               current.ty;
8029           }
8030           if (attribute_flag[9] == 0)
8031             argument_list[9].real_reference=0.0;
8032           if (attribute_flag[10] == 0)
8033             argument_list[10].real_reference=0.0;
8034           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8035             {
8036               char
8037                 geometry[MaxTextExtent];
8038
8039               (void) FormatMagickString(geometry,MaxTextExtent,"%+f%+f",
8040                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8041                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8042               (void) CloneString(&draw_info->geometry,geometry);
8043             }
8044           if (attribute_flag[17] != 0)
8045             draw_info->stroke_width=argument_list[17].real_reference;
8046           if (attribute_flag[18] != 0)
8047             {
8048               draw_info->text_antialias=argument_list[18].long_reference != 0 ?
8049                 MagickTrue : MagickFalse;
8050               draw_info->stroke_antialias=draw_info->text_antialias;
8051             }
8052           if (attribute_flag[19] != 0)
8053             (void) CloneString(&draw_info->family,
8054               argument_list[19].string_reference);
8055           if (attribute_flag[20] != 0)
8056             draw_info->style=(StyleType) argument_list[20].long_reference;
8057           if (attribute_flag[21] != 0)
8058             draw_info->stretch=(StretchType) argument_list[21].long_reference;
8059           if (attribute_flag[22] != 0)
8060             draw_info->weight=argument_list[22].long_reference;
8061           if (attribute_flag[23] != 0)
8062             draw_info->align=(AlignType) argument_list[23].long_reference;
8063           if (attribute_flag[24] != 0)
8064             (void) CloneString(&draw_info->encoding,
8065               argument_list[24].string_reference);
8066           if (attribute_flag[25] != 0)
8067             draw_info->fill_pattern=CloneImage(
8068               argument_list[25].image_reference,0,0,MagickTrue,exception);
8069           if (attribute_flag[26] != 0)
8070             draw_info->fill_pattern=CloneImage(
8071               argument_list[26].image_reference,0,0,MagickTrue,exception);
8072           if (attribute_flag[27] != 0)
8073             draw_info->stroke_pattern=CloneImage(
8074               argument_list[27].image_reference,0,0,MagickTrue,exception);
8075           if (attribute_flag[29] != 0)
8076             draw_info->kerning=argument_list[29].real_reference;
8077           if (attribute_flag[30] != 0)
8078             draw_info->interline_spacing=argument_list[30].real_reference;
8079           if (attribute_flag[31] != 0)
8080             draw_info->interword_spacing=argument_list[31].real_reference;
8081           if (attribute_flag[32] != 0)
8082             draw_info->direction=(DirectionType)
8083               argument_list[32].long_reference;
8084           (void) AnnotateImage(image,draw_info);
8085           draw_info=DestroyDrawInfo(draw_info);
8086           break;
8087         }
8088         case 34:  /* ColorFloodfill */
8089         {
8090           DrawInfo
8091             *draw_info;
8092
8093           MagickBooleanType
8094             invert;
8095
8096           MagickPixelPacket
8097             target;
8098
8099           draw_info=CloneDrawInfo(info ? info->image_info :
8100             (ImageInfo *) NULL,(DrawInfo *) NULL);
8101           if (attribute_flag[0] != 0)
8102             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8103               &geometry,exception);
8104           if (attribute_flag[1] != 0)
8105             geometry.x=argument_list[1].long_reference;
8106           if (attribute_flag[2] != 0)
8107             geometry.y=argument_list[2].long_reference;
8108           if (attribute_flag[3] != 0)
8109             (void) QueryColorDatabase(argument_list[3].string_reference,
8110               &draw_info->fill,exception);
8111           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8112             exception);
8113           invert=MagickFalse;
8114           if (attribute_flag[4] != 0)
8115             {
8116               QueryMagickColor(argument_list[4].string_reference,&target,
8117                 exception);
8118               invert=MagickTrue;
8119             }
8120           if (attribute_flag[5] != 0)
8121             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8122               QuantumRange);
8123           if (attribute_flag[6] != 0)
8124             invert=(MagickBooleanType) argument_list[6].long_reference;
8125           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8126             geometry.x,geometry.y,invert);
8127           draw_info=DestroyDrawInfo(draw_info);
8128           break;
8129         }
8130         case 35:  /* Composite */
8131         {
8132           char
8133             composite_geometry[MaxTextExtent];
8134
8135           Image
8136             *composite_image,
8137             *rotate_image;
8138
8139           compose=OverCompositeOp;
8140           if (attribute_flag[0] != 0)
8141             composite_image=argument_list[0].image_reference;
8142           else
8143             {
8144               ThrowPerlException(exception,OptionError,
8145                 "CompositeImageRequired",PackageName);
8146               goto PerlException;
8147             }
8148           /*
8149             Parameter Handling used for BOTH normal and tiled composition.
8150           */
8151           if (attribute_flag[1] != 0) /* compose */
8152             compose=(CompositeOperator) argument_list[1].long_reference;
8153           if (attribute_flag[6] != 0) /* opacity  */
8154             {
8155               if (compose != DissolveCompositeOp)
8156                 (void) SetImageOpacity(composite_image,(Quantum) (QuantumRange-
8157                   SiPrefixToDouble(argument_list[6].string_reference,
8158                   QuantumRange)));
8159               else
8160                 {
8161                   double
8162                     opacity;
8163
8164                   long
8165                     y;
8166
8167                   MagickBooleanType
8168                     sync;
8169
8170                   register long
8171                     x;
8172
8173                   register PixelPacket
8174                     *q;
8175
8176                   CacheView
8177                     *composite_view;
8178
8179                   /*
8180                     Handle dissolve composite operator (patch by
8181                     Kevin A. McGrail).
8182                   */
8183                   (void) CloneString(&image->geometry,
8184                     argument_list[6].string_reference);
8185                   opacity=(Quantum) (QuantumRange-SiPrefixToDouble(
8186                     argument_list[6].string_reference,QuantumRange));
8187                   if (composite_image->matte != MagickTrue)
8188                     (void) SetImageOpacity(composite_image,OpaqueOpacity);
8189                   composite_view=AcquireCacheView(composite_image);
8190                   for (y=0; y < (long) composite_image->rows ; y++)
8191                   {
8192                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(long)
8193                       composite_image->columns,1,exception);
8194                     for (x=0; x < (long) composite_image->columns; x++)
8195                     {
8196                       if (q->opacity == OpaqueOpacity)
8197                         q->opacity=ClampToQuantum(opacity);
8198                       q++;
8199                     }
8200                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8201                     if (sync == MagickFalse)
8202                       break;
8203                   }
8204                   composite_view=DestroyCacheView(composite_view);
8205                 }
8206             }
8207           if (attribute_flag[9] != 0)    /* "color=>" */
8208             QueryColorDatabase(argument_list[9].string_reference,
8209               &composite_image->background_color,exception);
8210           if (attribute_flag[12] != 0) /* "interpolate=>" */
8211             image->interpolate=(InterpolatePixelMethod)
8212               argument_list[12].long_reference;
8213           if (attribute_flag[13] != 0)   /* "args=>" */
8214             (void) SetImageArtifact(composite_image,"compose:args",
8215               argument_list[13].string_reference);
8216           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8217             (void) SetImageArtifact(composite_image,"compose:args",
8218               argument_list[14].string_reference);
8219           /*
8220             Tiling Composition (with orthogonal rotate).
8221           */
8222           rotate_image=(Image *) NULL;
8223           if (attribute_flag[8] != 0)   /* "rotate=>" */
8224             {
8225                /*
8226                  Rotate image.
8227                */
8228                rotate_image=RotateImage(composite_image,
8229                  argument_list[8].real_reference,exception);
8230                if (rotate_image == (Image *) NULL)
8231                  break;
8232             }
8233           if (attribute_flag[7] && argument_list[7].long_reference) /* tile */
8234             {
8235               long
8236                 x,
8237                 y;
8238
8239               /*
8240                 Tile the composite image.
8241               */
8242              if (attribute_flag[8] != 0)   /* "tile=>" */
8243                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8244                  "false");
8245              else
8246                (void) SetImageArtifact(composite_image,
8247                  "compose:outside-overlay","false");
8248              for (y=0; y < (long) image->rows; y+=composite_image->rows)
8249                 for (x=0; x < (long) image->columns; x+=composite_image->columns)
8250                 {
8251                   if (attribute_flag[8] != 0) /* rotate */
8252                     (void) CompositeImage(image,compose,rotate_image,x,y);
8253                   else
8254                     (void) CompositeImage(image,compose,composite_image,x,y);
8255                 }
8256               if (attribute_flag[8] != 0) /* rotate */
8257                 rotate_image=DestroyImage(rotate_image);
8258               break;
8259             }
8260           /*
8261             Parameter Handling used used ONLY for normal composition.
8262           */
8263           if (attribute_flag[5] != 0) /* gravity */
8264             image->gravity=(GravityType) argument_list[5].long_reference;
8265           if (attribute_flag[2] != 0) /* geometry offset */
8266             {
8267               SetGeometry(image,&geometry);
8268               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8269                 &geometry);
8270               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8271                 &geometry);
8272             }
8273           if (attribute_flag[3] != 0) /* x offset */
8274             geometry.x=argument_list[3].long_reference;
8275           if (attribute_flag[4] != 0) /* y offset */
8276             geometry.y=argument_list[4].long_reference;
8277           if (attribute_flag[10] != 0) /* mask */
8278             {
8279               if ((image->compose == DisplaceCompositeOp) ||
8280                   (image->compose == DistortCompositeOp))
8281                 {
8282                   /*
8283                     Merge Y displacement into X displacement image.
8284                   */
8285                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8286                     &image->exception);
8287                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8288                     argument_list[10].image_reference,0,0);
8289                 }
8290               else
8291                 {
8292                   /*
8293                     Set a blending mask for the composition.
8294                   */
8295                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8296                     MagickTrue,&image->exception);
8297                   (void) NegateImage(image->mask,MagickFalse);
8298                 }
8299             }
8300           if (attribute_flag[11] != 0) /* channel */
8301             channel=(ChannelType) argument_list[11].long_reference;
8302           /*
8303             Composite two images (normal composition).
8304           */
8305           (void) FormatMagickString(composite_geometry,MaxTextExtent,
8306             "%lux%lu%+ld%+ld",composite_image->columns,composite_image->rows,
8307             geometry.x,geometry.y);
8308           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8309             exception);
8310           if (attribute_flag[8] == 0) /* no rotate */
8311             CompositeImageChannel(image,channel,compose,composite_image,
8312               geometry.x,geometry.y);
8313           else
8314             {
8315               /*
8316                 Position adjust rotated image then composite.
8317               */
8318               geometry.x-=(long) (rotate_image->columns-
8319                 composite_image->columns)/2;
8320               geometry.y-=(long) (rotate_image->rows-composite_image->rows)/2;
8321               CompositeImageChannel(image,channel,compose,rotate_image,
8322                 geometry.x,geometry.y);
8323               rotate_image=DestroyImage(rotate_image);
8324             }
8325           if (attribute_flag[10] != 0) /* mask */
8326             {
8327               if ((image->compose == DisplaceCompositeOp) ||
8328                   (image->compose == DistortCompositeOp))
8329                 composite_image=DestroyImage(composite_image);
8330               else
8331                 image->mask=DestroyImage(image->mask);
8332             }
8333           break;
8334         }
8335         case 36:  /* Contrast */
8336         {
8337           if (attribute_flag[0] == 0)
8338             argument_list[0].long_reference=0;
8339           (void) ContrastImage(image,argument_list[0].long_reference != 0 ?
8340             MagickTrue : MagickFalse);
8341           break;
8342         }
8343         case 37:  /* CycleColormap */
8344         {
8345           if (attribute_flag[0] == 0)
8346             argument_list[0].long_reference=6;
8347           (void) CycleColormapImage(image,argument_list[0].long_reference);
8348           break;
8349         }
8350         case 38:  /* Draw */
8351         {
8352           DrawInfo
8353             *draw_info;
8354
8355           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8356             (DrawInfo *) NULL);
8357           (void) CloneString(&draw_info->primitive,"point");
8358           if (attribute_flag[0] != 0)
8359             {
8360               if (argument_list[0].long_reference < 0)
8361                 (void) CloneString(&draw_info->primitive,
8362                   argument_list[0].string_reference);
8363               else
8364                 (void) CloneString(&draw_info->primitive,MagickOptionToMnemonic(
8365                   MagickPrimitiveOptions,argument_list[0].long_reference));
8366             }
8367           if (attribute_flag[1] != 0)
8368             {
8369               if (LocaleCompare(draw_info->primitive,"path") == 0)
8370                 {
8371                   (void) ConcatenateString(&draw_info->primitive," '");
8372                   ConcatenateString(&draw_info->primitive,
8373                     argument_list[1].string_reference);
8374                   (void) ConcatenateString(&draw_info->primitive,"'");
8375                 }
8376               else
8377                 {
8378                   (void) ConcatenateString(&draw_info->primitive," ");
8379                   ConcatenateString(&draw_info->primitive,
8380                     argument_list[1].string_reference);
8381                 }
8382             }
8383           if (attribute_flag[2] != 0)
8384             {
8385               (void) ConcatenateString(&draw_info->primitive," ");
8386               (void) ConcatenateString(&draw_info->primitive,
8387                 MagickOptionToMnemonic(MagickMethodOptions,
8388                 argument_list[2].long_reference));
8389             }
8390           if (attribute_flag[3] != 0)
8391             {
8392               (void) QueryColorDatabase(argument_list[3].string_reference,
8393                 &draw_info->stroke,exception);
8394               if (argument_list[3].image_reference != (Image *) NULL)
8395                 draw_info->stroke_pattern=CloneImage(
8396                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8397             }
8398           if (attribute_flag[4] != 0)
8399             {
8400               (void) QueryColorDatabase(argument_list[4].string_reference,
8401                 &draw_info->fill,exception);
8402               if (argument_list[4].image_reference != (Image *) NULL)
8403                 draw_info->fill_pattern=CloneImage(
8404                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8405             }
8406           if (attribute_flag[5] != 0)
8407             draw_info->stroke_width=argument_list[5].real_reference;
8408           if (attribute_flag[6] != 0)
8409             (void) CloneString(&draw_info->font,
8410               argument_list[6].string_reference);
8411           if (attribute_flag[7] != 0)
8412             (void) QueryColorDatabase(argument_list[7].string_reference,
8413               &draw_info->border_color,exception);
8414           if (attribute_flag[8] != 0)
8415             draw_info->affine.tx=argument_list[8].real_reference;
8416           if (attribute_flag[9] != 0)
8417             draw_info->affine.ty=argument_list[9].real_reference;
8418           if (attribute_flag[20] != 0)
8419             {
8420               AV
8421                 *av;
8422
8423               av=(AV *) argument_list[20].array_reference;
8424               if ((av_len(av) != 3) && (av_len(av) != 5))
8425                 {
8426                   ThrowPerlException(exception,OptionError,
8427                     "affine matrix must have 4 or 6 elements",PackageName);
8428                   goto PerlException;
8429                 }
8430               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8431               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8432               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8433               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8434               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8435                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8436                 {
8437                   ThrowPerlException(exception,OptionError,
8438                     "affine matrix is singular",PackageName);
8439                    goto PerlException;
8440                 }
8441               if (av_len(av) == 5)
8442                 {
8443                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8444                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8445                 }
8446             }
8447           for (j=10; j < 15; j++)
8448           {
8449             if (attribute_flag[j] == 0)
8450               continue;
8451             value=argument_list[j].string_reference;
8452             angle=argument_list[j].real_reference;
8453             current=draw_info->affine;
8454             GetAffineMatrix(&affine);
8455             switch (j)
8456             {
8457               case 10:
8458               {
8459                 /*
8460                   Translate.
8461                 */
8462                 flags=ParseGeometry(value,&geometry_info);
8463                 affine.tx=geometry_info.xi;
8464                 affine.ty=geometry_info.psi;
8465                 if ((flags & PsiValue) == 0)
8466                   affine.ty=affine.tx;
8467                 break;
8468               }
8469               case 11:
8470               {
8471                 /*
8472                   Scale.
8473                 */
8474                 flags=ParseGeometry(value,&geometry_info);
8475                 affine.sx=geometry_info.rho;
8476                 affine.sy=geometry_info.sigma;
8477                 if ((flags & SigmaValue) == 0)
8478                   affine.sy=affine.sx;
8479                 break;
8480               }
8481               case 12:
8482               {
8483                 /*
8484                   Rotate.
8485                 */
8486                 if (angle == 0.0)
8487                   break;
8488                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8489                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8490                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8491                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8492                 break;
8493               }
8494               case 13:
8495               {
8496                 /*
8497                   SkewX.
8498                 */
8499                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8500                 break;
8501               }
8502               case 14:
8503               {
8504                 /*
8505                   SkewY.
8506                 */
8507                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8508                 break;
8509               }
8510             }
8511             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8512             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8513             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8514             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8515             draw_info->affine.tx=
8516               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8517             draw_info->affine.ty=
8518               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8519           }
8520           if (attribute_flag[15] != 0)
8521             draw_info->fill_pattern=CloneImage(
8522               argument_list[15].image_reference,0,0,MagickTrue,exception);
8523           if (attribute_flag[16] != 0)
8524             draw_info->pointsize=argument_list[16].real_reference;
8525           if (attribute_flag[17] != 0)
8526             {
8527               draw_info->stroke_antialias=argument_list[17].long_reference != 0
8528                 ? MagickTrue : MagickFalse;
8529               draw_info->text_antialias=draw_info->stroke_antialias;
8530             }
8531           if (attribute_flag[18] != 0)
8532             (void) CloneString(&draw_info->density,
8533               argument_list[18].string_reference);
8534           if (attribute_flag[19] != 0)
8535             draw_info->stroke_width=argument_list[19].real_reference;
8536           if (attribute_flag[21] != 0)
8537             draw_info->dash_offset=argument_list[21].real_reference;
8538           if (attribute_flag[22] != 0)
8539             {
8540               AV
8541                 *av;
8542
8543               av=(AV *) argument_list[22].array_reference;
8544               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8545                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8546               if (draw_info->dash_pattern != (double *) NULL)
8547                 {
8548                   for (i=0; i <= av_len(av); i++)
8549                     draw_info->dash_pattern[i]=(double)
8550                       SvNV(*(av_fetch(av,i,0)));
8551                   draw_info->dash_pattern[i]=0.0;
8552                 }
8553             }
8554           if (attribute_flag[23] != 0)
8555             image->interpolate=(InterpolatePixelMethod)
8556               argument_list[23].long_reference;
8557           if ((attribute_flag[24] != 0) &&
8558               (draw_info->fill_pattern != (Image *) NULL))
8559             flags=ParsePageGeometry(draw_info->fill_pattern,
8560               argument_list[24].string_reference,
8561               &draw_info->fill_pattern->tile_offset,exception);
8562           if (attribute_flag[25] != 0)
8563             {
8564               (void) ConcatenateString(&draw_info->primitive," '");
8565               (void) ConcatenateString(&draw_info->primitive,
8566                 argument_list[25].string_reference);
8567               (void) ConcatenateString(&draw_info->primitive,"'");
8568             }
8569           if (attribute_flag[26] != 0)
8570             draw_info->fill_pattern=CloneImage(
8571               argument_list[26].image_reference,0,0,MagickTrue,exception);
8572           if (attribute_flag[27] != 0)
8573             draw_info->stroke_pattern=CloneImage(
8574               argument_list[27].image_reference,0,0,MagickTrue,exception);
8575           if (attribute_flag[28] != 0)
8576             (void) CloneString(&draw_info->primitive,
8577               argument_list[28].string_reference);
8578           if (attribute_flag[29] != 0)
8579             draw_info->kerning=argument_list[29].real_reference;
8580           if (attribute_flag[30] != 0)
8581             draw_info->interline_spacing=argument_list[30].real_reference;
8582           if (attribute_flag[31] != 0)
8583             draw_info->interword_spacing=argument_list[31].real_reference;
8584           DrawImage(image,draw_info);
8585           draw_info=DestroyDrawInfo(draw_info);
8586           break;
8587         }
8588         case 39:  /* Equalize */
8589         {
8590           if (attribute_flag[0] != 0)
8591             channel=(ChannelType) argument_list[0].long_reference;
8592           EqualizeImageChannel(image,channel);
8593           break;
8594         }
8595         case 40:  /* Gamma */
8596         {
8597           if (attribute_flag[1] != 0)
8598             channel=(ChannelType) argument_list[1].long_reference;
8599           if (attribute_flag[2] == 0)
8600             argument_list[2].real_reference=1.0;
8601           if (attribute_flag[3] == 0)
8602             argument_list[3].real_reference=1.0;
8603           if (attribute_flag[4] == 0)
8604             argument_list[4].real_reference=1.0;
8605           if (attribute_flag[0] == 0)
8606             {
8607               (void) FormatMagickString(message,MaxTextExtent,
8608                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8609                 (double) argument_list[3].real_reference,
8610                 (double) argument_list[4].real_reference);
8611               argument_list[0].string_reference=message;
8612             }
8613           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8614             (void) GammaImage(image,argument_list[0].string_reference);
8615           else
8616             (void) GammaImageChannel(image,channel,
8617               StringToDouble(argument_list[0].string_reference));
8618           break;
8619         }
8620         case 41:  /* Map */
8621         {
8622           QuantizeInfo
8623             *quantize_info;
8624
8625           if (attribute_flag[0] == 0)
8626             {
8627               ThrowPerlException(exception,OptionError,"MapImageRequired",
8628                 PackageName);
8629               goto PerlException;
8630             }
8631           quantize_info=AcquireQuantizeInfo(info->image_info);
8632           if (attribute_flag[1] != 0)
8633             quantize_info->dither=(MagickBooleanType)
8634               argument_list[1].long_reference;
8635           if (attribute_flag[2] != 0)
8636             quantize_info->dither_method=(DitherMethod)
8637               argument_list[2].long_reference;
8638           (void) RemapImages(quantize_info,image,
8639             argument_list[0].image_reference);
8640           quantize_info=DestroyQuantizeInfo(quantize_info);
8641           break;
8642         }
8643         case 42:  /* MatteFloodfill */
8644         {
8645           DrawInfo
8646             *draw_info;
8647
8648           MagickBooleanType
8649             invert;
8650
8651           MagickPixelPacket
8652             target;
8653
8654           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8655             (DrawInfo *) NULL);
8656           if (attribute_flag[0] != 0)
8657           if (attribute_flag[0] != 0)
8658             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8659               &geometry,exception);
8660           if (attribute_flag[1] != 0)
8661             geometry.x=argument_list[1].long_reference;
8662           if (attribute_flag[2] != 0)
8663             geometry.y=argument_list[2].long_reference;
8664           if (image->matte == MagickFalse)
8665             (void) SetImageOpacity(image,OpaqueOpacity);
8666           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8667             exception);
8668           if (attribute_flag[4] != 0)
8669             QueryMagickColor(argument_list[4].string_reference,&target,
8670               exception);
8671           if (attribute_flag[3] != 0)
8672             target.opacity=SiPrefixToDouble(argument_list[3].string_reference,
8673               QuantumRange);
8674           if (attribute_flag[5] != 0)
8675             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8676               QuantumRange);
8677           invert=MagickFalse;
8678           if (attribute_flag[6] != 0)
8679             invert=(MagickBooleanType) argument_list[6].long_reference;
8680           (void) FloodfillPaintImage(image,OpacityChannel,draw_info,&target,
8681             geometry.x,geometry.y,invert);
8682           draw_info=DestroyDrawInfo(draw_info);
8683           break;
8684         }
8685         case 43:  /* Modulate */
8686         {
8687           char
8688             modulate[MaxTextExtent];
8689
8690           ColorspaceType
8691             colorspace;
8692
8693           colorspace=image->colorspace;
8694           geometry_info.rho=100.0;
8695           geometry_info.sigma=100.0;
8696           geometry_info.xi=100.0;
8697           if (attribute_flag[0] != 0)
8698             (void)ParseGeometry(argument_list[0].string_reference,
8699               &geometry_info);
8700           if (attribute_flag[1] != 0)
8701             geometry_info.xi=argument_list[1].real_reference;
8702           if (attribute_flag[2] != 0)
8703             geometry_info.sigma=argument_list[2].real_reference;
8704           if (attribute_flag[3] != 0)
8705             {
8706               (void) SetImageColorspace(image,HWBColorspace);
8707               geometry_info.sigma=argument_list[3].real_reference;
8708             }
8709           if (attribute_flag[4] != 0)
8710             geometry_info.rho=argument_list[4].real_reference;
8711           if (attribute_flag[5] != 0)
8712             {
8713               (void) SetImageColorspace(image,HSLColorspace);
8714               geometry_info.sigma=argument_list[5].real_reference;
8715             }
8716           if (attribute_flag[6] != 0)
8717             {
8718               (void) SetImageColorspace(image,HWBColorspace);
8719               geometry_info.rho=argument_list[6].real_reference;
8720             }
8721           (void) FormatMagickString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8722             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8723           (void) ModulateImage(image,modulate);
8724           (void) SetImageColorspace(image,colorspace);
8725           break;
8726         }
8727         case 44:  /* Negate */
8728         {
8729           if (attribute_flag[0] == 0)
8730             argument_list[0].long_reference=0;
8731           if (attribute_flag[1] != 0)
8732             channel=(ChannelType) argument_list[1].long_reference;
8733           (void) NegateImageChannel(image,channel,
8734             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse);
8735           break;
8736         }
8737         case 45:  /* Normalize */
8738         {
8739           if (attribute_flag[0] != 0)
8740             channel=(ChannelType) argument_list[0].long_reference;
8741           NormalizeImageChannel(image,channel);
8742           break;
8743         }
8744         case 46:  /* NumberColors */
8745           break;
8746         case 47:  /* Opaque */
8747         {
8748           MagickBooleanType
8749             invert;
8750
8751           MagickPixelPacket
8752             fill_color,
8753             target;
8754
8755           (void) QueryMagickColor("none",&target,exception);
8756           (void) QueryMagickColor("none",&fill_color,exception);
8757           if (attribute_flag[0] != 0)
8758             (void) QueryMagickColor(argument_list[0].string_reference,
8759               &target,exception);
8760           if (attribute_flag[1] != 0)
8761             (void) QueryMagickColor(argument_list[1].string_reference,
8762               &fill_color,exception);
8763           if (attribute_flag[2] != 0)
8764             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8765               QuantumRange);
8766           if (attribute_flag[3] != 0)
8767             channel=(ChannelType) argument_list[3].long_reference;
8768           invert=MagickFalse;
8769           if (attribute_flag[4] != 0)
8770             invert=(MagickBooleanType) argument_list[4].long_reference;
8771           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8772             invert);
8773           break;
8774         }
8775         case 48:  /* Quantize */
8776         {
8777           QuantizeInfo
8778             *quantize_info;
8779
8780           quantize_info=AcquireQuantizeInfo(info->image_info);
8781           if (attribute_flag[0] != 0)
8782             quantize_info->number_colors=(unsigned long)
8783               argument_list[0].long_reference;
8784           if (attribute_flag[1] != 0)
8785             quantize_info->tree_depth=(unsigned long)
8786               argument_list[1].long_reference;
8787           if (attribute_flag[2] != 0)
8788             quantize_info->colorspace=(ColorspaceType)
8789               argument_list[2].long_reference;
8790           if (attribute_flag[3] != 0)
8791             quantize_info->dither=argument_list[3].long_reference != 0 ?
8792               MagickTrue : MagickFalse;
8793           if (attribute_flag[4] != 0)
8794             quantize_info->measure_error=
8795               argument_list[4].long_reference != 0 ? MagickTrue : MagickFalse;
8796           if (attribute_flag[5] != 0)
8797             (void) QueryColorDatabase(argument_list[5].string_reference,
8798               &image->transparent_color,exception);
8799           if (attribute_flag[5] && argument_list[5].long_reference)
8800             {
8801               (void) QuantizeImages(quantize_info,image);
8802               goto PerlException;
8803             }
8804           if (attribute_flag[6] != 0)
8805             quantize_info->dither_method=(DitherMethod)
8806               argument_list[6].long_reference;
8807           if ((image->storage_class == DirectClass) ||
8808               (image->colors > quantize_info->number_colors) ||
8809               (quantize_info->colorspace == GRAYColorspace))
8810             (void) QuantizeImage(quantize_info,image);
8811           else
8812             CompressImageColormap(image);
8813           quantize_info=DestroyQuantizeInfo(quantize_info);
8814           break;
8815         }
8816         case 49:  /* Raise */
8817         {
8818           if (attribute_flag[0] != 0)
8819             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8820               &geometry,exception);
8821           if (attribute_flag[1] != 0)
8822             geometry.width=argument_list[1].long_reference;
8823           if (attribute_flag[2] != 0)
8824             geometry.height=argument_list[2].long_reference;
8825           if (attribute_flag[3] == 0)
8826             argument_list[3].long_reference=1;
8827           (void) RaiseImage(image,&geometry,argument_list[3].long_reference !=
8828             0 ? MagickTrue : MagickFalse);
8829           break;
8830         }
8831         case 50:  /* Segment */
8832         {
8833           ColorspaceType
8834             colorspace;
8835
8836           double
8837             cluster_threshold,
8838             smoothing_threshold;
8839
8840           MagickBooleanType
8841             verbose;
8842
8843           cluster_threshold=1.0;
8844           smoothing_threshold=1.5;
8845           colorspace=RGBColorspace;
8846           verbose=MagickFalse;
8847           if (attribute_flag[0] != 0)
8848             {
8849               flags=ParseGeometry(argument_list[0].string_reference,
8850                 &geometry_info);
8851               cluster_threshold=geometry_info.rho;
8852               if (flags & SigmaValue)
8853                 smoothing_threshold=geometry_info.sigma;
8854             }
8855           if (attribute_flag[1] != 0)
8856             cluster_threshold=argument_list[1].real_reference;
8857           if (attribute_flag[2] != 0)
8858             smoothing_threshold=argument_list[2].real_reference;
8859           if (attribute_flag[3] != 0)
8860             colorspace=(ColorspaceType) argument_list[3].long_reference;
8861           if (attribute_flag[4] != 0)
8862             verbose=argument_list[4].long_reference != 0 ?
8863               MagickTrue : MagickFalse;
8864           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8865             smoothing_threshold);
8866           break;
8867         }
8868         case 51:  /* Signature */
8869         {
8870           (void) SignatureImage(image);
8871           break;
8872         }
8873         case 52:  /* Solarize */
8874         {
8875           geometry_info.rho=QuantumRange/2.0;
8876           if (attribute_flag[0] != 0)
8877             flags=ParseGeometry(argument_list[0].string_reference,
8878               &geometry_info);
8879           if (attribute_flag[1] != 0)
8880             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8881              QuantumRange);
8882           (void) SolarizeImage(image,geometry_info.rho);
8883           break;
8884         }
8885         case 53:  /* Sync */
8886         {
8887           (void) SyncImage(image);
8888           break;
8889         }
8890         case 54:  /* Texture */
8891         {
8892           if (attribute_flag[0] == 0)
8893             break;
8894           TextureImage(image,argument_list[0].image_reference);
8895           break;
8896         }
8897         case 55:  /* Evalute */
8898         {
8899           MagickEvaluateOperator
8900             op;
8901
8902           op=SetEvaluateOperator;
8903           if (attribute_flag[0] == MagickFalse)
8904             argument_list[0].real_reference=0.0;
8905           if (attribute_flag[1] != MagickFalse)
8906             op=(MagickEvaluateOperator) argument_list[1].long_reference;
8907           if (attribute_flag[2] != MagickFalse)
8908             channel=(ChannelType) argument_list[2].long_reference;
8909           (void) EvaluateImageChannel(image,channel,op,
8910             argument_list[0].real_reference,exception);
8911           break;
8912         }
8913         case 56:  /* Transparent */
8914         {
8915           double
8916             opacity;
8917
8918           MagickBooleanType
8919             invert;
8920
8921           MagickPixelPacket
8922             target;
8923
8924           (void) QueryMagickColor("none",&target,exception);
8925           if (attribute_flag[0] != 0)
8926             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8927               exception);
8928           opacity=TransparentOpacity;
8929           if (attribute_flag[1] != 0)
8930             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8931               QuantumRange);
8932           if (attribute_flag[2] != 0)
8933             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8934               QuantumRange);
8935           if (attribute_flag[3] == 0)
8936             argument_list[3].long_reference=0;
8937           invert=MagickFalse;
8938           if (attribute_flag[3] != 0)
8939             invert=(MagickBooleanType) argument_list[3].long_reference;
8940           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8941             invert);
8942           break;
8943         }
8944         case 57:  /* Threshold */
8945         {
8946           double
8947             threshold;
8948
8949           if (attribute_flag[0] == 0)
8950             argument_list[0].string_reference="50%";
8951           if (attribute_flag[1] != 0)
8952             channel=(ChannelType) argument_list[1].long_reference;
8953           threshold=SiPrefixToDouble(argument_list[0].string_reference,
8954             QuantumRange);
8955           (void) BilevelImageChannel(image,channel,threshold);
8956           break;
8957         }
8958         case 58:  /* Charcoal */
8959         {
8960           if (attribute_flag[0] != 0)
8961             {
8962               flags=ParseGeometry(argument_list[0].string_reference,
8963                 &geometry_info);
8964               if ((flags & SigmaValue) == 0)
8965                 geometry_info.sigma=1.0;
8966             }
8967           if (attribute_flag[1] != 0)
8968             geometry_info.rho=argument_list[1].real_reference;
8969           if (attribute_flag[2] != 0)
8970             geometry_info.sigma=argument_list[2].real_reference;
8971           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
8972             exception);
8973           break;
8974         }
8975         case 59:  /* Trim */
8976         {
8977           if (attribute_flag[0] != 0)
8978             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
8979               QuantumRange);
8980           image=TrimImage(image,exception);
8981           break;
8982         }
8983         case 60:  /* Wave */
8984         {
8985           if (attribute_flag[0] != 0)
8986             {
8987               flags=ParseGeometry(argument_list[0].string_reference,
8988                 &geometry_info);
8989               if ((flags & SigmaValue) == 0)
8990                 geometry_info.sigma=1.0;
8991             }
8992           if (attribute_flag[1] != 0)
8993             geometry_info.rho=argument_list[1].real_reference;
8994           if (attribute_flag[2] != 0)
8995             geometry_info.sigma=argument_list[2].real_reference;
8996           if (attribute_flag[3] != 0)
8997             image->interpolate=(InterpolatePixelMethod)
8998               argument_list[3].long_reference;
8999           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9000             exception);
9001           break;
9002         }
9003         case 61:  /* Separate */
9004         {
9005           if (attribute_flag[0] != 0)
9006             channel=(ChannelType) argument_list[0].long_reference;
9007           (void) SeparateImageChannel(image,channel);
9008           break;
9009         }
9010         case 63:  /* Stereo */
9011         {
9012           if (attribute_flag[0] == 0)
9013             {
9014               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9015                 PackageName);
9016               goto PerlException;
9017             }
9018           if (attribute_flag[1] != 0)
9019             geometry.x=argument_list[1].long_reference;
9020           if (attribute_flag[2] != 0)
9021             geometry.y=argument_list[2].long_reference;
9022           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9023             geometry.x,geometry.y,exception);
9024           break;
9025         }
9026         case 64:  /* Stegano */
9027         {
9028           if (attribute_flag[0] == 0)
9029             {
9030               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9031                 PackageName);
9032               goto PerlException;
9033             }
9034           if (attribute_flag[1] == 0)
9035             argument_list[1].long_reference=0;
9036           image->offset=argument_list[1].long_reference;
9037           image=SteganoImage(image,argument_list[0].image_reference,exception);
9038           break;
9039         }
9040         case 65:  /* Deconstruct */
9041         {
9042           image=DeconstructImages(image,exception);
9043           break;
9044         }
9045         case 66:  /* GaussianBlur */
9046         {
9047           if (attribute_flag[0] != 0)
9048             {
9049               flags=ParseGeometry(argument_list[0].string_reference,
9050                 &geometry_info);
9051               if ((flags & SigmaValue) == 0)
9052                 geometry_info.sigma=1.0;
9053             }
9054           if (attribute_flag[1] != 0)
9055             geometry_info.rho=argument_list[1].real_reference;
9056           if (attribute_flag[2] != 0)
9057             geometry_info.sigma=argument_list[2].real_reference;
9058           if (attribute_flag[3] != 0)
9059             channel=(ChannelType) argument_list[3].long_reference;
9060           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9061             geometry_info.sigma,exception);
9062           break;
9063         }
9064         case 67:  /* Convolve */
9065         {
9066           AV
9067             *av;
9068
9069           double
9070             *kernel;
9071
9072           unsigned long
9073             order;
9074
9075           if (attribute_flag[0] == 0)
9076             break;
9077           if (attribute_flag[1] != 0)
9078             channel=(ChannelType) argument_list[1].long_reference;
9079           if (attribute_flag[2] != 0)
9080             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9081               QuantumRange);
9082           av=(AV *) argument_list[0].array_reference;
9083           order=(unsigned long) sqrt(av_len(av)+1);
9084           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9085           if (kernel == (double *) NULL)
9086             {
9087               ThrowPerlException(exception,ResourceLimitFatalError,
9088                 "MemoryAllocationFailed",PackageName);
9089               goto PerlException;
9090             }
9091           for (j=0; (j < (long) (order*order)) && (j < (av_len(av)+1)); j++)
9092             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9093           for ( ; j < (long) (order*order); j++)
9094             kernel[j]=0.0;
9095           image=ConvolveImageChannel(image,channel,order,kernel,exception);
9096           kernel=(double *) RelinquishMagickMemory(kernel);
9097           break;
9098         }
9099         case 68:  /* Profile */
9100         {
9101           const char
9102             *name;
9103
9104           Image
9105             *profile_image;
9106
9107           ImageInfo
9108             *profile_info;
9109
9110           StringInfo
9111             *profile;
9112
9113           name="*";
9114           if (attribute_flag[0] != 0)
9115             name=argument_list[0].string_reference;
9116           if (attribute_flag[2] != 0)
9117             image->rendering_intent=(RenderingIntent)
9118               argument_list[2].long_reference;
9119           if (attribute_flag[3] != 0)
9120             image->black_point_compensation=
9121               argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse;
9122           if (attribute_flag[1] != 0)
9123             {
9124               if (argument_list[1].length == 0)
9125                 {
9126                   /*
9127                     Remove a profile from the image.
9128                   */
9129                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9130                     MagickTrue);
9131                   break;
9132                 }
9133               /*
9134                 Associate user supplied profile with the image.
9135               */
9136               profile=AcquireStringInfo(argument_list[1].length);
9137               SetStringInfoDatum(profile,(const unsigned char *)
9138                 argument_list[1].string_reference);
9139               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9140                 (unsigned long) GetStringInfoLength(profile),MagickFalse);
9141               profile=DestroyStringInfo(profile);
9142               break;
9143             }
9144           /*
9145             Associate a profile with the image.
9146           */
9147           profile_info=
9148             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9149           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9150           profile_image=ReadImages(profile_info,&image->exception);
9151           if (profile_image == (Image *) NULL)
9152             break;
9153           ResetImageProfileIterator(profile_image);
9154           name=GetNextImageProfile(profile_image);
9155           while (name != (const char *) NULL)
9156           {
9157             const StringInfo
9158               *profile;
9159
9160             profile=GetImageProfile(profile_image,name);
9161             if (profile != (const StringInfo *) NULL)
9162               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9163                 (unsigned long) GetStringInfoLength(profile),MagickFalse);
9164             name=GetNextImageProfile(profile_image);
9165           }
9166           profile_image=DestroyImage(profile_image);
9167           profile_info=DestroyImageInfo(profile_info);
9168           break;
9169         }
9170         case 69:  /* UnsharpMask */
9171         {
9172           if (attribute_flag[0] != 0)
9173             {
9174               flags=ParseGeometry(argument_list[0].string_reference,
9175                 &geometry_info);
9176               if ((flags & SigmaValue) == 0)
9177                 geometry_info.sigma=1.0;
9178               if ((flags & XiValue) == 0)
9179                 geometry_info.xi=1.0;
9180               if ((flags & PsiValue) == 0)
9181                 geometry_info.psi=0.5;
9182             }
9183           if (attribute_flag[1] != 0)
9184             geometry_info.rho=argument_list[1].real_reference;
9185           if (attribute_flag[2] != 0)
9186             geometry_info.sigma=argument_list[2].real_reference;
9187           if (attribute_flag[3] != 0)
9188             geometry_info.xi=argument_list[3].real_reference;
9189           if (attribute_flag[4] != 0)
9190             geometry_info.psi=argument_list[4].real_reference;
9191           if (attribute_flag[5] != 0)
9192             channel=(ChannelType) argument_list[5].long_reference;
9193           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9194             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9195           break;
9196         }
9197         case 70:  /* MotionBlur */
9198         {
9199           if (attribute_flag[0] != 0)
9200             {
9201               flags=ParseGeometry(argument_list[0].string_reference,
9202                 &geometry_info);
9203               if ((flags & SigmaValue) == 0)
9204                 geometry_info.sigma=1.0;
9205               if ((flags & XiValue) == 0)
9206                 geometry_info.xi=1.0;
9207             }
9208           if (attribute_flag[1] != 0)
9209             geometry_info.rho=argument_list[1].real_reference;
9210           if (attribute_flag[2] != 0)
9211             geometry_info.sigma=argument_list[2].real_reference;
9212           if (attribute_flag[3] != 0)
9213             geometry_info.xi=argument_list[3].real_reference;
9214           if (attribute_flag[4] != 0)
9215             channel=(ChannelType) argument_list[4].long_reference;
9216           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9217             geometry_info.sigma,geometry_info.xi,exception);
9218           break;
9219         }
9220         case 71:  /* OrderedDither */
9221         {
9222           if (attribute_flag[0] == 0)
9223             argument_list[0].string_reference="o8x8";
9224           if (attribute_flag[1] != 0)
9225             channel=(ChannelType) argument_list[1].long_reference;
9226           (void) OrderedPosterizeImageChannel(image,channel,
9227             argument_list[0].string_reference,exception);
9228           break;
9229         }
9230         case 72:  /* Shave */
9231         {
9232           if (attribute_flag[0] != 0)
9233             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9234               &geometry,exception);
9235           if (attribute_flag[1] != 0)
9236             geometry.width=argument_list[1].long_reference;
9237           if (attribute_flag[2] != 0)
9238             geometry.height=argument_list[2].long_reference;
9239           image=ShaveImage(image,&geometry,exception);
9240           break;
9241         }
9242         case 73:  /* Level */
9243         {
9244           double
9245             black_point,
9246             gamma,
9247             white_point;
9248
9249           black_point=0.0;
9250           white_point=(MagickRealType) image->columns*image->rows;
9251           gamma=1.0;
9252           if (attribute_flag[0] != 0)
9253             {
9254               flags=ParseGeometry(argument_list[0].string_reference,
9255                 &geometry_info);
9256               black_point=geometry_info.rho;
9257               if ((flags & SigmaValue) != 0)
9258                 white_point=geometry_info.sigma;
9259               if ((flags & XiValue) != 0)
9260                 gamma=geometry_info.xi;
9261               if ((flags & PercentValue) != 0)
9262                 {
9263                   black_point*=(double) (QuantumRange/100.0);
9264                   white_point*=(double) (QuantumRange/100.0);
9265                 }
9266               if ((flags & SigmaValue) == 0)
9267                 white_point=(double) QuantumRange-black_point;
9268             }
9269           if (attribute_flag[1] != 0)
9270             black_point=argument_list[1].real_reference;
9271           if (attribute_flag[2] != 0)
9272             white_point=argument_list[2].real_reference;
9273           if (attribute_flag[3] != 0)
9274             gamma=argument_list[3].real_reference;
9275           if (attribute_flag[4] != 0)
9276             channel=(ChannelType) argument_list[4].long_reference;
9277           if (attribute_flag[5] != 0)
9278             {
9279               argument_list[0].real_reference=argument_list[5].real_reference;
9280               attribute_flag[0]=attribute_flag[5];
9281             }
9282           (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9283           break;
9284         }
9285         case 74:  /* Clip */
9286         {
9287           if (attribute_flag[0] == 0)
9288             argument_list[0].string_reference="#1";
9289           if (attribute_flag[1] == 0)
9290             argument_list[1].long_reference=MagickTrue;
9291           (void) ClipImagePath(image,argument_list[0].string_reference,
9292             argument_list[1].long_reference != 0 ? MagickTrue : MagickFalse);
9293           break;
9294         }
9295         case 75:  /* AffineTransform */
9296         {
9297           DrawInfo
9298             *draw_info;
9299
9300           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9301             (DrawInfo *) NULL);
9302           if (attribute_flag[0] != 0)
9303             {
9304               AV
9305                 *av;
9306
9307               av=(AV *) argument_list[0].array_reference;
9308               if ((av_len(av) != 3) && (av_len(av) != 5))
9309                 {
9310                   ThrowPerlException(exception,OptionError,
9311                     "affine matrix must have 4 or 6 elements",PackageName);
9312                   goto PerlException;
9313                 }
9314               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9315               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9316               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9317               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9318               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9319                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9320                 {
9321                   ThrowPerlException(exception,OptionError,
9322                     "affine matrix is singular",PackageName);
9323                    goto PerlException;
9324                 }
9325               if (av_len(av) == 5)
9326                 {
9327                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9328                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9329                 }
9330             }
9331           for (j=1; j < 6; j++)
9332           {
9333             if (attribute_flag[j] == 0)
9334               continue;
9335             value=argument_list[j].string_reference;
9336             angle=argument_list[j].real_reference;
9337             current=draw_info->affine;
9338             GetAffineMatrix(&affine);
9339             switch (j)
9340             {
9341               case 1:
9342               {
9343                 /*
9344                   Translate.
9345                 */
9346                 flags=ParseGeometry(value,&geometry_info);
9347                 affine.tx=geometry_info.xi;
9348                 affine.ty=geometry_info.psi;
9349                 if ((flags & PsiValue) == 0)
9350                   affine.ty=affine.tx;
9351                 break;
9352               }
9353               case 2:
9354               {
9355                 /*
9356                   Scale.
9357                 */
9358                 flags=ParseGeometry(value,&geometry_info);
9359                 affine.sx=geometry_info.rho;
9360                 affine.sy=geometry_info.sigma;
9361                 if ((flags & SigmaValue) == 0)
9362                   affine.sy=affine.sx;
9363                 break;
9364               }
9365               case 3:
9366               {
9367                 /*
9368                   Rotate.
9369                 */
9370                 if (angle == 0.0)
9371                   break;
9372                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9373                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9374                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9375                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9376                 break;
9377               }
9378               case 4:
9379               {
9380                 /*
9381                   SkewX.
9382                 */
9383                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9384                 break;
9385               }
9386               case 5:
9387               {
9388                 /*
9389                   SkewY.
9390                 */
9391                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9392                 break;
9393               }
9394             }
9395             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9396             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9397             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9398             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9399             draw_info->affine.tx=
9400               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9401             draw_info->affine.ty=
9402               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9403           }
9404           if (attribute_flag[6] != 0)
9405             image->interpolate=(InterpolatePixelMethod)
9406               argument_list[6].long_reference;
9407           if (attribute_flag[7] != 0)
9408             QueryColorDatabase(argument_list[7].string_reference,
9409               &image->background_color,exception);
9410           image=AffineTransformImage(image,&draw_info->affine,exception);
9411           draw_info=DestroyDrawInfo(draw_info);
9412           break;
9413         }
9414         case 76:  /* Difference */
9415         {
9416           if (attribute_flag[0] == 0)
9417             {
9418               ThrowPerlException(exception,OptionError,
9419                 "ReferenceImageRequired",PackageName);
9420               goto PerlException;
9421             }
9422           if (attribute_flag[1] != 0)
9423             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9424               QuantumRange);
9425           (void) IsImagesEqual(image,argument_list[0].image_reference);
9426           break;
9427         }
9428         case 77:  /* AdaptiveThreshold */
9429         {
9430           if (attribute_flag[0] != 0)
9431             {
9432               flags=ParseGeometry(argument_list[0].string_reference,
9433                 &geometry_info);
9434               if ((flags & PercentValue) != 0)
9435                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9436             }
9437           if (attribute_flag[1] != 0)
9438             geometry_info.rho=argument_list[1].long_reference;
9439           if (attribute_flag[2] != 0)
9440             geometry_info.sigma=argument_list[2].long_reference;
9441           if (attribute_flag[3] != 0)
9442             geometry_info.xi=argument_list[3].long_reference;;
9443           image=AdaptiveThresholdImage(image,(unsigned long) geometry_info.rho,
9444             (unsigned long) geometry_info.sigma,(long) geometry_info.xi,
9445             exception);
9446           break;
9447         }
9448         case 78:  /* Resample */
9449         {
9450           unsigned long
9451             height,
9452             width;
9453
9454           if (attribute_flag[0] != 0)
9455             {
9456               flags=ParseGeometry(argument_list[0].string_reference,
9457                 &geometry_info);
9458               if ((flags & SigmaValue) == 0)
9459                 geometry_info.sigma=geometry_info.rho;
9460             }
9461           if (attribute_flag[1] != 0)
9462             geometry_info.rho=argument_list[1].real_reference;
9463           if (attribute_flag[2] != 0)
9464             geometry_info.sigma=argument_list[2].real_reference;
9465           if (attribute_flag[3] == 0)
9466             argument_list[3].long_reference=(long) UndefinedFilter;
9467           if (attribute_flag[4] == 0)
9468             SetImageArtifact(image,"filter:support",
9469               argument_list[4].string_reference);
9470           if (attribute_flag[5] != 0)
9471             argument_list[5].real_reference=1.0;
9472           width=(unsigned long) (geometry_info.rho*image->columns/
9473             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9474           height=(unsigned long) (geometry_info.sigma*image->rows/
9475             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9476           image=ResizeImage(image,width,height,(FilterTypes)
9477             argument_list[3].long_reference,argument_list[5].real_reference,
9478             exception);
9479           if (image != (Image *) NULL)
9480             {
9481               image->x_resolution=geometry_info.rho;
9482               image->y_resolution=geometry_info.sigma;
9483             }
9484           break;
9485         }
9486         case 79:  /* Describe */
9487         {
9488           if (attribute_flag[0] == 0)
9489             argument_list[0].file_reference=(FILE *) NULL;
9490           if (attribute_flag[1] != 0)
9491             (void) SetImageArtifact(image,"identify:features",
9492               argument_list[1].string_reference);
9493           (void) IdentifyImage(image,argument_list[0].file_reference,
9494             MagickTrue);
9495           break;
9496         }
9497         case 80:  /* BlackThreshold */
9498         {
9499           if (attribute_flag[0] == 0)
9500             argument_list[0].string_reference="50%";
9501           if (attribute_flag[2] != 0)
9502             channel=(ChannelType) argument_list[2].long_reference;
9503           BlackThresholdImageChannel(image,channel,
9504             argument_list[0].string_reference,exception);
9505           break;
9506         }
9507         case 81:  /* WhiteThreshold */
9508         {
9509           if (attribute_flag[0] == 0)
9510             argument_list[0].string_reference="50%";
9511           if (attribute_flag[2] != 0)
9512             channel=(ChannelType) argument_list[2].long_reference;
9513           WhiteThresholdImageChannel(image,channel,
9514             argument_list[0].string_reference,exception);
9515           break;
9516         }
9517         case 82:  /* RadialBlur */
9518         {
9519           if (attribute_flag[0] != 0)
9520             {
9521               flags=ParseGeometry(argument_list[0].string_reference,
9522                 &geometry_info);
9523               if ((flags & SigmaValue) == 0)
9524                 geometry_info.sigma=1.0;
9525             }
9526           if (attribute_flag[1] != 0)
9527             geometry_info.rho=argument_list[1].real_reference;
9528           if (attribute_flag[2] != 0)
9529             channel=(ChannelType) argument_list[2].long_reference;
9530           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9531             exception);
9532           break;
9533         }
9534         case 83:  /* Thumbnail */
9535         {
9536           if (attribute_flag[0] != 0)
9537             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9538               &geometry,exception);
9539           if (attribute_flag[1] != 0)
9540             geometry.width=argument_list[1].long_reference;
9541           if (attribute_flag[2] != 0)
9542             geometry.height=argument_list[2].long_reference;
9543           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9544           break;
9545         }
9546         case 84:  /* Strip */
9547         {
9548           (void) StripImage(image);
9549           break;
9550         }
9551         case 85:  /* Tint */
9552         {
9553           PixelPacket
9554             target;
9555
9556           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9557           if (attribute_flag[0] != 0)
9558             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9559               exception);
9560           if (attribute_flag[1] == 0)
9561             argument_list[1].string_reference="100";
9562           image=TintImage(image,argument_list[1].string_reference,target,
9563             exception);
9564           break;
9565         }
9566         case 86:  /* Channel */
9567         {
9568           if (attribute_flag[0] != 0)
9569             channel=(ChannelType) argument_list[0].long_reference;
9570           (void) SeparateImageChannel(image,channel);
9571           break;
9572         }
9573         case 87:  /* Splice */
9574         {
9575           if (attribute_flag[0] != 0)
9576             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9577               &geometry,exception);
9578           if (attribute_flag[1] != 0)
9579             geometry.width=argument_list[1].long_reference;
9580           if (attribute_flag[2] != 0)
9581             geometry.height=argument_list[2].long_reference;
9582           if (attribute_flag[3] != 0)
9583             geometry.x=argument_list[3].long_reference;
9584           if (attribute_flag[4] != 0)
9585             geometry.y=argument_list[4].long_reference;
9586           if (attribute_flag[5] != 0)
9587             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9588               QuantumRange);
9589           if (attribute_flag[6] != 0)
9590             (void) QueryColorDatabase(argument_list[6].string_reference,
9591               &image->background_color,exception);
9592           if (attribute_flag[7] != 0)
9593             image->gravity=(GravityType) argument_list[7].long_reference;
9594           image=SpliceImage(image,&geometry,exception);
9595           break;
9596         }
9597         case 88:  /* Posterize */
9598         {
9599           if (attribute_flag[0] == 0)
9600             argument_list[0].long_reference=3;
9601           if (attribute_flag[1] == 0)
9602             argument_list[1].long_reference=0;
9603           (void) PosterizeImage(image,argument_list[0].long_reference,
9604             argument_list[1].long_reference ? MagickTrue : MagickFalse);
9605           break;
9606         }
9607         case 89:  /* Shadow */
9608         {
9609           if (attribute_flag[0] != 0)
9610             {
9611               flags=ParseGeometry(argument_list[0].string_reference,
9612                 &geometry_info);
9613               if ((flags & SigmaValue) == 0)
9614                 geometry_info.sigma=1.0;
9615               if ((flags & XiValue) == 0)
9616                 geometry_info.xi=4.0;
9617               if ((flags & PsiValue) == 0)
9618                 geometry_info.psi=4.0;
9619             }
9620           if (attribute_flag[1] != 0)
9621             geometry_info.rho=argument_list[1].real_reference;
9622           if (attribute_flag[2] != 0)
9623             geometry_info.sigma=argument_list[2].real_reference;
9624           if (attribute_flag[3] != 0)
9625             geometry_info.xi=argument_list[3].long_reference;
9626           if (attribute_flag[4] != 0)
9627             geometry_info.psi=argument_list[4].long_reference;
9628           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9629             (long) ceil(geometry_info.xi-0.5),(long) ceil(geometry_info.psi-
9630             0.5),exception);
9631           break;
9632         }
9633         case 90:  /* Identify */
9634         {
9635           if (attribute_flag[0] == 0)
9636             argument_list[0].file_reference=(FILE *) NULL;
9637           if (attribute_flag[1] != 0)
9638             (void) SetImageArtifact(image,"identify:features",
9639               argument_list[1].string_reference);
9640           if ((attribute_flag[2] != 0) &&
9641               (argument_list[2].long_reference != 0))
9642             (void) SetImageArtifact(image,"identify:unique","true");
9643           (void) IdentifyImage(image,argument_list[0].file_reference,
9644             MagickTrue);
9645           break;
9646         }
9647         case 91:  /* SepiaTone */
9648         {
9649           if (attribute_flag[0] == 0)
9650             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9651           image=SepiaToneImage(image,argument_list[0].real_reference,
9652             exception);
9653           break;
9654         }
9655         case 92:  /* SigmoidalContrast */
9656         {
9657           MagickBooleanType
9658             sharpen;
9659
9660           if (attribute_flag[0] != 0)
9661             {
9662               flags=ParseGeometry(argument_list[0].string_reference,
9663                 &geometry_info);
9664               if ((flags & SigmaValue) == 0)
9665                 geometry_info.sigma=QuantumRange/2.0;
9666               if ((flags & PercentValue) != 0)
9667                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9668             }
9669           if (attribute_flag[1] != 0)
9670             geometry_info.rho=argument_list[1].real_reference;
9671           if (attribute_flag[2] != 0)
9672             geometry_info.sigma=argument_list[2].real_reference;
9673           if (attribute_flag[3] != 0)
9674             channel=(ChannelType) argument_list[3].long_reference;
9675           sharpen=MagickTrue;
9676           if (attribute_flag[4] != 0)
9677             sharpen=argument_list[4].long_reference != 0 ? MagickTrue :
9678               MagickFalse;
9679           (void) SigmoidalContrastImageChannel(image,channel,sharpen,
9680             geometry_info.rho,geometry_info.sigma);
9681           break;
9682         }
9683         case 93:  /* Extent */
9684         {
9685           if (attribute_flag[7] != 0)
9686             image->gravity=(GravityType) argument_list[7].long_reference;
9687           if (attribute_flag[0] != 0)
9688             {
9689               int
9690                 flags;
9691
9692               flags=ParseGravityGeometry(image,
9693                 argument_list[0].string_reference,&geometry,exception);
9694               if (geometry.width == 0)
9695                 geometry.width=image->columns;
9696               if (geometry.height == 0)
9697                 geometry.height=image->rows;
9698               geometry.x=(-geometry.x);
9699               geometry.y=(-geometry.y);
9700             }
9701           if (attribute_flag[1] != 0)
9702             geometry.width=argument_list[1].long_reference;
9703           if (attribute_flag[2] != 0)
9704             geometry.height=argument_list[2].long_reference;
9705           if (attribute_flag[3] != 0)
9706             geometry.x=argument_list[3].long_reference;
9707           if (attribute_flag[4] != 0)
9708             geometry.y=argument_list[4].long_reference;
9709           if (attribute_flag[5] != 0)
9710             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9711               QuantumRange);
9712           if (attribute_flag[6] != 0)
9713             (void) QueryColorDatabase(argument_list[6].string_reference,
9714               &image->background_color,exception);
9715           image=ExtentImage(image,&geometry,exception);
9716           break;
9717         }
9718         case 94:  /* Vignette */
9719         {
9720           if (attribute_flag[0] != 0)
9721             {
9722               flags=ParseGeometry(argument_list[0].string_reference,
9723                 &geometry_info);
9724               if ((flags & SigmaValue) == 0)
9725                 geometry_info.sigma=1.0;
9726               if ((flags & XiValue) == 0)
9727                 geometry_info.xi=0.1*image->columns;
9728               if ((flags & PsiValue) == 0)
9729                 geometry_info.psi=0.1*image->rows;
9730             }
9731           if (attribute_flag[1] != 0)
9732             geometry_info.rho=argument_list[1].real_reference;
9733           if (attribute_flag[2] != 0)
9734             geometry_info.sigma=argument_list[2].real_reference;
9735           if (attribute_flag[3] != 0)
9736             geometry_info.xi=argument_list[3].long_reference;
9737           if (attribute_flag[4] != 0)
9738             geometry_info.psi=argument_list[4].long_reference;
9739           if (attribute_flag[5] != 0)
9740             (void) QueryColorDatabase(argument_list[5].string_reference,
9741               &image->background_color,exception);
9742           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9743             (long) ceil(geometry_info.xi-0.5),(long) ceil(geometry_info.psi-
9744             0.5),exception);
9745           break;
9746         }
9747         case 95:  /* ContrastStretch */
9748         {
9749           double
9750             black_point,
9751             white_point;
9752
9753           black_point=0.0;
9754           white_point=(MagickRealType) image->columns*image->rows;
9755           if (attribute_flag[0] != 0)
9756             {
9757               flags=ParseGeometry(argument_list[0].string_reference,
9758                 &geometry_info);
9759               black_point=geometry_info.rho;
9760               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9761                 black_point;
9762               if ((flags & PercentValue) != 0)
9763                 {
9764                   black_point*=(double) image->columns*image->rows/100.0;
9765                   white_point*=(double) image->columns*image->rows/100.0;
9766                 }
9767               white_point=(MagickRealType) image->columns*image->rows-
9768                 white_point;
9769             }
9770           if (attribute_flag[1] != 0)
9771             black_point=argument_list[1].real_reference;
9772           if (attribute_flag[2] != 0)
9773             white_point=argument_list[2].real_reference;
9774           if (attribute_flag[4] != 0)
9775             channel=(ChannelType) argument_list[4].long_reference;
9776           (void) ContrastStretchImageChannel(image,channel,black_point,
9777             white_point);
9778           break;
9779         }
9780         case 96:  /* Sans0 */
9781         {
9782           break;
9783         }
9784         case 97:  /* Sans1 */
9785         {
9786           break;
9787         }
9788         case 98:  /* AdaptiveSharpen */
9789         {
9790           if (attribute_flag[0] != 0)
9791             {
9792               flags=ParseGeometry(argument_list[0].string_reference,
9793                 &geometry_info);
9794               if ((flags & SigmaValue) == 0)
9795                 geometry_info.sigma=1.0;
9796             }
9797           if (attribute_flag[1] != 0)
9798             geometry_info.rho=argument_list[1].real_reference;
9799           if (attribute_flag[2] != 0)
9800             geometry_info.sigma=argument_list[2].real_reference;
9801           if (attribute_flag[3] != 0)
9802             channel=(ChannelType) argument_list[3].long_reference;
9803           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9804             geometry_info.sigma,exception);
9805           break;
9806         }
9807         case 99:  /* Transpose */
9808         {
9809           image=TransposeImage(image,exception);
9810           break;
9811         }
9812         case 100:  /* Tranverse */
9813         {
9814           image=TransverseImage(image,exception);
9815           break;
9816         }
9817         case 101:  /* AutoOrient */
9818         {
9819           switch (image->orientation)
9820           {
9821             case TopRightOrientation:
9822             {
9823               image=FlopImage(image,exception);
9824               break;
9825             }
9826             case BottomRightOrientation:
9827             {
9828               image=RotateImage(image,180.0,exception);
9829               break;
9830             }
9831             case BottomLeftOrientation:
9832             {
9833               image=FlipImage(image,exception);
9834               break;
9835             }
9836             case LeftTopOrientation:
9837             {
9838               image=TransposeImage(image,exception);
9839               break;
9840             }
9841             case RightTopOrientation:
9842             {
9843               image=RotateImage(image,90.0,exception);
9844               break;
9845             }
9846             case RightBottomOrientation:
9847             {
9848               image=TransverseImage(image,exception);
9849               break;
9850             }
9851             case LeftBottomOrientation:
9852             {
9853               image=RotateImage(image,270.0,exception);
9854               break;
9855             }
9856             default:
9857               break;
9858           }
9859           break;
9860         }
9861         case 102:  /* AdaptiveBlur */
9862         {
9863           if (attribute_flag[0] != 0)
9864             {
9865               flags=ParseGeometry(argument_list[0].string_reference,
9866                 &geometry_info);
9867               if ((flags & SigmaValue) == 0)
9868                 geometry_info.sigma=1.0;
9869             }
9870           if (attribute_flag[1] != 0)
9871             geometry_info.rho=argument_list[1].real_reference;
9872           if (attribute_flag[2] != 0)
9873             geometry_info.sigma=argument_list[2].real_reference;
9874           if (attribute_flag[3] != 0)
9875             channel=(ChannelType) argument_list[3].long_reference;
9876           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
9877             geometry_info.sigma,exception);
9878           break;
9879         }
9880         case 103:  /* Sketch */
9881         {
9882           if (attribute_flag[0] != 0)
9883             {
9884               flags=ParseGeometry(argument_list[0].string_reference,
9885                 &geometry_info);
9886               if ((flags & SigmaValue) == 0)
9887                 geometry_info.sigma=1.0;
9888               if ((flags & XiValue) == 0)
9889                 geometry_info.xi=1.0;
9890             }
9891           if (attribute_flag[1] != 0)
9892             geometry_info.rho=argument_list[1].real_reference;
9893           if (attribute_flag[2] != 0)
9894             geometry_info.sigma=argument_list[2].real_reference;
9895           if (attribute_flag[3] != 0)
9896             geometry_info.xi=argument_list[3].real_reference;
9897           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
9898             geometry_info.xi,exception);
9899           break;
9900         }
9901         case 104:  /* UniqueColors */
9902         {
9903           image=UniqueImageColors(image,exception);
9904           break;
9905         }
9906         case 105:  /* AdaptiveResize */
9907         {
9908           if (attribute_flag[0] != 0)
9909             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9910               &geometry,exception);
9911           if (attribute_flag[1] != 0)
9912             geometry.width=argument_list[1].long_reference;
9913           if (attribute_flag[2] != 0)
9914             geometry.height=argument_list[2].long_reference;
9915           if (attribute_flag[3] != 0)
9916             image->filter=(FilterTypes) argument_list[4].long_reference;
9917           if (attribute_flag[4] != 0)
9918             SetImageArtifact(image,"filter:support",
9919               argument_list[4].string_reference);
9920           if (attribute_flag[5] != 0)
9921             image->blur=argument_list[5].real_reference;
9922           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
9923             exception);
9924           break;
9925         }
9926         case 106:  /* ClipMask */
9927         {
9928           if (attribute_flag[0] == 0)
9929             {
9930               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9931                 PackageName);
9932               goto PerlException;
9933             }
9934           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
9935             MagickTrue,exception);
9936           (void) NegateImage(image->clip_mask,MagickFalse);
9937           break;
9938         }
9939         case 107:  /* LinearStretch */
9940         {
9941            double
9942              black_point,
9943              white_point;
9944
9945            black_point=0.0;
9946            white_point=(MagickRealType) image->columns*image->rows;
9947            if (attribute_flag[0] != 0)
9948              {
9949                flags=ParseGeometry(argument_list[0].string_reference,
9950                  &geometry_info);
9951                if ((flags & SigmaValue) != 0)
9952                   white_point=geometry_info.sigma;
9953                if ((flags & PercentValue) != 0)
9954                  {
9955                    black_point*=(double) image->columns*image->rows/100.0;
9956                    white_point*=(double) image->columns*image->rows/100.0;
9957                  }
9958                if ((flags & SigmaValue) == 0)
9959                  white_point=(double) image->columns*image->rows-black_point;
9960              }
9961           if (attribute_flag[1] != 0)
9962             black_point=argument_list[1].real_reference;
9963           if (attribute_flag[2] != 0)
9964             white_point=argument_list[2].real_reference;
9965           (void) LinearStretchImage(image,black_point,white_point);
9966           break;
9967         }
9968         case 109:  /* Mask */
9969         {
9970           if (attribute_flag[0] == 0)
9971             {
9972               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9973                 PackageName);
9974               goto PerlException;
9975             }
9976           image->mask=CloneImage(argument_list[0].image_reference,0,0,
9977             MagickTrue,exception);
9978           (void) NegateImage(image->mask,MagickFalse);
9979           break;
9980         }
9981         case 110:  /* Polaroid */
9982         {
9983           DrawInfo
9984             *draw_info;
9985
9986           double
9987             angle;
9988
9989           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9990             (DrawInfo *) NULL);
9991           if (attribute_flag[0] != 0)
9992             (void) SetImageProperty(image,"caption",InterpretImageProperties(
9993               info ? info->image_info : (ImageInfo *) NULL,image,
9994               argument_list[0].string_reference));
9995           angle=0.0;
9996           if (attribute_flag[1] != 0)
9997             angle=argument_list[1].real_reference;
9998           if (attribute_flag[2] != 0)
9999             (void) CloneString(&draw_info->font,
10000               argument_list[2].string_reference);
10001           if (attribute_flag[3] != 0)
10002             (void) QueryColorDatabase(argument_list[3].string_reference,
10003               &draw_info->stroke,exception);
10004           if (attribute_flag[4] != 0)
10005             (void) QueryColorDatabase(argument_list[4].string_reference,
10006               &draw_info->fill,exception);
10007           if (attribute_flag[5] != 0)
10008             draw_info->stroke_width=argument_list[5].real_reference;
10009           if (attribute_flag[6] != 0)
10010             draw_info->pointsize=argument_list[6].real_reference;
10011           if (attribute_flag[7] != 0)
10012             draw_info->gravity=(GravityType) argument_list[7].long_reference;
10013           if (attribute_flag[8] != 0)
10014             (void) QueryColorDatabase(argument_list[8].string_reference,
10015               &image->background_color,exception);
10016           image=PolaroidImage(image,draw_info,angle,exception);
10017           draw_info=DestroyDrawInfo(draw_info);
10018           break;
10019         }
10020         case 111:  /* FloodfillPaint */
10021         {
10022           DrawInfo
10023             *draw_info;
10024
10025           MagickBooleanType
10026             invert;
10027
10028           MagickPixelPacket
10029             target;
10030
10031           draw_info=CloneDrawInfo(info ? info->image_info :
10032             (ImageInfo *) NULL,(DrawInfo *) NULL);
10033           if (attribute_flag[0] != 0)
10034             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10035               &geometry,exception);
10036           if (attribute_flag[1] != 0)
10037             geometry.x=argument_list[1].long_reference;
10038           if (attribute_flag[2] != 0)
10039             geometry.y=argument_list[2].long_reference;
10040           if (attribute_flag[3] != 0)
10041             (void) QueryColorDatabase(argument_list[3].string_reference,
10042               &draw_info->fill,exception);
10043           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10044             exception);
10045           if (attribute_flag[4] != 0)
10046             QueryMagickColor(argument_list[4].string_reference,&target,
10047               exception);
10048           if (attribute_flag[5] != 0)
10049             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10050               QuantumRange);
10051           if (attribute_flag[6] != 0)
10052             channel=(ChannelType) argument_list[6].long_reference;
10053           invert=MagickFalse;
10054           if (attribute_flag[7] != 0)
10055             invert=(MagickBooleanType) argument_list[7].long_reference;
10056           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10057             geometry.y,invert);
10058           draw_info=DestroyDrawInfo(draw_info);
10059           break;
10060         }
10061         case 112:  /* Distort */
10062         {
10063           AV
10064             *av;
10065
10066           double
10067             *coordinates;
10068
10069           DistortImageMethod
10070             method;
10071
10072           unsigned long
10073             number_coordinates;
10074
10075           VirtualPixelMethod
10076             virtual_pixel;
10077
10078           if (attribute_flag[0] == 0)
10079             break;
10080           method=UndefinedDistortion;
10081           if (attribute_flag[1] != 0)
10082             method=(DistortImageMethod) argument_list[1].long_reference;
10083           av=(AV *) argument_list[0].array_reference;
10084           number_coordinates=(unsigned long) av_len(av)+1;
10085           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10086             sizeof(*coordinates));
10087           if (coordinates == (double *) NULL)
10088             {
10089               ThrowPerlException(exception,ResourceLimitFatalError,
10090                 "MemoryAllocationFailed",PackageName);
10091               goto PerlException;
10092             }
10093           for (j=0; j < (long) number_coordinates; j++)
10094             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10095           virtual_pixel=UndefinedVirtualPixelMethod;
10096           if (attribute_flag[2] != 0)
10097             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10098               argument_list[2].long_reference);
10099           image=DistortImage(image,method,number_coordinates,coordinates,
10100             argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse,
10101             exception);
10102           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10103             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10104           coordinates=(double *) RelinquishMagickMemory(coordinates);
10105           break;
10106         }
10107         case 113:  /* Clut */
10108         {
10109           if (attribute_flag[0] == 0)
10110             {
10111               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10112                 PackageName);
10113               goto PerlException;
10114             }
10115           if (attribute_flag[1] != 0)
10116             channel=(ChannelType) argument_list[1].long_reference;
10117           (void) ClutImageChannel(image,channel,
10118             argument_list[0].image_reference);
10119           break;
10120         }
10121         case 114:  /* LiquidRescale */
10122         {
10123           if (attribute_flag[0] != 0)
10124             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10125               &geometry,exception);
10126           if (attribute_flag[1] != 0)
10127             geometry.width=argument_list[1].long_reference;
10128           if (attribute_flag[2] != 0)
10129             geometry.height=argument_list[2].long_reference;
10130           if (attribute_flag[3] == 0)
10131             argument_list[3].real_reference=1.0;
10132           if (attribute_flag[4] == 0)
10133             argument_list[4].real_reference=0.0;
10134           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10135             argument_list[3].real_reference,argument_list[4].real_reference,
10136             exception);
10137           break;
10138         }
10139         case 115:  /* EncipherImage */
10140         {
10141           (void) EncipherImage(image,argument_list[0].string_reference,
10142             exception);
10143           break;
10144         }
10145         case 116:  /* DecipherImage */
10146         {
10147           (void) DecipherImage(image,argument_list[0].string_reference,
10148             exception);
10149           break;
10150         }
10151         case 117:  /* Deskew */
10152         {
10153           geometry_info.rho=QuantumRange/2.0;
10154           if (attribute_flag[0] != 0)
10155             flags=ParseGeometry(argument_list[0].string_reference,
10156               &geometry_info);
10157           if (attribute_flag[1] != 0)
10158             geometry_info.rho=SiPrefixToDouble(
10159               argument_list[1].string_reference,QuantumRange);
10160           image=DeskewImage(image,geometry_info.rho,exception);
10161           break;
10162         }
10163         case 118:  /* Remap */
10164         {
10165           QuantizeInfo
10166             *quantize_info;
10167
10168           if (attribute_flag[0] == 0)
10169             {
10170               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10171                 PackageName);
10172               goto PerlException;
10173             }
10174           quantize_info=AcquireQuantizeInfo(info->image_info);
10175           if (attribute_flag[1] != 0)
10176             quantize_info->dither=(MagickBooleanType)
10177               argument_list[1].long_reference;
10178           if (attribute_flag[2] != 0)
10179             quantize_info->dither_method=(DitherMethod)
10180               argument_list[2].long_reference;
10181           (void) RemapImages(quantize_info,image,
10182             argument_list[0].image_reference);
10183           quantize_info=DestroyQuantizeInfo(quantize_info);
10184           break;
10185         }
10186         case 119:  /* SparseColor */
10187         {
10188           AV
10189             *av;
10190
10191           double
10192             *coordinates;
10193
10194           SparseColorMethod
10195             method;
10196
10197           unsigned long
10198             number_coordinates;
10199
10200           VirtualPixelMethod
10201             virtual_pixel;
10202
10203           if (attribute_flag[0] == 0)
10204             break;
10205           method=UndefinedColorInterpolate;
10206           if (attribute_flag[1] != 0)
10207             method=(SparseColorMethod) argument_list[1].long_reference;
10208           av=(AV *) argument_list[0].array_reference;
10209           number_coordinates=(unsigned long) av_len(av)+1;
10210           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10211             sizeof(*coordinates));
10212           if (coordinates == (double *) NULL)
10213             {
10214               ThrowPerlException(exception,ResourceLimitFatalError,
10215                 "MemoryAllocationFailed",PackageName);
10216               goto PerlException;
10217             }
10218           for (j=0; j < (long) number_coordinates; j++)
10219             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10220           virtual_pixel=UndefinedVirtualPixelMethod;
10221           if (attribute_flag[2] != 0)
10222             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10223               argument_list[2].long_reference);
10224           if (attribute_flag[3] != 0)
10225             channel=(ChannelType) argument_list[3].long_reference;
10226           image=SparseColorImage(image,channel,method,number_coordinates,
10227             coordinates,exception);
10228           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10229             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10230           coordinates=(double *) RelinquishMagickMemory(coordinates);
10231           break;
10232         }
10233         case 120:  /* Function */
10234         {
10235           AV
10236             *av;
10237
10238           double
10239             *parameters;
10240
10241           MagickFunction
10242             function;
10243
10244           unsigned long
10245             number_parameters;
10246
10247           VirtualPixelMethod
10248             virtual_pixel;
10249
10250           if (attribute_flag[0] == 0)
10251             break;
10252           function=UndefinedFunction;
10253           if (attribute_flag[1] != 0)
10254             function=(MagickFunction) argument_list[1].long_reference;
10255           av=(AV *) argument_list[0].array_reference;
10256           number_parameters=(unsigned long) av_len(av)+1;
10257           parameters=(double *) AcquireQuantumMemory(number_parameters,
10258             sizeof(*parameters));
10259           if (parameters == (double *) NULL)
10260             {
10261               ThrowPerlException(exception,ResourceLimitFatalError,
10262                 "MemoryAllocationFailed",PackageName);
10263               goto PerlException;
10264             }
10265           for (j=0; j < (long) number_parameters; j++)
10266             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10267           virtual_pixel=UndefinedVirtualPixelMethod;
10268           if (attribute_flag[2] != 0)
10269             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10270               argument_list[2].long_reference);
10271           (void) FunctionImage(image,function,number_parameters,parameters,
10272             exception);
10273           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10274             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10275           parameters=(double *) RelinquishMagickMemory(parameters);
10276           break;
10277         }
10278         case 121:  /* SelectiveBlur */
10279         {
10280           if (attribute_flag[0] != 0)
10281             {
10282               flags=ParseGeometry(argument_list[0].string_reference,
10283                 &geometry_info);
10284               if ((flags & SigmaValue) == 0)
10285                 geometry_info.sigma=1.0;
10286               if ((flags & PercentValue) != 0)
10287                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10288             }
10289           if (attribute_flag[1] != 0)
10290             geometry_info.rho=argument_list[1].real_reference;
10291           if (attribute_flag[2] != 0)
10292             geometry_info.sigma=argument_list[2].real_reference;
10293           if (attribute_flag[3] != 0)
10294             geometry_info.xi=argument_list[3].long_reference;;
10295           if (attribute_flag[4] != 0)
10296             channel=(ChannelType) argument_list[4].long_reference;
10297           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10298             geometry_info.sigma,geometry_info.xi,exception);
10299           break;
10300         }
10301         case 122:  /* HaldClut */
10302         {
10303           if (attribute_flag[0] == 0)
10304             {
10305               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10306                 PackageName);
10307               goto PerlException;
10308             }
10309           if (attribute_flag[1] != 0)
10310             channel=(ChannelType) argument_list[1].long_reference;
10311           (void) HaldClutImageChannel(image,channel,
10312             argument_list[0].image_reference);
10313           break;
10314         }
10315         case 123:  /* BlueShift */
10316         {
10317           if (attribute_flag[0] != 0)
10318             (void) ParseGeometry(argument_list[0].string_reference,
10319               &geometry_info);
10320           image=BlueShiftImage(image,geometry_info.rho,exception);
10321           break;
10322         }
10323         case 124:  /* ForwardFourierTransformImage */
10324         {
10325           image=ForwardFourierTransformImage(image,
10326             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse,
10327             exception);
10328           break;
10329         }
10330         case 125:  /* InverseFourierTransformImage */
10331         {
10332           image=InverseFourierTransformImage(image,image->next,
10333             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse,
10334             exception);
10335           break;
10336         }
10337         case 126:  /* ColorDecisionList */
10338         {
10339           if (attribute_flag[0] == 0)
10340             argument_list[0].string_reference=(char *) NULL;
10341           (void) ColorDecisionListImage(image,
10342             argument_list[0].string_reference);
10343           break;
10344         }
10345         case 127:  /* AutoGamma */
10346         {
10347           if (attribute_flag[0] != 0)
10348             channel=(ChannelType) argument_list[0].long_reference;
10349           (void) AutoGammaImageChannel(image,channel);
10350           break;
10351         }
10352         case 128:  /* AutoLevel */
10353         {
10354           if (attribute_flag[0] != 0)
10355             channel=(ChannelType) argument_list[0].long_reference;
10356           (void) AutoLevelImageChannel(image,channel);
10357           break;
10358         }
10359         case 129:  /* LevelColors */
10360         {
10361           MagickPixelPacket
10362             black_point,
10363             white_point;
10364
10365           (void) QueryMagickColor("#000000",&black_point,exception);
10366           (void) QueryMagickColor("#ffffff",&black_point,exception);
10367           if (attribute_flag[1] != 0)
10368              (void) QueryMagickColor(argument_list[1].string_reference,
10369                &black_point,exception);
10370           if (attribute_flag[2] != 0)
10371              (void) QueryMagickColor(argument_list[2].string_reference,
10372                &white_point,exception);
10373           if (attribute_flag[3] != 0)
10374             channel=(ChannelType) argument_list[3].long_reference;
10375           (void) LevelColorsImageChannel(image,channel,&black_point,
10376             &white_point,argument_list[0].long_reference != 0 ? MagickTrue :
10377             MagickFalse);
10378           break;
10379         }
10380         case 130:  /* Clamp */
10381         {
10382           if (attribute_flag[0] != 0)
10383             channel=(ChannelType) argument_list[0].long_reference;
10384           (void) ClampImageChannel(image,channel);
10385           break;
10386         }
10387         case 131:  /* Filter */
10388         {
10389           KernelInfo
10390             *kernel;
10391
10392           if (attribute_flag[0] == 0)
10393             break;
10394           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10395           if (kernel == (KernelInfo *) NULL)
10396             break;
10397           if (attribute_flag[1] != 0)
10398             channel=(ChannelType) argument_list[1].long_reference;
10399           if (attribute_flag[2] != 0)
10400             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10401               QuantumRange);
10402           image=FilterImageChannel(image,channel,kernel,exception);
10403           kernel=DestroyKernelInfo(kernel);
10404           break;
10405         }
10406         case 132:  /* BrightnessContrast */
10407         {
10408           double
10409             brightness,
10410             contrast;
10411
10412           brightness=0.0;
10413           contrast=0.0;
10414           if (attribute_flag[0] != 0)
10415             {
10416               flags=ParseGeometry(argument_list[0].string_reference,
10417                 &geometry_info);
10418               brightness=geometry_info.rho;
10419               if ((flags & SigmaValue) == 0)
10420                 contrast=geometry_info.sigma;
10421             }
10422           if (attribute_flag[1] != 0)
10423             brightness=argument_list[1].real_reference;
10424           if (attribute_flag[2] != 0)
10425             contrast=argument_list[2].real_reference;
10426           if (attribute_flag[4] != 0)
10427             channel=(ChannelType) argument_list[4].long_reference;
10428           (void) BrightnessContrastImageChannel(image,channel,brightness,
10429             contrast);
10430           break;
10431         }
10432         case 133:  /* Morphology */
10433         {
10434           KernelInfo
10435             *kernel;
10436
10437           MorphologyMethod
10438             method;
10439
10440           long
10441             iterations;
10442
10443           if (attribute_flag[0] == 0)
10444             break;
10445           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10446           if (kernel == (KernelInfo *) NULL)
10447             break;
10448           if (attribute_flag[1] != 0)
10449             channel=(ChannelType) argument_list[1].long_reference;
10450           method=UndefinedMorphology;
10451           if (attribute_flag[2] != 0)
10452             method=argument_list[2].long_reference;
10453           iterations=1;
10454           if (attribute_flag[3] != 0)
10455             iterations=argument_list[4].long_reference;
10456           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10457             exception);
10458           kernel=DestroyKernelInfo(kernel);
10459           break;
10460         }
10461         case 108:  /* Recolor */
10462         case 134:  /* ColorMatrix */
10463         {
10464           AV
10465             *av;
10466
10467           double
10468             *color_matrix;
10469
10470           KernelInfo
10471             *kernel_info;
10472
10473           unsigned long
10474             order;
10475
10476           if (attribute_flag[0] == 0)
10477             break;
10478           av=(AV *) argument_list[0].array_reference;
10479           order=(unsigned long) sqrt(av_len(av)+1);
10480           color_matrix=(double *) AcquireQuantumMemory(order,order*
10481             sizeof(*color_matrix));
10482           if (color_matrix == (double *) NULL)
10483             {
10484               ThrowPerlException(exception,ResourceLimitFatalError,
10485                 "MemoryAllocationFailed",PackageName);
10486               goto PerlException;
10487            }
10488           for (j=0; (j < (long) (order*order)) && (j < (av_len(av)+1)); j++)
10489             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10490           for ( ; j < (long) (order*order); j++)
10491             color_matrix[j]=0.0;
10492           kernel_info=AcquireKernelInfo((const char *) NULL);
10493           kernel_info->width=order;
10494           kernel_info->height=order;
10495           kernel_info->values=color_matrix;
10496           image=ColorMatrixImage(image,kernel_info,exception);
10497           kernel_info->values=(double *) NULL;
10498           kernel_info=DestroyKernelInfo(kernel_info);
10499           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10500           break;
10501         }
10502       }
10503       if (next != (Image *) NULL)
10504         (void) CatchImageException(next);
10505       if (region_image != (Image *) NULL)
10506         {
10507           /*
10508             Composite region.
10509           */
10510           status=CompositeImage(region_image,CopyCompositeOp,image,
10511             region_info.x,region_info.y);
10512           (void) CatchImageException(region_image);
10513           image=DestroyImage(image);
10514           image=region_image;
10515         }
10516       if (image != (Image *) NULL)
10517         {
10518           number_images++;
10519           if (next && (next != image))
10520             {
10521               image->next=next->next;
10522               DeleteImageFromRegistry(*pv,next);
10523             }
10524           sv_setiv(*pv,(IV) image);
10525           next=image;
10526         }
10527       if (*pv)
10528         pv++;
10529     }
10530
10531   PerlException:
10532     if (reference_vector)
10533       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10534     InheritPerlException(exception,perl_exception);
10535     exception=DestroyExceptionInfo(exception);
10536     sv_setiv(perl_exception,(IV) number_images);
10537     SvPOK_on(perl_exception);
10538     ST(0)=sv_2mortal(perl_exception);
10539     XSRETURN(1);
10540   }
10541 \f
10542 #
10543 ###############################################################################
10544 #                                                                             #
10545 #                                                                             #
10546 #                                                                             #
10547 #   M o n t a g e                                                             #
10548 #                                                                             #
10549 #                                                                             #
10550 #                                                                             #
10551 ###############################################################################
10552 #
10553 #
10554 void
10555 Montage(ref,...)
10556   Image::Magick ref=NO_INIT
10557   ALIAS:
10558     MontageImage  = 1
10559     montage       = 2
10560     montageimage  = 3
10561   PPCODE:
10562   {
10563     AV
10564       *av;
10565
10566     char
10567       *attribute;
10568
10569     ExceptionInfo
10570       *exception;
10571
10572     HV
10573       *hv;
10574
10575     Image
10576       *image,
10577       *next;
10578
10579     long
10580       sp;
10581
10582     MagickPixelPacket
10583       transparent_color;
10584
10585     MontageInfo
10586       *montage_info;
10587
10588     register long
10589       i;
10590
10591     struct PackageInfo
10592       *info;
10593
10594     SV
10595       *av_reference,
10596       *perl_exception,
10597       *reference,
10598       *rv,
10599       *sv;
10600
10601     exception=AcquireExceptionInfo();
10602     perl_exception=newSVpv("",0);
10603     attribute=NULL;
10604     if (sv_isobject(ST(0)) == 0)
10605       {
10606         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10607           PackageName);
10608         goto PerlException;
10609       }
10610     reference=SvRV(ST(0));
10611     hv=SvSTASH(reference);
10612     av=newAV();
10613     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10614     SvREFCNT_dec(av);
10615     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10616     if (image == (Image *) NULL)
10617       {
10618         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10619           PackageName);
10620         goto PerlException;
10621       }
10622     /*
10623       Get options.
10624     */
10625     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10626     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10627     (void) QueryMagickColor("none",&transparent_color,exception);
10628     for (i=2; i < items; i+=2)
10629     {
10630       attribute=(char *) SvPV(ST(i-1),na);
10631       switch (*attribute)
10632       {
10633         case 'B':
10634         case 'b':
10635         {
10636           if (LocaleCompare(attribute,"background") == 0)
10637             {
10638               (void) QueryColorDatabase(SvPV(ST(i),na),
10639                 &montage_info->background_color,exception);
10640               for (next=image; next; next=next->next)
10641                 next->background_color=montage_info->background_color;
10642               break;
10643             }
10644           if (LocaleCompare(attribute,"border") == 0)
10645             {
10646               montage_info->border_width=SvIV(ST(i));
10647               break;
10648             }
10649           if (LocaleCompare(attribute,"bordercolor") == 0)
10650             {
10651               (void) QueryColorDatabase(SvPV(ST(i),na),
10652                 &montage_info->border_color,exception);
10653               for (next=image; next; next=next->next)
10654                 next->border_color=montage_info->border_color;
10655               break;
10656             }
10657           if (LocaleCompare(attribute,"borderwidth") == 0)
10658             {
10659               montage_info->border_width=SvIV(ST(i));
10660               break;
10661             }
10662           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10663             attribute);
10664           break;
10665         }
10666         case 'C':
10667         case 'c':
10668         {
10669           if (LocaleCompare(attribute,"compose") == 0)
10670             {
10671               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10672                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10673               if (sp < 0)
10674                 {
10675                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10676                     SvPV(ST(i),na));
10677                   break;
10678                 }
10679               for (next=image; next; next=next->next)
10680                 next->compose=(CompositeOperator) sp;
10681               break;
10682             }
10683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10684             attribute);
10685           break;
10686         }
10687         case 'F':
10688         case 'f':
10689         {
10690           if (LocaleCompare(attribute,"fill") == 0)
10691             {
10692               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10693                 exception);
10694               break;
10695             }
10696           if (LocaleCompare(attribute,"font") == 0)
10697             {
10698               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10699               break;
10700             }
10701           if (LocaleCompare(attribute,"frame") == 0)
10702             {
10703               char
10704                 *p;
10705
10706               p=SvPV(ST(i),na);
10707               if (IsGeometry(p) == MagickFalse)
10708                 {
10709                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10710                     p);
10711                   break;
10712                 }
10713               (void) CloneString(&montage_info->frame,p);
10714               if (*p == '\0')
10715                 montage_info->frame=(char *) NULL;
10716               break;
10717             }
10718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10719             attribute);
10720           break;
10721         }
10722         case 'G':
10723         case 'g':
10724         {
10725           if (LocaleCompare(attribute,"geometry") == 0)
10726             {
10727               char
10728                 *p;
10729
10730               p=SvPV(ST(i),na);
10731               if (IsGeometry(p) == MagickFalse)
10732                 {
10733                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10734                     p);
10735                   break;
10736                 }
10737              (void) CloneString(&montage_info->geometry,p);
10738              if (*p == '\0')
10739                montage_info->geometry=(char *) NULL;
10740              break;
10741            }
10742          if (LocaleCompare(attribute,"gravity") == 0)
10743            {
10744              long
10745                in;
10746
10747              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10748                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10749              if (in < 0)
10750                {
10751                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10752                    SvPV(ST(i),na));
10753                  return;
10754                }
10755              montage_info->gravity=(GravityType) in;
10756              for (next=image; next; next=next->next)
10757                next->gravity=(GravityType) in;
10758              break;
10759            }
10760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10761             attribute);
10762           break;
10763         }
10764         case 'L':
10765         case 'l':
10766         {
10767           if (LocaleCompare(attribute,"label") == 0)
10768             {
10769               for (next=image; next; next=next->next)
10770                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10771                   info ? info->image_info : (ImageInfo *) NULL,next,
10772                   SvPV(ST(i),na)));
10773               break;
10774             }
10775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10776             attribute);
10777           break;
10778         }
10779         case 'M':
10780         case 'm':
10781         {
10782           if (LocaleCompare(attribute,"mattecolor") == 0)
10783             {
10784               (void) QueryColorDatabase(SvPV(ST(i),na),
10785                 &montage_info->matte_color,exception);
10786               for (next=image; next; next=next->next)
10787                 next->matte_color=montage_info->matte_color;
10788               break;
10789             }
10790           if (LocaleCompare(attribute,"mode") == 0)
10791             {
10792               long
10793                 in;
10794
10795               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10796                 ParseMagickOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10797               switch (in)
10798               {
10799                 default:
10800                 {
10801                   ThrowPerlException(exception,OptionError,
10802                     "UnrecognizedModeType",SvPV(ST(i),na));
10803                   break;
10804                 }
10805                 case FrameMode:
10806                 {
10807                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10808                   montage_info->shadow=MagickTrue;
10809                   break;
10810                 }
10811                 case UnframeMode:
10812                 {
10813                   montage_info->frame=(char *) NULL;
10814                   montage_info->shadow=MagickFalse;
10815                   montage_info->border_width=0;
10816                   break;
10817                 }
10818                 case ConcatenateMode:
10819                 {
10820                   montage_info->frame=(char *) NULL;
10821                   montage_info->shadow=MagickFalse;
10822                   (void) CloneString(&montage_info->geometry,"+0+0");
10823                   montage_info->border_width=0;
10824                 }
10825               }
10826               break;
10827             }
10828           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10829             attribute);
10830           break;
10831         }
10832         case 'P':
10833         case 'p':
10834         {
10835           if (LocaleCompare(attribute,"pointsize") == 0)
10836             {
10837               montage_info->pointsize=SvIV(ST(i));
10838               break;
10839             }
10840           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10841             attribute);
10842           break;
10843         }
10844         case 'S':
10845         case 's':
10846         {
10847           if (LocaleCompare(attribute,"shadow") == 0)
10848             {
10849               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10850                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
10851               if (sp < 0)
10852                 {
10853                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10854                     SvPV(ST(i),na));
10855                   break;
10856                 }
10857              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
10858              break;
10859             }
10860           if (LocaleCompare(attribute,"stroke") == 0)
10861             {
10862               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
10863                 exception);
10864               break;
10865             }
10866           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10867             attribute);
10868           break;
10869         }
10870         case 'T':
10871         case 't':
10872         {
10873           if (LocaleCompare(attribute,"texture") == 0)
10874             {
10875               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
10876               break;
10877             }
10878           if (LocaleCompare(attribute,"tile") == 0)
10879             {
10880               char *p=SvPV(ST(i),na);
10881               if (IsGeometry(p) == MagickFalse)
10882                 {
10883                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10884                     p);
10885                   break;
10886                 }
10887               (void) CloneString(&montage_info->tile,p);
10888               if (*p == '\0')
10889                 montage_info->tile=(char *) NULL;
10890               break;
10891             }
10892           if (LocaleCompare(attribute,"title") == 0)
10893             {
10894               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
10895               break;
10896             }
10897           if (LocaleCompare(attribute,"transparent") == 0)
10898             {
10899               MagickPixelPacket
10900                 transparent_color;
10901
10902               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
10903               for (next=image; next; next=next->next)
10904                 (void) TransparentPaintImage(next,&transparent_color,
10905                   TransparentOpacity,MagickFalse);
10906               break;
10907             }
10908           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10909             attribute);
10910           break;
10911         }
10912         default:
10913         {
10914           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10915             attribute);
10916           break;
10917         }
10918       }
10919     }
10920     image=MontageImageList(info->image_info,montage_info,image,exception);
10921     montage_info=DestroyMontageInfo(montage_info);
10922     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
10923       goto PerlException;
10924     if (transparent_color.opacity != TransparentOpacity)
10925       for (next=image; next; next=next->next)
10926         (void) TransparentPaintImage(next,&transparent_color,
10927           TransparentOpacity,MagickFalse);
10928     for (  ; image; image=image->next)
10929     {
10930       AddImageToRegistry(image);
10931       rv=newRV(sv);
10932       av_push(av,sv_bless(rv,hv));
10933       SvREFCNT_dec(sv);
10934     }
10935     exception=DestroyExceptionInfo(exception);
10936     ST(0)=av_reference;
10937     SvREFCNT_dec(perl_exception);
10938     XSRETURN(1);
10939
10940   PerlException:
10941     InheritPerlException(exception,perl_exception);
10942     exception=DestroyExceptionInfo(exception);
10943     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
10944     SvPOK_on(perl_exception);
10945     ST(0)=sv_2mortal(perl_exception);
10946     XSRETURN(1);
10947   }
10948 \f
10949 #
10950 ###############################################################################
10951 #                                                                             #
10952 #                                                                             #
10953 #                                                                             #
10954 #   M o r p h                                                                 #
10955 #                                                                             #
10956 #                                                                             #
10957 #                                                                             #
10958 ###############################################################################
10959 #
10960 #
10961 void
10962 Morph(ref,...)
10963   Image::Magick ref=NO_INIT
10964   ALIAS:
10965     MorphImage  = 1
10966     morph       = 2
10967     morphimage  = 3
10968   PPCODE:
10969   {
10970     AV
10971       *av;
10972
10973     char
10974       *attribute;
10975
10976     ExceptionInfo
10977       *exception;
10978
10979     HV
10980       *hv;
10981
10982     Image
10983       *image;
10984
10985     long
10986       number_frames;
10987
10988     register long
10989       i;
10990
10991     struct PackageInfo
10992       *info;
10993
10994     SV
10995       *av_reference,
10996       *perl_exception,
10997       *reference,
10998       *rv,
10999       *sv;
11000
11001     exception=AcquireExceptionInfo();
11002     perl_exception=newSVpv("",0);
11003     av=NULL;
11004     attribute=NULL;
11005     if (sv_isobject(ST(0)) == 0)
11006       {
11007         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11008           PackageName);
11009         goto PerlException;
11010       }
11011     reference=SvRV(ST(0));
11012     hv=SvSTASH(reference);
11013     av=newAV();
11014     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11015     SvREFCNT_dec(av);
11016     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11017     if (image == (Image *) NULL)
11018       {
11019         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11020           PackageName);
11021         goto PerlException;
11022       }
11023     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11024     /*
11025       Get attribute.
11026     */
11027     number_frames=30;
11028     for (i=2; i < items; i+=2)
11029     {
11030       attribute=(char *) SvPV(ST(i-1),na);
11031       switch (*attribute)
11032       {
11033         case 'F':
11034         case 'f':
11035         {
11036           if (LocaleCompare(attribute,"frames") == 0)
11037             {
11038               number_frames=SvIV(ST(i));
11039               break;
11040             }
11041           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11042             attribute);
11043           break;
11044         }
11045         default:
11046         {
11047           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11048             attribute);
11049           break;
11050         }
11051       }
11052     }
11053     image=MorphImages(image,number_frames,exception);
11054     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11055       goto PerlException;
11056     for ( ; image; image=image->next)
11057     {
11058       AddImageToRegistry(image);
11059       rv=newRV(sv);
11060       av_push(av,sv_bless(rv,hv));
11061       SvREFCNT_dec(sv);
11062     }
11063     exception=DestroyExceptionInfo(exception);
11064     ST(0)=av_reference;
11065     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11066     XSRETURN(1);
11067
11068   PerlException:
11069     InheritPerlException(exception,perl_exception);
11070     exception=DestroyExceptionInfo(exception);
11071     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11072     SvPOK_on(perl_exception);
11073     ST(0)=sv_2mortal(perl_exception);
11074     XSRETURN(1);
11075   }
11076 \f
11077 #
11078 ###############################################################################
11079 #                                                                             #
11080 #                                                                             #
11081 #                                                                             #
11082 #   M o s a i c                                                               #
11083 #                                                                             #
11084 #                                                                             #
11085 #                                                                             #
11086 ###############################################################################
11087 #
11088 #
11089 void
11090 Mosaic(ref)
11091   Image::Magick ref=NO_INIT
11092   ALIAS:
11093     MosaicImage   = 1
11094     mosaic        = 2
11095     mosaicimage   = 3
11096   PPCODE:
11097   {
11098     AV
11099       *av;
11100
11101     ExceptionInfo
11102       *exception;
11103
11104     HV
11105       *hv;
11106
11107     Image
11108       *image;
11109
11110     struct PackageInfo
11111       *info;
11112
11113     SV
11114       *perl_exception,
11115       *reference,
11116       *rv,
11117       *sv;
11118
11119     exception=AcquireExceptionInfo();
11120     perl_exception=newSVpv("",0);
11121     if (sv_isobject(ST(0)) == 0)
11122       {
11123         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11124           PackageName);
11125         goto PerlException;
11126       }
11127     reference=SvRV(ST(0));
11128     hv=SvSTASH(reference);
11129     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11130     if (image == (Image *) NULL)
11131       {
11132         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11133           PackageName);
11134         goto PerlException;
11135       }
11136     image=MergeImageLayers(image,MosaicLayer,exception);
11137     /*
11138       Create blessed Perl array for the returned image.
11139     */
11140     av=newAV();
11141     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11142     SvREFCNT_dec(av);
11143     AddImageToRegistry(image);
11144     rv=newRV(sv);
11145     av_push(av,sv_bless(rv,hv));
11146     SvREFCNT_dec(sv);
11147     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11148     (void) CopyMagickString(image->filename,info->image_info->filename,
11149       MaxTextExtent);
11150     SetImageInfo(info->image_info,0,&image->exception);
11151     exception=DestroyExceptionInfo(exception);
11152     SvREFCNT_dec(perl_exception);
11153     XSRETURN(1);
11154
11155   PerlException:
11156     InheritPerlException(exception,perl_exception);
11157     exception=DestroyExceptionInfo(exception);
11158     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11159     SvPOK_on(perl_exception);  /* return messages in string context */
11160     ST(0)=sv_2mortal(perl_exception);
11161     XSRETURN(1);
11162   }
11163 \f
11164 #
11165 ###############################################################################
11166 #                                                                             #
11167 #                                                                             #
11168 #                                                                             #
11169 #   P i n g                                                                   #
11170 #                                                                             #
11171 #                                                                             #
11172 #                                                                             #
11173 ###############################################################################
11174 #
11175 #
11176 void
11177 Ping(ref,...)
11178   Image::Magick ref=NO_INIT
11179   ALIAS:
11180     PingImage  = 1
11181     ping       = 2
11182     pingimage  = 3
11183   PPCODE:
11184   {
11185     AV
11186       *av;
11187
11188     char
11189       **keep,
11190       **list;
11191
11192     ExceptionInfo
11193       *exception;
11194
11195     HV
11196       *hv;
11197
11198     Image
11199       *image,
11200       *next;
11201
11202     int
11203       n;
11204
11205     long
11206       ac;
11207
11208     MagickBooleanType
11209       status;
11210
11211     register char
11212       **p;
11213
11214     register long
11215       i;
11216
11217     STRLEN
11218       *length;
11219
11220     struct PackageInfo
11221       *info,
11222       *package_info;
11223
11224     SV
11225       *perl_exception,
11226       *reference;
11227
11228     unsigned long
11229       count;
11230
11231     exception=AcquireExceptionInfo();
11232     perl_exception=newSVpv("",0);
11233     package_info=(struct PackageInfo *) NULL;
11234     ac=(items < 2) ? 1 : items-1;
11235     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11236     keep=list;
11237     length=(STRLEN *) NULL;
11238     if (list == (char **) NULL)
11239       {
11240         ThrowPerlException(exception,ResourceLimitError,
11241           "MemoryAllocationFailed",PackageName);
11242         goto PerlException;
11243       }
11244     keep=list;
11245     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11246     if (length == (STRLEN *) NULL)
11247       {
11248         ThrowPerlException(exception,ResourceLimitError,
11249           "MemoryAllocationFailed",PackageName);
11250         goto PerlException;
11251       }
11252     if (sv_isobject(ST(0)) == 0)
11253       {
11254         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11255           PackageName);
11256         goto PerlException;
11257       }
11258     reference=SvRV(ST(0));
11259     hv=SvSTASH(reference);
11260     if (SvTYPE(reference) != SVt_PVAV)
11261       {
11262         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11263           PackageName);
11264         goto PerlException;
11265       }
11266     av=(AV *) reference;
11267     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11268       exception);
11269     package_info=ClonePackageInfo(info,exception);
11270     n=1;
11271     if (items <= 1)
11272       *list=(char *) (*package_info->image_info->filename ?
11273         package_info->image_info->filename : "XC:black");
11274     else
11275       for (n=0, i=0; i < ac; i++)
11276       {
11277         list[n]=(char *) SvPV(ST(i+1),length[n]);
11278         if ((items >= 3) && strEQcase(list[n],"blob"))
11279           {
11280             void
11281               *blob;
11282
11283             i++;
11284             blob=(void *) (SvPV(ST(i+1),length[n]));
11285             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11286           }
11287         if ((items >= 3) && strEQcase(list[n],"filename"))
11288           continue;
11289         if ((items >= 3) && strEQcase(list[n],"file"))
11290           {
11291             FILE
11292               *file;
11293
11294             PerlIO
11295               *io_info;
11296
11297             i++;
11298             io_info=IoIFP(sv_2io(ST(i+1)));
11299             if (io_info == (PerlIO *) NULL)
11300               {
11301                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11302                   PackageName);
11303                 continue;
11304               }
11305             file=PerlIO_findFILE(io_info);
11306             if (file == (FILE *) NULL)
11307               {
11308                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11309                   PackageName);
11310                 continue;
11311               }
11312             SetImageInfoFile(package_info->image_info,file);
11313           }
11314         if ((items >= 3) && strEQcase(list[n],"magick"))
11315           continue;
11316         n++;
11317       }
11318     list[n]=(char *) NULL;
11319     keep=list;
11320     status=ExpandFilenames(&n,&list);
11321     if (status == MagickFalse)
11322       {
11323         ThrowPerlException(exception,ResourceLimitError,
11324           "MemoryAllocationFailed",PackageName);
11325         goto PerlException;
11326       }
11327     count=0;
11328     for (i=0; i < n; i++)
11329     {
11330       (void) CopyMagickString(package_info->image_info->filename,list[i],
11331         MaxTextExtent);
11332       image=PingImage(package_info->image_info,exception);
11333       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11334         break;
11335       if ((package_info->image_info->file != (FILE *) NULL) ||
11336           (package_info->image_info->blob != (void *) NULL))
11337         DisassociateImageStream(image);
11338       count+=GetImageListLength(image);
11339       EXTEND(sp,4*count);
11340       for (next=image; next; next=next->next)
11341       {
11342         PUSHs(sv_2mortal(newSViv(next->columns)));
11343         PUSHs(sv_2mortal(newSViv(next->rows)));
11344         PUSHs(sv_2mortal(newSViv((unsigned long) GetBlobSize(next))));
11345         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11346       }
11347       image=DestroyImageList(image);
11348     }
11349     /*
11350       Free resources.
11351     */
11352     for (i=0; i < n; i++)
11353       if (list[i] != (char *) NULL)
11354         for (p=keep; list[i] != *p++; )
11355           if (*p == NULL)
11356             {
11357               list[i]=(char *) RelinquishMagickMemory(list[i]);
11358               break;
11359             }
11360
11361   PerlException:
11362     if (package_info != (struct PackageInfo *) NULL)
11363       DestroyPackageInfo(package_info);
11364     if (list && (list != keep))
11365       list=(char **) RelinquishMagickMemory(list);
11366     if (keep)
11367       keep=(char **) RelinquishMagickMemory(keep);
11368     if (length)
11369       length=(STRLEN *) RelinquishMagickMemory(length);
11370     InheritPerlException(exception,perl_exception);
11371     exception=DestroyExceptionInfo(exception);
11372     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11373   }
11374 \f
11375 #
11376 ###############################################################################
11377 #                                                                             #
11378 #                                                                             #
11379 #                                                                             #
11380 #   P r e v i e w                                                             #
11381 #                                                                             #
11382 #                                                                             #
11383 #                                                                             #
11384 ###############################################################################
11385 #
11386 #
11387 void
11388 Preview(ref,...)
11389   Image::Magick ref=NO_INIT
11390   ALIAS:
11391     PreviewImage = 1
11392     preview      = 2
11393     previewimage = 3
11394   PPCODE:
11395   {
11396     AV
11397       *av;
11398
11399     ExceptionInfo
11400       *exception;
11401
11402     HV
11403       *hv;
11404
11405     Image
11406       *image,
11407       *preview_image;
11408
11409     PreviewType
11410       preview_type;
11411
11412     struct PackageInfo
11413       *info;
11414
11415     SV
11416       *av_reference,
11417       *perl_exception,
11418       *reference,
11419       *rv,
11420       *sv;
11421
11422     exception=AcquireExceptionInfo();
11423     perl_exception=newSVpv("",0);
11424     av=NULL;
11425     if (sv_isobject(ST(0)) == 0)
11426       {
11427         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11428           PackageName);
11429         goto PerlException;
11430       }
11431     reference=SvRV(ST(0));
11432     hv=SvSTASH(reference);
11433     av=newAV();
11434     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11435     SvREFCNT_dec(av);
11436     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11437     if (image == (Image *) NULL)
11438       {
11439         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11440           PackageName);
11441         goto PerlException;
11442       }
11443     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11444     preview_type=GammaPreview;
11445     if (items > 1)
11446       preview_type=(PreviewType)
11447         ParseMagickOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11448     for ( ; image; image=image->next)
11449     {
11450       preview_image=PreviewImage(image,preview_type,exception);
11451       if (preview_image == (Image *) NULL)
11452         goto PerlException;
11453       AddImageToRegistry(preview_image);
11454       rv=newRV(sv);
11455       av_push(av,sv_bless(rv,hv));
11456       SvREFCNT_dec(sv);
11457     }
11458     exception=DestroyExceptionInfo(exception);
11459     ST(0)=av_reference;
11460     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11461     XSRETURN(1);
11462
11463   PerlException:
11464     InheritPerlException(exception,perl_exception);
11465     exception=DestroyExceptionInfo(exception);
11466     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11467     SvPOK_on(perl_exception);
11468     ST(0)=sv_2mortal(perl_exception);
11469     XSRETURN(1);
11470   }
11471 \f
11472 #
11473 ###############################################################################
11474 #                                                                             #
11475 #                                                                             #
11476 #                                                                             #
11477 #   Q u e r y C o l o r                                                       #
11478 #                                                                             #
11479 #                                                                             #
11480 #                                                                             #
11481 ###############################################################################
11482 #
11483 #
11484 void
11485 QueryColor(ref,...)
11486   Image::Magick ref=NO_INIT
11487   ALIAS:
11488     querycolor = 1
11489   PPCODE:
11490   {
11491     char
11492       *name;
11493
11494     ExceptionInfo
11495       *exception;
11496
11497     MagickPixelPacket
11498       color;
11499
11500     register long
11501       i;
11502
11503     SV
11504       *perl_exception;
11505
11506     exception=AcquireExceptionInfo();
11507     perl_exception=newSVpv("",0);
11508     if (items == 1)
11509       {
11510         const ColorInfo
11511           **colorlist;
11512
11513         unsigned long
11514           colors;
11515
11516         colorlist=GetColorInfoList("*",&colors,exception);
11517         EXTEND(sp,colors);
11518         for (i=0; i < (long) colors; i++)
11519         {
11520           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11521         }
11522         colorlist=(const ColorInfo **)
11523           RelinquishMagickMemory((ColorInfo **) colorlist);
11524         goto PerlException;
11525       }
11526     EXTEND(sp,5*items);
11527     for (i=1; i < items; i++)
11528     {
11529       name=(char *) SvPV(ST(i),na);
11530       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11531         {
11532           PUSHs(&sv_undef);
11533           continue;
11534         }
11535       PUSHs(sv_2mortal(newSViv((unsigned long) floor(color.red+0.5))));
11536       PUSHs(sv_2mortal(newSViv((unsigned long) floor(color.green+0.5))));
11537       PUSHs(sv_2mortal(newSViv((unsigned long) floor(color.blue+0.5))));
11538       if (color.matte != MagickFalse)
11539         PUSHs(sv_2mortal(newSViv((unsigned long) floor(color.opacity+0.5))));
11540       if (color.colorspace == CMYKColorspace)
11541         PUSHs(sv_2mortal(newSViv((unsigned long) floor(color.index+0.5))));
11542     }
11543
11544   PerlException:
11545     InheritPerlException(exception,perl_exception);
11546     exception=DestroyExceptionInfo(exception);
11547     SvREFCNT_dec(perl_exception);
11548   }
11549 \f
11550 #
11551 ###############################################################################
11552 #                                                                             #
11553 #                                                                             #
11554 #                                                                             #
11555 #   Q u e r y C o l o r N a m e                                               #
11556 #                                                                             #
11557 #                                                                             #
11558 #                                                                             #
11559 ###############################################################################
11560 #
11561 #
11562 void
11563 QueryColorname(ref,...)
11564   Image::Magick ref=NO_INIT
11565   ALIAS:
11566     querycolorname = 1
11567   PPCODE:
11568   {
11569     AV
11570       *av;
11571
11572     char
11573       message[MaxTextExtent];
11574
11575     ExceptionInfo
11576       *exception;
11577
11578     Image
11579       *image;
11580
11581     PixelPacket
11582       target_color;
11583
11584     register long
11585       i;
11586
11587     struct PackageInfo
11588       *info;
11589
11590     SV
11591       *perl_exception,
11592       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11593
11594     exception=AcquireExceptionInfo();
11595     perl_exception=newSVpv("",0);
11596     reference=SvRV(ST(0));
11597     av=(AV *) reference;
11598     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11599       exception);
11600     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11601     if (image == (Image *) NULL)
11602       {
11603         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11604           PackageName);
11605         goto PerlException;
11606       }
11607     EXTEND(sp,items);
11608     for (i=1; i < items; i++)
11609     {
11610       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11611       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11612         exception);
11613       PUSHs(sv_2mortal(newSVpv(message,0)));
11614     }
11615
11616   PerlException:
11617     InheritPerlException(exception,perl_exception);
11618     exception=DestroyExceptionInfo(exception);
11619     SvREFCNT_dec(perl_exception);
11620   }
11621 \f
11622 #
11623 ###############################################################################
11624 #                                                                             #
11625 #                                                                             #
11626 #                                                                             #
11627 #   Q u e r y F o n t                                                         #
11628 #                                                                             #
11629 #                                                                             #
11630 #                                                                             #
11631 ###############################################################################
11632 #
11633 #
11634 void
11635 QueryFont(ref,...)
11636   Image::Magick ref=NO_INIT
11637   ALIAS:
11638     queryfont = 1
11639   PPCODE:
11640   {
11641     char
11642       *name,
11643       message[MaxTextExtent];
11644
11645     ExceptionInfo
11646       *exception;
11647
11648     register long
11649       i;
11650
11651     SV
11652       *perl_exception;
11653
11654     volatile const TypeInfo
11655       *type_info;
11656
11657     exception=AcquireExceptionInfo();
11658     perl_exception=newSVpv("",0);
11659     if (items == 1)
11660       {
11661         const TypeInfo
11662           **typelist;
11663
11664         unsigned long
11665           types;
11666
11667         typelist=GetTypeInfoList("*",&types,exception);
11668         EXTEND(sp,types);
11669         for (i=0; i < (long) types; i++)
11670         {
11671           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11672         }
11673         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11674           typelist);
11675         goto PerlException;
11676       }
11677     EXTEND(sp,10*items);
11678     for (i=1; i < items; i++)
11679     {
11680       name=(char *) SvPV(ST(i),na);
11681       type_info=GetTypeInfo(name,exception);
11682       if (type_info == (TypeInfo *) NULL)
11683         {
11684           PUSHs(&sv_undef);
11685           continue;
11686         }
11687       if (type_info->name == (char *) NULL)
11688         PUSHs(&sv_undef);
11689       else
11690         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11691       if (type_info->description == (char *) NULL)
11692         PUSHs(&sv_undef);
11693       else
11694         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11695       if (type_info->family == (char *) NULL)
11696         PUSHs(&sv_undef);
11697       else
11698         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11699       if (type_info->style == UndefinedStyle)
11700         PUSHs(&sv_undef);
11701       else
11702         PUSHs(sv_2mortal(newSVpv(MagickOptionToMnemonic(MagickStyleOptions,
11703           type_info->style),0)));
11704       if (type_info->stretch == UndefinedStretch)
11705         PUSHs(&sv_undef);
11706       else
11707         PUSHs(sv_2mortal(newSVpv(MagickOptionToMnemonic(MagickStretchOptions,
11708           type_info->stretch),0)));
11709       (void) FormatMagickString(message,MaxTextExtent,"%lu",type_info->weight);
11710       PUSHs(sv_2mortal(newSVpv(message,0)));
11711       if (type_info->encoding == (char *) NULL)
11712         PUSHs(&sv_undef);
11713       else
11714         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11715       if (type_info->foundry == (char *) NULL)
11716         PUSHs(&sv_undef);
11717       else
11718         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11719       if (type_info->format == (char *) NULL)
11720         PUSHs(&sv_undef);
11721       else
11722         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11723       if (type_info->metrics == (char *) NULL)
11724         PUSHs(&sv_undef);
11725       else
11726         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11727       if (type_info->glyphs == (char *) NULL)
11728         PUSHs(&sv_undef);
11729       else
11730         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11731     }
11732
11733   PerlException:
11734     InheritPerlException(exception,perl_exception);
11735     exception=DestroyExceptionInfo(exception);
11736     SvREFCNT_dec(perl_exception);
11737   }
11738 \f
11739 #
11740 ###############################################################################
11741 #                                                                             #
11742 #                                                                             #
11743 #                                                                             #
11744 #   Q u e r y F o n t M e t r i c s                                           #
11745 #                                                                             #
11746 #                                                                             #
11747 #                                                                             #
11748 ###############################################################################
11749 #
11750 #
11751 void
11752 QueryFontMetrics(ref,...)
11753   Image::Magick ref=NO_INIT
11754   ALIAS:
11755     queryfontmetrics = 1
11756   PPCODE:
11757   {
11758     AffineMatrix
11759       affine,
11760       current;
11761
11762     AV
11763       *av;
11764
11765     char
11766       *attribute;
11767
11768     double
11769       x,
11770       y;
11771
11772     DrawInfo
11773       *draw_info;
11774
11775     ExceptionInfo
11776       *exception;
11777
11778     GeometryInfo
11779       geometry_info;
11780
11781     Image
11782       *image;
11783
11784     long
11785       type;
11786
11787     MagickBooleanType
11788       status;
11789
11790     MagickStatusType
11791       flags;
11792
11793     register long
11794       i;
11795
11796     struct PackageInfo
11797       *info,
11798       *package_info;
11799
11800     SV
11801       *perl_exception,
11802       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11803
11804     TypeMetric
11805       metrics;
11806
11807     exception=AcquireExceptionInfo();
11808     package_info=(struct PackageInfo *) NULL;
11809     perl_exception=newSVpv("",0);
11810     reference=SvRV(ST(0));
11811     av=(AV *) reference;
11812     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11813       exception);
11814     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11815     if (image == (Image *) NULL)
11816       {
11817         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11818           PackageName);
11819         goto PerlException;
11820       }
11821     package_info=ClonePackageInfo(info,exception);
11822     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
11823     CloneString(&draw_info->text,"");
11824     current=draw_info->affine;
11825     GetAffineMatrix(&affine);
11826     x=0.0;
11827     y=0.0;
11828     EXTEND(sp,7*items);
11829     for (i=2; i < items; i+=2)
11830     {
11831       attribute=(char *) SvPV(ST(i-1),na);
11832       switch (*attribute)
11833       {
11834         case 'A':
11835         case 'a':
11836         {
11837           if (LocaleCompare(attribute,"antialias") == 0)
11838             {
11839               type=ParseMagickOption(MagickBooleanOptions,MagickFalse,
11840                 SvPV(ST(i),na));
11841               if (type < 0)
11842                 {
11843                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11844                     SvPV(ST(i),na));
11845                   break;
11846                 }
11847               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
11848               break;
11849             }
11850           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11851             attribute);
11852           break;
11853         }
11854         case 'd':
11855         case 'D':
11856         {
11857           if (LocaleCompare(attribute,"density") == 0)
11858             {
11859               CloneString(&draw_info->density,SvPV(ST(i),na));
11860               break;
11861             }
11862           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11863             attribute);
11864           break;
11865         }
11866         case 'e':
11867         case 'E':
11868         {
11869           if (LocaleCompare(attribute,"encoding") == 0)
11870             {
11871               CloneString(&draw_info->encoding,SvPV(ST(i),na));
11872               break;
11873             }
11874           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11875             attribute);
11876           break;
11877         }
11878         case 'f':
11879         case 'F':
11880         {
11881           if (LocaleCompare(attribute,"family") == 0)
11882             {
11883               CloneString(&draw_info->family,SvPV(ST(i),na));
11884               break;
11885             }
11886           if (LocaleCompare(attribute,"fill") == 0)
11887             {
11888               if (info)
11889                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
11890                   &image->exception);
11891               break;
11892             }
11893           if (LocaleCompare(attribute,"font") == 0)
11894             {
11895               CloneString(&draw_info->font,SvPV(ST(i),na));
11896               break;
11897             }
11898           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11899             attribute);
11900           break;
11901         }
11902         case 'g':
11903         case 'G':
11904         {
11905           if (LocaleCompare(attribute,"geometry") == 0)
11906             {
11907               CloneString(&draw_info->geometry,SvPV(ST(i),na));
11908               break;
11909             }
11910           if (LocaleCompare(attribute,"gravity") == 0)
11911             {
11912               draw_info->gravity=(GravityType) ParseMagickOption(
11913                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11914               break;
11915             }
11916           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11917             attribute);
11918           break;
11919         }
11920         case 'i':
11921         case 'I':
11922         {
11923           if (LocaleCompare(attribute,"interline-spacing") == 0)
11924             {
11925               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11926               draw_info->interline_spacing=geometry_info.rho;
11927               break;
11928             }
11929           if (LocaleCompare(attribute,"interword-spacing") == 0)
11930             {
11931               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11932               draw_info->interword_spacing=geometry_info.rho;
11933               break;
11934             }
11935           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11936             attribute);
11937           break;
11938         }
11939         case 'k':
11940         case 'K':
11941         {
11942           if (LocaleCompare(attribute,"kerning") == 0)
11943             {
11944               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11945               draw_info->kerning=geometry_info.rho;
11946               break;
11947             }
11948           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11949             attribute);
11950           break;
11951         }
11952         case 'p':
11953         case 'P':
11954         {
11955           if (LocaleCompare(attribute,"pointsize") == 0)
11956             {
11957               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11958               draw_info->pointsize=geometry_info.rho;
11959               break;
11960             }
11961           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11962             attribute);
11963           break;
11964         }
11965         case 'r':
11966         case 'R':
11967         {
11968           if (LocaleCompare(attribute,"rotate") == 0)
11969             {
11970               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11971               affine.rx=geometry_info.rho;
11972               affine.ry=geometry_info.sigma;
11973               if ((flags & SigmaValue) == 0)
11974                 affine.ry=affine.rx;
11975               break;
11976             }
11977           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11978             attribute);
11979           break;
11980         }
11981         case 's':
11982         case 'S':
11983         {
11984           if (LocaleCompare(attribute,"scale") == 0)
11985             {
11986               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11987               affine.sx=geometry_info.rho;
11988               affine.sy=geometry_info.sigma;
11989               if ((flags & SigmaValue) == 0)
11990                 affine.sy=affine.sx;
11991               break;
11992             }
11993           if (LocaleCompare(attribute,"skew") == 0)
11994             {
11995               double
11996                 x_angle,
11997                 y_angle;
11998
11999               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12000               x_angle=geometry_info.rho;
12001               y_angle=geometry_info.sigma;
12002               if ((flags & SigmaValue) == 0)
12003                 y_angle=x_angle;
12004               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12005               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12006               break;
12007             }
12008           if (LocaleCompare(attribute,"stroke") == 0)
12009             {
12010               if (info)
12011                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12012                   &image->exception);
12013               break;
12014             }
12015           if (LocaleCompare(attribute,"style") == 0)
12016             {
12017               type=ParseMagickOption(MagickStyleOptions,MagickFalse,
12018                 SvPV(ST(i),na));
12019               if (type < 0)
12020                 {
12021                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12022                     SvPV(ST(i),na));
12023                   break;
12024                 }
12025               draw_info->style=(StyleType) type;
12026               break;
12027             }
12028           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12029             attribute);
12030           break;
12031         }
12032         case 't':
12033         case 'T':
12034         {
12035           if (LocaleCompare(attribute,"text") == 0)
12036             {
12037               CloneString(&draw_info->text,SvPV(ST(i),na));
12038               break;
12039             }
12040           if (LocaleCompare(attribute,"translate") == 0)
12041             {
12042               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12043               affine.tx=geometry_info.rho;
12044               affine.ty=geometry_info.sigma;
12045               if ((flags & SigmaValue) == 0)
12046                 affine.ty=affine.tx;
12047               break;
12048             }
12049           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12050             attribute);
12051           break;
12052         }
12053         case 'w':
12054         case 'W':
12055         {
12056           if (LocaleCompare(attribute,"weight") == 0)
12057             {
12058               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12059               draw_info->weight=(unsigned long) geometry_info.rho;
12060               break;
12061             }
12062           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12063             attribute);
12064           break;
12065         }
12066         case 'x':
12067         case 'X':
12068         {
12069           if (LocaleCompare(attribute,"x") == 0)
12070             {
12071               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12072               x=geometry_info.rho;
12073               break;
12074             }
12075           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12076             attribute);
12077           break;
12078         }
12079         case 'y':
12080         case 'Y':
12081         {
12082           if (LocaleCompare(attribute,"y") == 0)
12083             {
12084               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12085               y=geometry_info.rho;
12086               break;
12087             }
12088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12089             attribute);
12090           break;
12091         }
12092         default:
12093         {
12094           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12095             attribute);
12096           break;
12097         }
12098       }
12099     }
12100     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12101     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12102     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12103     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12104     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12105     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12106     if (draw_info->geometry == (char *) NULL)
12107       {
12108         draw_info->geometry=AcquireString((char *) NULL);
12109         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
12110           "%.15g,%.15g",x,y);
12111       }
12112     status=GetTypeMetrics(image,draw_info,&metrics);
12113     (void) CatchImageException(image);
12114     if (status == MagickFalse)
12115       PUSHs(&sv_undef);
12116     else
12117       {
12118         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12119         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12120         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12121         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12122         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12123         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12124         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12125         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12126         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12127         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12128         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12129         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12130         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12131       }
12132     draw_info=DestroyDrawInfo(draw_info);
12133
12134   PerlException:
12135     if (package_info != (struct PackageInfo *) NULL)
12136       DestroyPackageInfo(package_info);
12137     InheritPerlException(exception,perl_exception);
12138     exception=DestroyExceptionInfo(exception);
12139     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12140   }
12141 \f
12142 #
12143 ###############################################################################
12144 #                                                                             #
12145 #                                                                             #
12146 #                                                                             #
12147 #   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                         #
12148 #                                                                             #
12149 #                                                                             #
12150 #                                                                             #
12151 ###############################################################################
12152 #
12153 #
12154 void
12155 QueryMultilineFontMetrics(ref,...)
12156   Image::Magick ref=NO_INIT
12157   ALIAS:
12158     querymultilinefontmetrics = 1
12159   PPCODE:
12160   {
12161     AffineMatrix
12162       affine,
12163       current;
12164
12165     AV
12166       *av;
12167
12168     char
12169       *attribute;
12170
12171     double
12172       x,
12173       y;
12174
12175     DrawInfo
12176       *draw_info;
12177
12178     ExceptionInfo
12179       *exception;
12180
12181     GeometryInfo
12182       geometry_info;
12183
12184     Image
12185       *image;
12186
12187     long
12188       type;
12189
12190     MagickBooleanType
12191       status;
12192
12193     MagickStatusType
12194       flags;
12195
12196     register long
12197       i;
12198
12199     struct PackageInfo
12200       *info,
12201       *package_info;
12202
12203     SV
12204       *perl_exception,
12205       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12206
12207     TypeMetric
12208       metrics;
12209
12210     exception=AcquireExceptionInfo();
12211     package_info=(struct PackageInfo *) NULL;
12212     perl_exception=newSVpv("",0);
12213     reference=SvRV(ST(0));
12214     av=(AV *) reference;
12215     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12216       exception);
12217     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12218     if (image == (Image *) NULL)
12219       {
12220         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12221           PackageName);
12222         goto PerlException;
12223       }
12224     package_info=ClonePackageInfo(info,exception);
12225     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12226     CloneString(&draw_info->text,"");
12227     current=draw_info->affine;
12228     GetAffineMatrix(&affine);
12229     x=0.0;
12230     y=0.0;
12231     EXTEND(sp,7*items);
12232     for (i=2; i < items; i+=2)
12233     {
12234       attribute=(char *) SvPV(ST(i-1),na);
12235       switch (*attribute)
12236       {
12237         case 'A':
12238         case 'a':
12239         {
12240           if (LocaleCompare(attribute,"antialias") == 0)
12241             {
12242               type=ParseMagickOption(MagickBooleanOptions,MagickFalse,
12243                 SvPV(ST(i),na));
12244               if (type < 0)
12245                 {
12246                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12247                     SvPV(ST(i),na));
12248                   break;
12249                 }
12250               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12251               break;
12252             }
12253           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12254             attribute);
12255           break;
12256         }
12257         case 'd':
12258         case 'D':
12259         {
12260           if (LocaleCompare(attribute,"density") == 0)
12261             {
12262               CloneString(&draw_info->density,SvPV(ST(i),na));
12263               break;
12264             }
12265           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12266             attribute);
12267           break;
12268         }
12269         case 'e':
12270         case 'E':
12271         {
12272           if (LocaleCompare(attribute,"encoding") == 0)
12273             {
12274               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12275               break;
12276             }
12277           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12278             attribute);
12279           break;
12280         }
12281         case 'f':
12282         case 'F':
12283         {
12284           if (LocaleCompare(attribute,"family") == 0)
12285             {
12286               CloneString(&draw_info->family,SvPV(ST(i),na));
12287               break;
12288             }
12289           if (LocaleCompare(attribute,"fill") == 0)
12290             {
12291               if (info)
12292                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12293                   &image->exception);
12294               break;
12295             }
12296           if (LocaleCompare(attribute,"font") == 0)
12297             {
12298               CloneString(&draw_info->font,SvPV(ST(i),na));
12299               break;
12300             }
12301           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12302             attribute);
12303           break;
12304         }
12305         case 'g':
12306         case 'G':
12307         {
12308           if (LocaleCompare(attribute,"geometry") == 0)
12309             {
12310               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12311               break;
12312             }
12313           if (LocaleCompare(attribute,"gravity") == 0)
12314             {
12315               draw_info->gravity=(GravityType) ParseMagickOption(
12316                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12317               break;
12318             }
12319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12320             attribute);
12321           break;
12322         }
12323         case 'p':
12324         case 'P':
12325         {
12326           if (LocaleCompare(attribute,"pointsize") == 0)
12327             {
12328               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12329               draw_info->pointsize=geometry_info.rho;
12330               break;
12331             }
12332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12333             attribute);
12334           break;
12335         }
12336         case 'r':
12337         case 'R':
12338         {
12339           if (LocaleCompare(attribute,"rotate") == 0)
12340             {
12341               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12342               affine.rx=geometry_info.rho;
12343               affine.ry=geometry_info.sigma;
12344               if ((flags & SigmaValue) == 0)
12345                 affine.ry=affine.rx;
12346               break;
12347             }
12348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12349             attribute);
12350           break;
12351         }
12352         case 's':
12353         case 'S':
12354         {
12355           if (LocaleCompare(attribute,"scale") == 0)
12356             {
12357               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12358               affine.sx=geometry_info.rho;
12359               affine.sy=geometry_info.sigma;
12360               if ((flags & SigmaValue) == 0)
12361                 affine.sy=affine.sx;
12362               break;
12363             }
12364           if (LocaleCompare(attribute,"skew") == 0)
12365             {
12366               double
12367                 x_angle,
12368                 y_angle;
12369
12370               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12371               x_angle=geometry_info.rho;
12372               y_angle=geometry_info.sigma;
12373               if ((flags & SigmaValue) == 0)
12374                 y_angle=x_angle;
12375               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12376               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12377               break;
12378             }
12379           if (LocaleCompare(attribute,"stroke") == 0)
12380             {
12381               if (info)
12382                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12383                   &image->exception);
12384               break;
12385             }
12386           if (LocaleCompare(attribute,"style") == 0)
12387             {
12388               type=ParseMagickOption(MagickStyleOptions,MagickFalse,
12389                 SvPV(ST(i),na));
12390               if (type < 0)
12391                 {
12392                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12393                     SvPV(ST(i),na));
12394                   break;
12395                 }
12396               draw_info->style=(StyleType) type;
12397               break;
12398             }
12399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12400             attribute);
12401           break;
12402         }
12403         case 't':
12404         case 'T':
12405         {
12406           if (LocaleCompare(attribute,"text") == 0)
12407             {
12408               CloneString(&draw_info->text,SvPV(ST(i),na));
12409               break;
12410             }
12411           if (LocaleCompare(attribute,"translate") == 0)
12412             {
12413               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12414               affine.tx=geometry_info.rho;
12415               affine.ty=geometry_info.sigma;
12416               if ((flags & SigmaValue) == 0)
12417                 affine.ty=affine.tx;
12418               break;
12419             }
12420           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12421             attribute);
12422           break;
12423         }
12424         case 'w':
12425         case 'W':
12426         {
12427           if (LocaleCompare(attribute,"weight") == 0)
12428             {
12429               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12430               draw_info->weight=(unsigned long) geometry_info.rho;
12431               break;
12432             }
12433           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12434             attribute);
12435           break;
12436         }
12437         case 'x':
12438         case 'X':
12439         {
12440           if (LocaleCompare(attribute,"x") == 0)
12441             {
12442               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12443               x=geometry_info.rho;
12444               break;
12445             }
12446           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12447             attribute);
12448           break;
12449         }
12450         case 'y':
12451         case 'Y':
12452         {
12453           if (LocaleCompare(attribute,"y") == 0)
12454             {
12455               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12456               y=geometry_info.rho;
12457               break;
12458             }
12459           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12460             attribute);
12461           break;
12462         }
12463         default:
12464         {
12465           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12466             attribute);
12467           break;
12468         }
12469       }
12470     }
12471     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12472     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12473     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12474     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12475     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12476     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12477     if (draw_info->geometry == (char *) NULL)
12478       {
12479         draw_info->geometry=AcquireString((char *) NULL);
12480         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
12481           "%.15g,%.15g",x,y);
12482       }
12483     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12484     (void) CatchImageException(image);
12485     if (status == MagickFalse)
12486       PUSHs(&sv_undef);
12487     else
12488       {
12489         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12490         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12491         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12492         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12493         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12494         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12495         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12496         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12497         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12498         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12499         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12500         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12501         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12502       }
12503     draw_info=DestroyDrawInfo(draw_info);
12504
12505   PerlException:
12506     if (package_info != (struct PackageInfo *) NULL)
12507       DestroyPackageInfo(package_info);
12508     InheritPerlException(exception,perl_exception);
12509     exception=DestroyExceptionInfo(exception);
12510     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12511   }
12512 \f
12513 #
12514 ###############################################################################
12515 #                                                                             #
12516 #                                                                             #
12517 #                                                                             #
12518 #   Q u e r y F o r m a t                                                     #
12519 #                                                                             #
12520 #                                                                             #
12521 #                                                                             #
12522 ###############################################################################
12523 #
12524 #
12525 void
12526 QueryFormat(ref,...)
12527   Image::Magick ref=NO_INIT
12528   ALIAS:
12529     queryformat = 1
12530   PPCODE:
12531   {
12532     char
12533       *name;
12534
12535     ExceptionInfo
12536       *exception;
12537
12538     register long
12539       i;
12540
12541     SV
12542       *perl_exception;
12543
12544     volatile const MagickInfo
12545       *magick_info;
12546
12547     exception=AcquireExceptionInfo();
12548     perl_exception=newSVpv("",0);
12549     if (items == 1)
12550       {
12551         char
12552           format[MaxTextExtent];
12553
12554         const MagickInfo
12555           **format_list;
12556
12557         unsigned long
12558           types;
12559
12560         format_list=GetMagickInfoList("*",&types,exception);
12561         EXTEND(sp,types);
12562         for (i=0; i < (long) types; i++)
12563         {
12564           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12565           LocaleLower(format);
12566           PUSHs(sv_2mortal(newSVpv(format,0)));
12567         }
12568         format_list=(const MagickInfo **)
12569           RelinquishMagickMemory((MagickInfo *) format_list);
12570         goto PerlException;
12571       }
12572     EXTEND(sp,8*items);
12573     for (i=1; i < items; i++)
12574     {
12575       name=(char *) SvPV(ST(i),na);
12576       magick_info=GetMagickInfo(name,exception);
12577       if (magick_info == (const MagickInfo *) NULL)
12578         {
12579           PUSHs(&sv_undef);
12580           continue;
12581         }
12582       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12583       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12584       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12585       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12586       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12587       if (magick_info->description == (char *) NULL)
12588         PUSHs(&sv_undef);
12589       else
12590         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12591       if (magick_info->module == (char *) NULL)
12592         PUSHs(&sv_undef);
12593       else
12594         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12595     }
12596
12597   PerlException:
12598     InheritPerlException(exception,perl_exception);
12599     exception=DestroyExceptionInfo(exception);
12600     SvREFCNT_dec(perl_exception);
12601   }
12602 \f
12603 #
12604 ###############################################################################
12605 #                                                                             #
12606 #                                                                             #
12607 #                                                                             #
12608 #   Q u e r y O p t i o n                                                     #
12609 #                                                                             #
12610 #                                                                             #
12611 #                                                                             #
12612 ###############################################################################
12613 #
12614 #
12615 void
12616 QueryOption(ref,...)
12617   Image::Magick ref=NO_INIT
12618   ALIAS:
12619     queryoption = 1
12620   PPCODE:
12621   {
12622     char
12623       **options;
12624
12625     ExceptionInfo
12626       *exception;
12627
12628     long
12629       j,
12630       option;
12631
12632     register long
12633       i;
12634
12635     SV
12636       *perl_exception;
12637
12638     exception=AcquireExceptionInfo();
12639     perl_exception=newSVpv("",0);
12640     EXTEND(sp,8*items);
12641     for (i=1; i < items; i++)
12642     {
12643       option=ParseMagickOption(MagickListOptions,MagickFalse,(char *)
12644         SvPV(ST(i),na));
12645       options=GetMagickOptions((MagickOption) option);
12646       if (options == (char **) NULL)
12647         PUSHs(&sv_undef);
12648       else
12649         {
12650           for (j=0; options[j] != (char *) NULL; j++)
12651             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12652           options=DestroyStringList(options);
12653         }
12654     }
12655
12656   PerlException:
12657     InheritPerlException(exception,perl_exception);
12658     exception=DestroyExceptionInfo(exception);
12659     SvREFCNT_dec(perl_exception);
12660   }
12661 \f
12662 #
12663 ###############################################################################
12664 #                                                                             #
12665 #                                                                             #
12666 #                                                                             #
12667 #   R e a d                                                                   #
12668 #                                                                             #
12669 #                                                                             #
12670 #                                                                             #
12671 ###############################################################################
12672 #
12673 #
12674 void
12675 Read(ref,...)
12676   Image::Magick ref=NO_INIT
12677   ALIAS:
12678     ReadImage  = 1
12679     read       = 2
12680     readimage  = 3
12681   PPCODE:
12682   {
12683     AV
12684       *av;
12685
12686     char
12687       **keep,
12688       **list;
12689
12690     ExceptionInfo
12691       *exception;
12692
12693     HV
12694       *hv;
12695
12696     Image
12697       *image;
12698
12699     int
12700       n;
12701
12702     long
12703       ac,
12704       number_images;
12705
12706     MagickBooleanType
12707       status;
12708
12709     register char
12710       **p;
12711
12712     register long
12713       i;
12714
12715     STRLEN
12716       *length;
12717
12718     struct PackageInfo
12719       *info,
12720       *package_info;
12721
12722     SV
12723       *perl_exception,  /* Perl variable for storing messages */
12724       *reference,
12725       *rv,
12726       *sv;
12727
12728     exception=AcquireExceptionInfo();
12729     perl_exception=newSVpv("",0);
12730     package_info=(struct PackageInfo *) NULL;
12731     number_images=0;
12732     ac=(items < 2) ? 1 : items-1;
12733     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12734     keep=list;
12735     length=(STRLEN *) NULL;
12736     if (list == (char **) NULL)
12737       {
12738         ThrowPerlException(exception,ResourceLimitError,
12739           "MemoryAllocationFailed",PackageName);
12740         goto PerlException;
12741       }
12742     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12743     if (length == (STRLEN *) NULL)
12744       {
12745         ThrowPerlException(exception,ResourceLimitError,
12746           "MemoryAllocationFailed",PackageName);
12747         goto PerlException;
12748       }
12749     if (sv_isobject(ST(0)) == 0)
12750       {
12751         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12752           PackageName);
12753         goto PerlException;
12754       }
12755     reference=SvRV(ST(0));
12756     hv=SvSTASH(reference);
12757     if (SvTYPE(reference) != SVt_PVAV)
12758       {
12759         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12760           PackageName);
12761         goto PerlException;
12762       }
12763     av=(AV *) reference;
12764     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12765       exception);
12766     package_info=ClonePackageInfo(info,exception);
12767     n=1;
12768     if (items <= 1)
12769       *list=(char *) (*package_info->image_info->filename ?
12770         package_info->image_info->filename : "XC:black");
12771     else
12772       for (n=0, i=0; i < ac; i++)
12773       {
12774         list[n]=(char *) SvPV(ST(i+1),length[n]);
12775         if ((items >= 3) && strEQcase(list[n],"blob"))
12776           {
12777             void
12778               *blob;
12779
12780             i++;
12781             blob=(void *) (SvPV(ST(i+1),length[n]));
12782             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12783           }
12784         if ((items >= 3) && strEQcase(list[n],"filename"))
12785           continue;
12786         if ((items >= 3) && strEQcase(list[n],"file"))
12787           {
12788             FILE
12789               *file;
12790
12791             PerlIO
12792               *io_info;
12793
12794             i++;
12795             io_info=IoIFP(sv_2io(ST(i+1)));
12796             if (io_info == (PerlIO *) NULL)
12797               {
12798                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12799                   PackageName);
12800                 continue;
12801               }
12802             file=PerlIO_findFILE(io_info);
12803             if (file == (FILE *) NULL)
12804               {
12805                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12806                   PackageName);
12807                 continue;
12808               }
12809             SetImageInfoFile(package_info->image_info,file);
12810           }
12811         if ((items >= 3) && strEQcase(list[n],"magick"))
12812           continue;
12813         n++;
12814       }
12815     list[n]=(char *) NULL;
12816     keep=list;
12817     status=ExpandFilenames(&n,&list);
12818     if (status == MagickFalse)
12819       {
12820         ThrowPerlException(exception,ResourceLimitError,
12821           "MemoryAllocationFailed",PackageName);
12822         goto PerlException;
12823       }
12824     number_images=0;
12825     for (i=0; i < n; i++)
12826     {
12827       if ((package_info->image_info->file != (FILE *) NULL) ||
12828           (package_info->image_info->blob != (void *) NULL))
12829         {
12830           image=ReadImages(package_info->image_info,exception);
12831           if (image != (Image *) NULL)
12832             DisassociateImageStream(image);
12833         }
12834       else
12835         {
12836           (void) CopyMagickString(package_info->image_info->filename,list[i],
12837             MaxTextExtent);
12838           image=ReadImages(package_info->image_info,exception);
12839         }
12840       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
12841         break;
12842       for ( ; image; image=image->next)
12843       {
12844         AddImageToRegistry(image);
12845         rv=newRV(sv);
12846         av_push(av,sv_bless(rv,hv));
12847         SvREFCNT_dec(sv);
12848         number_images++;
12849       }
12850     }
12851     /*
12852       Free resources.
12853     */
12854     for (i=0; i < n; i++)
12855       if (list[i] != (char *) NULL)
12856         for (p=keep; list[i] != *p++; )
12857           if (*p == (char *) NULL)
12858             {
12859               list[i]=(char *) RelinquishMagickMemory(list[i]);
12860               break;
12861             }
12862
12863   PerlException:
12864     if (package_info != (struct PackageInfo *) NULL)
12865       DestroyPackageInfo(package_info);
12866     if (list && (list != keep))
12867       list=(char **) RelinquishMagickMemory(list);
12868     if (keep)
12869       keep=(char **) RelinquishMagickMemory(keep);
12870     if (length)
12871       length=(STRLEN *) RelinquishMagickMemory(length);
12872     InheritPerlException(exception,perl_exception);
12873     exception=DestroyExceptionInfo(exception);
12874     sv_setiv(perl_exception,(IV) number_images);
12875     SvPOK_on(perl_exception);
12876     ST(0)=sv_2mortal(perl_exception);
12877     XSRETURN(1);
12878   }
12879 \f
12880 #
12881 ###############################################################################
12882 #                                                                             #
12883 #                                                                             #
12884 #                                                                             #
12885 #   R e m o t e                                                               #
12886 #                                                                             #
12887 #                                                                             #
12888 #                                                                             #
12889 ###############################################################################
12890 #
12891 #
12892 void
12893 Remote(ref,...)
12894   Image::Magick ref=NO_INIT
12895   ALIAS:
12896     RemoteCommand  = 1
12897     remote         = 2
12898     remoteCommand  = 3
12899   PPCODE:
12900   {
12901     AV
12902       *av;
12903
12904     ExceptionInfo
12905       *exception;
12906
12907     register long
12908       i;
12909
12910     SV
12911       *perl_exception,
12912       *reference;
12913
12914     struct PackageInfo
12915       *info;
12916
12917     exception=AcquireExceptionInfo();
12918     perl_exception=newSVpv("",0);
12919     reference=SvRV(ST(0));
12920     av=(AV *) reference;
12921     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12922       exception);
12923     for (i=1; i < items; i++)
12924       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
12925         SvPV(ST(i),na),exception);
12926     InheritPerlException(exception,perl_exception);
12927     exception=DestroyExceptionInfo(exception);
12928     SvREFCNT_dec(perl_exception);    /* throw away all errors */
12929   }
12930 \f
12931 #
12932 ###############################################################################
12933 #                                                                             #
12934 #                                                                             #
12935 #                                                                             #
12936 #   S e t                                                                     #
12937 #                                                                             #
12938 #                                                                             #
12939 #                                                                             #
12940 ###############################################################################
12941 #
12942 #
12943 void
12944 Set(ref,...)
12945   Image::Magick ref=NO_INIT
12946   ALIAS:
12947     SetAttributes  = 1
12948     SetAttribute   = 2
12949     set            = 3
12950     setattributes  = 4
12951     setattribute   = 5
12952   PPCODE:
12953   {
12954     ExceptionInfo
12955       *exception;
12956
12957     Image
12958       *image;
12959
12960     register long
12961       i;
12962
12963     struct PackageInfo
12964       *info;
12965
12966     SV
12967       *perl_exception,
12968       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12969
12970     exception=AcquireExceptionInfo();
12971     perl_exception=newSVpv("",0);
12972     if (sv_isobject(ST(0)) == 0)
12973       {
12974         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12975           PackageName);
12976         goto PerlException;
12977       }
12978     reference=SvRV(ST(0));
12979     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12980     if (items == 2)
12981       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
12982     else
12983       for (i=2; i < items; i+=2)
12984         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
12985
12986   PerlException:
12987     InheritPerlException(exception,perl_exception);
12988     exception=DestroyExceptionInfo(exception);
12989     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
12990     SvPOK_on(perl_exception);
12991     ST(0)=sv_2mortal(perl_exception);
12992     XSRETURN(1);
12993   }
12994 \f
12995 #
12996 ###############################################################################
12997 #                                                                             #
12998 #                                                                             #
12999 #                                                                             #
13000 #   S e t P i x e l                                                           #
13001 #                                                                             #
13002 #                                                                             #
13003 #                                                                             #
13004 ###############################################################################
13005 #
13006 #
13007 void
13008 SetPixel(ref,...)
13009   Image::Magick ref=NO_INIT
13010   ALIAS:
13011     setpixel = 1
13012     setPixel = 2
13013   PPCODE:
13014   {
13015     AV
13016       *av;
13017
13018     char
13019       *attribute;
13020
13021     ChannelType
13022       channel;
13023
13024     ExceptionInfo
13025       *exception;
13026
13027     Image
13028       *image;
13029
13030     long
13031       option;
13032
13033     MagickBooleanType
13034       normalize;
13035
13036     RectangleInfo
13037       region;
13038
13039     register IndexPacket
13040       *indexes;
13041
13042     register long
13043       i;
13044
13045     register PixelPacket
13046       *q;
13047
13048     struct PackageInfo
13049       *info;
13050
13051     SV
13052       *perl_exception,
13053       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13054
13055     exception=AcquireExceptionInfo();
13056     perl_exception=newSVpv("",0);
13057     reference=SvRV(ST(0));
13058     av=(AV *) reference;
13059     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13060       exception);
13061     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13062     if (image == (Image *) NULL)
13063       {
13064         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13065           PackageName);
13066         goto PerlException;
13067       }
13068     av=(AV *) NULL;
13069     channel=DefaultChannels;
13070     normalize=MagickTrue;
13071     region.x=0;
13072     region.y=0;
13073     region.width=image->columns;
13074     region.height=1;
13075     if (items == 1)
13076       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13077     for (i=2; i < items; i+=2)
13078     {
13079       attribute=(char *) SvPV(ST(i-1),na);
13080       switch (*attribute)
13081       {
13082         case 'C':
13083         case 'c':
13084         {
13085           if (LocaleCompare(attribute,"channel") == 0)
13086             {
13087               long
13088                 option;
13089
13090               option=ParseChannelOption(SvPV(ST(i),na));
13091               if (option < 0)
13092                 {
13093                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13094                     SvPV(ST(i),na));
13095                   return;
13096                 }
13097                channel=(ChannelType) option;
13098               break;
13099             }
13100           if (LocaleCompare(attribute,"color") == 0)
13101             {
13102               if (SvTYPE(ST(i)) != SVt_RV)
13103                 {
13104                   char
13105                     message[MaxTextExtent];
13106
13107                   (void) FormatMagickString(message,MaxTextExtent,
13108                     "invalid %.60s value",attribute);
13109                   ThrowPerlException(exception,OptionError,message,
13110                     SvPV(ST(i),na));
13111                 }
13112               av=(AV *) SvRV(ST(i));
13113               break;
13114             }
13115           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13116             attribute);
13117           break;
13118         }
13119         case 'g':
13120         case 'G':
13121         {
13122           if (LocaleCompare(attribute,"geometry") == 0)
13123             {
13124               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13125               break;
13126             }
13127           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13128             attribute);
13129           break;
13130         }
13131         case 'N':
13132         case 'n':
13133         {
13134           if (LocaleCompare(attribute,"normalize") == 0)
13135             {
13136               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
13137                 SvPV(ST(i),na));
13138               if (option < 0)
13139                 {
13140                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13141                     SvPV(ST(i),na));
13142                   break;
13143                 }
13144              normalize=option != 0 ? MagickTrue : MagickFalse;
13145              break;
13146             }
13147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13148             attribute);
13149           break;
13150         }
13151         case 'x':
13152         case 'X':
13153         {
13154           if (LocaleCompare(attribute,"x") == 0)
13155             {
13156               region.x=SvIV(ST(i));
13157               break;
13158             }
13159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13160             attribute);
13161           break;
13162         }
13163         case 'y':
13164         case 'Y':
13165         {
13166           if (LocaleCompare(attribute,"y") == 0)
13167             {
13168               region.y=SvIV(ST(i));
13169               break;
13170             }
13171           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13172             attribute);
13173           break;
13174         }
13175         default:
13176         {
13177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13178             attribute);
13179           break;
13180         }
13181       }
13182     }
13183     (void) SetImageStorageClass(image,DirectClass);
13184     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13185     if ((q == (PixelPacket *) NULL) || (av == (AV *) NULL))
13186       PUSHs(&sv_undef);
13187     else
13188       {
13189         double
13190           scale;
13191
13192         register long
13193           i;
13194
13195         i=0;
13196         indexes=GetAuthenticIndexQueue(image);
13197         scale=1.0;
13198         if (normalize != MagickFalse)
13199           scale=QuantumRange;
13200         if (((channel & RedChannel) != 0) && (i <= av_len(av)))
13201           {
13202             q->red=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13203             i++;
13204           }
13205         if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
13206           {
13207             q->green=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13208             i++;
13209           }
13210         if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
13211           {
13212             q->blue=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13213             i++;
13214           }
13215         if ((((channel & IndexChannel) != 0) &&
13216             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13217           {
13218             *indexes=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13219             i++;
13220           }
13221         if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
13222           {
13223             q->opacity=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13224             i++;
13225           }
13226         (void) SyncAuthenticPixels(image,exception);
13227       }
13228
13229   PerlException:
13230     InheritPerlException(exception,perl_exception);
13231     exception=DestroyExceptionInfo(exception);
13232     SvREFCNT_dec(perl_exception);
13233   }
13234 \f
13235 #
13236 ###############################################################################
13237 #                                                                             #
13238 #                                                                             #
13239 #                                                                             #
13240 #   S t a t i s t i c s                                                       #
13241 #                                                                             #
13242 #                                                                             #
13243 #                                                                             #
13244 ###############################################################################
13245 #
13246 #
13247 void
13248 Statistics(ref,...)
13249   Image::Magick ref=NO_INIT
13250   ALIAS:
13251     StatisticsImage = 1
13252     statistics      = 2
13253     statisticsimage = 3
13254   PPCODE:
13255   {
13256 #define ChannelStatistics(channel) \
13257 { \
13258   (void) FormatMagickString(message,MaxTextExtent,"%lu", \
13259     channel_statistics[channel].depth); \
13260   PUSHs(sv_2mortal(newSVpv(message,0))); \
13261   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13262     channel_statistics[channel].minima/scale); \
13263   PUSHs(sv_2mortal(newSVpv(message,0))); \
13264   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13265     channel_statistics[channel].maxima/scale); \
13266   PUSHs(sv_2mortal(newSVpv(message,0))); \
13267   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13268     channel_statistics[channel].mean/scale); \
13269   PUSHs(sv_2mortal(newSVpv(message,0))); \
13270   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13271     channel_statistics[channel].standard_deviation/scale); \
13272   PUSHs(sv_2mortal(newSVpv(message,0))); \
13273   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13274     channel_statistics[channel].kurtosis); \
13275   PUSHs(sv_2mortal(newSVpv(message,0))); \
13276   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13277     channel_statistics[channel].skewness); \
13278   PUSHs(sv_2mortal(newSVpv(message,0))); \
13279 }
13280
13281     AV
13282       *av;
13283
13284     char
13285       message[MaxTextExtent];
13286
13287     ChannelStatistics
13288       *channel_statistics;
13289
13290     double
13291       scale;
13292
13293     ExceptionInfo
13294       *exception;
13295
13296     HV
13297       *hv;
13298
13299     Image
13300       *image;
13301
13302     ssize_t
13303       count;
13304
13305     struct PackageInfo
13306       *info;
13307
13308     SV
13309       *av_reference,
13310       *perl_exception,
13311       *reference;
13312
13313     exception=AcquireExceptionInfo();
13314     perl_exception=newSVpv("",0);
13315     av=NULL;
13316     if (sv_isobject(ST(0)) == 0)
13317       {
13318         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13319           PackageName);
13320         goto PerlException;
13321       }
13322     reference=SvRV(ST(0));
13323     hv=SvSTASH(reference);
13324     av=newAV();
13325     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13326     SvREFCNT_dec(av);
13327     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13328     if (image == (Image *) NULL)
13329       {
13330         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13331           PackageName);
13332         goto PerlException;
13333       }
13334     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13335     count=0;
13336     for ( ; image; image=image->next)
13337     {
13338       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13339       if (channel_statistics == (ChannelStatistics *) NULL)
13340         continue;
13341       count++;
13342       EXTEND(sp,35*count);
13343       scale=(double) QuantumRange;
13344       ChannelStatistics(RedChannel);
13345       ChannelStatistics(GreenChannel);
13346       ChannelStatistics(BlueChannel);
13347       if (image->colorspace == CMYKColorspace)
13348         ChannelStatistics(IndexChannel);
13349       if (image->matte != MagickFalse)
13350         ChannelStatistics(OpacityChannel);
13351       channel_statistics=(ChannelStatistics *)
13352         RelinquishMagickMemory(channel_statistics);
13353     }
13354
13355   PerlException:
13356     InheritPerlException(exception,perl_exception);
13357     exception=DestroyExceptionInfo(exception);
13358     SvREFCNT_dec(perl_exception);
13359   }
13360 \f
13361 #
13362 ###############################################################################
13363 #                                                                             #
13364 #                                                                             #
13365 #                                                                             #
13366 #   S y n c A u t h e n t i c P i x e l s                                     #
13367 #                                                                             #
13368 #                                                                             #
13369 #                                                                             #
13370 ###############################################################################
13371 #
13372 #
13373 void
13374 SyncAuthenticPixels(ref,...)
13375   Image::Magick ref = NO_INIT
13376   ALIAS:
13377     Syncauthenticpixels = 1
13378     SyncImagePixels = 2
13379     syncimagepixels = 3
13380   CODE:
13381   {
13382     ExceptionInfo
13383       *exception;
13384
13385     Image
13386       *image;
13387
13388     MagickBooleanType
13389       status;
13390
13391     struct PackageInfo
13392       *info;
13393
13394     SV
13395       *perl_exception,
13396       *reference;
13397
13398     exception=AcquireExceptionInfo();
13399     perl_exception=newSVpv("",0);
13400
13401     if (sv_isobject(ST(0)) == 0)
13402       {
13403         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13404           PackageName);
13405         goto PerlException;
13406       }
13407
13408     reference=SvRV(ST(0));
13409     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13410     if (image == (Image *) NULL)
13411       {
13412         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13413           PackageName);
13414         goto PerlException;
13415       }
13416
13417     status=SyncAuthenticPixels(image,exception);
13418     if (status != MagickFalse)
13419       return;
13420     InheritException(exception,&image->exception);
13421
13422   PerlException:
13423     InheritPerlException(exception,perl_exception);
13424     exception=DestroyExceptionInfo(exception);
13425     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13426   }
13427 \f
13428 #
13429 ###############################################################################
13430 #                                                                             #
13431 #                                                                             #
13432 #                                                                             #
13433 #   T r a n s f o r m                                                         #
13434 #                                                                             #
13435 #                                                                             #
13436 #                                                                             #
13437 ###############################################################################
13438 #
13439 #
13440 void
13441 Transform(ref,...)
13442   Image::Magick ref=NO_INIT
13443   ALIAS:
13444     TransformImage = 1
13445     transform      = 2
13446     transformimage = 3
13447   PPCODE:
13448   {
13449     AV
13450       *av;
13451
13452     char
13453       *attribute,
13454       *crop_geometry,
13455       *geometry;
13456
13457     ExceptionInfo
13458       *exception;
13459
13460     HV
13461       *hv;
13462
13463     Image
13464       *clone,
13465       *image;
13466
13467     register long
13468       i;
13469
13470     struct PackageInfo
13471       *info;
13472
13473     SV
13474       *av_reference,
13475       *perl_exception,
13476       *reference,
13477       *rv,
13478       *sv;
13479
13480     exception=AcquireExceptionInfo();
13481     perl_exception=newSVpv("",0);
13482     av=NULL;
13483     attribute=NULL;
13484     if (sv_isobject(ST(0)) == 0)
13485       {
13486         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13487           PackageName);
13488         goto PerlException;
13489       }
13490     reference=SvRV(ST(0));
13491     hv=SvSTASH(reference);
13492     av=newAV();
13493     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13494     SvREFCNT_dec(av);
13495     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13496     if (image == (Image *) NULL)
13497       {
13498         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13499           PackageName);
13500         goto PerlException;
13501       }
13502     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13503     /*
13504       Get attribute.
13505     */
13506     crop_geometry=(char *) NULL;
13507     geometry=(char *) NULL;
13508     for (i=2; i < items; i+=2)
13509     {
13510       attribute=(char *) SvPV(ST(i-1),na);
13511       switch (*attribute)
13512       {
13513         case 'c':
13514         case 'C':
13515         {
13516           if (LocaleCompare(attribute,"crop") == 0)
13517             {
13518               crop_geometry=SvPV(ST(i),na);
13519               break;
13520             }
13521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13522             attribute);
13523           break;
13524         }
13525         case 'g':
13526         case 'G':
13527         {
13528           if (LocaleCompare(attribute,"geometry") == 0)
13529             {
13530               geometry=SvPV(ST(i),na);
13531               break;
13532             }
13533          if (LocaleCompare(attribute,"gravity") == 0)
13534            {
13535              Image
13536                *next;
13537
13538              long
13539                in;
13540
13541              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
13542                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13543              if (in < 0)
13544                {
13545                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13546                    SvPV(ST(i),na));
13547                  return;
13548                }
13549              for (next=image; next; next=next->next)
13550                next->gravity=(GravityType) in;
13551              break;
13552            }
13553           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13554             attribute);
13555           break;
13556         }
13557         default:
13558         {
13559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13560             attribute);
13561           break;
13562         }
13563       }
13564     }
13565     for ( ; image; image=image->next)
13566     {
13567       clone=CloneImage(image,0,0,MagickTrue,exception);
13568       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13569         goto PerlException;
13570       TransformImage(&clone,crop_geometry,geometry);
13571       for ( ; clone; clone=clone->next)
13572       {
13573         AddImageToRegistry(clone);
13574         rv=newRV(sv);
13575         av_push(av,sv_bless(rv,hv));
13576         SvREFCNT_dec(sv);
13577       }
13578     }
13579     exception=DestroyExceptionInfo(exception);
13580     ST(0)=av_reference;
13581     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13582     XSRETURN(1);
13583
13584   PerlException:
13585     InheritPerlException(exception,perl_exception);
13586     exception=DestroyExceptionInfo(exception);
13587     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13588     SvPOK_on(perl_exception);
13589     ST(0)=sv_2mortal(perl_exception);
13590     XSRETURN(1);
13591   }
13592 \f
13593 #
13594 ###############################################################################
13595 #                                                                             #
13596 #                                                                             #
13597 #                                                                             #
13598 #   W r i t e                                                                 #
13599 #                                                                             #
13600 #                                                                             #
13601 #                                                                             #
13602 ###############################################################################
13603 #
13604 #
13605 void
13606 Write(ref,...)
13607   Image::Magick ref=NO_INIT
13608   ALIAS:
13609     WriteImage    = 1
13610     write         = 2
13611     writeimage    = 3
13612   PPCODE:
13613   {
13614     char
13615       filename[MaxTextExtent];
13616
13617     ExceptionInfo
13618       *exception;
13619
13620     Image
13621       *image,
13622       *next;
13623
13624     long
13625       number_images,
13626       scene;
13627
13628     register long
13629       i;
13630
13631     struct PackageInfo
13632       *info,
13633       *package_info;
13634
13635     SV
13636       *perl_exception,
13637       *reference;
13638
13639     exception=AcquireExceptionInfo();
13640     perl_exception=newSVpv("",0);
13641     number_images=0;
13642     package_info=(struct PackageInfo *) NULL;
13643     if (sv_isobject(ST(0)) == 0)
13644       {
13645         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13646           PackageName);
13647         goto PerlException;
13648       }
13649     reference=SvRV(ST(0));
13650     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13651     if (image == (Image *) NULL)
13652       {
13653         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13654           PackageName);
13655         goto PerlException;
13656       }
13657     package_info=ClonePackageInfo(info,exception);
13658     if (items == 2)
13659       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
13660     else
13661       if (items > 2)
13662         for (i=2; i < items; i+=2)
13663           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
13664             exception);
13665     (void) CopyMagickString(filename,package_info->image_info->filename,
13666       MaxTextExtent);
13667     scene=0;
13668     for (next=image; next; next=next->next)
13669     {
13670       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
13671       next->scene=scene++;
13672     }
13673     SetImageInfo(package_info->image_info,(unsigned int)
13674       GetImageListLength(image),&image->exception);
13675     for (next=image; next; next=next->next)
13676     {
13677       (void) WriteImage(package_info->image_info,next);
13678       if (next->exception.severity >= ErrorException)
13679         InheritException(exception,&next->exception);
13680       GetImageException(next,exception);
13681       number_images++;
13682       if (package_info->image_info->adjoin)
13683         break;
13684     }
13685
13686   PerlException:
13687     if (package_info != (struct PackageInfo *) NULL)
13688       DestroyPackageInfo(package_info);
13689     InheritPerlException(exception,perl_exception);
13690     exception=DestroyExceptionInfo(exception);
13691     sv_setiv(perl_exception,(IV) number_images);
13692     SvPOK_on(perl_exception);
13693     ST(0)=sv_2mortal(perl_exception);
13694     XSRETURN(1);
13695   }