]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-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     { "ColorFloodfill", { {"geometry", StringReference},
290       {"x", IntegerReference}, {"y", IntegerReference},
291       {"fill", StringReference}, {"bordercolor", StringReference},
292       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
293     { "Composite", { {"image", ImageReference},
294       {"compose", MagickComposeOptions}, {"geometry", StringReference},
295       {"x", IntegerReference}, {"y", IntegerReference},
296       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
297       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
298       {"color", StringReference}, {"mask", ImageReference},
299       {"channel", MagickChannelOptions},
300       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
301       {"blend", StringReference} } },
302     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
303     { "CycleColormap", { {"display", IntegerReference} } },
304     { "Draw", { {"primitive", MagickPrimitiveOptions},
305       {"points", StringReference}, {"method", MagickMethodOptions},
306       {"stroke", StringReference}, {"fill", StringReference},
307       {"strokewidth", RealReference}, {"font", StringReference},
308       {"bordercolor", StringReference}, {"x", RealReference},
309       {"y", RealReference}, {"translate", StringReference},
310       {"scale", StringReference}, {"rotate", RealReference},
311       {"skewX", RealReference}, {"skewY", RealReference},
312       {"tile", ImageReference}, {"pointsize", RealReference},
313       {"antialias", MagickBooleanOptions}, {"density", StringReference},
314       {"linewidth", RealReference}, {"affine", ArrayReference},
315       {"stroke-dashoffset", RealReference},
316       {"stroke-dasharray", ArrayReference},
317       {"interpolate", MagickInterpolateOptions},
318       {"origin", StringReference}, {"text", StringReference},
319       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
320       {"vector-graphics", StringReference}, {"kerning", RealReference},
321       {"interline-spacing", RealReference},
322       {"interword-spacing", RealReference} } },
323     { "Equalize", { {"channel", MagickChannelOptions} } },
324     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
325       {"red", RealReference}, {"green", RealReference},
326       {"blue", RealReference} } },
327     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
328       {"dither-method", MagickDitherOptions} } },
329     { "MatteFloodfill", { {"geometry", StringReference},
330       {"x", IntegerReference}, {"y", IntegerReference},
331       {"opacity", StringReference}, {"bordercolor", StringReference},
332       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
333     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
334       {"saturation", RealReference}, {"whiteness", RealReference},
335       {"brightness", RealReference}, {"lightness", RealReference},
336       {"blackness", RealReference} } },
337     { "Negate", { {"gray", MagickBooleanOptions},
338       {"channel", MagickChannelOptions} } },
339     { "Normalize", { {"channel", MagickChannelOptions} } },
340     { "NumberColors", },
341     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
342       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
343       {"invert", MagickBooleanOptions} } },
344     { "Quantize", { {"colors", IntegerReference},
345       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
346       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
347       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
348       {"dither-method", MagickDitherOptions} } },
349     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
350       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
351     { "Segment", { {"geometry", StringReference},
352       {"cluster-threshold", RealReference},
353       {"smoothing-threshold", RealReference},
354       {"colorspace", MagickColorspaceOptions},
355       {"verbose", MagickBooleanOptions} } },
356     { "Signature", },
357     { "Solarize", { {"geometry", StringReference},
358       {"threshold", StringReference} } },
359     { "Sync", },
360     { "Texture", { {"texture", ImageReference} } },
361     { "Evaluate", { {"value", RealReference},
362       {"operator", MagickEvaluateOptions},
363       {"channel", MagickChannelOptions} } },
364     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
365       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
366     { "Threshold", { {"threshold", StringReference},
367       {"channel", MagickChannelOptions} } },
368     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
369       {"sigma", RealReference} } },
370     { "Trim", { {"fuzz", StringReference} } },
371     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
372       {"wavelength", RealReference},
373       {"interpolate", MagickInterpolateOptions} } },
374     { "Separate", { {"channel", MagickChannelOptions} } },
375     { "Condense", },
376     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
377       {"y", IntegerReference} } },
378     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
379     { "Deconstruct", },
380     { "GaussianBlur", { {"geometry", StringReference},
381       {"radius", RealReference}, {"sigma", RealReference},
382       {"channel", MagickChannelOptions} } },
383     { "Convolve", { {"coefficients", ArrayReference},
384       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
385     { "Profile", { {"name", StringReference}, {"profile", StringReference},
386       { "rendering-intent", MagickIntentOptions},
387       { "black-point-compensation", MagickBooleanOptions} } },
388     { "UnsharpMask", { {"geometry", StringReference},
389       {"radius", RealReference}, {"sigma", RealReference},
390       {"amount", RealReference}, {"threshold", RealReference},
391       {"channel", MagickChannelOptions} } },
392     { "MotionBlur", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
395     { "OrderedDither", { {"threshold", StringReference},
396       {"channel", MagickChannelOptions} } },
397     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
398       {"height", IntegerReference} } },
399     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
400       {"white-point", RealReference}, {"gamma", RealReference},
401       {"channel", MagickChannelOptions}, {"level", StringReference} } },
402     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
403     { "AffineTransform", { {"affine", ArrayReference},
404       {"translate", StringReference}, {"scale", StringReference},
405       {"rotate", RealReference}, {"skewX", RealReference},
406       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
407       {"background", StringReference} } },
408     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
409     { "AdaptiveThreshold", { {"geometry", StringReference},
410       {"width", IntegerReference}, {"height", IntegerReference},
411       {"offset", IntegerReference} } },
412     { "Resample", { {"density", StringReference}, {"x", RealReference},
413       {"y", RealReference}, {"filter", MagickFilterOptions},
414       {"support", RealReference }, {"blur", RealReference } } },
415     { "Describe", { {"file", FileReference} } },
416     { "BlackThreshold", { {"threshold", StringReference},
417       {"channel", MagickChannelOptions} } },
418     { "WhiteThreshold", { {"threshold", StringReference},
419       {"channel", MagickChannelOptions} } },
420     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
421       {"channel", MagickChannelOptions} } },
422     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
423       {"height", IntegerReference} } },
424     { "Strip", },
425     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
426     { "Channel", { {"channel", MagickChannelOptions} } },
427     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
428       {"height", IntegerReference}, {"x", IntegerReference},
429       {"y", IntegerReference}, {"fuzz", StringReference},
430       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
431     { "Posterize", { {"levels", IntegerReference},
432       {"dither", MagickBooleanOptions} } },
433     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
434       {"sigma", RealReference}, {"x", IntegerReference},
435       {"y", IntegerReference} } },
436     { "Identify", { {"file", FileReference}, {"features", StringReference},
437       {"unique", MagickBooleanOptions} } },
438     { "SepiaTone", { {"threshold", RealReference} } },
439     { "SigmoidalContrast", { {"geometry", StringReference},
440       {"contrast", RealReference}, {"mid-point", RealReference},
441       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
442     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
443       {"height", IntegerReference}, {"x", IntegerReference},
444       {"y", IntegerReference}, {"fuzz", StringReference},
445       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
446     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
447       {"sigma", RealReference}, {"x", IntegerReference},
448       {"y", IntegerReference}, {"background", StringReference} } },
449     { "ContrastStretch", { {"levels", StringReference},
450       {"black-point", RealReference},{"white-point", RealReference},
451       {"channel", MagickChannelOptions} } },
452     { "Sans0", },
453     { "Sans1", },
454     { "AdaptiveSharpen", { {"geometry", StringReference},
455       {"radius", RealReference}, {"sigma", RealReference},
456       {"channel", MagickChannelOptions} } },
457     { "Transpose", },
458     { "Transverse", },
459     { "AutoOrient", },
460     { "AdaptiveBlur", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"channel", MagickChannelOptions} } },
463     { "Sketch", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"angle", RealReference} } },
466     { "UniqueColors", },
467     { "AdaptiveResize", { {"geometry", StringReference},
468       {"width", IntegerReference}, {"height", IntegerReference},
469       {"filter", MagickFilterOptions}, {"support", StringReference },
470       {"blur", RealReference } } },
471     { "ClipMask", { {"mask", ImageReference} } },
472     { "LinearStretch", { {"levels", StringReference},
473       {"black-point", RealReference},{"white-point", RealReference} } },
474     { "Recolor", { {"matrix", ArrayReference} } },
475     { "Mask", { {"mask", ImageReference} } },
476     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
477       {"font", StringReference}, {"stroke", StringReference},
478       {"fill", StringReference}, {"strokewidth", RealReference},
479       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
480       {"background", StringReference} } },
481     { "FloodfillPaint", { {"geometry", StringReference},
482       {"x", IntegerReference}, {"y", IntegerReference},
483       {"fill", StringReference}, {"bordercolor", StringReference},
484       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
485       {"invert", MagickBooleanOptions} } },
486     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
487       {"virtual-pixel", MagickVirtualPixelOptions},
488       {"best-fit", MagickBooleanOptions} } },
489     { "Clut", { {"image", ImageReference},
490       {"channel", MagickChannelOptions} } },
491     { "LiquidRescale", { {"geometry", StringReference},
492       {"width", IntegerReference}, {"height", IntegerReference},
493       {"delta-x", RealReference}, {"rigidity", RealReference } } },
494     { "Encipher", { {"passphrase", StringReference} } },
495     { "Decipher", { {"passphrase", StringReference} } },
496     { "Deskew", { {"geometry", StringReference},
497       {"threshold", StringReference} } },
498     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
499       {"dither-method", MagickDitherOptions} } },
500     { "SparseColor", { {"points", ArrayReference},
501       {"method", MagickSparseColorOptions},
502       {"virtual-pixel", MagickVirtualPixelOptions},
503       {"channel", MagickChannelOptions} } },
504     { "Function", { {"parameters", ArrayReference},
505       {"function", MagickFunctionOptions},
506       {"virtual-pixel", MagickVirtualPixelOptions} } },
507     { "SelectiveBlur", { {"geometry", StringReference},
508       {"radius", RealReference}, {"sigma", RealReference},
509       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
510     { "HaldClut", { {"image", ImageReference},
511       {"channel", MagickChannelOptions} } },
512     { "BlueShift", { {"factor", StringReference} } },
513     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
514     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
515     { "ColorDecisionList", {
516       {"color-correction-collection", StringReference} } },
517     { "AutoGamma", { {"channel", MagickChannelOptions} } },
518     { "AutoLevel", { {"channel", MagickChannelOptions} } },
519     { "LevelColors", { {"invert", MagickBooleanOptions},
520       {"black-point", RealReference}, {"white-point", RealReference},
521       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
522     { "Clamp", { {"channel", MagickChannelOptions} } },
523     { "Filter", { {"kernel", StringReference},
524       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
525     { "BrightnessContrast", { {"levels", StringReference},
526       {"brightness", RealReference},{"contrast", RealReference},
527       {"channel", MagickChannelOptions} } },
528     { "Morphology", { {"kernel", StringReference},
529       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
530       {"iterations", IntegerReference} } },
531   };
532
533 static SplayTreeInfo
534   *magick_registry = (SplayTreeInfo *) NULL;
535 \f
536 /*
537   Forward declarations.
538 */
539 static Image
540   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
541
542 static long
543   strEQcase(const char *,const char *);
544 \f
545 /*
546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 %                                                                             %
548 %                                                                             %
549 %                                                                             %
550 %   C l o n e P a c k a g e I n f o                                           %
551 %                                                                             %
552 %                                                                             %
553 %                                                                             %
554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 %
556 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
557 %  a new one.
558 %
559 %  The format of the ClonePackageInfo routine is:
560 %
561 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
562 %        exception)
563 %
564 %  A description of each parameter follows:
565 %
566 %    o info: a structure of type info.
567 %
568 %    o exception: Return any errors or warnings in this structure.
569 %
570 */
571 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
572   ExceptionInfo *exception)
573 {
574   struct PackageInfo
575     *clone_info;
576
577   clone_info=(struct PackageInfo *) AcquireAlignedMemory(1,sizeof(*clone_info));
578   if (clone_info == (struct PackageInfo *) NULL)
579     {
580       ThrowPerlException(exception,ResourceLimitError,
581         "UnableToClonePackageInfo",PackageName);
582       return((struct PackageInfo *) NULL);
583     }
584   if (info == (struct PackageInfo *) NULL)
585     {
586       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
587       return(clone_info);
588     }
589   *clone_info=(*info);
590   clone_info->image_info=CloneImageInfo(info->image_info);
591   return(clone_info);
592 }
593 \f
594 /*
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 %                                                                             %
597 %                                                                             %
598 %                                                                             %
599 %   c o n s t a n t                                                           %
600 %                                                                             %
601 %                                                                             %
602 %                                                                             %
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 %
605 %  constant() returns a double value for the specified name.
606 %
607 %  The format of the constant routine is:
608 %
609 %      double constant(char *name,long sans)
610 %
611 %  A description of each parameter follows:
612 %
613 %    o value: Method constant returns a double value for the specified name.
614 %
615 %    o name: The name of the constant.
616 %
617 %    o sans: This integer value is not used.
618 %
619 */
620 static double constant(char *name,long sans)
621 {
622   (void) sans;
623   errno=0;
624   switch (*name)
625   {
626     case 'B':
627     {
628       if (strEQ(name,"BlobError"))
629         return(BlobError);
630       if (strEQ(name,"BlobWarning"))
631         return(BlobWarning);
632       break;
633     }
634     case 'C':
635     {
636       if (strEQ(name,"CacheError"))
637         return(CacheError);
638       if (strEQ(name,"CacheWarning"))
639         return(CacheWarning);
640       if (strEQ(name,"CoderError"))
641         return(CoderError);
642       if (strEQ(name,"CoderWarning"))
643         return(CoderWarning);
644       if (strEQ(name,"ConfigureError"))
645         return(ConfigureError);
646       if (strEQ(name,"ConfigureWarning"))
647         return(ConfigureWarning);
648       if (strEQ(name,"CorruptImageError"))
649         return(CorruptImageError);
650       if (strEQ(name,"CorruptImageWarning"))
651         return(CorruptImageWarning);
652       break;
653     }
654     case 'D':
655     {
656       if (strEQ(name,"DelegateError"))
657         return(DelegateError);
658       if (strEQ(name,"DelegateWarning"))
659         return(DelegateWarning);
660       if (strEQ(name,"DrawError"))
661         return(DrawError);
662       if (strEQ(name,"DrawWarning"))
663         return(DrawWarning);
664       break;
665     }
666     case 'E':
667     {
668       if (strEQ(name,"ErrorException"))
669         return(ErrorException);
670       if (strEQ(name,"ExceptionError"))
671         return(CoderError);
672       if (strEQ(name,"ExceptionWarning"))
673         return(CoderWarning);
674       break;
675     }
676     case 'F':
677     {
678       if (strEQ(name,"FatalErrorException"))
679         return(FatalErrorException);
680       if (strEQ(name,"FileOpenError"))
681         return(FileOpenError);
682       if (strEQ(name,"FileOpenWarning"))
683         return(FileOpenWarning);
684       break;
685     }
686     case 'I':
687     {
688       if (strEQ(name,"ImageError"))
689         return(ImageError);
690       if (strEQ(name,"ImageWarning"))
691         return(ImageWarning);
692       break;
693     }
694     case 'M':
695     {
696       if (strEQ(name,"MaxRGB"))
697         return(QuantumRange);
698       if (strEQ(name,"MissingDelegateError"))
699         return(MissingDelegateError);
700       if (strEQ(name,"MissingDelegateWarning"))
701         return(MissingDelegateWarning);
702       if (strEQ(name,"ModuleError"))
703         return(ModuleError);
704       if (strEQ(name,"ModuleWarning"))
705         return(ModuleWarning);
706       break;
707     }
708     case 'O':
709     {
710       if (strEQ(name,"Opaque"))
711         return(OpaqueOpacity);
712       if (strEQ(name,"OptionError"))
713         return(OptionError);
714       if (strEQ(name,"OptionWarning"))
715         return(OptionWarning);
716       break;
717     }
718     case 'Q':
719     {
720       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
721         return(MAGICKCORE_QUANTUM_DEPTH);
722       if (strEQ(name,"QuantumDepth"))
723         return(QuantumDepth);
724       if (strEQ(name,"QuantumRange"))
725         return(QuantumRange);
726       break;
727     }
728     case 'R':
729     {
730       if (strEQ(name,"ResourceLimitError"))
731         return(ResourceLimitError);
732       if (strEQ(name,"ResourceLimitWarning"))
733         return(ResourceLimitWarning);
734       if (strEQ(name,"RegistryError"))
735         return(RegistryError);
736       if (strEQ(name,"RegistryWarning"))
737         return(RegistryWarning);
738       break;
739     }
740     case 'S':
741     {
742       if (strEQ(name,"StreamError"))
743         return(StreamError);
744       if (strEQ(name,"StreamWarning"))
745         return(StreamWarning);
746       if (strEQ(name,"Success"))
747         return(0);
748       break;
749     }
750     case 'T':
751     {
752       if (strEQ(name,"Transparent"))
753         return(TransparentOpacity);
754       if (strEQ(name,"TypeError"))
755         return(TypeError);
756       if (strEQ(name,"TypeWarning"))
757         return(TypeWarning);
758       break;
759     }
760     case 'W':
761     {
762       if (strEQ(name,"WarningException"))
763         return(WarningException);
764       break;
765     }
766     case 'X':
767     {
768       if (strEQ(name,"XServerError"))
769         return(XServerError);
770       if (strEQ(name,"XServerWarning"))
771         return(XServerWarning);
772       break;
773     }
774   }
775   errno=EINVAL;
776   return(0);
777 }
778 \f
779 /*
780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781 %                                                                             %
782 %                                                                             %
783 %                                                                             %
784 %   D e s t r o y P a c k a g e I n f o                                       %
785 %                                                                             %
786 %                                                                             %
787 %                                                                             %
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 %
790 %  Method DestroyPackageInfo frees a previously created info structure.
791 %
792 %  The format of the DestroyPackageInfo routine is:
793 %
794 %      DestroyPackageInfo(struct PackageInfo *info)
795 %
796 %  A description of each parameter follows:
797 %
798 %    o info: a structure of type info.
799 %
800 */
801 static void DestroyPackageInfo(struct PackageInfo *info)
802 {
803   info->image_info=DestroyImageInfo(info->image_info);
804   info=(struct PackageInfo *) RelinquishMagickMemory(info);
805 }
806 \f
807 /*
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
809 %                                                                             %
810 %                                                                             %
811 %                                                                             %
812 %   G e t L i s t                                                             %
813 %                                                                             %
814 %                                                                             %
815 %                                                                             %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %
818 %  Method GetList is recursively called by SetupList to traverse the
819 %  Image__Magick reference.  If building an reference_vector (see SetupList),
820 %  *current is the current position in *reference_vector and *last is the final
821 %  entry in *reference_vector.
822 %
823 %  The format of the GetList routine is:
824 %
825 %      GetList(info)
826 %
827 %  A description of each parameter follows:
828 %
829 %    o info: a structure of type info.
830 %
831 */
832 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,long *current,
833   long *last,ExceptionInfo *exception)
834 {
835   Image
836     *image;
837
838   if (reference == (SV *) NULL)
839     return(NULL);
840   switch (SvTYPE(reference))
841   {
842     case SVt_PVAV:
843     {
844       AV
845         *av;
846
847       Image
848         *head,
849         *previous;
850
851       long
852         n;
853
854       register long
855         i;
856
857       /*
858         Array of images.
859       */
860       previous=(Image *) NULL;
861       head=(Image *) NULL;
862       av=(AV *) reference;
863       n=av_len(av);
864       for (i=0; i <= n; i++)
865       {
866         SV
867           **rv;
868
869         rv=av_fetch(av,i,0);
870         if (rv && *rv && sv_isobject(*rv))
871           {
872             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
873               exception);
874             if (image == (Image *) NULL)
875               continue;
876             if (image == previous)
877               {
878                 image=CloneImage(image,0,0,MagickTrue,exception);
879                 if (image == (Image *) NULL)
880                   return(NULL);
881               }
882             image->previous=previous;
883             *(previous ? &previous->next : &head)=image;
884             for (previous=image; previous->next; previous=previous->next) ;
885           }
886       }
887       return(head);
888     }
889     case SVt_PVMG:
890     {
891       /*
892         Blessed scalar, one image.
893       */
894       image=(Image *) SvIV(reference);
895       if (image == (Image *) NULL)
896         return(NULL);
897       image->previous=(Image *) NULL;
898       image->next=(Image *) NULL;
899       if (reference_vector)
900         {
901           if (*current == *last)
902             {
903               *last+=256;
904               if (*reference_vector == (SV **) NULL)
905                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
906                   sizeof(*reference_vector));
907               else
908                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
909                   *last,sizeof(*reference_vector));
910             }
911           if (*reference_vector == (SV **) NULL)
912             {
913               ThrowPerlException(exception,ResourceLimitError,
914                 "MemoryAllocationFailed",PackageName);
915               return((Image *) NULL);
916             }
917           (*reference_vector)[*current]=reference;
918           (*reference_vector)[++(*current)]=NULL;
919         }
920       return(image);
921     }
922     default:
923       break;
924   }
925   (void) fprintf(stderr,"GetList: UnrecognizedType %ld\n",
926     (long) SvTYPE(reference));
927   return((Image *) NULL);
928 }
929 \f
930 /*
931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932 %                                                                             %
933 %                                                                             %
934 %                                                                             %
935 %   G e t P a c k a g e I n f o                                               %
936 %                                                                             %
937 %                                                                             %
938 %                                                                             %
939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 %
941 %  Method GetPackageInfo looks up or creates an info structure for the given
942 %  Image__Magick reference.  If it does create a new one, the information in
943 %  package_info is used to initialize it.
944 %
945 %  The format of the GetPackageInfo routine is:
946 %
947 %      struct PackageInfo *GetPackageInfo(void *reference,
948 %        struct PackageInfo *package_info,ExceptionInfo *exception)
949 %
950 %  A description of each parameter follows:
951 %
952 %    o info: a structure of type info.
953 %
954 %    o exception: Return any errors or warnings in this structure.
955 %
956 */
957 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
958   struct PackageInfo *package_info,ExceptionInfo *exception)
959 {
960   char
961     message[MaxTextExtent];
962
963   struct PackageInfo
964     *clone_info;
965
966   SV
967     *sv;
968
969   (void) FormatMagickString(message,MaxTextExtent,"%s::package%s%lx",
970     PackageName,XS_VERSION,(long) reference);
971   sv=perl_get_sv(message,(TRUE | 0x02));
972   if (sv == (SV *) NULL)
973     {
974       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
975         message);
976       return(package_info);
977     }
978   if (SvREFCNT(sv) == 0)
979     (void) SvREFCNT_inc(sv);
980   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
981     return(clone_info);
982   clone_info=ClonePackageInfo(package_info,exception);
983   sv_setiv(sv,(IV) clone_info);
984   return(clone_info);
985 }
986 \f
987 /*
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989 %                                                                             %
990 %                                                                             %
991 %                                                                             %
992 %   S e t A t t r i b u t e                                                   %
993 %                                                                             %
994 %                                                                             %
995 %                                                                             %
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 %
998 %  SetAttribute() sets the attribute to the value in sval.  This can change
999 %  either or both of image or info.
1000 %
1001 %  The format of the SetAttribute routine is:
1002 %
1003 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1004 %        SV *sval,ExceptionInfo *exception)
1005 %
1006 %  A description of each parameter follows:
1007 %
1008 %    o list: a list of strings.
1009 %
1010 %    o string: a character string.
1011 %
1012 */
1013
1014 static inline double SiPrefixToDouble(const char *string,const double interval)
1015 {
1016   char
1017     *q;
1018
1019   double
1020     scale,
1021     value;
1022
1023   value=strtod(string,&q);
1024   scale=1000.0;
1025   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1026     scale=1024.0;
1027   switch (tolower((int) ((unsigned char) *q)))
1028   {
1029     case '%': value*=pow(scale,0)*interval/100.0; break;
1030     case 'k': value*=pow(scale,1); break;
1031     case 'm': value*=pow(scale,2); break;
1032     case 'g': value*=pow(scale,3); break;
1033     case 't': value*=pow(scale,4); break;
1034     case 'p': value*=pow(scale,5); break;
1035     case 'e': value*=pow(scale,6); break;
1036     case 'z': value*=pow(scale,7); break;
1037     case 'y': value*=pow(scale,8); break;
1038     default:  break;
1039   }
1040   return(value);
1041 }
1042
1043 static inline double StringToDouble(const char *value)
1044 {
1045   return(strtod(value,(char **) NULL));
1046 }
1047
1048 static inline long StringToLong(const char *value)
1049 {
1050   return(strtol(value,(char **) NULL,10));
1051 }
1052
1053 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1054   const char *attribute,SV *sval,ExceptionInfo *exception)
1055 {
1056   GeometryInfo
1057     geometry_info;
1058
1059   long
1060     sp;
1061
1062   long
1063     x,
1064     y;
1065
1066   MagickPixelPacket
1067     pixel;
1068
1069   MagickStatusType
1070     flags;
1071
1072   PixelPacket
1073     *color,
1074     target_color;
1075
1076   switch (*attribute)
1077   {
1078     case 'A':
1079     case 'a':
1080     {
1081       if (LocaleCompare(attribute,"adjoin") == 0)
1082         {
1083           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1084             SvPV(sval,na)) : SvIV(sval);
1085           if (sp < 0)
1086             {
1087               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1088                 SvPV(sval,na));
1089               break;
1090             }
1091           if (info)
1092             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1093           break;
1094         }
1095       if (LocaleCompare(attribute,"alpha") == 0)
1096         {
1097           sp=SvPOK(sval) ? ParseMagickOption(MagickAlphaOptions,MagickFalse,
1098             SvPV(sval,na)) : SvIV(sval);
1099           if (sp < 0)
1100             {
1101               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1102                 SvPV(sval,na));
1103               break;
1104             }
1105           for ( ; image; image=image->next)
1106             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1107           break;
1108         }
1109       if (LocaleCompare(attribute,"antialias") == 0)
1110         {
1111           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1112             SvPV(sval,na)) : SvIV(sval);
1113           if (sp < 0)
1114             {
1115               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1116                 SvPV(sval,na));
1117               break;
1118             }
1119           if (info)
1120             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1121           break;
1122         }
1123       if (LocaleCompare(attribute,"area-limit") == 0)
1124         {
1125           MagickSizeType
1126             limit;
1127
1128           limit=MagickResourceInfinity;
1129           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1130             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1131           (void) SetMagickResourceLimit(AreaResource,limit);
1132           break;
1133         }
1134       if (LocaleCompare(attribute,"attenuate") == 0)
1135         {
1136           if (info)
1137             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1138           break;
1139         }
1140       if (LocaleCompare(attribute,"authenticate") == 0)
1141         {
1142           if (info)
1143             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1144           break;
1145         }
1146       if (info)
1147         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1148       for ( ; image; image=image->next)
1149         SetImageProperty(image,attribute,SvPV(sval,na));
1150       break;
1151     }
1152     case 'B':
1153     case 'b':
1154     {
1155       if (LocaleCompare(attribute,"background") == 0)
1156         {
1157           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1158           if (info)
1159             info->image_info->background_color=target_color;
1160           for ( ; image; image=image->next)
1161             image->background_color=target_color;
1162           break;
1163         }
1164       if (LocaleCompare(attribute,"bias") == 0)
1165         {
1166           for ( ; image; image=image->next)
1167             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1168           break;
1169         }
1170       if (LocaleCompare(attribute,"blue-primary") == 0)
1171         {
1172           for ( ; image; image=image->next)
1173           {
1174             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1175             image->chromaticity.blue_primary.x=geometry_info.rho;
1176             image->chromaticity.blue_primary.y=geometry_info.sigma;
1177             if ((flags & SigmaValue) == 0)
1178               image->chromaticity.blue_primary.y=
1179                 image->chromaticity.blue_primary.x;
1180           }
1181           break;
1182         }
1183       if (LocaleCompare(attribute,"bordercolor") == 0)
1184         {
1185           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1186           if (info)
1187             info->image_info->border_color=target_color;
1188           for ( ; image; image=image->next)
1189             image->border_color=target_color;
1190           break;
1191         }
1192       if (info)
1193         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1194       for ( ; image; image=image->next)
1195         SetImageProperty(image,attribute,SvPV(sval,na));
1196       break;
1197     }
1198     case 'C':
1199     case 'c':
1200     {
1201       if (LocaleCompare(attribute,"cache-threshold") == 0)
1202         {
1203           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1204             SiPrefixToDouble(SvPV(sval,na),100.0));
1205           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1206             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1207           break;
1208         }
1209       if (LocaleCompare(attribute,"clip-mask") == 0)
1210         {
1211           Image
1212             *clip_mask;
1213
1214           clip_mask=(Image *) NULL;
1215           if (SvPOK(sval))
1216             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1217           for ( ; image; image=image->next)
1218             SetImageClipMask(image,clip_mask);
1219           break;
1220         }
1221       if (LocaleNCompare(attribute,"colormap",8) == 0)
1222         {
1223           for ( ; image; image=image->next)
1224           {
1225             int
1226               items;
1227
1228             long
1229               i;
1230
1231             if (image->storage_class == DirectClass)
1232               continue;
1233             i=0;
1234             items=sscanf(attribute,"%*[^[][%ld",&i);
1235             if (i > (long) image->colors)
1236               i%=image->colors;
1237             if ((strchr(SvPV(sval,na),',') == 0) ||
1238                 (strchr(SvPV(sval,na),')') != 0))
1239               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1240             else
1241               {
1242                 color=image->colormap+i;
1243                 pixel.red=color->red;
1244                 pixel.green=color->green;
1245                 pixel.blue=color->blue;
1246                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1247                 pixel.red=geometry_info.rho;
1248                 pixel.green=geometry_info.sigma;
1249                 pixel.blue=geometry_info.xi;
1250                 color->red=ClampToQuantum(pixel.red);
1251                 color->green=ClampToQuantum(pixel.green);
1252                 color->blue=ClampToQuantum(pixel.blue);
1253               }
1254           }
1255           break;
1256         }
1257       if (LocaleCompare(attribute,"colorspace") == 0)
1258         {
1259           sp=SvPOK(sval) ? ParseMagickOption(MagickColorspaceOptions,
1260             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1261           if (sp < 0)
1262             {
1263               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1264                 SvPV(sval,na));
1265               break;
1266             }
1267           for ( ; image; image=image->next)
1268             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1269           break;
1270         }
1271       if (LocaleCompare(attribute,"comment") == 0)
1272         {
1273           for ( ; image; image=image->next)
1274             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1275               info ? info->image_info : (ImageInfo *) NULL,image,
1276               SvPV(sval,na)));
1277           break;
1278         }
1279       if (LocaleCompare(attribute,"compression") == 0)
1280         {
1281           sp=SvPOK(sval) ? ParseMagickOption(MagickCompressOptions,
1282             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1283           if (sp < 0)
1284             {
1285               ThrowPerlException(exception,OptionError,
1286                 "UnrecognizedImageCompression",SvPV(sval,na));
1287               break;
1288             }
1289           if (info)
1290             info->image_info->compression=(CompressionType) sp;
1291           for ( ; image; image=image->next)
1292             image->compression=(CompressionType) sp;
1293           break;
1294         }
1295       if (info)
1296         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1297       for ( ; image; image=image->next)
1298         SetImageProperty(image,attribute,SvPV(sval,na));
1299       break;
1300     }
1301     case 'D':
1302     case 'd':
1303     {
1304       if (LocaleCompare(attribute,"debug") == 0)
1305         {
1306           SetLogEventMask(SvPV(sval,na));
1307           break;
1308         }
1309       if (LocaleCompare(attribute,"delay") == 0)
1310         {
1311           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1312           for ( ; image; image=image->next)
1313           {
1314             image->delay=(unsigned long) (geometry_info.rho+0.5);
1315             if ((flags & SigmaValue) != 0)
1316               image->ticks_per_second=(unsigned long) (geometry_info.sigma+0.5);
1317           }
1318           break;
1319         }
1320       if (LocaleCompare(attribute,"disk-limit") == 0)
1321         {
1322           MagickSizeType
1323             limit;
1324
1325           limit=MagickResourceInfinity;
1326           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1327             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1328           (void) SetMagickResourceLimit(DiskResource,limit);
1329           break;
1330         }
1331       if (LocaleCompare(attribute,"density") == 0)
1332         {
1333           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1334             {
1335               ThrowPerlException(exception,OptionError,"MissingGeometry",
1336                 SvPV(sval,na));
1337               break;
1338             }
1339           if (info)
1340             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1341           for ( ; image; image=image->next)
1342           {
1343             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1344             image->x_resolution=geometry_info.rho;
1345             image->y_resolution=geometry_info.sigma;
1346             if ((flags & SigmaValue) == 0)
1347               image->y_resolution=image->x_resolution;
1348           }
1349           break;
1350         }
1351       if (LocaleCompare(attribute,"depth") == 0)
1352         {
1353           if (info)
1354             info->image_info->depth=SvIV(sval);
1355           for ( ; image; image=image->next)
1356             (void) SetImageDepth(image,SvIV(sval));
1357           break;
1358         }
1359       if (LocaleCompare(attribute,"dispose") == 0)
1360         {
1361           sp=SvPOK(sval) ? ParseMagickOption(MagickDisposeOptions,MagickFalse,
1362             SvPV(sval,na)) : SvIV(sval);
1363           if (sp < 0)
1364             {
1365               ThrowPerlException(exception,OptionError,
1366                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1367               break;
1368             }
1369           for ( ; image; image=image->next)
1370             image->dispose=(DisposeType) sp;
1371           break;
1372         }
1373       if (LocaleCompare(attribute,"dither") == 0)
1374         {
1375           if (info)
1376             {
1377               sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,
1378                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1379               if (sp < 0)
1380                 {
1381                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1382                     SvPV(sval,na));
1383                   break;
1384                 }
1385               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1386             }
1387           break;
1388         }
1389       if (LocaleCompare(attribute,"display") == 0)
1390         {
1391           display:
1392           if (info)
1393             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1394           break;
1395         }
1396       if (info)
1397         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1398       for ( ; image; image=image->next)
1399         SetImageProperty(image,attribute,SvPV(sval,na));
1400       break;
1401     }
1402     case 'E':
1403     case 'e':
1404     {
1405       if (LocaleCompare(attribute,"endian") == 0)
1406         {
1407           sp=SvPOK(sval) ? ParseMagickOption(MagickEndianOptions,MagickFalse,
1408             SvPV(sval,na)) : SvIV(sval);
1409           if (sp < 0)
1410             {
1411               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1412                 SvPV(sval,na));
1413               break;
1414             }
1415           if (info)
1416             info->image_info->endian=(EndianType) sp;
1417           for ( ; image; image=image->next)
1418             image->endian=(EndianType) sp;
1419           break;
1420         }
1421       if (LocaleCompare(attribute,"extract") == 0)
1422         {
1423           /*
1424             Set image extract geometry.
1425           */
1426           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1427           break;
1428         }
1429       if (info)
1430         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1431       for ( ; image; image=image->next)
1432         SetImageProperty(image,attribute,SvPV(sval,na));
1433       break;
1434     }
1435     case 'F':
1436     case 'f':
1437     {
1438       if (LocaleCompare(attribute,"filename") == 0)
1439         {
1440           if (info)
1441             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1442               MaxTextExtent);
1443           for ( ; image; image=image->next)
1444             (void) CopyMagickString(image->filename,SvPV(sval,na),
1445               MaxTextExtent);
1446           break;
1447         }
1448       if (LocaleCompare(attribute,"file") == 0)
1449         {
1450           FILE
1451             *file;
1452
1453           PerlIO
1454             *io_info;
1455
1456           if (info == (struct PackageInfo *) NULL)
1457             break;
1458           io_info=IoIFP(sv_2io(sval));
1459           if (io_info == (PerlIO *) NULL)
1460             {
1461               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1462                 PackageName);
1463               break;
1464             }
1465           file=PerlIO_findFILE(io_info);
1466           if (file == (FILE *) NULL)
1467             {
1468               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1469                 PackageName);
1470               break;
1471             }
1472           SetImageInfoFile(info->image_info,file);
1473           break;
1474         }
1475       if (LocaleCompare(attribute,"fill") == 0)
1476         {
1477           if (info)
1478             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1479           break;
1480         }
1481       if (LocaleCompare(attribute,"font") == 0)
1482         {
1483           if (info)
1484             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1485           break;
1486         }
1487       if (LocaleCompare(attribute,"foreground") == 0)
1488         break;
1489       if (LocaleCompare(attribute,"fuzz") == 0)
1490         {
1491           if (info)
1492             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1493           for ( ; image; image=image->next)
1494             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1495           break;
1496         }
1497       if (info)
1498         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1499       for ( ; image; image=image->next)
1500         SetImageProperty(image,attribute,SvPV(sval,na));
1501       break;
1502     }
1503     case 'G':
1504     case 'g':
1505     {
1506       if (LocaleCompare(attribute,"gamma") == 0)
1507         {
1508           for ( ; image; image=image->next)
1509             image->gamma=SvNV(sval);
1510           break;
1511         }
1512       if (LocaleCompare(attribute,"gravity") == 0)
1513         {
1514           sp=SvPOK(sval) ? ParseMagickOption(MagickGravityOptions,MagickFalse,
1515             SvPV(sval,na)) : SvIV(sval);
1516           if (sp < 0)
1517             {
1518               ThrowPerlException(exception,OptionError,
1519                 "UnrecognizedGravityType",SvPV(sval,na));
1520               break;
1521             }
1522           for ( ; image; image=image->next)
1523             image->gravity=(GravityType) sp;
1524           break;
1525         }
1526       if (LocaleCompare(attribute,"green-primary") == 0)
1527         {
1528           for ( ; image; image=image->next)
1529           {
1530             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1531             image->chromaticity.green_primary.x=geometry_info.rho;
1532             image->chromaticity.green_primary.y=geometry_info.sigma;
1533             if ((flags & SigmaValue) == 0)
1534               image->chromaticity.green_primary.y=
1535                 image->chromaticity.green_primary.x;
1536           }
1537           break;
1538         }
1539       if (info)
1540         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1541       for ( ; image; image=image->next)
1542         SetImageProperty(image,attribute,SvPV(sval,na));
1543       break;
1544     }
1545     case 'I':
1546     case 'i':
1547     {
1548       if (LocaleNCompare(attribute,"index",5) == 0)
1549         {
1550           IndexPacket
1551             *indexes;
1552
1553           int
1554             items;
1555
1556           long
1557             index;
1558
1559           register PixelPacket
1560             *p;
1561
1562           CacheView
1563             *image_view;
1564
1565           for ( ; image; image=image->next)
1566           {
1567             if (image->storage_class != PseudoClass)
1568               continue;
1569             x=0;
1570             y=0;
1571             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1572             image_view=AcquireCacheView(image);
1573             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1574             if (p != (PixelPacket *) NULL)
1575               {
1576                 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1577                 items=sscanf(SvPV(sval,na),"%ld",&index);
1578                 if ((index >= 0) && (index < (long) image->colors))
1579                   *indexes=(IndexPacket) index;
1580                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1581               }
1582             image_view=DestroyCacheView(image_view);
1583           }
1584           break;
1585         }
1586       if (LocaleCompare(attribute,"iterations") == 0)
1587         {
1588   iterations:
1589           for ( ; image; image=image->next)
1590             image->iterations=SvIV(sval);
1591           break;
1592         }
1593       if (LocaleCompare(attribute,"interlace") == 0)
1594         {
1595           sp=SvPOK(sval) ? ParseMagickOption(MagickInterlaceOptions,MagickFalse,
1596             SvPV(sval,na)) : SvIV(sval);
1597           if (sp < 0)
1598             {
1599               ThrowPerlException(exception,OptionError,
1600                 "UnrecognizedInterlaceType",SvPV(sval,na));
1601               break;
1602             }
1603           if (info)
1604             info->image_info->interlace=(InterlaceType) sp;
1605           for ( ; image; image=image->next)
1606             image->interlace=(InterlaceType) sp;
1607           break;
1608         }
1609       if (info)
1610         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1611       for ( ; image; image=image->next)
1612         SetImageProperty(image,attribute,SvPV(sval,na));
1613       break;
1614     }
1615     case 'L':
1616     case 'l':
1617     {
1618       if (LocaleCompare(attribute,"label") == 0)
1619         {
1620           for ( ; image; image=image->next)
1621             (void) SetImageProperty(image,"label",InterpretImageProperties(
1622               info ? info->image_info : (ImageInfo *) NULL,image,
1623               SvPV(sval,na)));
1624           break;
1625         }
1626       if (LocaleCompare(attribute,"loop") == 0)
1627         goto iterations;
1628       if (info)
1629         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1630       for ( ; image; image=image->next)
1631         SetImageProperty(image,attribute,SvPV(sval,na));
1632       break;
1633     }
1634     case 'M':
1635     case 'm':
1636     {
1637       if (LocaleCompare(attribute,"magick") == 0)
1638         {
1639           if (info)
1640             (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
1641               "%.1024s:",SvPV(sval,na));
1642           for ( ; image; image=image->next)
1643             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1644           break;
1645         }
1646       if (LocaleCompare(attribute,"map-limit") == 0)
1647         {
1648           MagickSizeType
1649             limit;
1650
1651           limit=MagickResourceInfinity;
1652           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1653             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1654           (void) SetMagickResourceLimit(MapResource,limit);
1655           break;
1656         }
1657       if (LocaleCompare(attribute,"mask") == 0)
1658         {
1659           Image
1660             *mask;
1661
1662           mask=(Image *) NULL;
1663           if (SvPOK(sval))
1664             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1665           for ( ; image; image=image->next)
1666             SetImageMask(image,mask);
1667           break;
1668         }
1669       if (LocaleCompare(attribute,"mattecolor") == 0)
1670         {
1671           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1672           if (info)
1673             info->image_info->matte_color=target_color;
1674           for ( ; image; image=image->next)
1675             image->matte_color=target_color;
1676           break;
1677         }
1678       if (LocaleCompare(attribute,"matte") == 0)
1679         {
1680           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1681             SvPV(sval,na)) : SvIV(sval);
1682           if (sp < 0)
1683             {
1684               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1685                 SvPV(sval,na));
1686               break;
1687             }
1688           for ( ; image; image=image->next)
1689             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1690           break;
1691         }
1692       if (LocaleCompare(attribute,"memory-limit") == 0)
1693         {
1694           MagickSizeType
1695             limit;
1696
1697           limit=MagickResourceInfinity;
1698           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1699             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1700           (void) SetMagickResourceLimit(MemoryResource,limit);
1701           break;
1702         }
1703       if (LocaleCompare(attribute,"monochrome") == 0)
1704         {
1705           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
1706             SvPV(sval,na)) : SvIV(sval);
1707           if (sp < 0)
1708             {
1709               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1710                 SvPV(sval,na));
1711               break;
1712             }
1713           if (info)
1714             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1715           for ( ; image; image=image->next)
1716             (void) SetImageType(image,BilevelType);
1717           break;
1718         }
1719       if (info)
1720         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1721       for ( ; image; image=image->next)
1722         SetImageProperty(image,attribute,SvPV(sval,na));
1723       break;
1724     }
1725     case 'O':
1726     case 'o':
1727     {
1728       if (LocaleCompare(attribute,"option") == 0)
1729         {
1730           if (info)
1731             DefineImageOption(info->image_info,SvPV(sval,na));
1732           break;
1733         }
1734       if (LocaleCompare(attribute,"orientation") == 0)
1735         {
1736           sp=SvPOK(sval) ? ParseMagickOption(MagickOrientationOptions,
1737             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1738           if (sp < 0)
1739             {
1740               ThrowPerlException(exception,OptionError,
1741                 "UnrecognizedOrientationType",SvPV(sval,na));
1742               break;
1743             }
1744           if (info)
1745             info->image_info->orientation=(OrientationType) sp;
1746           for ( ; image; image=image->next)
1747             image->orientation=(OrientationType) sp;
1748           break;
1749         }
1750       if (info)
1751         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1752       for ( ; image; image=image->next)
1753         SetImageProperty(image,attribute,SvPV(sval,na));
1754       break;
1755     }
1756     case 'P':
1757     case 'p':
1758     {
1759       if (LocaleCompare(attribute,"page") == 0)
1760         {
1761           char
1762             *geometry;
1763
1764           geometry=GetPageGeometry(SvPV(sval,na));
1765           if (info)
1766             (void) CloneString(&info->image_info->page,geometry);
1767           for ( ; image; image=image->next)
1768             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1769           geometry=(char *) RelinquishMagickMemory(geometry);
1770           break;
1771         }
1772       if (LocaleCompare(attribute,"pen") == 0)
1773         {
1774           if (info)
1775             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1776           break;
1777         }
1778       if (LocaleNCompare(attribute,"pixel",5) == 0)
1779         {
1780           int
1781             items;
1782
1783           MagickPixelPacket
1784             pixel;
1785
1786           register IndexPacket
1787             *indexes;
1788
1789           register PixelPacket
1790             *p;
1791
1792           CacheView
1793             *image_view;
1794
1795           for ( ; image; image=image->next)
1796           {
1797             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1798               break;
1799             x=0;
1800             y=0;
1801             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1802             image_view=AcquireCacheView(image);
1803             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1804             indexes=GetCacheViewAuthenticIndexQueue(image_view);
1805             if (p != (PixelPacket *) NULL)
1806               {
1807                 if ((strchr(SvPV(sval,na),',') == 0) ||
1808                     (strchr(SvPV(sval,na),')') != 0))
1809                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1810                 else
1811                   {
1812                     GetMagickPixelPacket(image,&pixel);
1813                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1814                     pixel.red=geometry_info.rho;
1815                     if ((flags & SigmaValue) != 0)
1816                       pixel.green=geometry_info.sigma;
1817                     if ((flags & XiValue) != 0)
1818                       pixel.blue=geometry_info.xi;
1819                     if ((flags & PsiValue) != 0)
1820                       pixel.opacity=geometry_info.psi;
1821                     if ((flags & ChiValue) != 0)
1822                       pixel.index=geometry_info.chi;
1823                   }
1824                 p->red=ClampToQuantum(pixel.red);
1825                 p->green=ClampToQuantum(pixel.green);
1826                 p->blue=ClampToQuantum(pixel.blue);
1827                 p->opacity=ClampToQuantum(pixel.opacity);
1828                 if (((image->colorspace == CMYKColorspace) ||
1829                      (image->storage_class == PseudoClass)) &&
1830                     (indexes != (IndexPacket *) NULL))
1831                   *indexes=ClampToQuantum(pixel.index);
1832                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1833               }
1834             image_view=DestroyCacheView(image_view);
1835           }
1836           break;
1837         }
1838       if (LocaleCompare(attribute,"pointsize") == 0)
1839         {
1840           if (info)
1841             {
1842               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1843               info->image_info->pointsize=geometry_info.rho;
1844             }
1845           break;
1846         }
1847       if (LocaleCompare(attribute,"preview") == 0)
1848         {
1849           sp=SvPOK(sval) ? ParseMagickOption(MagickPreviewOptions,MagickFalse,
1850             SvPV(sval,na)) : SvIV(sval);
1851           if (sp < 0)
1852             {
1853               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1854                 SvPV(sval,na));
1855               break;
1856             }
1857           if (info)
1858             info->image_info->preview_type=(PreviewType) sp;
1859           break;
1860         }
1861       if (info)
1862         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1863       for ( ; image; image=image->next)
1864         SetImageProperty(image,attribute,SvPV(sval,na));
1865       break;
1866     }
1867     case 'Q':
1868     case 'q':
1869     {
1870       if (LocaleCompare(attribute,"quality") == 0)
1871         {
1872           if (info)
1873             info->image_info->quality=SvIV(sval);
1874           for ( ; image; image=image->next)
1875             image->quality=SvIV(sval);
1876           break;
1877         }
1878       if (info)
1879         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1880       for ( ; image; image=image->next)
1881         SetImageProperty(image,attribute,SvPV(sval,na));
1882       break;
1883     }
1884     case 'R':
1885     case 'r':
1886     {
1887       if (LocaleCompare(attribute,"red-primary") == 0)
1888         {
1889           for ( ; image; image=image->next)
1890           {
1891             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1892             image->chromaticity.red_primary.x=geometry_info.rho;
1893             image->chromaticity.red_primary.y=geometry_info.sigma;
1894             if ((flags & SigmaValue) == 0)
1895               image->chromaticity.red_primary.y=
1896                 image->chromaticity.red_primary.x;
1897           }
1898           break;
1899         }
1900       if (LocaleCompare(attribute,"render") == 0)
1901         {
1902           sp=SvPOK(sval) ? ParseMagickOption(MagickIntentOptions,MagickFalse,
1903             SvPV(sval,na)) : SvIV(sval);
1904           if (sp < 0)
1905             {
1906               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1907                 SvPV(sval,na));
1908               break;
1909             }
1910          for ( ; image; image=image->next)
1911            image->rendering_intent=(RenderingIntent) sp;
1912          break;
1913        }
1914       if (LocaleCompare(attribute,"repage") == 0)
1915         {
1916           RectangleInfo
1917             geometry;
1918
1919           for ( ; image; image=image->next)
1920           {
1921             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1922             if ((flags & WidthValue) != 0)
1923               {
1924                 if ((flags & HeightValue) == 0)
1925                   geometry.height=geometry.width;
1926                 image->page.width=geometry.width;
1927                 image->page.height=geometry.height;
1928               }
1929             if ((flags & AspectValue) != 0)
1930               {
1931                 if ((flags & XValue) != 0)
1932                   image->page.x+=geometry.x;
1933                 if ((flags & YValue) != 0)
1934                   image->page.y+=geometry.y;
1935               }
1936             else
1937               {
1938                 if ((flags & XValue) != 0)
1939                   {
1940                     image->page.x=geometry.x;
1941                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1942                       image->page.width=image->columns+geometry.x;
1943                   }
1944                 if ((flags & YValue) != 0)
1945                   {
1946                     image->page.y=geometry.y;
1947                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1948                       image->page.height=image->rows+geometry.y;
1949                   }
1950               }
1951           }
1952           break;
1953         }
1954       if (info)
1955         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1956       for ( ; image; image=image->next)
1957         SetImageProperty(image,attribute,SvPV(sval,na));
1958       break;
1959     }
1960     case 'S':
1961     case 's':
1962     {
1963       if (LocaleCompare(attribute,"sampling-factor") == 0)
1964         {
1965           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1966             {
1967               ThrowPerlException(exception,OptionError,"MissingGeometry",
1968                 SvPV(sval,na));
1969               break;
1970             }
1971           if (info)
1972             (void) CloneString(&info->image_info->sampling_factor,
1973               SvPV(sval,na));
1974           break;
1975         }
1976       if (LocaleCompare(attribute,"scene") == 0)
1977         {
1978           for ( ; image; image=image->next)
1979             image->scene=SvIV(sval);
1980           break;
1981         }
1982       if (LocaleCompare(attribute,"subimage") == 0)
1983         {
1984           if (info)
1985             info->image_info->subimage=SvIV(sval);
1986           break;
1987         }
1988       if (LocaleCompare(attribute,"subrange") == 0)
1989         {
1990           if (info)
1991             info->image_info->subrange=SvIV(sval);
1992           break;
1993         }
1994       if (LocaleCompare(attribute,"server") == 0)
1995         goto display;
1996       if (LocaleCompare(attribute,"size") == 0)
1997         {
1998           if (info)
1999             {
2000               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2001                 {
2002                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2003                     SvPV(sval,na));
2004                   break;
2005                 }
2006               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2007             }
2008           break;
2009         }
2010       if (LocaleCompare(attribute,"stroke") == 0)
2011         {
2012           if (info)
2013             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2014           break;
2015         }
2016       if (info)
2017         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2018       for ( ; image; image=image->next)
2019         SetImageProperty(image,attribute,SvPV(sval,na));
2020       break;
2021     }
2022     case 'T':
2023     case 't':
2024     {
2025       if (LocaleCompare(attribute,"tile") == 0)
2026         {
2027           if (info)
2028             (void) CloneString(&info->image_info->tile,SvPV(sval,na));
2029           break;
2030         }
2031       if (LocaleCompare(attribute,"texture") == 0)
2032         {
2033           if (info)
2034             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2035           break;
2036         }
2037       if (LocaleCompare(attribute,"tile-offset") == 0)
2038         {
2039           char
2040             *geometry;
2041
2042           geometry=GetPageGeometry(SvPV(sval,na));
2043           if (info)
2044             (void) CloneString(&info->image_info->page,geometry);
2045           for ( ; image; image=image->next)
2046             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2047               exception);
2048           geometry=(char *) RelinquishMagickMemory(geometry);
2049           break;
2050         }
2051       if (LocaleCompare(attribute,"time-limit") == 0)
2052         {
2053           MagickSizeType
2054             limit;
2055
2056           limit=MagickResourceInfinity;
2057           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2058             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2059           (void) SetMagickResourceLimit(TimeResource,limit);
2060           break;
2061         }
2062       if (LocaleCompare(attribute,"transparent-color") == 0)
2063         {
2064           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2065           if (info)
2066             info->image_info->transparent_color=target_color;
2067           for ( ; image; image=image->next)
2068             image->transparent_color=target_color;
2069           break;
2070         }
2071       if (LocaleCompare(attribute,"type") == 0)
2072         {
2073           sp=SvPOK(sval) ? ParseMagickOption(MagickTypeOptions,MagickFalse,
2074             SvPV(sval,na)) : SvIV(sval);
2075           if (sp < 0)
2076             {
2077               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2078                 SvPV(sval,na));
2079               break;
2080             }
2081           if (info)
2082             info->image_info->type=(ImageType) sp;
2083           for ( ; image; image=image->next)
2084             SetImageType(image,(ImageType) sp);
2085           break;
2086         }
2087       if (info)
2088         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2089       for ( ; image; image=image->next)
2090         SetImageProperty(image,attribute,SvPV(sval,na));
2091       break;
2092     }
2093     case 'U':
2094     case 'u':
2095     {
2096       if (LocaleCompare(attribute,"units") == 0)
2097         {
2098           sp=SvPOK(sval) ? ParseMagickOption(MagickResolutionOptions,
2099             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2100           if (sp < 0)
2101             {
2102               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2103                 SvPV(sval,na));
2104               break;
2105             }
2106           if (info)
2107             info->image_info->units=(ResolutionType) sp;
2108           for ( ; image; image=image->next)
2109           {
2110             ResolutionType
2111               units;
2112
2113             units=(ResolutionType) sp;
2114             if (image->units != units)
2115               switch (image->units)
2116               {
2117                 case UndefinedResolution:
2118                 case PixelsPerInchResolution:
2119                 {
2120                   if (units == PixelsPerCentimeterResolution)
2121                     {
2122                       image->x_resolution*=2.54;
2123                       image->y_resolution*=2.54;
2124                     }
2125                   break;
2126                 }
2127                 case PixelsPerCentimeterResolution:
2128                 {
2129                   if (units == PixelsPerInchResolution)
2130                     {
2131                       image->x_resolution/=2.54;
2132                       image->y_resolution/=2.54;
2133                     }
2134                   break;
2135                 }
2136               }
2137             image->units=units;
2138           }
2139           break;
2140         }
2141       if (info)
2142         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2143       for ( ; image; image=image->next)
2144         SetImageProperty(image,attribute,SvPV(sval,na));
2145       break;
2146     }
2147     case 'V':
2148     case 'v':
2149     {
2150       if (LocaleCompare(attribute,"verbose") == 0)
2151         {
2152           sp=SvPOK(sval) ? ParseMagickOption(MagickBooleanOptions,MagickFalse,
2153             SvPV(sval,na)) : SvIV(sval);
2154           if (sp < 0)
2155             {
2156               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2157                 SvPV(sval,na));
2158               break;
2159             }
2160           if (info)
2161             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2162           break;
2163         }
2164       if (LocaleCompare(attribute,"view") == 0)
2165         {
2166           if (info)
2167             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2168           break;
2169         }
2170       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2171         {
2172           sp=SvPOK(sval) ? ParseMagickOption(MagickVirtualPixelOptions,
2173             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2174           if (sp < 0)
2175             {
2176               ThrowPerlException(exception,OptionError,
2177                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2178               break;
2179             }
2180           if (info)
2181             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2182           for ( ; image; image=image->next)
2183             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2184           break;
2185         }
2186       if (info)
2187         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2188       for ( ; image; image=image->next)
2189         SetImageProperty(image,attribute,SvPV(sval,na));
2190       break;
2191     }
2192     case 'W':
2193     case 'w':
2194     {
2195       if (LocaleCompare(attribute,"white-point") == 0)
2196         {
2197           for ( ; image; image=image->next)
2198           {
2199             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2200             image->chromaticity.white_point.x=geometry_info.rho;
2201             image->chromaticity.white_point.y=geometry_info.sigma;
2202             if ((flags & SigmaValue) == 0)
2203               image->chromaticity.white_point.y=
2204                 image->chromaticity.white_point.x;
2205           }
2206           break;
2207         }
2208       if (info)
2209         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2210       for ( ; image; image=image->next)
2211         SetImageProperty(image,attribute,SvPV(sval,na));
2212       break;
2213     }
2214     default:
2215     {
2216       if (info)
2217         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2218       for ( ; image; image=image->next)
2219         SetImageProperty(image,attribute,SvPV(sval,na));
2220       break;
2221     }
2222   }
2223 }
2224 \f
2225 /*
2226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2227 %                                                                             %
2228 %                                                                             %
2229 %                                                                             %
2230 %   S e t u p L i s t                                                         %
2231 %                                                                             %
2232 %                                                                             %
2233 %                                                                             %
2234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2235 %
2236 %  Method SetupList returns the list of all the images linked by their
2237 %  image->next and image->previous link lists for use with ImageMagick.  If
2238 %  info is non-NULL, an info structure is returned in *info.  If
2239 %  reference_vector is non-NULL,an array of SV* are returned in
2240 %  *reference_vector.  Reference_vector is used when the images are going to be
2241 %  replaced with new Image*'s.
2242 %
2243 %  The format of the SetupList routine is:
2244 %
2245 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2246 %        SV ***reference_vector,ExceptionInfo *exception)
2247 %
2248 %  A description of each parameter follows:
2249 %
2250 %    o list: a list of strings.
2251 %
2252 %    o string: a character string.
2253 %
2254 %    o exception: Return any errors or warnings in this structure.
2255 %
2256 */
2257 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2258   SV ***reference_vector,ExceptionInfo *exception)
2259 {
2260   Image
2261     *image;
2262
2263   long
2264     current,
2265     last;
2266
2267   if (reference_vector)
2268     *reference_vector=NULL;
2269   if (info)
2270     *info=NULL;
2271   current=0;
2272   last=0;
2273   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2274   if (info && (SvTYPE(reference) == SVt_PVAV))
2275     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2276       exception);
2277   return(image);
2278 }
2279 \f
2280 /*
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %                                                                             %
2283 %                                                                             %
2284 %                                                                             %
2285 %   s t r E Q c a s e                                                         %
2286 %                                                                             %
2287 %                                                                             %
2288 %                                                                             %
2289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2290 %
2291 %  strEQcase() compares two strings and returns 0 if they are the
2292 %  same or if the second string runs out first.  The comparison is case
2293 %  insensitive.
2294 %
2295 %  The format of the strEQcase routine is:
2296 %
2297 %      long strEQcase(const char *p,const char *q)
2298 %
2299 %  A description of each parameter follows:
2300 %
2301 %    o p: a character string.
2302 %
2303 %    o q: a character string.
2304 %
2305 %
2306 */
2307 static long strEQcase(const char *p,const char *q)
2308 {
2309   char
2310     c;
2311
2312   register long
2313     i;
2314
2315   for (i=0 ; (c=(*q)) != 0; i++)
2316   {
2317     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2318         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2319       return(0);
2320     p++;
2321     q++;
2322   }
2323   return(((*q == 0) && (*p == 0)) ? i : 0);
2324 }
2325 \f
2326 /*
2327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2328 %                                                                             %
2329 %                                                                             %
2330 %                                                                             %
2331 %   I m a g e : : M a g i c k                                                 %
2332 %                                                                             %
2333 %                                                                             %
2334 %                                                                             %
2335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2336 %
2337 %
2338 */
2339 MODULE = Image::Magick PACKAGE = Image::Magick
2340
2341 PROTOTYPES: ENABLE
2342
2343 BOOT:
2344   MagickCoreGenesis("PerlMagick",MagickFalse);
2345   SetWarningHandler(NULL);
2346   SetErrorHandler(NULL);
2347   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2348     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2349
2350 void
2351 UNLOAD()
2352   PPCODE:
2353   {
2354     if (magick_registry != (SplayTreeInfo *) NULL)
2355       magick_registry=DestroySplayTree(magick_registry);
2356     MagickCoreTerminus();
2357   }
2358
2359 double
2360 constant(name,argument)
2361   char *name
2362   long argument
2363 \f
2364 #
2365 ###############################################################################
2366 #                                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 #   A n i m a t e                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 #                                                                             #
2373 ###############################################################################
2374 #
2375 #
2376 void
2377 Animate(ref,...)
2378   Image::Magick ref=NO_INIT
2379   ALIAS:
2380     AnimateImage  = 1
2381     animate       = 2
2382     animateimage  = 3
2383   PPCODE:
2384   {
2385     ExceptionInfo
2386       *exception;
2387
2388     Image
2389       *image;
2390
2391     register long
2392       i;
2393
2394     struct PackageInfo
2395       *info,
2396       *package_info;
2397
2398     SV
2399       *perl_exception,
2400       *reference;
2401
2402     exception=AcquireExceptionInfo();
2403     perl_exception=newSVpv("",0);
2404     package_info=(struct PackageInfo *) NULL;
2405     if (sv_isobject(ST(0)) == 0)
2406       {
2407         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2408           PackageName);
2409         goto PerlException;
2410       }
2411     reference=SvRV(ST(0));
2412     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2413     if (image == (Image *) NULL)
2414       {
2415         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2416           PackageName);
2417         goto PerlException;
2418       }
2419     package_info=ClonePackageInfo(info,exception);
2420     if (items == 2)
2421       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2422     else
2423       if (items > 2)
2424         for (i=2; i < items; i+=2)
2425           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2426             exception);
2427     (void) AnimateImages(package_info->image_info,image);
2428     (void) CatchImageException(image);
2429     InheritException(exception,&image->exception);
2430
2431   PerlException:
2432     if (package_info != (struct PackageInfo *) NULL)
2433       DestroyPackageInfo(package_info);
2434     InheritPerlException(exception,perl_exception);
2435     exception=DestroyExceptionInfo(exception);
2436     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2437     SvPOK_on(perl_exception);
2438     ST(0)=sv_2mortal(perl_exception);
2439     XSRETURN(1);
2440   }
2441 \f
2442 #
2443 ###############################################################################
2444 #                                                                             #
2445 #                                                                             #
2446 #                                                                             #
2447 #   A p p e n d                                                               #
2448 #                                                                             #
2449 #                                                                             #
2450 #                                                                             #
2451 ###############################################################################
2452 #
2453 #
2454 void
2455 Append(ref,...)
2456   Image::Magick ref=NO_INIT
2457   ALIAS:
2458     AppendImage  = 1
2459     append       = 2
2460     appendimage  = 3
2461   PPCODE:
2462   {
2463     AV
2464       *av;
2465
2466     char
2467       *attribute;
2468
2469     ExceptionInfo
2470       *exception;
2471
2472     HV
2473       *hv;
2474
2475     Image
2476       *image;
2477
2478     long
2479       stack;
2480
2481     register long
2482       i;
2483
2484     struct PackageInfo
2485       *info;
2486
2487     SV
2488       *av_reference,
2489       *perl_exception,
2490       *reference,
2491       *rv,
2492       *sv;
2493
2494     exception=AcquireExceptionInfo();
2495     perl_exception=newSVpv("",0);
2496     attribute=NULL;
2497     av=NULL;
2498     if (sv_isobject(ST(0)) == 0)
2499       {
2500         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2501           PackageName);
2502         goto PerlException;
2503       }
2504     reference=SvRV(ST(0));
2505     hv=SvSTASH(reference);
2506     av=newAV();
2507     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2508     SvREFCNT_dec(av);
2509     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2510     if (image == (Image *) NULL)
2511       {
2512         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2513           PackageName);
2514         goto PerlException;
2515       }
2516     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2517     /*
2518       Get options.
2519     */
2520     stack=MagickTrue;
2521     for (i=2; i < items; i+=2)
2522     {
2523       attribute=(char *) SvPV(ST(i-1),na);
2524       switch (*attribute)
2525       {
2526         case 'S':
2527         case 's':
2528         {
2529           if (LocaleCompare(attribute,"stack") == 0)
2530             {
2531               stack=ParseMagickOption(MagickBooleanOptions,MagickFalse,
2532                 SvPV(ST(i),na));
2533               if (stack < 0)
2534                 {
2535                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2536                     SvPV(ST(i),na));
2537                   return;
2538                 }
2539               break;
2540             }
2541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2542             attribute);
2543           break;
2544         }
2545         default:
2546         {
2547           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2548             attribute);
2549           break;
2550         }
2551       }
2552     }
2553     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2554     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2555       goto PerlException;
2556     for ( ; image; image=image->next)
2557     {
2558       AddImageToRegistry(image);
2559       rv=newRV(sv);
2560       av_push(av,sv_bless(rv,hv));
2561       SvREFCNT_dec(sv);
2562     }
2563     exception=DestroyExceptionInfo(exception);
2564     ST(0)=av_reference;
2565     SvREFCNT_dec(perl_exception);
2566     XSRETURN(1);
2567
2568   PerlException:
2569     InheritPerlException(exception,perl_exception);
2570     exception=DestroyExceptionInfo(exception);
2571     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2572     SvPOK_on(perl_exception);
2573     ST(0)=sv_2mortal(perl_exception);
2574     XSRETURN(1);
2575   }
2576 \f
2577 #
2578 ###############################################################################
2579 #                                                                             #
2580 #                                                                             #
2581 #                                                                             #
2582 #   A v e r a g e                                                             #
2583 #                                                                             #
2584 #                                                                             #
2585 #                                                                             #
2586 ###############################################################################
2587 #
2588 #
2589 void
2590 Average(ref)
2591   Image::Magick ref=NO_INIT
2592   ALIAS:
2593     AverageImage   = 1
2594     average        = 2
2595     averageimage   = 3
2596   PPCODE:
2597   {
2598     AV
2599       *av;
2600
2601     char
2602       *p;
2603
2604     ExceptionInfo
2605       *exception;
2606
2607     HV
2608       *hv;
2609
2610     Image
2611       *image;
2612
2613     struct PackageInfo
2614       *info;
2615
2616     SV
2617       *perl_exception,
2618       *reference,
2619       *rv,
2620       *sv;
2621
2622     exception=AcquireExceptionInfo();
2623     perl_exception=newSVpv("",0);
2624     if (sv_isobject(ST(0)) == 0)
2625       {
2626         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2627           PackageName);
2628         goto PerlException;
2629       }
2630     reference=SvRV(ST(0));
2631     hv=SvSTASH(reference);
2632     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2633     if (image == (Image *) NULL)
2634       {
2635         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2636           PackageName);
2637         goto PerlException;
2638       }
2639     image=AverageImages(image,exception);
2640     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2641       goto PerlException;
2642     /*
2643       Create blessed Perl array for the returned image.
2644     */
2645     av=newAV();
2646     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2647     SvREFCNT_dec(av);
2648     AddImageToRegistry(image);
2649     rv=newRV(sv);
2650     av_push(av,sv_bless(rv,hv));
2651     SvREFCNT_dec(sv);
2652     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2653     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
2654       "average-%.*s",(int) (MaxTextExtent-9),
2655       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2656     (void) CopyMagickString(image->filename,info->image_info->filename,
2657       MaxTextExtent);
2658     SetImageInfo(info->image_info,MagickFalse,exception);
2659     exception=DestroyExceptionInfo(exception);
2660     SvREFCNT_dec(perl_exception);
2661     XSRETURN(1);
2662
2663   PerlException:
2664     InheritPerlException(exception,perl_exception);
2665     exception=DestroyExceptionInfo(exception);
2666     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2667     SvPOK_on(perl_exception);
2668     ST(0)=sv_2mortal(perl_exception);
2669     XSRETURN(1);
2670   }
2671 \f
2672 #
2673 ###############################################################################
2674 #                                                                             #
2675 #                                                                             #
2676 #                                                                             #
2677 #   B l o b T o I m a g e                                                     #
2678 #                                                                             #
2679 #                                                                             #
2680 #                                                                             #
2681 ###############################################################################
2682 #
2683 #
2684 void
2685 BlobToImage(ref,...)
2686   Image::Magick ref=NO_INIT
2687   ALIAS:
2688     BlobToImage  = 1
2689     blobtoimage  = 2
2690     blobto       = 3
2691   PPCODE:
2692   {
2693     AV
2694       *av;
2695
2696     char
2697       **keep,
2698       **list;
2699
2700     ExceptionInfo
2701       *exception;
2702
2703     HV
2704       *hv;
2705
2706     Image
2707       *image;
2708
2709     long
2710       ac,
2711       n,
2712       number_images;
2713
2714     register char
2715       **p;
2716
2717     register long
2718       i;
2719
2720     STRLEN
2721       *length;
2722
2723     struct PackageInfo
2724       *info;
2725
2726     SV
2727       *perl_exception,
2728       *reference,
2729       *rv,
2730       *sv;
2731
2732     exception=AcquireExceptionInfo();
2733     perl_exception=newSVpv("",0);
2734     number_images=0;
2735     ac=(items < 2) ? 1 : items-1;
2736     length=(STRLEN *) NULL;
2737     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2738     if (list == (char **) NULL)
2739       {
2740         ThrowPerlException(exception,ResourceLimitError,
2741           "MemoryAllocationFailed",PackageName);
2742         goto PerlException;
2743       }
2744     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2745     if (length == (STRLEN *) NULL)
2746       {
2747         ThrowPerlException(exception,ResourceLimitError,
2748           "MemoryAllocationFailed",PackageName);
2749         goto PerlException;
2750       }
2751     if (sv_isobject(ST(0)) == 0)
2752       {
2753         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2754           PackageName);
2755         goto PerlException;
2756       }
2757     reference=SvRV(ST(0));
2758     hv=SvSTASH(reference);
2759     if (SvTYPE(reference) != SVt_PVAV)
2760       {
2761         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2762           PackageName);
2763         goto PerlException;
2764       }
2765     av=(AV *) reference;
2766     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2767       exception);
2768     n=1;
2769     if (items <= 1)
2770       {
2771         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2772         goto PerlException;
2773       }
2774     for (n=0, i=0; i < ac; i++)
2775     {
2776       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2777       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2778         {
2779           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2780           continue;
2781         }
2782       n++;
2783     }
2784     list[n]=(char *) NULL;
2785     keep=list;
2786     for (i=number_images=0; i < n; i++)
2787     {
2788       image=BlobToImage(info->image_info,list[i],length[i],exception);
2789       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2790         break;
2791       for ( ; image; image=image->next)
2792       {
2793         AddImageToRegistry(image);
2794         rv=newRV(sv);
2795         av_push(av,sv_bless(rv,hv));
2796         SvREFCNT_dec(sv);
2797         number_images++;
2798       }
2799     }
2800     /*
2801       Free resources.
2802     */
2803     for (i=0; i < n; i++)
2804       if (list[i] != (char *) NULL)
2805         for (p=keep; list[i] != *p++; )
2806           if (*p == (char *) NULL)
2807             {
2808               list[i]=(char *) RelinquishMagickMemory(list[i]);
2809               break;
2810             }
2811
2812   PerlException:
2813     if (list)
2814       list=(char **) RelinquishMagickMemory(list);
2815     if (length)
2816       length=(STRLEN *) RelinquishMagickMemory(length);
2817     InheritPerlException(exception,perl_exception);
2818     exception=DestroyExceptionInfo(exception);
2819     sv_setiv(perl_exception,(IV) number_images);
2820     SvPOK_on(perl_exception);
2821     ST(0)=sv_2mortal(perl_exception);
2822     XSRETURN(1);
2823   }
2824 \f
2825 #
2826 ###############################################################################
2827 #                                                                             #
2828 #                                                                             #
2829 #                                                                             #
2830 #   C l o n e                                                                 #
2831 #                                                                             #
2832 #                                                                             #
2833 #                                                                             #
2834 ###############################################################################
2835 #
2836 #
2837 void
2838 Clone(ref)
2839   Image::Magick ref=NO_INIT
2840   ALIAS:
2841     CopyImage   = 1
2842     copy        = 2
2843     copyimage   = 3
2844     CloneImage  = 4
2845     clone       = 5
2846     cloneimage  = 6
2847     Clone       = 7
2848   PPCODE:
2849   {
2850     AV
2851       *av;
2852
2853     ExceptionInfo
2854       *exception;
2855
2856     HV
2857       *hv;
2858
2859     Image
2860       *clone,
2861       *image;
2862
2863     struct PackageInfo
2864       *info;
2865
2866     SV
2867       *perl_exception,
2868       *reference,
2869       *rv,
2870       *sv;
2871
2872     exception=AcquireExceptionInfo();
2873     perl_exception=newSVpv("",0);
2874     if (sv_isobject(ST(0)) == 0)
2875       {
2876         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2877           PackageName);
2878         goto PerlException;
2879       }
2880     reference=SvRV(ST(0));
2881     hv=SvSTASH(reference);
2882     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2883     if (image == (Image *) NULL)
2884       {
2885         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2886           PackageName);
2887         goto PerlException;
2888       }
2889     /*
2890       Create blessed Perl array for the returned image.
2891     */
2892     av=newAV();
2893     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2894     SvREFCNT_dec(av);
2895     for ( ; image; image=image->next)
2896     {
2897       clone=CloneImage(image,0,0,MagickTrue,exception);
2898       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2899         break;
2900       AddImageToRegistry(clone);
2901       rv=newRV(sv);
2902       av_push(av,sv_bless(rv,hv));
2903       SvREFCNT_dec(sv);
2904     }
2905     exception=DestroyExceptionInfo(exception);
2906     SvREFCNT_dec(perl_exception);
2907     XSRETURN(1);
2908
2909   PerlException:
2910     InheritPerlException(exception,perl_exception);
2911     exception=DestroyExceptionInfo(exception);
2912     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2913     SvPOK_on(perl_exception);
2914     ST(0)=sv_2mortal(perl_exception);
2915     XSRETURN(1);
2916   }
2917 \f
2918 #
2919 ###############################################################################
2920 #                                                                             #
2921 #                                                                             #
2922 #                                                                             #
2923 #   C L O N E                                                                 #
2924 #                                                                             #
2925 #                                                                             #
2926 #                                                                             #
2927 ###############################################################################
2928 #
2929 #
2930 void
2931 CLONE(ref,...)
2932   SV *ref;
2933   CODE:
2934   {
2935     if (magick_registry != (SplayTreeInfo *) NULL)
2936       {
2937         register Image
2938           *p;
2939
2940         ResetSplayTreeIterator(magick_registry);
2941         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2942         while (p != (Image *) NULL)
2943         {
2944           ReferenceImage(p);
2945           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2946         }
2947       }
2948   }
2949 \f
2950 #
2951 ###############################################################################
2952 #                                                                             #
2953 #                                                                             #
2954 #                                                                             #
2955 #   C o a l e s c e                                                           #
2956 #                                                                             #
2957 #                                                                             #
2958 #                                                                             #
2959 ###############################################################################
2960 #
2961 #
2962 void
2963 Coalesce(ref)
2964   Image::Magick ref=NO_INIT
2965   ALIAS:
2966     CoalesceImage   = 1
2967     coalesce        = 2
2968     coalesceimage   = 3
2969   PPCODE:
2970   {
2971     AV
2972       *av;
2973
2974     ExceptionInfo
2975       *exception;
2976
2977     HV
2978       *hv;
2979
2980     Image
2981       *image;
2982
2983     struct PackageInfo
2984       *info;
2985
2986     SV
2987       *av_reference,
2988       *perl_exception,
2989       *reference,
2990       *rv,
2991       *sv;
2992
2993     exception=AcquireExceptionInfo();
2994     perl_exception=newSVpv("",0);
2995     if (sv_isobject(ST(0)) == 0)
2996       {
2997         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2998           PackageName);
2999         goto PerlException;
3000       }
3001     reference=SvRV(ST(0));
3002     hv=SvSTASH(reference);
3003     av=newAV();
3004     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3005     SvREFCNT_dec(av);
3006     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3007     if (image == (Image *) NULL)
3008       {
3009         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3010           PackageName);
3011         goto PerlException;
3012       }
3013     image=CoalesceImages(image,exception);
3014     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3015       goto PerlException;
3016     for ( ; image; image=image->next)
3017     {
3018       AddImageToRegistry(image);
3019       rv=newRV(sv);
3020       av_push(av,sv_bless(rv,hv));
3021       SvREFCNT_dec(sv);
3022     }
3023     exception=DestroyExceptionInfo(exception);
3024     ST(0)=av_reference;
3025     SvREFCNT_dec(perl_exception);
3026     XSRETURN(1);
3027
3028   PerlException:
3029     InheritPerlException(exception,perl_exception);
3030     exception=DestroyExceptionInfo(exception);
3031     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3032     SvPOK_on(perl_exception);
3033     ST(0)=sv_2mortal(perl_exception);
3034     XSRETURN(1);
3035   }
3036 \f
3037 #
3038 ###############################################################################
3039 #                                                                             #
3040 #                                                                             #
3041 #                                                                             #
3042 #   C o m p a r e                                                             #
3043 #                                                                             #
3044 #                                                                             #
3045 #                                                                             #
3046 ###############################################################################
3047 #
3048 #
3049 void
3050 Compare(ref,...)
3051   Image::Magick ref=NO_INIT
3052   ALIAS:
3053     CompareImage = 1
3054     compare      = 2
3055     compareimage = 3
3056   PPCODE:
3057   {
3058     AV
3059       *av;
3060
3061     char
3062       *attribute;
3063
3064     ChannelType
3065       channel;
3066
3067     double
3068       distortion;
3069
3070     ExceptionInfo
3071       *exception;
3072
3073     HV
3074       *hv;
3075
3076     Image
3077       *difference_image,
3078       *image,
3079       *reconstruct_image;
3080
3081     long
3082       option;
3083
3084     MetricType
3085       metric;
3086
3087     register long
3088       i;
3089
3090     struct PackageInfo
3091       *info;
3092
3093     SV
3094       *av_reference,
3095       *perl_exception,
3096       *reference,
3097       *rv,
3098       *sv;
3099
3100     exception=AcquireExceptionInfo();
3101     perl_exception=newSVpv("",0);
3102     av=NULL;
3103     attribute=NULL;
3104     if (sv_isobject(ST(0)) == 0)
3105       {
3106         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3107           PackageName);
3108         goto PerlException;
3109       }
3110     reference=SvRV(ST(0));
3111     hv=SvSTASH(reference);
3112     av=newAV();
3113     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3114     SvREFCNT_dec(av);
3115     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3116     if (image == (Image *) NULL)
3117       {
3118         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3119           PackageName);
3120         goto PerlException;
3121       }
3122     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3123     /*
3124       Get attribute.
3125     */
3126     channel=DefaultChannels;
3127     reconstruct_image=image;
3128     metric=RootMeanSquaredErrorMetric;
3129     for (i=2; i < items; i+=2)
3130     {
3131       attribute=(char *) SvPV(ST(i-1),na);
3132       switch (*attribute)
3133       {
3134         case 'C':
3135         case 'c':
3136         {
3137           if (LocaleCompare(attribute,"channel") == 0)
3138             {
3139               long
3140                 option;
3141
3142               option=ParseChannelOption(SvPV(ST(i),na));
3143               if (option < 0)
3144                 {
3145                   ThrowPerlException(exception,OptionError,
3146                     "UnrecognizedType",SvPV(ST(i),na));
3147                   return;
3148                 }
3149               channel=(ChannelType) option;
3150               break;
3151             }
3152           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3153             attribute);
3154           break;
3155         }
3156         case 'F':
3157         case 'f':
3158         {
3159           if (LocaleCompare(attribute,"fuzz") == 0)
3160             {
3161               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3162               break;
3163             }
3164           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3165             attribute);
3166           break;
3167         }
3168         case 'I':
3169         case 'i':
3170         {
3171           if (LocaleCompare(attribute,"image") == 0)
3172             {
3173               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3174                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3175             }
3176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3177             attribute);
3178           break;
3179         }
3180         case 'M':
3181         case 'm':
3182         {
3183           if (LocaleCompare(attribute,"metric") == 0)
3184             {
3185               option=ParseMagickOption(MagickMetricOptions,MagickFalse,
3186                 SvPV(ST(i),na));
3187               if (option < 0)
3188                 {
3189                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3190                     SvPV(ST(i),na));
3191                   break;
3192                 }
3193                metric=(MetricType) option;
3194               break;
3195             }
3196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3197             attribute);
3198           break;
3199         }
3200         default:
3201         {
3202           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3203             attribute);
3204           break;
3205         }
3206       }
3207     }
3208     difference_image=CompareImageChannels(image,reconstruct_image,channel,
3209       metric,&distortion,exception);
3210     if (difference_image != (Image *) NULL)
3211       {
3212         difference_image->error.mean_error_per_pixel=distortion;
3213         AddImageToRegistry(difference_image);
3214         rv=newRV(sv);
3215         av_push(av,sv_bless(rv,hv));
3216         SvREFCNT_dec(sv);
3217       }
3218     exception=DestroyExceptionInfo(exception);
3219     ST(0)=av_reference;
3220     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3221     XSRETURN(1);
3222
3223   PerlException:
3224     InheritPerlException(exception,perl_exception);
3225     exception=DestroyExceptionInfo(exception);
3226     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3227     SvPOK_on(perl_exception);
3228     ST(0)=sv_2mortal(perl_exception);
3229     XSRETURN(1);
3230   }
3231 \f
3232 #
3233 ###############################################################################
3234 #                                                                             #
3235 #                                                                             #
3236 #                                                                             #
3237 #   C o m p a r e L a y e r s                                                 #
3238 #                                                                             #
3239 #                                                                             #
3240 #                                                                             #
3241 ###############################################################################
3242 #
3243 #
3244 void
3245 CompareLayers(ref)
3246   Image::Magick ref=NO_INIT
3247   ALIAS:
3248     CompareImageLayers   = 1
3249     comparelayers        = 2
3250     compareimagelayers   = 3
3251   PPCODE:
3252   {
3253     AV
3254       *av;
3255
3256     char
3257       *attribute;
3258
3259     ExceptionInfo
3260       *exception;
3261
3262     HV
3263       *hv;
3264
3265     Image
3266       *image;
3267
3268     long
3269       option;
3270
3271     ImageLayerMethod
3272       method;
3273
3274     register long
3275       i;
3276
3277     struct PackageInfo
3278       *info;
3279
3280     SV
3281       *av_reference,
3282       *perl_exception,
3283       *reference,
3284       *rv,
3285       *sv;
3286
3287     exception=AcquireExceptionInfo();
3288     perl_exception=newSVpv("",0);
3289     if (sv_isobject(ST(0)) == 0)
3290       {
3291         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3292           PackageName);
3293         goto PerlException;
3294       }
3295     reference=SvRV(ST(0));
3296     hv=SvSTASH(reference);
3297     av=newAV();
3298     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3299     SvREFCNT_dec(av);
3300     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3301     if (image == (Image *) NULL)
3302       {
3303         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3304           PackageName);
3305         goto PerlException;
3306       }
3307     method=CompareAnyLayer;
3308     for (i=2; i < items; i+=2)
3309     {
3310       attribute=(char *) SvPV(ST(i-1),na);
3311       switch (*attribute)
3312       {
3313         case 'M':
3314         case 'm':
3315         {
3316           if (LocaleCompare(attribute,"method") == 0)
3317             {
3318               option=ParseMagickOption(MagickLayerOptions,MagickFalse,
3319                 SvPV(ST(i),na));
3320               if (option < 0)
3321                 {
3322                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3323                     SvPV(ST(i),na));
3324                   break;
3325                 }
3326                method=(ImageLayerMethod) option;
3327               break;
3328             }
3329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3330             attribute);
3331           break;
3332         }
3333         default:
3334         {
3335           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3336             attribute);
3337           break;
3338         }
3339       }
3340     }
3341     image=CompareImageLayers(image,method,exception);
3342     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3343       goto PerlException;
3344     for ( ; image; image=image->next)
3345     {
3346       AddImageToRegistry(image);
3347       rv=newRV(sv);
3348       av_push(av,sv_bless(rv,hv));
3349       SvREFCNT_dec(sv);
3350     }
3351     exception=DestroyExceptionInfo(exception);
3352     ST(0)=av_reference;
3353     SvREFCNT_dec(perl_exception);
3354     XSRETURN(1);
3355
3356   PerlException:
3357     InheritPerlException(exception,perl_exception);
3358     exception=DestroyExceptionInfo(exception);
3359     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3360     SvPOK_on(perl_exception);
3361     ST(0)=sv_2mortal(perl_exception);
3362     XSRETURN(1);
3363   }
3364 \f
3365 #
3366 ###############################################################################
3367 #                                                                             #
3368 #                                                                             #
3369 #                                                                             #
3370 #   D e s t r o y                                                             #
3371 #                                                                             #
3372 #                                                                             #
3373 #                                                                             #
3374 ###############################################################################
3375 #
3376 #
3377 void
3378 DESTROY(ref)
3379   Image::Magick ref=NO_INIT
3380   PPCODE:
3381   {
3382     SV
3383       *reference;
3384
3385     if (sv_isobject(ST(0)) == 0)
3386       croak("ReferenceIsNotMyType");
3387     reference=SvRV(ST(0));
3388     switch (SvTYPE(reference))
3389     {
3390       case SVt_PVAV:
3391       {
3392         char
3393           message[MaxTextExtent];
3394
3395         struct PackageInfo
3396           *info;
3397
3398         HV
3399           *hv;
3400
3401         GV
3402           **gvp;
3403
3404         SV
3405           *sv;
3406
3407         /*
3408           Array (AV *) reference
3409         */
3410         (void) FormatMagickString(message,MaxTextExtent,"package%s%lx",
3411           XS_VERSION,(long) reference);
3412         hv=gv_stashpv(PackageName, FALSE);
3413         if (!hv)
3414           break;
3415         gvp=(GV **) hv_fetch(hv,message,strlen(message),FALSE);
3416         if (!gvp)
3417           break;
3418         sv=GvSV(*gvp);
3419         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3420           {
3421             info=(struct PackageInfo *) SvIV(sv);
3422             DestroyPackageInfo(info);
3423           }
3424         hv_delete(hv,message,strlen(message),G_DISCARD);
3425         break;
3426       }
3427       case SVt_PVMG:
3428       {
3429         Image
3430           *image;
3431
3432         /*
3433           Blessed scalar = (Image *) SvIV(reference)
3434         */
3435         image=(Image *) SvIV(reference);
3436         if (image != (Image *) NULL)
3437           DeleteImageFromRegistry(reference,image);
3438         break;
3439       }
3440       default:
3441         break;
3442     }
3443   }
3444 \f
3445 #
3446 ###############################################################################
3447 #                                                                             #
3448 #                                                                             #
3449 #                                                                             #
3450 #   D i s p l a y                                                             #
3451 #                                                                             #
3452 #                                                                             #
3453 #                                                                             #
3454 ###############################################################################
3455 #
3456 #
3457 void
3458 Display(ref,...)
3459   Image::Magick ref=NO_INIT
3460   ALIAS:
3461     DisplayImage  = 1
3462     display       = 2
3463     displayimage  = 3
3464   PPCODE:
3465   {
3466     ExceptionInfo
3467       *exception;
3468
3469     Image
3470       *image;
3471
3472     register long
3473       i;
3474
3475     struct PackageInfo
3476       *info,
3477       *package_info;
3478
3479     SV
3480       *perl_exception,
3481       *reference;
3482
3483     exception=AcquireExceptionInfo();
3484     perl_exception=newSVpv("",0);
3485     package_info=(struct PackageInfo *) NULL;
3486     if (sv_isobject(ST(0)) == 0)
3487       {
3488         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3489           PackageName);
3490         goto PerlException;
3491       }
3492     reference=SvRV(ST(0));
3493     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3494     if (image == (Image *) NULL)
3495       {
3496         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3497           PackageName);
3498         goto PerlException;
3499       }
3500     package_info=ClonePackageInfo(info,exception);
3501     if (items == 2)
3502       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3503     else
3504       if (items > 2)
3505         for (i=2; i < items; i+=2)
3506           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3507             exception);
3508     (void) DisplayImages(package_info->image_info,image);
3509     (void) CatchImageException(image);
3510     InheritException(exception,&image->exception);
3511
3512   PerlException:
3513     if (package_info != (struct PackageInfo *) NULL)
3514       DestroyPackageInfo(package_info);
3515     InheritPerlException(exception,perl_exception);
3516     exception=DestroyExceptionInfo(exception);
3517     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3518     SvPOK_on(perl_exception);
3519     ST(0)=sv_2mortal(perl_exception);
3520     XSRETURN(1);
3521   }
3522 \f
3523 #
3524 ###############################################################################
3525 #                                                                             #
3526 #                                                                             #
3527 #                                                                             #
3528 #   F e a t u r e s                                                           #
3529 #                                                                             #
3530 #                                                                             #
3531 #                                                                             #
3532 ###############################################################################
3533 #
3534 #
3535 void
3536 Features(ref,...)
3537   Image::Magick ref=NO_INIT
3538   ALIAS:
3539     FeaturesImage = 1
3540     features      = 2
3541     featuresimage = 3
3542   PPCODE:
3543   {
3544 #define ChannelFeatures(channel,direction) \
3545 { \
3546   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3547     channel_features[channel].angular_second_moment[direction]); \
3548   PUSHs(sv_2mortal(newSVpv(message,0))); \
3549   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3550     channel_features[channel].contrast[direction]); \
3551   PUSHs(sv_2mortal(newSVpv(message,0))); \
3552   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3553     channel_features[channel].contrast[direction]); \
3554   PUSHs(sv_2mortal(newSVpv(message,0))); \
3555   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3556     channel_features[channel].variance_sum_of_squares[direction]); \
3557   PUSHs(sv_2mortal(newSVpv(message,0))); \
3558   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3559     channel_features[channel].inverse_difference_moment[direction]); \
3560   PUSHs(sv_2mortal(newSVpv(message,0))); \
3561   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3562     channel_features[channel].sum_average[direction]); \
3563   PUSHs(sv_2mortal(newSVpv(message,0))); \
3564   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3565     channel_features[channel].sum_variance[direction]); \
3566   PUSHs(sv_2mortal(newSVpv(message,0))); \
3567   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3568     channel_features[channel].sum_entropy[direction]); \
3569   PUSHs(sv_2mortal(newSVpv(message,0))); \
3570   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3571     channel_features[channel].entropy[direction]); \
3572   PUSHs(sv_2mortal(newSVpv(message,0))); \
3573   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3574     channel_features[channel].difference_variance[direction]); \
3575   PUSHs(sv_2mortal(newSVpv(message,0))); \
3576   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3577     channel_features[channel].difference_entropy[direction]); \
3578   PUSHs(sv_2mortal(newSVpv(message,0))); \
3579   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3580     channel_features[channel].measure_of_correlation_1[direction]); \
3581   PUSHs(sv_2mortal(newSVpv(message,0))); \
3582   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3583     channel_features[channel].measure_of_correlation_2[direction]); \
3584   PUSHs(sv_2mortal(newSVpv(message,0))); \
3585   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3586     channel_features[channel].maximum_correlation_coefficient[direction]); \
3587   PUSHs(sv_2mortal(newSVpv(message,0))); \
3588 }
3589
3590     AV
3591       *av;
3592
3593     char
3594       *attribute,
3595       message[MaxTextExtent];
3596
3597     ChannelFeatures
3598       *channel_features;
3599
3600     double
3601       distance,
3602       scale;
3603
3604     ExceptionInfo
3605       *exception;
3606
3607     HV
3608       *hv;
3609
3610     Image
3611       *image;
3612
3613     register long
3614       i;
3615
3616     ssize_t
3617       count;
3618
3619     struct PackageInfo
3620       *info;
3621
3622     SV
3623       *av_reference,
3624       *perl_exception,
3625       *reference;
3626
3627     exception=AcquireExceptionInfo();
3628     perl_exception=newSVpv("",0);
3629     av=NULL;
3630     if (sv_isobject(ST(0)) == 0)
3631       {
3632         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3633           PackageName);
3634         goto PerlException;
3635       }
3636     reference=SvRV(ST(0));
3637     hv=SvSTASH(reference);
3638     av=newAV();
3639     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3640     SvREFCNT_dec(av);
3641     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3642     if (image == (Image *) NULL)
3643       {
3644         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3645           PackageName);
3646         goto PerlException;
3647       }
3648     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3649     distance=1;
3650     for (i=2; i < items; i+=2)
3651     {
3652       attribute=(char *) SvPV(ST(i-1),na);
3653       switch (*attribute)
3654       {
3655         case 'D':
3656         case 'd':
3657         {
3658           if (LocaleCompare(attribute,"distance") == 0)
3659             {
3660               distance=StringToLong((char *) SvPV(ST(1),na));
3661               break;
3662             }
3663           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3664             attribute);
3665           break;
3666         }
3667         default:
3668         {
3669           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3670             attribute);
3671           break;
3672         }
3673       }
3674     }
3675     count=0;
3676     for ( ; image; image=image->next)
3677     {
3678       channel_features=GetImageChannelFeatures(image,distance,
3679         &image->exception);
3680       if (channel_features == (ChannelFeatures *) NULL)
3681         continue;
3682       count++;
3683       EXTEND(sp,75*count);
3684       for (i=0; i < 4; i++)
3685       {
3686         ChannelFeatures(RedChannel,i);
3687         ChannelFeatures(GreenChannel,i);
3688         ChannelFeatures(BlueChannel,i);
3689         if (image->colorspace == CMYKColorspace)
3690           ChannelFeatures(IndexChannel,i);
3691         if (image->matte != MagickFalse)
3692           ChannelFeatures(OpacityChannel,i);
3693       }
3694       channel_features=(ChannelFeatures *)
3695         RelinquishMagickMemory(channel_features);
3696     }
3697
3698   PerlException:
3699     InheritPerlException(exception,perl_exception);
3700     exception=DestroyExceptionInfo(exception);
3701     SvREFCNT_dec(perl_exception);
3702   }
3703 \f
3704 #
3705 ###############################################################################
3706 #                                                                             #
3707 #                                                                             #
3708 #                                                                             #
3709 #   F l a t t e n                                                             #
3710 #                                                                             #
3711 #                                                                             #
3712 #                                                                             #
3713 ###############################################################################
3714 #
3715 #
3716 void
3717 Flatten(ref)
3718   Image::Magick ref=NO_INIT
3719   ALIAS:
3720     FlattenImage   = 1
3721     flatten        = 2
3722     flattenimage   = 3
3723   PPCODE:
3724   {
3725     AV
3726       *av;
3727
3728     char
3729       *attribute,
3730       *p;
3731
3732     ExceptionInfo
3733       *exception;
3734
3735     HV
3736       *hv;
3737
3738     Image
3739       *image;
3740
3741     PixelPacket
3742       background_color;
3743
3744     register long
3745       i;
3746
3747     struct PackageInfo
3748       *info;
3749
3750     SV
3751       *perl_exception,
3752       *reference,
3753       *rv,
3754       *sv;
3755
3756     exception=AcquireExceptionInfo();
3757     perl_exception=newSVpv("",0);
3758     if (sv_isobject(ST(0)) == 0)
3759       {
3760         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3761           PackageName);
3762         goto PerlException;
3763       }
3764     reference=SvRV(ST(0));
3765     hv=SvSTASH(reference);
3766     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3767     if (image == (Image *) NULL)
3768       {
3769         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3770           PackageName);
3771         goto PerlException;
3772       }
3773     background_color=image->background_color;
3774     if (items == 2)
3775       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3776         exception);
3777     else
3778       for (i=2; i < items; i+=2)
3779       {
3780         attribute=(char *) SvPV(ST(i-1),na);
3781         switch (*attribute)
3782         {
3783           case 'B':
3784           case 'b':
3785           {
3786             if (LocaleCompare(attribute,"background") == 0)
3787               {
3788                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3789                   &background_color,exception);
3790                 break;
3791               }
3792             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3793               attribute);
3794             break;
3795           }
3796           default:
3797           {
3798             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3799               attribute);
3800             break;
3801           }
3802         }
3803       }
3804     image->background_color=background_color;
3805     image=MergeImageLayers(image,FlattenLayer,exception);
3806     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3807       goto PerlException;
3808     /*
3809       Create blessed Perl array for the returned image.
3810     */
3811     av=newAV();
3812     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3813     SvREFCNT_dec(av);
3814     AddImageToRegistry(image);
3815     rv=newRV(sv);
3816     av_push(av,sv_bless(rv,hv));
3817     SvREFCNT_dec(sv);
3818     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3819     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
3820       "flatten-%.*s",(int) (MaxTextExtent-9),
3821       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3822     (void) CopyMagickString(image->filename,info->image_info->filename,
3823       MaxTextExtent);
3824     SetImageInfo(info->image_info,MagickFalse,exception);
3825     exception=DestroyExceptionInfo(exception);
3826     SvREFCNT_dec(perl_exception);
3827     XSRETURN(1);
3828
3829   PerlException:
3830     InheritPerlException(exception,perl_exception);
3831     exception=DestroyExceptionInfo(exception);
3832     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3833     SvPOK_on(perl_exception);  /* return messages in string context */
3834     ST(0)=sv_2mortal(perl_exception);
3835     XSRETURN(1);
3836   }
3837 \f
3838 #
3839 ###############################################################################
3840 #                                                                             #
3841 #                                                                             #
3842 #                                                                             #
3843 #   F x                                                                       #
3844 #                                                                             #
3845 #                                                                             #
3846 #                                                                             #
3847 ###############################################################################
3848 #
3849 #
3850 void
3851 Fx(ref,...)
3852   Image::Magick ref=NO_INIT
3853   ALIAS:
3854     FxImage  = 1
3855     fx       = 2
3856     fximage  = 3
3857   PPCODE:
3858   {
3859     AV
3860       *av;
3861
3862     char
3863       *attribute,
3864       expression[MaxTextExtent];
3865
3866     ChannelType
3867       channel;
3868
3869     ExceptionInfo
3870       *exception;
3871
3872     HV
3873       *hv;
3874
3875     Image
3876       *image;
3877
3878     register long
3879       i;
3880
3881     struct PackageInfo
3882       *info;
3883
3884     SV
3885       *av_reference,
3886       *perl_exception,
3887       *reference,
3888       *rv,
3889       *sv;
3890
3891     exception=AcquireExceptionInfo();
3892     perl_exception=newSVpv("",0);
3893     attribute=NULL;
3894     av=NULL;
3895     if (sv_isobject(ST(0)) == 0)
3896       {
3897         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3898           PackageName);
3899         goto PerlException;
3900       }
3901     reference=SvRV(ST(0));
3902     hv=SvSTASH(reference);
3903     av=newAV();
3904     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3905     SvREFCNT_dec(av);
3906     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3907     if (image == (Image *) NULL)
3908       {
3909         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3910           PackageName);
3911         goto PerlException;
3912       }
3913     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3914     /*
3915       Get options.
3916     */
3917     channel=DefaultChannels;
3918     (void) CopyMagickString(expression,"u",MaxTextExtent);
3919     if (items == 2)
3920       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
3921     else
3922       for (i=2; i < items; i+=2)
3923       {
3924         attribute=(char *) SvPV(ST(i-1),na);
3925         switch (*attribute)
3926         {
3927           case 'C':
3928           case 'c':
3929           {
3930             if (LocaleCompare(attribute,"channel") == 0)
3931               {
3932                 long
3933                   option;
3934
3935                 option=ParseChannelOption(SvPV(ST(i),na));
3936                 if (option < 0)
3937                   {
3938                     ThrowPerlException(exception,OptionError,
3939                       "UnrecognizedType",SvPV(ST(i),na));
3940                     return;
3941                   }
3942                 channel=(ChannelType) option;
3943                 break;
3944               }
3945             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3946               attribute);
3947             break;
3948           }
3949           case 'E':
3950           case 'e':
3951           {
3952             if (LocaleCompare(attribute,"expression") == 0)
3953               {
3954                 (void) CopyMagickString(expression,SvPV(ST(i),na),
3955                   MaxTextExtent);
3956                 break;
3957               }
3958             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3959               attribute);
3960             break;
3961           }
3962           default:
3963           {
3964             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3965               attribute);
3966             break;
3967           }
3968         }
3969       }
3970     image=FxImageChannel(image,channel,expression,exception);
3971     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3972       goto PerlException;
3973     for ( ; image; image=image->next)
3974     {
3975       AddImageToRegistry(image);
3976       rv=newRV(sv);
3977       av_push(av,sv_bless(rv,hv));
3978       SvREFCNT_dec(sv);
3979     }
3980     exception=DestroyExceptionInfo(exception);
3981     ST(0)=av_reference;
3982     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
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);
3990     ST(0)=sv_2mortal(perl_exception);
3991     XSRETURN(1);
3992   }
3993 \f
3994 #
3995 ###############################################################################
3996 #                                                                             #
3997 #                                                                             #
3998 #                                                                             #
3999 #   G e t                                                                     #
4000 #                                                                             #
4001 #                                                                             #
4002 #                                                                             #
4003 ###############################################################################
4004 #
4005 #
4006 void
4007 Get(ref,...)
4008   Image::Magick ref=NO_INIT
4009   ALIAS:
4010     GetAttributes = 1
4011     GetAttribute  = 2
4012     get           = 3
4013     getattributes = 4
4014     getattribute  = 5
4015   PPCODE:
4016   {
4017     char
4018       *attribute,
4019       color[MaxTextExtent];
4020
4021     const char
4022       *value;
4023
4024     ExceptionInfo
4025       *exception;
4026
4027     Image
4028       *image;
4029
4030     long
4031       j;
4032
4033     register long
4034       i;
4035
4036     struct PackageInfo
4037       *info;
4038
4039     SV
4040       *perl_exception,
4041       *reference,
4042       *s;
4043
4044     exception=AcquireExceptionInfo();
4045     perl_exception=newSVpv("",0);
4046     if (sv_isobject(ST(0)) == 0)
4047       {
4048         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4049           PackageName);
4050         XSRETURN_EMPTY;
4051       }
4052     reference=SvRV(ST(0));
4053     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4054     if (image == (Image *) NULL && !info)
4055       XSRETURN_EMPTY;
4056     EXTEND(sp,items);
4057     for (i=1; i < items; i++)
4058     {
4059       attribute=(char *) SvPV(ST(i),na);
4060       s=NULL;
4061       switch (*attribute)
4062       {
4063         case 'A':
4064         case 'a':
4065         {
4066           if (LocaleCompare(attribute,"adjoin") == 0)
4067             {
4068               if (info)
4069                 s=newSViv((long) info->image_info->adjoin);
4070               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4071               continue;
4072             }
4073           if (LocaleCompare(attribute,"antialias") == 0)
4074             {
4075               if (info)
4076                 s=newSViv((long) info->image_info->antialias);
4077               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4078               continue;
4079             }
4080           if (LocaleCompare(attribute,"area") == 0)
4081             {
4082               s=newSViv(GetMagickResource(AreaResource));
4083               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4084               continue;
4085             }
4086           if (LocaleCompare(attribute,"attenuate") == 0)
4087             {
4088               const char
4089                 *value;
4090
4091               value=GetImageProperty(image,attribute);
4092               if (value != (const char *) NULL)
4093                 s=newSVpv(value,0);
4094               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4095               continue;
4096             }
4097           if (LocaleCompare(attribute,"authenticate") == 0)
4098             {
4099               if (info)
4100                 s=newSVpv(info->image_info->authenticate,0);
4101               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4102               continue;
4103             }
4104           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4105             attribute);
4106           break;
4107         }
4108         case 'B':
4109         case 'b':
4110         {
4111           if (LocaleCompare(attribute,"background") == 0)
4112             {
4113               if (image == (Image *) NULL)
4114                 break;
4115               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4116                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4117                 image->background_color.red,image->background_color.green,
4118                 image->background_color.blue,image->background_color.opacity);
4119               s=newSVpv(color,0);
4120               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4121               continue;
4122             }
4123           if (LocaleCompare(attribute,"base-columns") == 0)
4124             {
4125               if (image != (Image *) NULL)
4126                 s=newSViv((long) image->magick_columns);
4127               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4128               continue;
4129             }
4130           if (LocaleCompare(attribute,"base-filename") == 0)
4131             {
4132               if (image != (Image *) NULL)
4133                 s=newSVpv(image->magick_filename,0);
4134               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4135               continue;
4136             }
4137           if (LocaleCompare(attribute,"base-height") == 0)
4138             {
4139               if (image != (Image *) NULL)
4140                 s=newSViv((long) image->magick_rows);
4141               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4142               continue;
4143             }
4144           if (LocaleCompare(attribute,"base-rows") == 0)
4145             {
4146               if (image != (Image *) NULL)
4147                 s=newSViv((long) image->magick_rows);
4148               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4149               continue;
4150             }
4151           if (LocaleCompare(attribute,"base-width") == 0)
4152             {
4153               if (image != (Image *) NULL)
4154                 s=newSViv((long) image->magick_columns);
4155               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4156               continue;
4157             }
4158           if (LocaleCompare(attribute,"bias") == 0)
4159             {
4160               if (image != (Image *) NULL)
4161                 s=newSVnv(image->bias);
4162               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4163               continue;
4164             }
4165           if (LocaleCompare(attribute,"blue-primary") == 0)
4166             {
4167               if (image == (Image *) NULL)
4168                 break;
4169               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4170                 image->chromaticity.blue_primary.x,
4171                 image->chromaticity.blue_primary.y);
4172               s=newSVpv(color,0);
4173               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4174               continue;
4175             }
4176           if (LocaleCompare(attribute,"bordercolor") == 0)
4177             {
4178               if (image == (Image *) NULL)
4179                 break;
4180               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4181                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4182                 image->border_color.red,image->border_color.green,
4183                 image->border_color.blue,image->border_color.opacity);
4184               s=newSVpv(color,0);
4185               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4186               continue;
4187             }
4188           if (LocaleCompare(attribute,"bounding-box") == 0)
4189             {
4190               char
4191                 geometry[MaxTextExtent];
4192
4193               RectangleInfo
4194                 page;
4195
4196               if (image == (Image *) NULL)
4197                 break;
4198               page=GetImageBoundingBox(image,&image->exception);
4199               (void) FormatMagickString(geometry,MaxTextExtent,
4200                 "%lux%lu%+ld%+ld",page.width,page.height,page.x,page.y);
4201               s=newSVpv(geometry,0);
4202               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4203               continue;
4204             }
4205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4206             attribute);
4207           break;
4208         }
4209         case 'C':
4210         case 'c':
4211         {
4212           if (LocaleCompare(attribute,"class") == 0)
4213             {
4214               if (image == (Image *) NULL)
4215                 break;
4216               s=newSViv(image->storage_class);
4217               (void) sv_setpv(s,MagickOptionToMnemonic(MagickClassOptions,
4218                 image->storage_class));
4219               SvIOK_on(s);
4220               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4221               continue;
4222             }
4223           if (LocaleCompare(attribute,"clip-mask") == 0)
4224             {
4225               if (image != (Image *) NULL)
4226                 {
4227                   SV
4228                     *sv;
4229
4230                   if (image->mask == (Image *) NULL)
4231                     ClipImage(image);
4232                   if (image->mask != (Image *) NULL)
4233                     {
4234                       AddImageToRegistry(image->mask);
4235                       s=sv_bless(newRV(sv),SvSTASH(reference));
4236                     }
4237                 }
4238               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4239               continue;
4240             }
4241           if (LocaleCompare(attribute,"clip-path") == 0)
4242             {
4243               if (image != (Image *) NULL)
4244                 {
4245                   SV
4246                     *sv;
4247
4248                   if (image->clip_mask == (Image *) NULL)
4249                     ClipImage(image);
4250                   if (image->clip_mask != (Image *) NULL)
4251                     {
4252                       AddImageToRegistry(image->clip_mask);
4253                       s=sv_bless(newRV(sv),SvSTASH(reference));
4254                     }
4255                 }
4256               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4257               continue;
4258             }
4259           if (LocaleCompare(attribute,"compression") == 0)
4260             {
4261               j=info ? info->image_info->compression : image->compression;
4262               if (info)
4263                 if (info->image_info->compression == UndefinedCompression)
4264                   j=image->compression;
4265               s=newSViv(j);
4266               (void) sv_setpv(s,MagickOptionToMnemonic(MagickCompressOptions,
4267                 j));
4268               SvIOK_on(s);
4269               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4270               continue;
4271             }
4272           if (LocaleCompare(attribute,"colorspace") == 0)
4273             {
4274               j=image ? image->colorspace : RGBColorspace;
4275               s=newSViv(j);
4276               (void) sv_setpv(s,MagickOptionToMnemonic(MagickColorspaceOptions,
4277                 j));
4278               SvIOK_on(s);
4279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4280               continue;
4281             }
4282           if (LocaleCompare(attribute,"colors") == 0)
4283             {
4284               if (image != (Image *) NULL)
4285                 s=newSViv((long) GetNumberColors(image,(FILE *) NULL,
4286                   &image->exception));
4287               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4288               continue;
4289             }
4290           if (LocaleNCompare(attribute,"colormap",8) == 0)
4291             {
4292               int
4293                 items;
4294
4295               if (image == (Image *) NULL || !image->colormap)
4296                 break;
4297               j=0;
4298               items=sscanf(attribute,"%*[^[][%ld",&j);
4299               if (j > (long) image->colors)
4300                 j%=image->colors;
4301               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4302                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4303                 image->colormap[j].red,image->colormap[j].green,
4304                 image->colormap[j].blue,image->colormap[j].opacity);
4305               s=newSVpv(color,0);
4306               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4307               continue;
4308             }
4309           if (LocaleCompare(attribute,"columns") == 0)
4310             {
4311               if (image != (Image *) NULL)
4312                 s=newSViv((long) image->columns);
4313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4314               continue;
4315             }
4316           if (LocaleCompare(attribute,"comment") == 0)
4317             {
4318               const char
4319                 *value;
4320
4321               value=GetImageProperty(image,attribute);
4322               if (value != (const char *) NULL)
4323                 s=newSVpv(value,0);
4324               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4325               continue;
4326             }
4327           if (LocaleCompare(attribute,"copyright") == 0)
4328             {
4329               s=newSVpv(GetMagickCopyright(),0);
4330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4331               continue;
4332             }
4333           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4334             attribute);
4335           break;
4336         }
4337         case 'D':
4338         case 'd':
4339         {
4340           if (LocaleCompare(attribute,"density") == 0)
4341             {
4342               char
4343                 geometry[MaxTextExtent];
4344
4345               if (image == (Image *) NULL)
4346                 break;
4347               (void) FormatMagickString(geometry,MaxTextExtent,"%.15gx%.15g",
4348                 image->x_resolution,image->y_resolution);
4349               s=newSVpv(geometry,0);
4350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4351               continue;
4352             }
4353           if (LocaleCompare(attribute,"delay") == 0)
4354             {
4355               if (image != (Image *) NULL)
4356                 s=newSViv((long) image->delay);
4357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4358               continue;
4359             }
4360           if (LocaleCompare(attribute,"depth") == 0)
4361             {
4362               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4363               if (image != (Image *) NULL)
4364                 s=newSViv((long) GetImageDepth(image,&image->exception));
4365               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4366               continue;
4367             }
4368           if (LocaleCompare(attribute,"directory") == 0)
4369             {
4370               if (image && image->directory)
4371                 s=newSVpv(image->directory,0);
4372               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4373               continue;
4374             }
4375           if (LocaleCompare(attribute,"dispose") == 0)
4376             {
4377               if (image == (Image *) NULL)
4378                 break;
4379
4380               s=newSViv(image->dispose);
4381               (void) sv_setpv(s,
4382                 MagickOptionToMnemonic(MagickDisposeOptions,image->dispose));
4383               SvIOK_on(s);
4384               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4385               continue;
4386             }
4387           if (LocaleCompare(attribute,"disk") == 0)
4388             {
4389               s=newSViv(GetMagickResource(DiskResource));
4390               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4391               continue;
4392             }
4393           if (LocaleCompare(attribute,"dither") == 0)
4394             {
4395               if (info)
4396                 s=newSViv((long) info->image_info->dither);
4397               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4398               continue;
4399             }
4400           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4401             {
4402               if (info && info->image_info->server_name)
4403                 s=newSVpv(info->image_info->server_name,0);
4404               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4405               continue;
4406             }
4407           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4408             attribute);
4409           break;
4410         }
4411         case 'E':
4412         case 'e':
4413         {
4414           if (LocaleCompare(attribute,"elapsed-time") == 0)
4415             {
4416               if (image != (Image *) NULL)
4417                 s=newSVnv(GetElapsedTime(&image->timer));
4418               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4419               continue;
4420             }
4421           if (LocaleCompare(attribute,"endian") == 0)
4422             {
4423               j=info ? info->image_info->endian : image->endian;
4424               s=newSViv(j);
4425               (void) sv_setpv(s,MagickOptionToMnemonic(MagickEndianOptions,j));
4426               SvIOK_on(s);
4427               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4428               continue;
4429             }
4430           if (LocaleCompare(attribute,"error") == 0)
4431             {
4432               if (image != (Image *) NULL)
4433                 s=newSVnv(image->error.mean_error_per_pixel);
4434               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4435               continue;
4436             }
4437           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4438             attribute);
4439           break;
4440         }
4441         case 'F':
4442         case 'f':
4443         {
4444           if (LocaleCompare(attribute,"filesize") == 0)
4445             {
4446               if (image != (Image *) NULL)
4447                 s=newSViv((long) GetBlobSize(image));
4448               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4449               continue;
4450             }
4451           if (LocaleCompare(attribute,"filename") == 0)
4452             {
4453               if (info && info->image_info->filename &&
4454                   *info->image_info->filename)
4455                 s=newSVpv(info->image_info->filename,0);
4456               if (image != (Image *) NULL)
4457                 s=newSVpv(image->filename,0);
4458               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4459               continue;
4460             }
4461           if (LocaleCompare(attribute,"filter") == 0)
4462             {
4463               s=newSViv(image->filter);
4464               (void) sv_setpv(s,MagickOptionToMnemonic(MagickFilterOptions,
4465                 image->filter));
4466               SvIOK_on(s);
4467               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4468               continue;
4469             }
4470           if (LocaleCompare(attribute,"font") == 0)
4471             {
4472               if (info && info->image_info->font)
4473                 s=newSVpv(info->image_info->font,0);
4474               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4475               continue;
4476             }
4477           if (LocaleCompare(attribute,"foreground") == 0)
4478             continue;
4479           if (LocaleCompare(attribute,"format") == 0)
4480             {
4481               const MagickInfo
4482                 *magick_info;
4483
4484               magick_info=(const MagickInfo *) NULL;
4485               if (info && (*info->image_info->magick != '\0'))
4486                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4487               if (image != (Image *) NULL)
4488                 magick_info=GetMagickInfo(image->magick,&image->exception);
4489               if ((magick_info != (const MagickInfo *) NULL) &&
4490                   (*magick_info->description != '\0'))
4491                 s=newSVpv((char *) magick_info->description,0);
4492               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4493               continue;
4494             }
4495           if (LocaleCompare(attribute,"fuzz") == 0)
4496             {
4497               if (info)
4498                 s=newSVnv(info->image_info->fuzz);
4499               if (image != (Image *) NULL)
4500                 s=newSVnv(image->fuzz);
4501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4502               continue;
4503             }
4504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4505             attribute);
4506           break;
4507         }
4508         case 'G':
4509         case 'g':
4510         {
4511           if (LocaleCompare(attribute,"gamma") == 0)
4512             {
4513               if (image != (Image *) NULL)
4514                 s=newSVnv(image->gamma);
4515               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4516               continue;
4517             }
4518           if (LocaleCompare(attribute,"geometry") == 0)
4519             {
4520               if (image && image->geometry)
4521                 s=newSVpv(image->geometry,0);
4522               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4523               continue;
4524             }
4525           if (LocaleCompare(attribute,"gravity") == 0)
4526             {
4527               s=newSViv(image->gravity);
4528               (void) sv_setpv(s,
4529                 MagickOptionToMnemonic(MagickGravityOptions,image->gravity));
4530               SvIOK_on(s);
4531               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4532               continue;
4533             }
4534           if (LocaleCompare(attribute,"green-primary") == 0)
4535             {
4536               if (image == (Image *) NULL)
4537                 break;
4538               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4539                 image->chromaticity.green_primary.x,
4540                 image->chromaticity.green_primary.y);
4541               s=newSVpv(color,0);
4542               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4543               continue;
4544             }
4545           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4546             attribute);
4547           break;
4548         }
4549         case 'H':
4550         case 'h':
4551         {
4552           if (LocaleCompare(attribute,"height") == 0)
4553             {
4554               if (image != (Image *) NULL)
4555                 s=newSViv((long) image->rows);
4556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4557               continue;
4558             }
4559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4560             attribute);
4561           break;
4562         }
4563         case 'I':
4564         case 'i':
4565         {
4566           if (LocaleCompare(attribute,"icc") == 0)
4567             {
4568               if (image != (Image *) NULL)
4569                 {
4570                   const StringInfo
4571                     *profile;
4572
4573                   profile=GetImageProfile(image,"icc");
4574                   if (profile != (StringInfo *) NULL)
4575                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4576                       GetStringInfoLength(profile));
4577                 }
4578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4579               continue;
4580             }
4581           if (LocaleCompare(attribute,"icm") == 0)
4582             {
4583               if (image != (Image *) NULL)
4584                 {
4585                   const StringInfo
4586                     *profile;
4587
4588                   profile=GetImageProfile(image,"icm");
4589                   if (profile != (const StringInfo *) NULL)
4590                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4591                       GetStringInfoLength(profile));
4592                 }
4593               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4594               continue;
4595             }
4596           if (LocaleCompare(attribute,"id") == 0)
4597             {
4598               if (image != (Image *) NULL)
4599                 {
4600                   char
4601                     key[MaxTextExtent];
4602
4603                   MagickBooleanType
4604                     status;
4605
4606                   static long
4607                     id = 0;
4608
4609                   (void) FormatMagickString(key,MaxTextExtent,"%ld\n",id);
4610                   status=SetImageRegistry(ImageRegistryType,key,image,
4611                     &image->exception);
4612                   s=newSViv(id++);
4613                 }
4614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4615               continue;
4616             }
4617           if (LocaleNCompare(attribute,"index",5) == 0)
4618             {
4619               char
4620                 name[MaxTextExtent];
4621
4622               int
4623                 items;
4624
4625               long
4626                 x,
4627                 y;
4628
4629               register const IndexPacket
4630                 *indexes;
4631
4632               register const PixelPacket
4633                 *p;
4634
4635               CacheView
4636                 *image_view;
4637
4638               if (image == (Image *) NULL)
4639                 break;
4640               if (image->storage_class != PseudoClass)
4641                 break;
4642               x=0;
4643               y=0;
4644               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4645               image_view=AcquireCacheView(image);
4646               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4647               if (p != (const PixelPacket *) NULL)
4648                 {
4649                   indexes=GetCacheViewVirtualIndexQueue(image_view);
4650                   (void) FormatMagickString(name,MaxTextExtent,QuantumFormat,
4651                     *indexes);
4652                   s=newSVpv(name,0);
4653                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4654                 }
4655               image_view=DestroyCacheView(image_view);
4656               continue;
4657             }
4658           if (LocaleCompare(attribute,"iptc") == 0)
4659             {
4660               if (image != (Image *) NULL)
4661                 {
4662                   const StringInfo
4663                     *profile;
4664
4665                   profile=GetImageProfile(image,"iptc");
4666                   if (profile != (const StringInfo *) NULL)
4667                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4668                       GetStringInfoLength(profile));
4669                 }
4670               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4671               continue;
4672             }
4673           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4674             {
4675               if (image != (Image *) NULL)
4676                 s=newSViv((long) image->iterations);
4677               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4678               continue;
4679             }
4680           if (LocaleCompare(attribute,"interlace") == 0)
4681             {
4682               j=info ? info->image_info->interlace : image->interlace;
4683               s=newSViv(j);
4684               (void) sv_setpv(s,MagickOptionToMnemonic(MagickInterlaceOptions,
4685                 j));
4686               SvIOK_on(s);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4691             attribute);
4692           break;
4693         }
4694         case 'L':
4695         case 'l':
4696         {
4697           if (LocaleCompare(attribute,"label") == 0)
4698             {
4699               const char
4700                 *value;
4701
4702               if (image == (Image *) NULL)
4703                 break;
4704               value=GetImageProperty(image,"Label");
4705               if (value != (const char *) NULL)
4706                 s=newSVpv(value,0);
4707               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4708               continue;
4709             }
4710           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4711             {
4712               if (image != (Image *) NULL)
4713                 s=newSViv((long) image->iterations);
4714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715               continue;
4716             }
4717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4718             attribute);
4719           break;
4720         }
4721         case 'M':
4722         case 'm':
4723         {
4724           if (LocaleCompare(attribute,"magick") == 0)
4725             {
4726               if (info && *info->image_info->magick)
4727                 s=newSVpv(info->image_info->magick,0);
4728               if (image != (Image *) NULL)
4729                 s=newSVpv(image->magick,0);
4730               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4731               continue;
4732             }
4733           if (LocaleCompare(attribute,"map") == 0)
4734             {
4735               s=newSViv(GetMagickResource(MapResource));
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           if (LocaleCompare(attribute,"maximum-error") == 0)
4740             {
4741               if (image != (Image *) NULL)
4742                 s=newSVnv(image->error.normalized_maximum_error);
4743               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4744               continue;
4745             }
4746           if (LocaleCompare(attribute,"memory") == 0)
4747             {
4748               s=newSViv(GetMagickResource(MemoryResource));
4749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4750               continue;
4751             }
4752           if (LocaleCompare(attribute,"mean-error") == 0)
4753             {
4754               if (image != (Image *) NULL)
4755                 s=newSVnv(image->error.normalized_mean_error);
4756               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4757               continue;
4758             }
4759           if (LocaleCompare(attribute,"mime") == 0)
4760             {
4761               if (info && *info->image_info->magick)
4762                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4763               if (image != (Image *) NULL)
4764                 s=newSVpv(MagickToMime(image->magick),0);
4765               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4766               continue;
4767             }
4768           if (LocaleCompare(attribute,"mattecolor") == 0)
4769             {
4770               if (image == (Image *) NULL)
4771                 break;
4772               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4773                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4774                 image->matte_color.red,image->matte_color.green,
4775                 image->matte_color.blue,image->matte_color.opacity);
4776               s=newSVpv(color,0);
4777               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4778               continue;
4779             }
4780           if (LocaleCompare(attribute,"matte") == 0)
4781             {
4782               if (image != (Image *) NULL)
4783                 s=newSViv((long) image->matte);
4784               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4785               continue;
4786             }
4787           if (LocaleCompare(attribute,"mime") == 0)
4788             {
4789               const char
4790                 *magick;
4791
4792               magick=NULL;
4793               if (info && *info->image_info->magick)
4794                 magick=info->image_info->magick;
4795               if (image != (Image *) NULL)
4796                 magick=image->magick;
4797               if (magick)
4798                 {
4799                   char
4800                     *mime;
4801
4802                   mime=MagickToMime(magick);
4803                   s=newSVpv(mime,0);
4804                   mime=(char *) RelinquishMagickMemory(mime);
4805                 }
4806               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4807               continue;
4808             }
4809           if (LocaleCompare(attribute,"monochrome") == 0)
4810             {
4811               if (image == (Image *) NULL)
4812                 continue;
4813               j=info ? info->image_info->monochrome :
4814                 IsMonochromeImage(image,&image->exception);
4815               s=newSViv(j);
4816               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4817               continue;
4818             }
4819           if (LocaleCompare(attribute,"montage") == 0)
4820             {
4821               if (image && image->montage)
4822                 s=newSVpv(image->montage,0);
4823               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4824               continue;
4825             }
4826           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4827             attribute);
4828           break;
4829         }
4830         case 'O':
4831         case 'o':
4832         {
4833           if (LocaleCompare(attribute,"orientation") == 0)
4834             {
4835               j=info ? info->image_info->orientation : image->orientation;
4836               s=newSViv(j);
4837               (void) sv_setpv(s,MagickOptionToMnemonic(MagickOrientationOptions,
4838                 j));
4839               SvIOK_on(s);
4840               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4841               continue;
4842             }
4843           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4844             attribute);
4845           break;
4846         }
4847         case 'P':
4848         case 'p':
4849         {
4850           if (LocaleCompare(attribute,"page") == 0)
4851             {
4852               if (info && info->image_info->page)
4853                 s=newSVpv(info->image_info->page,0);
4854               if (image != (Image *) NULL)
4855                 {
4856                   char
4857                     geometry[MaxTextExtent];
4858
4859                   (void) FormatMagickString(geometry,MaxTextExtent,
4860                     "%lux%lu%+ld%+ld",image->page.width,image->page.height,
4861                     image->page.x,image->page.y);
4862                   s=newSVpv(geometry,0);
4863                 }
4864               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4865               continue;
4866             }
4867           if (LocaleCompare(attribute,"page.x") == 0)
4868             {
4869               if (image != (Image *) NULL)
4870                 s=newSViv((long) image->page.x);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           if (LocaleCompare(attribute,"page.y") == 0)
4875             {
4876               if (image != (Image *) NULL)
4877                 s=newSViv((long) image->page.y);
4878               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4879               continue;
4880             }
4881           if (LocaleNCompare(attribute,"pixel",5) == 0)
4882             {
4883               char
4884                 tuple[MaxTextExtent];
4885
4886               int
4887                 items;
4888
4889               long
4890                 x,
4891                 y;
4892
4893               register const PixelPacket
4894                 *p;
4895
4896               register const IndexPacket
4897                 *indexes;
4898
4899               if (image == (Image *) NULL)
4900                 break;
4901               x=0;
4902               y=0;
4903               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4904               p=GetVirtualPixels(image,x,y,1,1,exception);
4905               indexes=GetVirtualIndexQueue(image);
4906               if (image->colorspace != CMYKColorspace)
4907                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
4908                   QuantumFormat "," QuantumFormat "," QuantumFormat,
4909                   p->red,p->green,p->blue,p->opacity);
4910               else
4911                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
4912                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
4913                   QuantumFormat,p->red,p->green,p->blue,*indexes,p->opacity);
4914               s=newSVpv(tuple,0);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           if (LocaleCompare(attribute,"pointsize") == 0)
4919             {
4920               if (info)
4921                 s=newSViv((long) info->image_info->pointsize);
4922               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4923               continue;
4924             }
4925           if (LocaleCompare(attribute,"preview") == 0)
4926             {
4927               s=newSViv(info->image_info->preview_type);
4928               (void) sv_setpv(s,MagickOptionToMnemonic(MagickPreviewOptions,
4929                 info->image_info->preview_type));
4930               SvIOK_on(s);
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4935             attribute);
4936           break;
4937         }
4938         case 'Q':
4939         case 'q':
4940         {
4941           if (LocaleCompare(attribute,"quality") == 0)
4942             {
4943               if (info)
4944                 s=newSViv((long) info->image_info->quality);
4945               if (image != (Image *) NULL)
4946                 s=newSViv((long) image->quality);
4947               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4948               continue;
4949             }
4950           if (LocaleCompare(attribute,"quantum") == 0)
4951             {
4952               if (info)
4953                 s=newSViv((long) MAGICKCORE_QUANTUM_DEPTH);
4954               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4955               continue;
4956             }
4957           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4958             attribute);
4959           break;
4960         }
4961         case 'R':
4962         case 'r':
4963         {
4964           if (LocaleCompare(attribute,"rendering-intent") == 0)
4965             {
4966               s=newSViv(image->rendering_intent);
4967               (void) sv_setpv(s,MagickOptionToMnemonic(MagickIntentOptions,
4968                 image->rendering_intent));
4969               SvIOK_on(s);
4970               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4971               continue;
4972             }
4973           if (LocaleCompare(attribute,"red-primary") == 0)
4974             {
4975               if (image == (Image *) NULL)
4976                 break;
4977               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4978                 image->chromaticity.red_primary.x,
4979                 image->chromaticity.red_primary.y);
4980               s=newSVpv(color,0);
4981               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982               continue;
4983             }
4984           if (LocaleCompare(attribute,"rows") == 0)
4985             {
4986               if (image != (Image *) NULL)
4987                 s=newSViv((long) image->rows);
4988               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4989               continue;
4990             }
4991           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4992             attribute);
4993           break;
4994         }
4995         case 'S':
4996         case 's':
4997         {
4998           if (LocaleCompare(attribute,"sampling-factor") == 0)
4999             {
5000               if (info && info->image_info->sampling_factor)
5001                 s=newSVpv(info->image_info->sampling_factor,0);
5002               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5003               continue;
5004             }
5005           if (LocaleCompare(attribute,"subimage") == 0)
5006             {
5007               if (info)
5008                 s=newSViv((long) info->image_info->subimage);
5009               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5010               continue;
5011             }
5012           if (LocaleCompare(attribute,"subrange") == 0)
5013             {
5014               if (info)
5015                 s=newSViv((long) info->image_info->subrange);
5016               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5017               continue;
5018             }
5019           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5020             {
5021               if (info && info->image_info->server_name)
5022                 s=newSVpv(info->image_info->server_name,0);
5023               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5024               continue;
5025             }
5026           if (LocaleCompare(attribute,"size") == 0)
5027             {
5028               if (info && info->image_info->size)
5029                 s=newSVpv(info->image_info->size,0);
5030               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5031               continue;
5032             }
5033           if (LocaleCompare(attribute,"scene") == 0)
5034             {
5035               if (image != (Image *) NULL)
5036                 s=newSViv((long) image->scene);
5037               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5038               continue;
5039             }
5040           if (LocaleCompare(attribute,"scenes") == 0)
5041             {
5042               if (image != (Image *) NULL)
5043                 s=newSViv((long) info->image_info->number_scenes);
5044               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5045               continue;
5046             }
5047           if (LocaleCompare(attribute,"signature") == 0)
5048             {
5049               const char
5050                 *value;
5051
5052               if (image == (Image *) NULL)
5053                 break;
5054               (void) SignatureImage(image);
5055               value=GetImageProperty(image,"Signature");
5056               if (value != (const char *) NULL)
5057                 s=newSVpv(value,0);
5058               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5059               continue;
5060             }
5061           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5062             attribute);
5063           break;
5064         }
5065         case 'T':
5066         case 't':
5067         {
5068           if (LocaleCompare(attribute,"taint") == 0)
5069             {
5070               if (image != (Image *) NULL)
5071                 s=newSViv((long) IsTaintImage(image));
5072               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5073               continue;
5074             }
5075           if (LocaleCompare(attribute,"tile") == 0)
5076             {
5077               if (info && info->image_info->tile)
5078                 s=newSVpv(info->image_info->tile,0);
5079               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5080               continue;
5081             }
5082           if (LocaleCompare(attribute,"texture") == 0)
5083             {
5084               if (info && info->image_info->texture)
5085                 s=newSVpv(info->image_info->texture,0);
5086               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5087               continue;
5088             }
5089           if (LocaleCompare(attribute,"total-ink-density") == 0)
5090             {
5091               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5092               if (image != (Image *) NULL)
5093                 s=newSVnv(GetImageTotalInkDensity(image));
5094               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095               continue;
5096             }
5097           if (LocaleCompare(attribute,"transparent-color") == 0)
5098             {
5099               if (image == (Image *) NULL)
5100                 break;
5101               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
5102                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5103                 image->transparent_color.red,image->transparent_color.green,
5104                 image->transparent_color.blue,image->transparent_color.opacity);
5105               s=newSVpv(color,0);
5106               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5107               continue;
5108             }
5109           if (LocaleCompare(attribute,"type") == 0)
5110             {
5111               if (image == (Image *) NULL)
5112                 break;
5113               j=(long) GetImageType(image,&image->exception);
5114               s=newSViv(j);
5115               (void) sv_setpv(s,MagickOptionToMnemonic(MagickTypeOptions,j));
5116               SvIOK_on(s);
5117               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5118               continue;
5119             }
5120           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5121             attribute);
5122           break;
5123         }
5124         case 'U':
5125         case 'u':
5126         {
5127           if (LocaleCompare(attribute,"units") == 0)
5128             {
5129               j=info ? info->image_info->units : image->units;
5130               if (info)
5131                 if (info->image_info->units == UndefinedResolution)
5132                   j=image->units;
5133               if (j == UndefinedResolution)
5134                 s=newSVpv("undefined units",0);
5135               else
5136                 if (j == PixelsPerInchResolution)
5137                   s=newSVpv("pixels / inch",0);
5138                 else
5139                   s=newSVpv("pixels / centimeter",0);
5140               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5141               continue;
5142             }
5143           if (LocaleCompare(attribute,"user-time") == 0)
5144             {
5145               if (image != (Image *) NULL)
5146                 s=newSVnv(GetUserTime(&image->timer));
5147               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148               continue;
5149             }
5150           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5151             attribute);
5152           break;
5153         }
5154         case 'V':
5155         case 'v':
5156         {
5157           if (LocaleCompare(attribute,"verbose") == 0)
5158             {
5159               if (info)
5160                 s=newSViv((long) info->image_info->verbose);
5161               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5162               continue;
5163             }
5164           if (LocaleCompare(attribute,"version") == 0)
5165             {
5166               s=newSVpv(GetMagickVersion((unsigned long *) NULL),0);
5167               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5168               continue;
5169             }
5170           if (LocaleCompare(attribute,"view") == 0)
5171             {
5172               if (info && info->image_info->view)
5173                 s=newSVpv(info->image_info->view,0);
5174               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5175               continue;
5176             }
5177           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5178             {
5179               if (image == (Image *) NULL)
5180                 break;
5181               j=(long) GetImageVirtualPixelMethod(image);
5182               s=newSViv(j);
5183               (void) sv_setpv(s,MagickOptionToMnemonic(
5184                 MagickVirtualPixelOptions,j));
5185               SvIOK_on(s);
5186               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5187               continue;
5188             }
5189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5190             attribute);
5191           break;
5192         }
5193         case 'W':
5194         case 'w':
5195         {
5196           if (LocaleCompare(attribute,"white-point") == 0)
5197             {
5198               if (image == (Image *) NULL)
5199                 break;
5200               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
5201                 image->chromaticity.white_point.x,
5202                 image->chromaticity.white_point.y);
5203               s=newSVpv(color,0);
5204               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5205               continue;
5206             }
5207           if (LocaleCompare(attribute,"width") == 0)
5208             {
5209               if (image != (Image *) NULL)
5210                 s=newSViv((long) image->columns);
5211               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5212               continue;
5213             }
5214           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5215              attribute);
5216           break;
5217         }
5218         case 'X':
5219         case 'x':
5220         {
5221           if (LocaleCompare(attribute,"x-resolution") == 0)
5222             {
5223               if (image != (Image *) NULL)
5224                 s=newSVnv(image->x_resolution);
5225               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5226               continue;
5227             }
5228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5229             attribute);
5230           break;
5231         }
5232         case 'Y':
5233         case 'y':
5234         {
5235           if (LocaleCompare(attribute,"y-resolution") == 0)
5236             {
5237               if (image != (Image *) NULL)
5238                 s=newSVnv(image->y_resolution);
5239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240               continue;
5241             }
5242           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5243             attribute);
5244           break;
5245         }
5246         default:
5247           break;
5248       }
5249       if (image == (Image *) NULL)
5250         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5251           attribute)
5252       else
5253         {
5254           value=GetImageProperty(image,attribute);
5255           if (value != (const char *) NULL)
5256             {
5257               s=newSVpv(value,0);
5258               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5259             }
5260           else
5261             if (*attribute != '%')
5262               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5263                 attribute)
5264             else
5265               {
5266                  char
5267                    *meta;
5268
5269                  meta=InterpretImageProperties(info ? info->image_info :
5270                    (ImageInfo *) NULL,image,attribute);
5271                  s=newSVpv(meta,0);
5272                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5273                  meta=(char *) RelinquishMagickMemory(meta);
5274               }
5275         }
5276     }
5277     exception=DestroyExceptionInfo(exception);
5278     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5279   }
5280 \f
5281 #
5282 ###############################################################################
5283 #                                                                             #
5284 #                                                                             #
5285 #                                                                             #
5286 #   G e t A u t h e n t i c P i x e l s                                       #
5287 #                                                                             #
5288 #                                                                             #
5289 #                                                                             #
5290 ###############################################################################
5291 #
5292 #
5293 void *
5294 GetAuthenticPixels(ref,...)
5295   Image::Magick ref = NO_INIT
5296   ALIAS:
5297     getauthenticpixels = 1
5298     GetImagePixels = 2
5299     getimagepixels = 3
5300   CODE:
5301   {
5302     char
5303       *attribute;
5304
5305     ExceptionInfo
5306       *exception;
5307
5308     Image
5309       *image;
5310
5311     long
5312       i;
5313
5314     RectangleInfo
5315       region;
5316
5317     struct PackageInfo
5318       *info;
5319
5320     SV
5321       *perl_exception,
5322       *reference;
5323
5324     void
5325       *blob = NULL;
5326
5327     exception=AcquireExceptionInfo();
5328     perl_exception=newSVpv("",0);
5329     if (sv_isobject(ST(0)) == 0)
5330       {
5331         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5332           PackageName);
5333         goto PerlException;
5334       }
5335     reference=SvRV(ST(0));
5336
5337     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5338     if (image == (Image *) NULL)
5339       {
5340         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5341           PackageName);
5342         goto PerlException;
5343       }
5344
5345     region.x=0;
5346     region.y=0;
5347     region.width=image->columns;
5348     region.height=1;
5349     if (items == 1)
5350       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5351     for (i=2; i < items; i+=2)
5352     {
5353       attribute=(char *) SvPV(ST(i-1),na);
5354       switch (*attribute)
5355       {
5356         case 'g':
5357         case 'G':
5358         {
5359           if (LocaleCompare(attribute,"geometry") == 0)
5360             {
5361               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5362               break;
5363             }
5364           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5365             attribute);
5366           break;
5367         }
5368         case 'H':
5369         case 'h':
5370         {
5371           if (LocaleCompare(attribute,"height") == 0)
5372             {
5373               region.height=SvIV(ST(i));
5374               continue;
5375             }
5376           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5377             attribute);
5378           break;
5379         }
5380         case 'X':
5381         case 'x':
5382         {
5383           if (LocaleCompare(attribute,"x") == 0)
5384             {
5385               region.x=SvIV(ST(i));
5386               continue;
5387             }
5388           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5389             attribute);
5390           break;
5391         }
5392         case 'Y':
5393         case 'y':
5394         {
5395           if (LocaleCompare(attribute,"y") == 0)
5396             {
5397               region.y=SvIV(ST(i));
5398               continue;
5399             }
5400           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5401             attribute);
5402           break;
5403         }
5404         case 'W':
5405         case 'w':
5406         {
5407           if (LocaleCompare(attribute,"width") == 0)
5408             {
5409               region.width=SvIV(ST(i));
5410               continue;
5411             }
5412           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5413             attribute);
5414           break;
5415         }
5416       }
5417     }
5418     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5419       region.height,exception);
5420     if (blob != (void *) NULL)
5421       goto PerlEnd;
5422
5423   PerlException:
5424     InheritPerlException(exception,perl_exception);
5425     exception=DestroyExceptionInfo(exception);
5426     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5427
5428   PerlEnd:
5429     RETVAL = blob;
5430   }
5431   OUTPUT:
5432     RETVAL
5433 \f
5434 #
5435 ###############################################################################
5436 #                                                                             #
5437 #                                                                             #
5438 #                                                                             #
5439 #   G e t V i r t u a l P i x e l s                                           #
5440 #                                                                             #
5441 #                                                                             #
5442 #                                                                             #
5443 ###############################################################################
5444 #
5445 #
5446 void *
5447 GetVirtualPixels(ref,...)
5448   Image::Magick ref = NO_INIT
5449   ALIAS:
5450     getvirtualpixels = 1
5451     AcquireImagePixels = 2
5452     acquireimagepixels = 3
5453   CODE:
5454   {
5455     char
5456       *attribute;
5457
5458     const void
5459       *blob = NULL;
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     exception=AcquireExceptionInfo();
5481     perl_exception=newSVpv("",0);
5482     if (sv_isobject(ST(0)) == 0)
5483       {
5484         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5485           PackageName);
5486         goto PerlException;
5487       }
5488     reference=SvRV(ST(0));
5489
5490     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5491     if (image == (Image *) NULL)
5492       {
5493         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5494           PackageName);
5495         goto PerlException;
5496       }
5497
5498     region.x=0;
5499     region.y=0;
5500     region.width=image->columns;
5501     region.height=1;
5502     if (items == 1)
5503       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5504     for (i=2; i < items; i+=2)
5505     {
5506       attribute=(char *) SvPV(ST(i-1),na);
5507       switch (*attribute)
5508       {
5509         case 'g':
5510         case 'G':
5511         {
5512           if (LocaleCompare(attribute,"geometry") == 0)
5513             {
5514               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5515               break;
5516             }
5517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5518             attribute);
5519           break;
5520         }
5521         case 'H':
5522         case 'h':
5523         {
5524           if (LocaleCompare(attribute,"height") == 0)
5525             {
5526               region.height=SvIV(ST(i));
5527               continue;
5528             }
5529           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5530             attribute);
5531           break;
5532         }
5533         case 'X':
5534         case 'x':
5535         {
5536           if (LocaleCompare(attribute,"x") == 0)
5537             {
5538               region.x=SvIV(ST(i));
5539               continue;
5540             }
5541           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5542             attribute);
5543           break;
5544         }
5545         case 'Y':
5546         case 'y':
5547         {
5548           if (LocaleCompare(attribute,"y") == 0)
5549             {
5550               region.y=SvIV(ST(i));
5551               continue;
5552             }
5553           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5554             attribute);
5555           break;
5556         }
5557         case 'W':
5558         case 'w':
5559         {
5560           if (LocaleCompare(attribute,"width") == 0)
5561             {
5562               region.width=SvIV(ST(i));
5563               continue;
5564             }
5565           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5566             attribute);
5567           break;
5568         }
5569       }
5570     }
5571     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5572       region.height,exception);
5573     if (blob != (void *) NULL)
5574       goto PerlEnd;
5575
5576   PerlException:
5577     InheritPerlException(exception,perl_exception);
5578     exception=DestroyExceptionInfo(exception);
5579     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5580
5581   PerlEnd:
5582     RETVAL = (void *) blob;
5583   }
5584   OUTPUT:
5585     RETVAL
5586 \f
5587 #
5588 ###############################################################################
5589 #                                                                             #
5590 #                                                                             #
5591 #                                                                             #
5592 #   G e t A u t h e n t i c I n d e x Q u e u e                               #
5593 #                                                                             #
5594 #                                                                             #
5595 #                                                                             #
5596 ###############################################################################
5597 #
5598 #
5599 void *
5600 GetAuthenticIndexQueue(ref,...)
5601   Image::Magick ref = NO_INIT
5602   ALIAS:
5603     getauthenticindexqueue = 1
5604     GetIndexes = 2
5605     getindexes = 3
5606   CODE:
5607   {
5608     ExceptionInfo
5609       *exception;
5610
5611     Image
5612       *image;
5613
5614     struct PackageInfo
5615       *info;
5616
5617     SV
5618       *perl_exception,
5619       *reference;
5620
5621     void
5622       *blob = NULL;
5623
5624     exception=AcquireExceptionInfo();
5625     perl_exception=newSVpv("",0);
5626     if (sv_isobject(ST(0)) == 0)
5627       {
5628         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5629           PackageName);
5630         goto PerlException;
5631       }
5632     reference=SvRV(ST(0));
5633
5634     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5635     if (image == (Image *) NULL)
5636       {
5637         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5638           PackageName);
5639         goto PerlException;
5640       }
5641
5642     blob=(void *) GetAuthenticIndexQueue(image);
5643     if (blob != (void *) NULL)
5644       goto PerlEnd;
5645
5646   PerlException:
5647     InheritPerlException(exception,perl_exception);
5648     exception=DestroyExceptionInfo(exception);
5649     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5650
5651   PerlEnd:
5652     RETVAL = blob;
5653   }
5654   OUTPUT:
5655     RETVAL
5656 \f
5657 #
5658 ###############################################################################
5659 #                                                                             #
5660 #                                                                             #
5661 #                                                                             #
5662 #   G e t V i r t u a l I n d e x Q u e u e                                   #
5663 #                                                                             #
5664 #                                                                             #
5665 #                                                                             #
5666 ###############################################################################
5667 #
5668 #
5669 void *
5670 GetVirtualIndexQueue(ref,...)
5671   Image::Magick ref = NO_INIT
5672   ALIAS:
5673     getvirtualindexqueue = 1
5674   CODE:
5675   {
5676     ExceptionInfo
5677       *exception;
5678
5679     Image
5680       *image;
5681
5682     struct PackageInfo
5683       *info;
5684
5685     SV
5686       *perl_exception,
5687       *reference;
5688
5689     void
5690       *blob = NULL;
5691
5692     exception=AcquireExceptionInfo();
5693     perl_exception=newSVpv("",0);
5694     if (sv_isobject(ST(0)) == 0)
5695       {
5696         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5697           PackageName);
5698         goto PerlException;
5699       }
5700     reference=SvRV(ST(0));
5701
5702     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5703     if (image == (Image *) NULL)
5704       {
5705         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5706           PackageName);
5707         goto PerlException;
5708       }
5709
5710     blob=(void *) GetVirtualIndexQueue(image);
5711     if (blob != (void *) NULL)
5712       goto PerlEnd;
5713
5714   PerlException:
5715     InheritPerlException(exception,perl_exception);
5716     exception=DestroyExceptionInfo(exception);
5717     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5718
5719   PerlEnd:
5720     RETVAL = blob;
5721   }
5722   OUTPUT:
5723     RETVAL
5724 \f
5725 #
5726 ###############################################################################
5727 #                                                                             #
5728 #                                                                             #
5729 #                                                                             #
5730 #   H i s t o g r a m                                                         #
5731 #                                                                             #
5732 #                                                                             #
5733 #                                                                             #
5734 ###############################################################################
5735 #
5736 #
5737 void
5738 Histogram(ref,...)
5739   Image::Magick ref=NO_INIT
5740   ALIAS:
5741     HistogramImage = 1
5742     histogram      = 2
5743     histogramimage = 3
5744   PPCODE:
5745   {
5746     AV
5747       *av;
5748
5749     char
5750       message[MaxTextExtent];
5751
5752     ColorPacket
5753       *histogram;
5754
5755     ExceptionInfo
5756       *exception;
5757
5758     HV
5759       *hv;
5760
5761     Image
5762       *image;
5763
5764     register long
5765       i;
5766
5767     ssize_t
5768       count;
5769
5770     struct PackageInfo
5771       *info;
5772
5773     SV
5774       *av_reference,
5775       *perl_exception,
5776       *reference;
5777
5778     unsigned long
5779       number_colors;
5780
5781     exception=AcquireExceptionInfo();
5782     perl_exception=newSVpv("",0);
5783     av=NULL;
5784     if (sv_isobject(ST(0)) == 0)
5785       {
5786         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5787           PackageName);
5788         goto PerlException;
5789       }
5790     reference=SvRV(ST(0));
5791     hv=SvSTASH(reference);
5792     av=newAV();
5793     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
5794     SvREFCNT_dec(av);
5795     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5796     if (image == (Image *) NULL)
5797       {
5798         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5799           PackageName);
5800         goto PerlException;
5801       }
5802     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5803     count=0;
5804     for ( ; image; image=image->next)
5805     {
5806       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5807       if (histogram == (ColorPacket *) NULL)
5808         continue;
5809       count+=number_colors;
5810       EXTEND(sp,6*count);
5811       for (i=0; i < (long) number_colors; i++)
5812       {
5813         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5814           histogram[i].pixel.red);
5815         PUSHs(sv_2mortal(newSVpv(message,0)));
5816         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5817           histogram[i].pixel.green);
5818         PUSHs(sv_2mortal(newSVpv(message,0)));
5819         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5820           histogram[i].pixel.blue);
5821         PUSHs(sv_2mortal(newSVpv(message,0)));
5822         if (image->colorspace == CMYKColorspace)
5823           {
5824             (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5825               histogram[i].index);
5826             PUSHs(sv_2mortal(newSVpv(message,0)));
5827           }
5828         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
5829           histogram[i].pixel.opacity);
5830         PUSHs(sv_2mortal(newSVpv(message,0)));
5831         (void) FormatMagickString(message,MaxTextExtent,"%lu",
5832            (unsigned long) histogram[i].count);
5833         PUSHs(sv_2mortal(newSVpv(message,0)));
5834       }
5835       histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
5836     }
5837
5838   PerlException:
5839     InheritPerlException(exception,perl_exception);
5840     exception=DestroyExceptionInfo(exception);
5841     SvREFCNT_dec(perl_exception);
5842   }
5843 \f
5844 #
5845 ###############################################################################
5846 #                                                                             #
5847 #                                                                             #
5848 #                                                                             #
5849 #   G e t P i x e l                                                           #
5850 #                                                                             #
5851 #                                                                             #
5852 #                                                                             #
5853 ###############################################################################
5854 #
5855 #
5856 void
5857 GetPixel(ref,...)
5858   Image::Magick ref=NO_INIT
5859   ALIAS:
5860     getpixel = 1
5861     getPixel = 2
5862   PPCODE:
5863   {
5864     AV
5865       *av;
5866
5867     char
5868       *attribute;
5869
5870     ChannelType
5871       channel;
5872
5873     ExceptionInfo
5874       *exception;
5875
5876     Image
5877       *image;
5878
5879     long
5880       option;
5881
5882     MagickBooleanType
5883       normalize;
5884
5885     RectangleInfo
5886       region;
5887
5888     register const IndexPacket
5889       *indexes;
5890
5891     register const PixelPacket
5892       *p;
5893
5894     register long
5895       i;
5896
5897     struct PackageInfo
5898       *info;
5899
5900     SV
5901       *perl_exception,
5902       *reference;  /* reference is the SV* of ref=SvIV(reference) */
5903
5904     exception=AcquireExceptionInfo();
5905     perl_exception=newSVpv("",0);
5906     reference=SvRV(ST(0));
5907     av=(AV *) reference;
5908     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
5909       exception);
5910     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5911     if (image == (Image *) NULL)
5912       {
5913         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5914           PackageName);
5915         goto PerlException;
5916       }
5917     channel=DefaultChannels;
5918     normalize=MagickTrue;
5919     region.x=0;
5920     region.y=0;
5921     region.width=image->columns;
5922     region.height=1;
5923     if (items == 1)
5924       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5925     for (i=2; i < items; i+=2)
5926     {
5927       attribute=(char *) SvPV(ST(i-1),na);
5928       switch (*attribute)
5929       {
5930         case 'C':
5931         case 'c':
5932         {
5933           if (LocaleCompare(attribute,"channel") == 0)
5934             {
5935               long
5936                 option;
5937
5938               option=ParseChannelOption(SvPV(ST(i),na));
5939               if (option < 0)
5940                 {
5941                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
5942                     SvPV(ST(i),na));
5943                   return;
5944                 }
5945                channel=(ChannelType) option;
5946               break;
5947             }
5948           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5949             attribute);
5950           break;
5951         }
5952         case 'g':
5953         case 'G':
5954         {
5955           if (LocaleCompare(attribute,"geometry") == 0)
5956             {
5957               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5958               break;
5959             }
5960           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5961             attribute);
5962           break;
5963         }
5964         case 'N':
5965         case 'n':
5966         {
5967           if (LocaleCompare(attribute,"normalize") == 0)
5968             {
5969               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
5970                 SvPV(ST(i),na));
5971               if (option < 0)
5972                 {
5973                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
5974                     SvPV(ST(i),na));
5975                   break;
5976                 }
5977              normalize=option != 0 ? MagickTrue : MagickFalse;
5978              break;
5979             }
5980           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5981             attribute);
5982           break;
5983         }
5984         case 'x':
5985         case 'X':
5986         {
5987           if (LocaleCompare(attribute,"x") == 0)
5988             {
5989               region.x=SvIV(ST(i));
5990               break;
5991             }
5992           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5993             attribute);
5994           break;
5995         }
5996         case 'y':
5997         case 'Y':
5998         {
5999           if (LocaleCompare(attribute,"y") == 0)
6000             {
6001               region.y=SvIV(ST(i));
6002               break;
6003             }
6004           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6005             attribute);
6006           break;
6007         }
6008         default:
6009         {
6010           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6011             attribute);
6012           break;
6013         }
6014       }
6015     }
6016     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6017     if (p == (const PixelPacket *) NULL)
6018       PUSHs(&sv_undef);
6019     else
6020       {
6021         double
6022           scale;
6023
6024         indexes=GetVirtualIndexQueue(image);
6025         scale=1.0;
6026         if (normalize != MagickFalse)
6027           scale=1.0/QuantumRange;
6028         if ((channel & RedChannel) != 0)
6029           PUSHs(sv_2mortal(newSVnv(scale*p->red)));
6030         if ((channel & GreenChannel) != 0)
6031           PUSHs(sv_2mortal(newSVnv(scale*p->green)));
6032         if ((channel & BlueChannel) != 0)
6033           PUSHs(sv_2mortal(newSVnv(scale*p->blue)));
6034         if (((channel & IndexChannel) != 0) &&
6035             (image->colorspace == CMYKColorspace))
6036           PUSHs(sv_2mortal(newSVnv(scale*(*indexes))));
6037         if ((channel & OpacityChannel) != 0)
6038           PUSHs(sv_2mortal(newSVnv(scale*p->opacity)));
6039       }
6040
6041   PerlException:
6042     InheritPerlException(exception,perl_exception);
6043     exception=DestroyExceptionInfo(exception);
6044     SvREFCNT_dec(perl_exception);
6045   }
6046 \f
6047 #
6048 ###############################################################################
6049 #                                                                             #
6050 #                                                                             #
6051 #                                                                             #
6052 #   G e t P i x e l s                                                         #
6053 #                                                                             #
6054 #                                                                             #
6055 #                                                                             #
6056 ###############################################################################
6057 #
6058 #
6059 void
6060 GetPixels(ref,...)
6061   Image::Magick ref=NO_INIT
6062   ALIAS:
6063     getpixels = 1
6064     getPixels = 2
6065   PPCODE:
6066   {
6067     AV
6068       *av;
6069
6070     char
6071       *attribute;
6072
6073     const char
6074       *map;
6075
6076     ExceptionInfo
6077       *exception;
6078
6079     Image
6080       *image;
6081
6082     long
6083       option;
6084
6085     MagickBooleanType
6086       normalize,
6087       status;
6088
6089     RectangleInfo
6090       region;
6091
6092     register long
6093       i;
6094
6095     struct PackageInfo
6096       *info;
6097
6098     SV
6099       *perl_exception,
6100       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6101
6102     exception=AcquireExceptionInfo();
6103     perl_exception=newSVpv("",0);
6104     reference=SvRV(ST(0));
6105     av=(AV *) reference;
6106     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6107       exception);
6108     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6109     if (image == (Image *) NULL)
6110       {
6111         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6112           PackageName);
6113         goto PerlException;
6114       }
6115     map="RGB";
6116     if (image->matte != MagickFalse)
6117       map="RGBA";
6118     if (image->colorspace == CMYKColorspace)
6119       {
6120         map="CMYK";
6121         if (image->matte != MagickFalse)
6122           map="CMYKA";
6123       }
6124     normalize=MagickFalse;
6125     region.x=0;
6126     region.y=0;
6127     region.width=image->columns;
6128     region.height=1;
6129     if (items == 1)
6130       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6131     for (i=2; i < items; i+=2)
6132     {
6133       attribute=(char *) SvPV(ST(i-1),na);
6134       switch (*attribute)
6135       {
6136         case 'g':
6137         case 'G':
6138         {
6139           if (LocaleCompare(attribute,"geometry") == 0)
6140             {
6141               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6142               break;
6143             }
6144           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6145             attribute);
6146           break;
6147         }
6148         case 'H':
6149         case 'h':
6150         {
6151           if (LocaleCompare(attribute,"height") == 0)
6152             {
6153               region.height=SvIV(ST(i));
6154               break;
6155             }
6156           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6157             attribute);
6158           break;
6159         }
6160         case 'M':
6161         case 'm':
6162         {
6163           if (LocaleCompare(attribute,"map") == 0)
6164             {
6165               map=SvPV(ST(i),na);
6166               break;
6167             }
6168           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6169             attribute);
6170           break;
6171         }
6172         case 'N':
6173         case 'n':
6174         {
6175           if (LocaleCompare(attribute,"normalize") == 0)
6176             {
6177               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
6178                 SvPV(ST(i),na));
6179               if (option < 0)
6180                 {
6181                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6182                     SvPV(ST(i),na));
6183                   break;
6184                 }
6185              normalize=option != 0 ? MagickTrue : MagickFalse;
6186              break;
6187             }
6188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6189             attribute);
6190           break;
6191         }
6192         case 'W':
6193         case 'w':
6194         {
6195           if (LocaleCompare(attribute,"width") == 0)
6196             {
6197               region.width=SvIV(ST(i));
6198               break;
6199             }
6200           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6201             attribute);
6202           break;
6203         }
6204         case 'x':
6205         case 'X':
6206         {
6207           if (LocaleCompare(attribute,"x") == 0)
6208             {
6209               region.x=SvIV(ST(i));
6210               break;
6211             }
6212           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6213             attribute);
6214           break;
6215         }
6216         case 'y':
6217         case 'Y':
6218         {
6219           if (LocaleCompare(attribute,"y") == 0)
6220             {
6221               region.y=SvIV(ST(i));
6222               break;
6223             }
6224           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6225             attribute);
6226           break;
6227         }
6228         default:
6229         {
6230           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6231             attribute);
6232           break;
6233         }
6234       }
6235     }
6236     if (normalize != MagickFalse)
6237       {
6238         float
6239           *pixels;
6240
6241         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6242           region.height*sizeof(*pixels));
6243         if (pixels == (float *) NULL)
6244           {
6245             ThrowPerlException(exception,ResourceLimitError,
6246               "MemoryAllocationFailed",PackageName);
6247             goto PerlException;
6248           }
6249         status=ExportImagePixels(image,region.x,region.y,region.width,
6250           region.height,map,FloatPixel,pixels,exception);
6251         if (status == MagickFalse)
6252           PUSHs(&sv_undef);
6253         else
6254           {
6255             EXTEND(sp,strlen(map)*region.width*region.height);
6256             for (i=0; i < (long) (strlen(map)*region.width*region.height); i++)
6257               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6258           }
6259         pixels=(float *) RelinquishMagickMemory(pixels);
6260       }
6261     else
6262       {
6263         Quantum
6264           *pixels;
6265
6266         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6267           region.height*sizeof(*pixels));
6268         if (pixels == (Quantum *) NULL)
6269           {
6270             ThrowPerlException(exception,ResourceLimitError,
6271               "MemoryAllocationFailed",PackageName);
6272             goto PerlException;
6273           }
6274         status=ExportImagePixels(image,region.x,region.y,region.width,
6275           region.height,map,QuantumPixel,pixels,exception);
6276         if (status == MagickFalse)
6277           PUSHs(&sv_undef);
6278         else
6279           {
6280             EXTEND(sp,strlen(map)*region.width*region.height);
6281             for (i=0; i < (long) (strlen(map)*region.width*region.height); i++)
6282               PUSHs(sv_2mortal(newSViv(pixels[i])));
6283           }
6284         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6285       }
6286
6287   PerlException:
6288     InheritPerlException(exception,perl_exception);
6289     exception=DestroyExceptionInfo(exception);
6290     SvREFCNT_dec(perl_exception);
6291   }
6292 \f
6293 #
6294 ###############################################################################
6295 #                                                                             #
6296 #                                                                             #
6297 #                                                                             #
6298 #   I m a g e T o B l o b                                                     #
6299 #                                                                             #
6300 #                                                                             #
6301 #                                                                             #
6302 ###############################################################################
6303 #
6304 #
6305 void
6306 ImageToBlob(ref,...)
6307   Image::Magick ref=NO_INIT
6308   ALIAS:
6309     ImageToBlob  = 1
6310     imagetoblob  = 2
6311     toblob       = 3
6312     blob         = 4
6313   PPCODE:
6314   {
6315     char
6316       filename[MaxTextExtent];
6317
6318     ExceptionInfo
6319       *exception;
6320
6321     Image
6322       *image,
6323       *next;
6324
6325     long
6326       scene;
6327
6328     register long
6329       i;
6330
6331     struct PackageInfo
6332       *info,
6333       *package_info;
6334
6335     size_t
6336       length;
6337
6338     SV
6339       *perl_exception,
6340       *reference;
6341
6342     void
6343       *blob;
6344
6345     exception=AcquireExceptionInfo();
6346     perl_exception=newSVpv("",0);
6347     package_info=(struct PackageInfo *) NULL;
6348     if (sv_isobject(ST(0)) == 0)
6349       {
6350         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6351           PackageName);
6352         goto PerlException;
6353       }
6354     reference=SvRV(ST(0));
6355     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6356     if (image == (Image *) NULL)
6357       {
6358         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6359           PackageName);
6360         goto PerlException;
6361       }
6362     package_info=ClonePackageInfo(info,exception);
6363     for (i=2; i < items; i+=2)
6364       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6365     (void) CopyMagickString(filename,package_info->image_info->filename,
6366       MaxTextExtent);
6367     scene=0;
6368     for (next=image; next; next=next->next)
6369     {
6370       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6371       next->scene=scene++;
6372     }
6373     SetImageInfo(package_info->image_info,MagickTrue,&image->exception);
6374     EXTEND(sp,(long) GetImageListLength(image));
6375     for ( ; image; image=image->next)
6376     {
6377       length=0;
6378       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6379       if (blob != (char *) NULL)
6380         {
6381           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6382           blob=(unsigned char *) RelinquishMagickMemory(blob);
6383         }
6384       if (package_info->image_info->adjoin)
6385         break;
6386     }
6387
6388   PerlException:
6389     if (package_info != (struct PackageInfo *) NULL)
6390       DestroyPackageInfo(package_info);
6391     InheritPerlException(exception,perl_exception);
6392     exception=DestroyExceptionInfo(exception);
6393     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6394   }
6395 \f
6396 #
6397 ###############################################################################
6398 #                                                                             #
6399 #                                                                             #
6400 #                                                                             #
6401 #   L a y e r s                                                               #
6402 #                                                                             #
6403 #                                                                             #
6404 #                                                                             #
6405 ###############################################################################
6406 #
6407 #
6408 void
6409 Layers(ref,...)
6410   Image::Magick ref=NO_INIT
6411   ALIAS:
6412     Layers                = 1
6413     layers           = 2
6414     OptimizeImageLayers   = 3
6415     optimizelayers        = 4
6416     optimizeimagelayers   = 5
6417   PPCODE:
6418   {
6419     AV
6420       *av;
6421
6422     char
6423       *attribute;
6424
6425     CompositeOperator
6426       compose;
6427
6428     ExceptionInfo
6429       *exception;
6430
6431     HV
6432       *hv;
6433
6434     Image
6435       *image,
6436       *layers;
6437
6438     long
6439       option,
6440       sp;
6441
6442     MagickBooleanType
6443       dither;
6444
6445     ImageLayerMethod
6446       method;
6447
6448     register long
6449       i;
6450
6451     struct PackageInfo
6452       *info;
6453
6454     SV
6455       *av_reference,
6456       *perl_exception,
6457       *reference,
6458       *rv,
6459       *sv;
6460
6461     exception=AcquireExceptionInfo();
6462     perl_exception=newSVpv("",0);
6463     if (sv_isobject(ST(0)) == 0)
6464       {
6465         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6466           PackageName);
6467         goto PerlException;
6468       }
6469     reference=SvRV(ST(0));
6470     hv=SvSTASH(reference);
6471     av=newAV();
6472     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6473     SvREFCNT_dec(av);
6474     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6475     if (image == (Image *) NULL)
6476       {
6477         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6478           PackageName);
6479         goto PerlException;
6480       }
6481     compose=image->compose;
6482     dither=MagickFalse;
6483     method=OptimizeLayer;
6484     for (i=2; i < items; i+=2)
6485     {
6486       attribute=(char *) SvPV(ST(i-1),na);
6487       switch (*attribute)
6488       {
6489         case 'C':
6490         case 'c':
6491         {
6492           if (LocaleCompare(attribute,"compose") == 0)
6493             {
6494               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
6495                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6496               if (sp < 0)
6497                 {
6498                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6499                     SvPV(ST(i),na));
6500                   break;
6501                 }
6502               compose=(CompositeOperator) sp;
6503               break;
6504             }
6505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6506             attribute);
6507           break;
6508         }
6509         case 'D':
6510         case 'd':
6511         {
6512           if (LocaleCompare(attribute,"dither") == 0)
6513             {
6514               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
6515                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
6516               if (sp < 0)
6517                 {
6518                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6519                     SvPV(ST(i),na));
6520                   break;
6521                 }
6522               dither=(MagickBooleanType) sp;
6523               break;
6524             }
6525           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6526             attribute);
6527           break;
6528         }
6529         case 'M':
6530         case 'm':
6531         {
6532           if (LocaleCompare(attribute,"method") == 0)
6533             {
6534               option=ParseMagickOption(MagickLayerOptions,MagickFalse,
6535                 SvPV(ST(i),na));
6536               if (option < 0)
6537                 {
6538                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6539                     SvPV(ST(i),na));
6540                   break;
6541                 }
6542               method=(ImageLayerMethod) option;
6543               break;
6544             }
6545           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6546             attribute);
6547           break;
6548         }
6549         default:
6550         {
6551           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6552             attribute);
6553           break;
6554         }
6555       }
6556     }
6557     layers=(Image *) NULL;
6558     switch (method)
6559     {
6560       case CompareAnyLayer:
6561       case CompareClearLayer:
6562       case CompareOverlayLayer:
6563       default:
6564       {
6565         layers=CompareImageLayers(image,method,exception);
6566         break;
6567       }
6568       case MergeLayer:
6569       case FlattenLayer:
6570       case MosaicLayer:
6571       {
6572         layers=MergeImageLayers(image,method,exception);
6573         break;
6574       }
6575       case DisposeLayer:
6576       {
6577         layers=DisposeImages(image,exception);
6578         break;
6579       }
6580       case OptimizeImageLayer:
6581       {
6582         layers=OptimizeImageLayers(image,exception);
6583         break;
6584       }
6585       case OptimizePlusLayer:
6586       {
6587         layers=OptimizePlusImageLayers(image,exception);
6588         break;
6589       }
6590       case OptimizeTransLayer:
6591       {
6592         OptimizeImageTransparency(image,exception);
6593         InheritException(&(image->exception),exception);
6594         break;
6595       }
6596       case RemoveDupsLayer:
6597       {
6598         RemoveDuplicateLayers(&image,exception);
6599         InheritException(&(image->exception),exception);
6600         break;
6601       }
6602       case RemoveZeroLayer:
6603       {
6604         RemoveZeroDelayLayers(&image,exception);
6605         InheritException(&(image->exception),exception);
6606         break;
6607       }
6608       case OptimizeLayer:
6609       {
6610         QuantizeInfo
6611           *quantize_info;
6612
6613         /*
6614           General Purpose, GIF Animation Optimizer.
6615         */
6616         layers=CoalesceImages(image,exception);
6617         if (layers == (Image *) NULL)
6618           break;
6619         InheritException(&(layers->exception),exception);
6620         image=layers;
6621         layers=OptimizeImageLayers(image,exception);
6622         if (layers == (Image *) NULL)
6623           break;
6624         InheritException(&(layers->exception),exception);
6625         image=DestroyImageList(image);
6626         image=layers;
6627         layers=(Image *) NULL;
6628         OptimizeImageTransparency(image,exception);
6629         InheritException(&(image->exception),exception);
6630         quantize_info=AcquireQuantizeInfo(info->image_info);
6631         (void) RemapImages(quantize_info,image,(Image *) NULL);
6632         quantize_info=DestroyQuantizeInfo(quantize_info);
6633         break;
6634       }
6635       case CompositeLayer:
6636       {
6637         Image
6638           *source;
6639
6640         RectangleInfo
6641           geometry;
6642
6643         /*
6644           Split image sequence at the first 'NULL:' image.
6645         */
6646         source=image;
6647         while (source != (Image *) NULL)
6648         {
6649           source=GetNextImageInList(source);
6650           if ((source != (Image *) NULL) &&
6651               (LocaleCompare(source->magick,"NULL") == 0))
6652             break;
6653         }
6654         if (source != (Image *) NULL)
6655           {
6656             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6657                 (GetNextImageInList(source) == (Image *) NULL))
6658               source=(Image *) NULL;
6659             else
6660               {
6661                 /*
6662                   Separate the two lists, junk the null: image.
6663                 */
6664                 source=SplitImageList(source->previous);
6665                 DeleteImageFromList(&source);
6666               }
6667           }
6668         if (source == (Image *) NULL)
6669           {
6670             (void) ThrowMagickException(exception,GetMagickModule(),
6671               OptionError,"MissingNullSeparator","layers Composite");
6672             break;
6673           }
6674         /*
6675           Adjust offset with gravity and virtual canvas.
6676         */
6677         SetGeometry(image,&geometry);
6678         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6679         geometry.width=source->page.width != 0 ? source->page.width :
6680           source->columns;
6681         geometry.height=source->page.height != 0 ? source->page.height :
6682           source->rows;
6683         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6684           image->columns,image->page.height != 0 ? image->page.height :
6685           image->rows,image->gravity,&geometry);
6686         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6687         source=DestroyImageList(source);
6688         InheritException(&(image->exception),exception);
6689         break;
6690       }
6691     }
6692     if (layers != (Image *) NULL)
6693       {
6694         InheritException(&(layers->exception),exception);
6695         image=layers;
6696       }
6697     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6698       goto PerlException;
6699     for ( ; image; image=image->next)
6700     {
6701       AddImageToRegistry(image);
6702       rv=newRV(sv);
6703       av_push(av,sv_bless(rv,hv));
6704       SvREFCNT_dec(sv);
6705     }
6706     exception=DestroyExceptionInfo(exception);
6707     ST(0)=av_reference;
6708     SvREFCNT_dec(perl_exception);
6709     XSRETURN(1);
6710
6711   PerlException:
6712     InheritPerlException(exception,perl_exception);
6713     exception=DestroyExceptionInfo(exception);
6714     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6715     SvPOK_on(perl_exception);
6716     ST(0)=sv_2mortal(perl_exception);
6717     XSRETURN(1);
6718   }
6719 \f
6720 #
6721 ###############################################################################
6722 #                                                                             #
6723 #                                                                             #
6724 #                                                                             #
6725 #   M a g i c k T o M i m e                                                   #
6726 #                                                                             #
6727 #                                                                             #
6728 #                                                                             #
6729 ###############################################################################
6730 #
6731 #
6732 SV *
6733 MagickToMime(ref,name)
6734   Image::Magick ref=NO_INIT
6735   char *name
6736   ALIAS:
6737     magicktomime = 1
6738   CODE:
6739   {
6740     char
6741       *mime;
6742
6743     mime=MagickToMime(name);
6744     RETVAL=newSVpv(mime,0);
6745     mime=(char *) RelinquishMagickMemory(mime);
6746   }
6747   OUTPUT:
6748     RETVAL
6749 \f
6750 #
6751 ###############################################################################
6752 #                                                                             #
6753 #                                                                             #
6754 #                                                                             #
6755 #   M o g r i f y                                                             #
6756 #                                                                             #
6757 #                                                                             #
6758 #                                                                             #
6759 ###############################################################################
6760 #
6761 #
6762 void
6763 Mogrify(ref,...)
6764   Image::Magick ref=NO_INIT
6765   ALIAS:
6766     Comment            =   1
6767     CommentImage       =   2
6768     Label              =   3
6769     LabelImage         =   4
6770     AddNoise           =   5
6771     AddNoiseImage      =   6
6772     Colorize           =   7
6773     ColorizeImage      =   8
6774     Border             =   9
6775     BorderImage        =  10
6776     Blur               =  11
6777     BlurImage          =  12
6778     Chop               =  13
6779     ChopImage          =  14
6780     Crop               =  15
6781     CropImage          =  16
6782     Despeckle          =  17
6783     DespeckleImage     =  18
6784     Edge               =  19
6785     EdgeImage          =  20
6786     Emboss             =  21
6787     EmbossImage        =  22
6788     Enhance            =  23
6789     EnhanceImage       =  24
6790     Flip               =  25
6791     FlipImage          =  26
6792     Flop               =  27
6793     FlopImage          =  28
6794     Frame              =  29
6795     FrameImage         =  30
6796     Implode            =  31
6797     ImplodeImage       =  32
6798     Magnify            =  33
6799     MagnifyImage       =  34
6800     MedianFilter       =  35
6801     MedianFilterImage  =  36
6802     Minify             =  37
6803     MinifyImage        =  38
6804     OilPaint           =  39
6805     OilPaintImage      =  40
6806     ReduceNoise        =  41
6807     ReduceNoiseImage   =  42
6808     Roll               =  43
6809     RollImage          =  44
6810     Rotate             =  45
6811     RotateImage        =  46
6812     Sample             =  47
6813     SampleImage        =  48
6814     Scale              =  49
6815     ScaleImage         =  50
6816     Shade              =  51
6817     ShadeImage         =  52
6818     Sharpen            =  53
6819     SharpenImage       =  54
6820     Shear              =  55
6821     ShearImage         =  56
6822     Spread             =  57
6823     SpreadImage        =  58
6824     Swirl              =  59
6825     SwirlImage         =  60
6826     Resize             =  61
6827     ResizeImage        =  62
6828     Zoom               =  63
6829     ZoomImage          =  64
6830     Annotate           =  65
6831     AnnotateImage      =  66
6832     ColorFloodfill     =  67
6833     ColorFloodfillImage=  68
6834     Composite          =  69
6835     CompositeImage     =  70
6836     Contrast           =  71
6837     ContrastImage      =  72
6838     CycleColormap      =  73
6839     CycleColormapImage =  74
6840     Draw               =  75
6841     DrawImage          =  76
6842     Equalize           =  77
6843     EqualizeImage      =  78
6844     Gamma              =  79
6845     GammaImage         =  80
6846     Map                =  81
6847     MapImage           =  82
6848     MatteFloodfill     =  83
6849     MatteFloodfillImage=  84
6850     Modulate           =  85
6851     ModulateImage      =  86
6852     Negate             =  87
6853     NegateImage        =  88
6854     Normalize          =  89
6855     NormalizeImage     =  90
6856     NumberColors       =  91
6857     NumberColorsImage  =  92
6858     Opaque             =  93
6859     OpaqueImage        =  94
6860     Quantize           =  95
6861     QuantizeImage      =  96
6862     Raise              =  97
6863     RaiseImage         =  98
6864     Segment            =  99
6865     SegmentImage       = 100
6866     Signature          = 101
6867     SignatureImage     = 102
6868     Solarize           = 103
6869     SolarizeImage      = 104
6870     Sync               = 105
6871     SyncImage          = 106
6872     Texture            = 107
6873     TextureImage       = 108
6874     Evaluate           = 109
6875     EvaluateImage      = 110
6876     Transparent        = 111
6877     TransparentImage   = 112
6878     Threshold          = 113
6879     ThresholdImage     = 114
6880     Charcoal           = 115
6881     CharcoalImage      = 116
6882     Trim               = 117
6883     TrimImage          = 118
6884     Wave               = 119
6885     WaveImage          = 120
6886     Separate           = 121
6887     SeparateImage      = 122
6888     Stereo             = 125
6889     StereoImage        = 126
6890     Stegano            = 127
6891     SteganoImage       = 128
6892     Deconstruct        = 129
6893     DeconstructImage   = 130
6894     GaussianBlur       = 131
6895     GaussianBlurImage  = 132
6896     Convolve           = 133
6897     ConvolveImage      = 134
6898     Profile            = 135
6899     ProfileImage       = 136
6900     UnsharpMask        = 137
6901     UnsharpMaskImage   = 138
6902     MotionBlur         = 139
6903     MotionBlurImage    = 140
6904     OrderedDither      = 141
6905     OrderedDitherImage = 142
6906     Shave              = 143
6907     ShaveImage         = 144
6908     Level              = 145
6909     LevelImage         = 146
6910     Clip               = 147
6911     ClipImage          = 148
6912     AffineTransform    = 149
6913     AffineTransformImage = 150
6914     Difference         = 151
6915     DifferenceImage    = 152
6916     AdaptiveThreshold  = 153
6917     AdaptiveThresholdImage = 154
6918     Resample           = 155
6919     ResampleImage      = 156
6920     Describe           = 157
6921     DescribeImage      = 158
6922     BlackThreshold     = 159
6923     BlackThresholdImage= 160
6924     WhiteThreshold     = 161
6925     WhiteThresholdImage= 162
6926     RadialBlur         = 163
6927     RadialBlurImage    = 164
6928     Thumbnail          = 165
6929     ThumbnailImage     = 166
6930     Strip              = 167
6931     StripImage         = 168
6932     Tint               = 169
6933     TintImage          = 170
6934     Channel            = 171
6935     ChannelImage       = 172
6936     Splice             = 173
6937     SpliceImage        = 174
6938     Posterize          = 175
6939     PosterizeImage     = 176
6940     Shadow             = 177
6941     ShadowImage        = 178
6942     Identify           = 179
6943     IdentifyImage      = 180
6944     SepiaTone          = 181
6945     SepiaToneImage     = 182
6946     SigmoidalContrast  = 183
6947     SigmoidalContrastImage = 184
6948     Extent             = 185
6949     ExtentImage        = 186
6950     Vignette           = 187
6951     VignetteImage      = 188
6952     ContrastStretch    = 189
6953     ContrastStretchImage = 190
6954     Sans0              = 191
6955     Sans0Image         = 192
6956     Sans1              = 193
6957     Sans1Image         = 194
6958     AdaptiveSharpen    = 195
6959     AdaptiveSharpenImage = 196
6960     Transpose          = 197
6961     TransposeImage     = 198
6962     Transverse         = 199
6963     TransverseImage    = 200
6964     AutoOrient         = 201
6965     AutoOrientImage    = 202
6966     AdaptiveBlur       = 203
6967     AdaptiveBlurImage  = 204
6968     Sketch             = 205
6969     SketchImage        = 206
6970     UniqueColors       = 207
6971     UniqueColorsImage  = 208
6972     AdaptiveResize     = 209
6973     AdaptiveResizeImage= 210
6974     ClipMask           = 211
6975     ClipMaskImage      = 212
6976     LinearStretch      = 213
6977     LinearStretchImage = 214
6978     RecolorImage       = 215
6979     Recolor            = 216
6980     Mask               = 217
6981     MaskImage          = 218
6982     Polaroid           = 219
6983     PolaroidImage      = 220
6984     FloodfillPaint     = 221
6985     FloodfillPaintImage= 222
6986     Distort            = 223
6987     DistortImage       = 224
6988     Clut               = 225
6989     ClutImage          = 226
6990     LiquidRescale      = 227
6991     LiquidRescaleImage = 228
6992     Encipher           = 229
6993     EncipherImage      = 230
6994     Decipher           = 231
6995     DecipherImage      = 232
6996     Deskew             = 233
6997     DeskewImage        = 234
6998     Remap              = 235
6999     RemapImage         = 236
7000     SparseColor        = 237
7001     SparseColorImage   = 238
7002     Function           = 239
7003     FunctionImage      = 240
7004     SelectiveBlur      = 241
7005     SelectiveBlurImage = 242
7006     HaldClut           = 243
7007     HaldClutImage      = 244
7008     BlueShift          = 245
7009     BlueShiftImage     = 246
7010     ForwardFourierTransform  = 247
7011     ForwardFourierTransformImage = 248
7012     InverseFourierTransform = 249
7013     InverseFourierTransformImage = 250
7014     ColorDecisionList  = 251
7015     ColorDecisionListImage = 252
7016     AutoGamma          = 253
7017     AutoGammaImage     = 254
7018     AutoLevel          = 255
7019     AutoLevelImage     = 256
7020     LevelColors        = 257
7021     LevelColorsImage   = 258
7022     Clamp              = 259
7023     ClampImage         = 260
7024     Filter             = 261
7025     FilterImage        = 262
7026     BrightnessContrast = 263
7027     BrightnessContrastImage = 264
7028     Morphology         = 265
7029     MorphologyImage    = 266
7030     MogrifyRegion      = 666
7031   PPCODE:
7032   {
7033     AffineMatrix
7034       affine,
7035       current;
7036
7037     char
7038       attribute_flag[MaxArguments],
7039       message[MaxTextExtent];
7040
7041     ChannelType
7042       channel;
7043
7044     CompositeOperator
7045       compose;
7046
7047     const char
7048       *attribute,
7049       *value;
7050
7051     double
7052       angle;
7053
7054     ExceptionInfo
7055       *exception;
7056
7057     GeometryInfo
7058       geometry_info;
7059
7060     Image
7061       *image,
7062       *next,
7063       *region_image;
7064
7065     long
7066       base,
7067       j,
7068       number_images;
7069
7070     MagickBooleanType
7071       status;
7072
7073     MagickStatusType
7074       flags;
7075
7076     PixelPacket
7077       fill_color;
7078
7079     RectangleInfo
7080       geometry,
7081       region_info;
7082
7083     register long
7084       i;
7085
7086     struct PackageInfo
7087       *info;
7088
7089     struct Methods
7090       *rp;
7091
7092     SV
7093       *perl_exception,
7094       **pv,
7095       *reference,
7096       **reference_vector;
7097
7098     struct ArgumentList
7099       argument_list[MaxArguments];
7100
7101     exception=AcquireExceptionInfo();
7102     perl_exception=newSVpv("",0);
7103     reference_vector=NULL;
7104     region_image=NULL;
7105     number_images=0;
7106     base=2;
7107     if (sv_isobject(ST(0)) == 0)
7108       {
7109         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7110           PackageName);
7111         goto PerlException;
7112       }
7113     reference=SvRV(ST(0));
7114     region_info.width=0;
7115     region_info.height=0;
7116     region_info.x=0;
7117     region_info.y=0;
7118     region_image=(Image *) NULL;
7119     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7120     if (ix && (ix != 666))
7121       {
7122         /*
7123           Called as Method(...)
7124         */
7125         ix=(ix+1)/2;
7126         rp=(&Methods[ix-1]);
7127         attribute=rp->name;
7128       }
7129     else
7130       {
7131         /*
7132           Called as Mogrify("Method",...)
7133         */
7134         attribute=(char *) SvPV(ST(1),na);
7135         if (ix)
7136           {
7137             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7138             attribute=(char *) SvPV(ST(2),na);
7139             base++;
7140           }
7141         for (rp=Methods; ; rp++)
7142         {
7143           if (rp >= EndOf(Methods))
7144             {
7145               ThrowPerlException(exception,OptionError,
7146                 "UnrecognizedPerlMagickMethod",attribute);
7147               goto PerlException;
7148             }
7149           if (strEQcase(attribute,rp->name))
7150             break;
7151         }
7152         ix=rp-Methods+1;
7153         base++;
7154       }
7155     if (image == (Image *) NULL)
7156       {
7157         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7158         goto PerlException;
7159       }
7160     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7161     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7162     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7163     {
7164       long
7165         longest;
7166
7167       Arguments
7168         *pp,
7169         *qq;
7170
7171       struct ArgumentList
7172         *al;
7173
7174       SV
7175         *sv;
7176
7177       longest=0;
7178       pp=(Arguments *) NULL;
7179       qq=rp->arguments;
7180       if (i == items)
7181         {
7182           pp=rp->arguments,
7183           sv=ST(i-1);
7184         }
7185       else
7186         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7187         {
7188           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7189             break;
7190           if (strEQcase(attribute,qq->method) > longest)
7191             {
7192               pp=qq;
7193               longest=strEQcase(attribute,qq->method);
7194             }
7195         }
7196       if (pp == (Arguments *) NULL)
7197         {
7198           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7199             attribute);
7200           goto continue_outer_loop;
7201         }
7202       al=(&argument_list[pp-rp->arguments]);
7203       switch (pp->type)
7204       {
7205         case ArrayReference:
7206         {
7207           if (SvTYPE(sv) != SVt_RV)
7208             {
7209               (void) FormatMagickString(message,MaxTextExtent,
7210                 "invalid %.60s value",pp->method);
7211               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7212               goto continue_outer_loop;
7213             }
7214           al->array_reference=SvRV(sv);
7215           break;
7216         }
7217         case RealReference:
7218         {
7219           al->real_reference=SvNV(sv);
7220           break;
7221         }
7222         case FileReference:
7223         {
7224           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7225           break;
7226         }
7227         case ImageReference:
7228         {
7229           if (!sv_isobject(sv) ||
7230               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7231                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7232             {
7233               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7234                 PackageName);
7235               goto PerlException;
7236             }
7237           break;
7238         }
7239         case IntegerReference:
7240         {
7241           al->long_reference=SvIV(sv);
7242           break;
7243         }
7244         case StringReference:
7245         {
7246           al->string_reference=(char *) SvPV(sv,al->length);
7247           if (sv_isobject(sv))
7248             al->image_reference=SetupList(aTHX_ SvRV(sv),
7249               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7250           break;
7251         }
7252         default:
7253         {
7254           /*
7255             Is a string; look up name.
7256           */
7257           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7258             {
7259               al->string_reference=(char *) SvPV(sv,al->length);
7260               al->long_reference=(-1);
7261               break;
7262             }
7263           al->long_reference=ParseMagickOption((MagickOption) pp->type,
7264             MagickFalse,SvPV(sv,na));
7265           if (pp->type == MagickChannelOptions)
7266             al->long_reference=ParseChannelOption(SvPV(sv,na));
7267           if ((al->long_reference < 0) && ((al->long_reference=SvIV(sv)) <= 0))
7268             {
7269               (void) FormatMagickString(message,MaxTextExtent,
7270                 "invalid %.60s value",pp->method);
7271               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7272               goto continue_outer_loop;
7273             }
7274           break;
7275         }
7276       }
7277       attribute_flag[pp-rp->arguments]++;
7278       continue_outer_loop: ;
7279     }
7280     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7281     pv=reference_vector;
7282     SetGeometryInfo(&geometry_info);
7283     channel=DefaultChannels;
7284     for (next=image; next; next=next->next)
7285     {
7286       image=next;
7287       SetGeometry(image,&geometry);
7288       if ((region_info.width*region_info.height) != 0)
7289         {
7290           region_image=image;
7291           image=CropImage(image,&region_info,exception);
7292         }
7293       switch (ix)
7294       {
7295         default:
7296         {
7297           (void) FormatMagickString(message,MaxTextExtent,"%ld",(long) ix);
7298           ThrowPerlException(exception,OptionError,
7299             "UnrecognizedPerlMagickMethod",message);
7300           goto PerlException;
7301         }
7302         case 1:  /* Comment */
7303         {
7304           if (attribute_flag[0] == 0)
7305             argument_list[0].string_reference=(char *) NULL;
7306           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7307             info ? info->image_info : (ImageInfo *) NULL,image,
7308             argument_list[0].string_reference));
7309           break;
7310         }
7311         case 2:  /* Label */
7312         {
7313           if (attribute_flag[0] == 0)
7314             argument_list[0].string_reference=(char *) NULL;
7315           (void) SetImageProperty(image,"label",InterpretImageProperties(
7316             info ? info->image_info : (ImageInfo *) NULL,image,
7317             argument_list[0].string_reference));
7318           break;
7319         }
7320         case 3:  /* AddNoise */
7321         {
7322           if (attribute_flag[0] == 0)
7323             argument_list[0].long_reference=UniformNoise;
7324           if (attribute_flag[1] != 0)
7325             channel=(ChannelType) argument_list[1].long_reference;
7326           image=AddNoiseImageChannel(image,channel,(NoiseType)
7327             argument_list[0].long_reference,exception);
7328           break;
7329         }
7330         case 4:  /* Colorize */
7331         {
7332           PixelPacket
7333             target;
7334
7335           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7336           if (attribute_flag[0] != 0)
7337             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7338               exception);
7339           if (attribute_flag[1] == 0)
7340             argument_list[1].string_reference="100%";
7341           image=ColorizeImage(image,argument_list[1].string_reference,target,
7342             exception);
7343           break;
7344         }
7345         case 5:  /* Border */
7346         {
7347           geometry.width=0;
7348           geometry.height=0;
7349           if (attribute_flag[0] != 0)
7350             {
7351               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7352                 &geometry,exception);
7353               if ((flags & HeightValue) == 0)
7354                 geometry.height=geometry.width;
7355             }
7356           if (attribute_flag[1] != 0)
7357             geometry.width=argument_list[1].long_reference;
7358           if (attribute_flag[2] != 0)
7359             geometry.height=argument_list[2].long_reference;
7360           if (attribute_flag[3] != 0)
7361             QueryColorDatabase(argument_list[3].string_reference,
7362               &image->border_color,exception);
7363           if (attribute_flag[4] != 0)
7364             QueryColorDatabase(argument_list[4].string_reference,
7365               &image->border_color,exception);
7366           if (attribute_flag[5] != 0)
7367             QueryColorDatabase(argument_list[5].string_reference,
7368               &image->border_color,exception);
7369           if (attribute_flag[6] != 0)
7370             image->compose=(CompositeOperator) argument_list[6].long_reference;
7371           image=BorderImage(image,&geometry,exception);
7372           break;
7373         }
7374         case 6:  /* Blur */
7375         {
7376           if (attribute_flag[0] != 0)
7377             {
7378               flags=ParseGeometry(argument_list[0].string_reference,
7379                 &geometry_info);
7380               if ((flags & SigmaValue) == 0)
7381                 geometry_info.sigma=1.0;
7382             }
7383           if (attribute_flag[1] != 0)
7384             geometry_info.rho=argument_list[1].real_reference;
7385           if (attribute_flag[2] != 0)
7386             geometry_info.sigma=argument_list[2].real_reference;
7387           if (attribute_flag[3] != 0)
7388             channel=(ChannelType) argument_list[3].long_reference;
7389           image=BlurImageChannel(image,channel,geometry_info.rho,
7390             geometry_info.sigma,exception);
7391           break;
7392         }
7393         case 7:  /* Chop */
7394         {
7395           if (attribute_flag[0] != 0)
7396             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7397               &geometry,exception);
7398           if (attribute_flag[1] != 0)
7399             geometry.width=argument_list[1].long_reference;
7400           if (attribute_flag[2] != 0)
7401             geometry.height=argument_list[2].long_reference;
7402           if (attribute_flag[3] != 0)
7403             geometry.x=argument_list[3].long_reference;
7404           if (attribute_flag[4] != 0)
7405             geometry.y=argument_list[4].long_reference;
7406           image=ChopImage(image,&geometry,exception);
7407           break;
7408         }
7409         case 8:  /* Crop */
7410         {
7411           if (attribute_flag[6] != 0)
7412             image->gravity=(GravityType) argument_list[6].long_reference;
7413           if (attribute_flag[0] != 0)
7414             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7415               &geometry,exception);
7416           if (attribute_flag[1] != 0)
7417             geometry.width=argument_list[1].long_reference;
7418           if (attribute_flag[2] != 0)
7419             geometry.height=argument_list[2].long_reference;
7420           if (attribute_flag[3] != 0)
7421             geometry.x=argument_list[3].long_reference;
7422           if (attribute_flag[4] != 0)
7423             geometry.y=argument_list[4].long_reference;
7424           if (attribute_flag[5] != 0)
7425             image->fuzz=
7426               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7427           image=CropImage(image,&geometry,exception);
7428           break;
7429         }
7430         case 9:  /* Despeckle */
7431         {
7432           image=DespeckleImage(image,exception);
7433           break;
7434         }
7435         case 10:  /* Edge */
7436         {
7437           if (attribute_flag[0] != 0)
7438             geometry_info.rho=argument_list[0].real_reference;
7439           image=EdgeImage(image,geometry_info.rho,exception);
7440           break;
7441         }
7442         case 11:  /* Emboss */
7443         {
7444           if (attribute_flag[0] != 0)
7445             {
7446               flags=ParseGeometry(argument_list[0].string_reference,
7447                 &geometry_info);
7448               if ((flags & SigmaValue) == 0)
7449                 geometry_info.sigma=1.0;
7450             }
7451           if (attribute_flag[1] != 0)
7452             geometry_info.rho=argument_list[1].real_reference;
7453           if (attribute_flag[2] != 0)
7454             geometry_info.sigma=argument_list[2].real_reference;
7455           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7456             exception);
7457           break;
7458         }
7459         case 12:  /* Enhance */
7460         {
7461           image=EnhanceImage(image,exception);
7462           break;
7463         }
7464         case 13:  /* Flip */
7465         {
7466           image=FlipImage(image,exception);
7467           break;
7468         }
7469         case 14:  /* Flop */
7470         {
7471           image=FlopImage(image,exception);
7472           break;
7473         }
7474         case 15:  /* Frame */
7475         {
7476           FrameInfo
7477             frame_info;
7478
7479           if (attribute_flag[0] != 0)
7480             {
7481               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7482                 &geometry,exception);
7483               if ((flags & HeightValue) == 0)
7484                 geometry.height=geometry.width;
7485               frame_info.width=geometry.width;
7486               frame_info.height=geometry.height;
7487               frame_info.outer_bevel=geometry.x;
7488               frame_info.inner_bevel=geometry.y;
7489             }
7490           if (attribute_flag[1] != 0)
7491             frame_info.width=argument_list[1].long_reference;
7492           if (attribute_flag[2] != 0)
7493             frame_info.height=argument_list[2].long_reference;
7494           if (attribute_flag[3] != 0)
7495             frame_info.inner_bevel=argument_list[3].long_reference;
7496           if (attribute_flag[4] != 0)
7497             frame_info.outer_bevel=argument_list[4].long_reference;
7498           if (attribute_flag[5] != 0)
7499             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7500               exception);
7501           if (attribute_flag[6] != 0)
7502             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7503               exception);
7504           frame_info.x=(long) frame_info.width;
7505           frame_info.y=(long) frame_info.height;
7506           frame_info.width=image->columns+2*frame_info.x;
7507           frame_info.height=image->rows+2*frame_info.y;
7508           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7509             image->matte_color=fill_color;
7510           if (attribute_flag[7] != 0)
7511             image->compose=(CompositeOperator) argument_list[7].long_reference;
7512           image=FrameImage(image,&frame_info,exception);
7513           break;
7514         }
7515         case 16:  /* Implode */
7516         {
7517           if (attribute_flag[0] == 0)
7518             argument_list[0].real_reference=0.5;
7519           if (attribute_flag[1] != 0)
7520             image->interpolate=(InterpolatePixelMethod)
7521               argument_list[1].long_reference;
7522           image=ImplodeImage(image,argument_list[0].real_reference,
7523             exception);
7524           break;
7525         }
7526         case 17:  /* Magnify */
7527         {
7528           image=MagnifyImage(image,exception);
7529           break;
7530         }
7531         case 18:  /* MedianFilter */
7532         {
7533           if (attribute_flag[0] == 0)
7534             argument_list[0].real_reference=0.0;
7535           image=MedianFilterImage(image,argument_list[0].real_reference,
7536             exception);
7537           break;
7538         }
7539         case 19:  /* Minify */
7540         {
7541           image=MinifyImage(image,exception);
7542           break;
7543         }
7544         case 20:  /* OilPaint */
7545         {
7546           if (attribute_flag[0] == 0)
7547             argument_list[0].real_reference=0.0;
7548           image=OilPaintImage(image,argument_list[0].real_reference,
7549             exception);
7550           break;
7551         }
7552         case 21:  /* ReduceNoise */
7553         {
7554           if (attribute_flag[0] == 0)
7555             argument_list[0].real_reference=0.0;
7556           image=ReduceNoiseImage(image,argument_list[0].real_reference,
7557             exception);
7558           break;
7559         }
7560         case 22:  /* Roll */
7561         {
7562           if (attribute_flag[0] != 0)
7563             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7564               &geometry,exception);
7565           if (attribute_flag[1] != 0)
7566             geometry.x=argument_list[1].long_reference;
7567           if (attribute_flag[2] != 0)
7568             geometry.y=argument_list[2].long_reference;
7569           image=RollImage(image,geometry.x,geometry.y,exception);
7570           break;
7571         }
7572         case 23:  /* Rotate */
7573         {
7574           if (attribute_flag[0] == 0)
7575             argument_list[0].real_reference=90.0;
7576           if (attribute_flag[1] != 0)
7577             QueryColorDatabase(argument_list[1].string_reference,
7578               &image->background_color,exception);
7579           if (attribute_flag[2] != 0)
7580             QueryColorDatabase(argument_list[2].string_reference,
7581               &image->background_color,exception);
7582           if (attribute_flag[3] != 0)
7583             QueryColorDatabase(argument_list[3].string_reference,
7584               &image->background_color,exception);
7585           image=RotateImage(image,argument_list[0].real_reference,exception);
7586           break;
7587         }
7588         case 24:  /* Sample */
7589         {
7590           if (attribute_flag[0] != 0)
7591             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7592               &geometry,exception);
7593           if (attribute_flag[1] != 0)
7594             geometry.width=argument_list[1].long_reference;
7595           if (attribute_flag[2] != 0)
7596             geometry.height=argument_list[2].long_reference;
7597           image=SampleImage(image,geometry.width,geometry.height,exception);
7598           break;
7599         }
7600         case 25:  /* Scale */
7601         {
7602           if (attribute_flag[0] != 0)
7603             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7604               &geometry,exception);
7605           if (attribute_flag[1] != 0)
7606             geometry.width=argument_list[1].long_reference;
7607           if (attribute_flag[2] != 0)
7608             geometry.height=argument_list[2].long_reference;
7609           image=ScaleImage(image,geometry.width,geometry.height,exception);
7610           break;
7611         }
7612         case 26:  /* Shade */
7613         {
7614           if (attribute_flag[0] != 0)
7615             {
7616               flags=ParseGeometry(argument_list[0].string_reference,
7617                 &geometry_info);
7618               if ((flags & SigmaValue) == 0)
7619                 geometry_info.sigma=0.0;
7620             }
7621           if (attribute_flag[1] != 0)
7622             geometry_info.rho=argument_list[1].real_reference;
7623           if (attribute_flag[2] != 0)
7624             geometry_info.sigma=argument_list[2].real_reference;
7625           image=ShadeImage(image,
7626             argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse,
7627             geometry_info.rho,geometry_info.sigma,exception);
7628           break;
7629         }
7630         case 27:  /* Sharpen */
7631         {
7632           if (attribute_flag[0] != 0)
7633             {
7634               flags=ParseGeometry(argument_list[0].string_reference,
7635                 &geometry_info);
7636               if ((flags & SigmaValue) == 0)
7637                 geometry_info.sigma=1.0;
7638             }
7639           if (attribute_flag[1] != 0)
7640             geometry_info.rho=argument_list[1].real_reference;
7641           if (attribute_flag[2] != 0)
7642             geometry_info.sigma=argument_list[2].real_reference;
7643           if (attribute_flag[3] != 0)
7644             channel=(ChannelType) argument_list[3].long_reference;
7645           image=SharpenImageChannel(image,channel,geometry_info.rho,
7646             geometry_info.sigma,exception);
7647           break;
7648         }
7649         case 28:  /* Shear */
7650         {
7651           if (attribute_flag[0] != 0)
7652             {
7653               flags=ParseGeometry(argument_list[0].string_reference,
7654                 &geometry_info);
7655               if ((flags & SigmaValue) == 0)
7656                 geometry_info.sigma=geometry_info.rho;
7657             }
7658           if (attribute_flag[1] != 0)
7659             geometry_info.rho=argument_list[1].real_reference;
7660           if (attribute_flag[2] != 0)
7661             geometry_info.sigma=argument_list[2].real_reference;
7662           if (attribute_flag[3] != 0)
7663             QueryColorDatabase(argument_list[3].string_reference,
7664               &image->background_color,exception);
7665           if (attribute_flag[4] != 0)
7666             QueryColorDatabase(argument_list[4].string_reference,
7667               &image->background_color,exception);
7668           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7669             exception);
7670           break;
7671         }
7672         case 29:  /* Spread */
7673         {
7674           if (attribute_flag[0] == 0)
7675             argument_list[0].real_reference=1.0;
7676           image=SpreadImage(image,argument_list[0].real_reference,exception);
7677           break;
7678         }
7679         case 30:  /* Swirl */
7680         {
7681           if (attribute_flag[0] == 0)
7682             argument_list[0].real_reference=50.0;
7683           if (attribute_flag[1] != 0)
7684             image->interpolate=(InterpolatePixelMethod)
7685               argument_list[1].long_reference;
7686           image=SwirlImage(image,argument_list[0].real_reference,exception);
7687           break;
7688         }
7689         case 31:  /* Resize */
7690         case 32:  /* Zoom */
7691         {
7692           if (attribute_flag[0] != 0)
7693             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7694               &geometry,exception);
7695           if (attribute_flag[1] != 0)
7696             geometry.width=argument_list[1].long_reference;
7697           if (attribute_flag[2] != 0)
7698             geometry.height=argument_list[2].long_reference;
7699           if (attribute_flag[3] == 0)
7700             argument_list[3].long_reference=(long) UndefinedFilter;
7701           if (attribute_flag[4] != 0)
7702             SetImageArtifact(image,"filter:support",
7703               argument_list[4].string_reference);
7704           if (attribute_flag[5] == 0)
7705             argument_list[5].real_reference=1.0;
7706           image=ResizeImage(image,geometry.width,geometry.height,
7707             (FilterTypes) argument_list[3].long_reference,
7708             argument_list[5].real_reference,exception);
7709           break;
7710         }
7711         case 33:  /* Annotate */
7712         {
7713           DrawInfo
7714             *draw_info;
7715
7716           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7717             (DrawInfo *) NULL);
7718           if (attribute_flag[0] != 0)
7719             {
7720               char
7721                 *text;
7722
7723               text=InterpretImageProperties(info ? info->image_info :
7724                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7725               (void) CloneString(&draw_info->text,text);
7726               text=DestroyString(text);
7727             }
7728           if (attribute_flag[1] != 0)
7729             (void) CloneString(&draw_info->font,
7730               argument_list[1].string_reference);
7731           if (attribute_flag[2] != 0)
7732             draw_info->pointsize=argument_list[2].real_reference;
7733           if (attribute_flag[3] != 0)
7734             (void) CloneString(&draw_info->density,
7735               argument_list[3].string_reference);
7736           if (attribute_flag[4] != 0)
7737             (void) QueryColorDatabase(argument_list[4].string_reference,
7738               &draw_info->undercolor,exception);
7739           if (attribute_flag[5] != 0)
7740             {
7741               (void) QueryColorDatabase(argument_list[5].string_reference,
7742                 &draw_info->stroke,exception);
7743               if (argument_list[5].image_reference != (Image *) NULL)
7744                 draw_info->stroke_pattern=CloneImage(
7745                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7746             }
7747           if (attribute_flag[6] != 0)
7748             {
7749               (void) QueryColorDatabase(argument_list[6].string_reference,
7750                 &draw_info->fill,exception);
7751               if (argument_list[6].image_reference != (Image *) NULL)
7752                 draw_info->fill_pattern=CloneImage(
7753                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7754             }
7755           if (attribute_flag[7] != 0)
7756             {
7757               (void) CloneString(&draw_info->geometry,
7758                 argument_list[7].string_reference);
7759               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7760                 &geometry,exception);
7761               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7762                 geometry_info.sigma=geometry_info.xi;
7763             }
7764           if (attribute_flag[8] != 0)
7765             (void) QueryColorDatabase(argument_list[8].string_reference,
7766               &draw_info->fill,exception);
7767           if (attribute_flag[11] != 0)
7768             draw_info->gravity=(GravityType) argument_list[11].long_reference;
7769           if (attribute_flag[25] != 0)
7770             {
7771               AV
7772                 *av;
7773
7774               av=(AV *) argument_list[25].array_reference;
7775               if ((av_len(av) != 3) && (av_len(av) != 5))
7776                 {
7777                   ThrowPerlException(exception,OptionError,
7778                     "affine matrix must have 4 or 6 elements",PackageName);
7779                   goto PerlException;
7780                 }
7781               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7782               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7783               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7784               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7785               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7786                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7787                 {
7788                   ThrowPerlException(exception,OptionError,
7789                     "affine matrix is singular",PackageName);
7790                    goto PerlException;
7791                 }
7792               if (av_len(av) == 5)
7793                 {
7794                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7795                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
7796                 }
7797             }
7798           for (j=12; j < 17; j++)
7799           {
7800             if (attribute_flag[j] == 0)
7801               continue;
7802             value=argument_list[j].string_reference;
7803             angle=argument_list[j].real_reference;
7804             current=draw_info->affine;
7805             GetAffineMatrix(&affine);
7806             switch (j)
7807             {
7808               case 12:
7809               {
7810                 /*
7811                   Translate.
7812                 */
7813                 flags=ParseGeometry(value,&geometry_info);
7814                 affine.tx=geometry_info.xi;
7815                 affine.ty=geometry_info.psi;
7816                 if ((flags & PsiValue) == 0)
7817                   affine.ty=affine.tx;
7818                 break;
7819               }
7820               case 13:
7821               {
7822                 /*
7823                   Scale.
7824                 */
7825                 flags=ParseGeometry(value,&geometry_info);
7826                 affine.sx=geometry_info.rho;
7827                 affine.sy=geometry_info.sigma;
7828                 if ((flags & SigmaValue) == 0)
7829                   affine.sy=affine.sx;
7830                 break;
7831               }
7832               case 14:
7833               {
7834                 /*
7835                   Rotate.
7836                 */
7837                 if (angle == 0.0)
7838                   break;
7839                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
7840                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
7841                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
7842                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
7843                 break;
7844               }
7845               case 15:
7846               {
7847                 /*
7848                   SkewX.
7849                 */
7850                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
7851                 break;
7852               }
7853               case 16:
7854               {
7855                 /*
7856                   SkewY.
7857                 */
7858                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
7859                 break;
7860               }
7861             }
7862             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
7863             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
7864             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
7865             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
7866             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
7867               current.tx;
7868             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
7869               current.ty;
7870           }
7871           if (attribute_flag[9] == 0)
7872             argument_list[9].real_reference=0.0;
7873           if (attribute_flag[10] == 0)
7874             argument_list[10].real_reference=0.0;
7875           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
7876             {
7877               char
7878                 geometry[MaxTextExtent];
7879
7880               (void) FormatMagickString(geometry,MaxTextExtent,"%+f%+f",
7881                 (double) argument_list[9].real_reference+draw_info->affine.tx,
7882                 (double) argument_list[10].real_reference+draw_info->affine.ty);
7883               (void) CloneString(&draw_info->geometry,geometry);
7884             }
7885           if (attribute_flag[17] != 0)
7886             draw_info->stroke_width=argument_list[17].real_reference;
7887           if (attribute_flag[18] != 0)
7888             {
7889               draw_info->text_antialias=argument_list[18].long_reference != 0 ?
7890                 MagickTrue : MagickFalse;
7891               draw_info->stroke_antialias=draw_info->text_antialias;
7892             }
7893           if (attribute_flag[19] != 0)
7894             (void) CloneString(&draw_info->family,
7895               argument_list[19].string_reference);
7896           if (attribute_flag[20] != 0)
7897             draw_info->style=(StyleType) argument_list[20].long_reference;
7898           if (attribute_flag[21] != 0)
7899             draw_info->stretch=(StretchType) argument_list[21].long_reference;
7900           if (attribute_flag[22] != 0)
7901             draw_info->weight=argument_list[22].long_reference;
7902           if (attribute_flag[23] != 0)
7903             draw_info->align=(AlignType) argument_list[23].long_reference;
7904           if (attribute_flag[24] != 0)
7905             (void) CloneString(&draw_info->encoding,
7906               argument_list[24].string_reference);
7907           if (attribute_flag[25] != 0)
7908             draw_info->fill_pattern=CloneImage(
7909               argument_list[25].image_reference,0,0,MagickTrue,exception);
7910           if (attribute_flag[26] != 0)
7911             draw_info->fill_pattern=CloneImage(
7912               argument_list[26].image_reference,0,0,MagickTrue,exception);
7913           if (attribute_flag[27] != 0)
7914             draw_info->stroke_pattern=CloneImage(
7915               argument_list[27].image_reference,0,0,MagickTrue,exception);
7916           if (attribute_flag[29] != 0)
7917             draw_info->kerning=argument_list[29].real_reference;
7918           if (attribute_flag[30] != 0)
7919             draw_info->interline_spacing=argument_list[30].real_reference;
7920           if (attribute_flag[31] != 0)
7921             draw_info->interword_spacing=argument_list[31].real_reference;
7922           (void) AnnotateImage(image,draw_info);
7923           draw_info=DestroyDrawInfo(draw_info);
7924           break;
7925         }
7926         case 34:  /* ColorFloodfill */
7927         {
7928           DrawInfo
7929             *draw_info;
7930
7931           MagickBooleanType
7932             invert;
7933
7934           MagickPixelPacket
7935             target;
7936
7937           draw_info=CloneDrawInfo(info ? info->image_info :
7938             (ImageInfo *) NULL,(DrawInfo *) NULL);
7939           if (attribute_flag[0] != 0)
7940             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7941               &geometry,exception);
7942           if (attribute_flag[1] != 0)
7943             geometry.x=argument_list[1].long_reference;
7944           if (attribute_flag[2] != 0)
7945             geometry.y=argument_list[2].long_reference;
7946           if (attribute_flag[3] != 0)
7947             (void) QueryColorDatabase(argument_list[3].string_reference,
7948               &draw_info->fill,exception);
7949           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
7950             exception);
7951           invert=MagickFalse;
7952           if (attribute_flag[4] != 0)
7953             {
7954               QueryMagickColor(argument_list[4].string_reference,&target,
7955                 exception);
7956               invert=MagickTrue;
7957             }
7958           if (attribute_flag[5] != 0)
7959             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
7960               QuantumRange);
7961           if (attribute_flag[6] != 0)
7962             invert=(MagickBooleanType) argument_list[6].long_reference;
7963           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
7964             geometry.x,geometry.y,invert);
7965           draw_info=DestroyDrawInfo(draw_info);
7966           break;
7967         }
7968         case 35:  /* Composite */
7969         {
7970           char
7971             composite_geometry[MaxTextExtent];
7972
7973           Image
7974             *composite_image,
7975             *rotate_image;
7976
7977           compose=OverCompositeOp;
7978           if (attribute_flag[0] != 0)
7979             composite_image=argument_list[0].image_reference;
7980           else
7981             {
7982               ThrowPerlException(exception,OptionError,
7983                 "CompositeImageRequired",PackageName);
7984               goto PerlException;
7985             }
7986           /*
7987             Parameter Handling used for BOTH normal and tiled composition.
7988           */
7989           if (attribute_flag[1] != 0) /* compose */
7990             compose=(CompositeOperator) argument_list[1].long_reference;
7991           if (attribute_flag[6] != 0) /* opacity  */
7992             {
7993               if (compose != DissolveCompositeOp)
7994                 (void) SetImageOpacity(composite_image,(Quantum) (QuantumRange-
7995                   SiPrefixToDouble(argument_list[6].string_reference,
7996                   QuantumRange)));
7997               else
7998                 {
7999                   double
8000                     opacity;
8001
8002                   long
8003                     y;
8004
8005                   MagickBooleanType
8006                     sync;
8007
8008                   register long
8009                     x;
8010
8011                   register PixelPacket
8012                     *q;
8013
8014                   CacheView
8015                     *composite_view;
8016
8017                   /*
8018                     Handle dissolve composite operator (patch by
8019                     Kevin A. McGrail).
8020                   */
8021                   (void) CloneString(&image->geometry,
8022                     argument_list[6].string_reference);
8023                   opacity=(Quantum) (QuantumRange-SiPrefixToDouble(
8024                     argument_list[6].string_reference,QuantumRange));
8025                   if (composite_image->matte != MagickTrue)
8026                     (void) SetImageOpacity(composite_image,OpaqueOpacity);
8027                   composite_view=AcquireCacheView(composite_image);
8028                   for (y=0; y < (long) composite_image->rows ; y++)
8029                   {
8030                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(long)
8031                       composite_image->columns,1,exception);
8032                     for (x=0; x < (long) composite_image->columns; x++)
8033                     {
8034                       if (q->opacity == OpaqueOpacity)
8035                         q->opacity=ClampToQuantum(opacity);
8036                       q++;
8037                     }
8038                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8039                     if (sync == MagickFalse)
8040                       break;
8041                   }
8042                   composite_view=DestroyCacheView(composite_view);
8043                 }
8044             }
8045           if (attribute_flag[9] != 0)    /* "color=>" */
8046             QueryColorDatabase(argument_list[9].string_reference,
8047               &composite_image->background_color,exception);
8048           if (attribute_flag[12] != 0) /* "interpolate=>" */
8049             image->interpolate=(InterpolatePixelMethod)
8050               argument_list[12].long_reference;
8051           if (attribute_flag[13] != 0)   /* "args=>" */
8052             (void) SetImageArtifact(composite_image,"compose:args",
8053               argument_list[13].string_reference);
8054           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8055             (void) SetImageArtifact(composite_image,"compose:args",
8056               argument_list[14].string_reference);
8057           /*
8058             Tiling Composition (with orthogonal rotate).
8059           */
8060           rotate_image=(Image *) NULL;
8061           if (attribute_flag[8] != 0)   /* "rotate=>" */
8062             {
8063                /*
8064                  Rotate image.
8065                */
8066                rotate_image=RotateImage(composite_image,
8067                  argument_list[8].real_reference,exception);
8068                if (rotate_image == (Image *) NULL)
8069                  break;
8070             }
8071           if (attribute_flag[7] && argument_list[7].long_reference) /* tile */
8072             {
8073               long
8074                 x,
8075                 y;
8076
8077               /*
8078                 Tile the composite image.
8079               */
8080              if (attribute_flag[8] != 0)   /* "tile=>" */
8081                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8082                  "false");
8083              else
8084                (void) SetImageArtifact(composite_image,
8085                  "compose:outside-overlay","false");
8086              for (y=0; y < (long) image->rows; y+=composite_image->rows)
8087                 for (x=0; x < (long) image->columns; x+=composite_image->columns)
8088                 {
8089                   if (attribute_flag[8] != 0) /* rotate */
8090                     (void) CompositeImage(image,compose,rotate_image,x,y);
8091                   else
8092                     (void) CompositeImage(image,compose,composite_image,x,y);
8093                 }
8094               if (attribute_flag[8] != 0) /* rotate */
8095                 rotate_image=DestroyImage(rotate_image);
8096               break;
8097             }
8098           /*
8099             Parameter Handling used used ONLY for normal composition.
8100           */
8101           if (attribute_flag[5] != 0) /* gravity */
8102             image->gravity=(GravityType) argument_list[5].long_reference;
8103           if (attribute_flag[2] != 0) /* geometry offset */
8104             {
8105               SetGeometry(image,&geometry);
8106               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8107                 &geometry);
8108               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8109                 &geometry);
8110             }
8111           if (attribute_flag[3] != 0) /* x offset */
8112             geometry.x=argument_list[3].long_reference;
8113           if (attribute_flag[4] != 0) /* y offset */
8114             geometry.y=argument_list[4].long_reference;
8115           if (attribute_flag[10] != 0) /* mask */
8116             {
8117               if ((image->compose == DisplaceCompositeOp) ||
8118                   (image->compose == DistortCompositeOp))
8119                 {
8120                   /*
8121                     Merge Y displacement into X displacement image.
8122                   */
8123                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8124                     &image->exception);
8125                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8126                     argument_list[10].image_reference,0,0);
8127                 }
8128               else
8129                 {
8130                   /*
8131                     Set a blending mask for the composition.
8132                   */
8133                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8134                     MagickTrue,&image->exception);
8135                   (void) NegateImage(image->mask,MagickFalse);
8136                 }
8137             }
8138           if (attribute_flag[11] != 0) /* channel */
8139             channel=(ChannelType) argument_list[11].long_reference;
8140           /*
8141             Composite two images (normal composition).
8142           */
8143           (void) FormatMagickString(composite_geometry,MaxTextExtent,
8144             "%lux%lu%+ld%+ld",composite_image->columns,composite_image->rows,
8145             geometry.x,geometry.y);
8146           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8147             exception);
8148           if (attribute_flag[8] == 0) /* no rotate */
8149             CompositeImageChannel(image,channel,compose,composite_image,
8150               geometry.x,geometry.y);
8151           else
8152             {
8153               /*
8154                 Position adjust rotated image then composite.
8155               */
8156               geometry.x-=(long) (rotate_image->columns-
8157                 composite_image->columns)/2;
8158               geometry.y-=(long) (rotate_image->rows-composite_image->rows)/2;
8159               CompositeImageChannel(image,channel,compose,rotate_image,
8160                 geometry.x,geometry.y);
8161               rotate_image=DestroyImage(rotate_image);
8162             }
8163           if (attribute_flag[10] != 0) /* mask */
8164             {
8165               if ((image->compose == DisplaceCompositeOp) ||
8166                   (image->compose == DistortCompositeOp))
8167                 composite_image=DestroyImage(composite_image);
8168               else
8169                 image->mask=DestroyImage(image->mask);
8170             }
8171           break;
8172         }
8173         case 36:  /* Contrast */
8174         {
8175           if (attribute_flag[0] == 0)
8176             argument_list[0].long_reference=0;
8177           (void) ContrastImage(image,argument_list[0].long_reference != 0 ?
8178             MagickTrue : MagickFalse);
8179           break;
8180         }
8181         case 37:  /* CycleColormap */
8182         {
8183           if (attribute_flag[0] == 0)
8184             argument_list[0].long_reference=6;
8185           (void) CycleColormapImage(image,argument_list[0].long_reference);
8186           break;
8187         }
8188         case 38:  /* Draw */
8189         {
8190           DrawInfo
8191             *draw_info;
8192
8193           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8194             (DrawInfo *) NULL);
8195           (void) CloneString(&draw_info->primitive,"point");
8196           if (attribute_flag[0] != 0)
8197             {
8198               if (argument_list[0].long_reference < 0)
8199                 (void) CloneString(&draw_info->primitive,
8200                   argument_list[0].string_reference);
8201               else
8202                 (void) CloneString(&draw_info->primitive,MagickOptionToMnemonic(
8203                   MagickPrimitiveOptions,argument_list[0].long_reference));
8204             }
8205           if (attribute_flag[1] != 0)
8206             {
8207               if (LocaleCompare(draw_info->primitive,"path") == 0)
8208                 {
8209                   (void) ConcatenateString(&draw_info->primitive," '");
8210                   ConcatenateString(&draw_info->primitive,
8211                     argument_list[1].string_reference);
8212                   (void) ConcatenateString(&draw_info->primitive,"'");
8213                 }
8214               else
8215                 {
8216                   (void) ConcatenateString(&draw_info->primitive," ");
8217                   ConcatenateString(&draw_info->primitive,
8218                     argument_list[1].string_reference);
8219                 }
8220             }
8221           if (attribute_flag[2] != 0)
8222             {
8223               (void) ConcatenateString(&draw_info->primitive," ");
8224               (void) ConcatenateString(&draw_info->primitive,
8225                 MagickOptionToMnemonic(MagickMethodOptions,
8226                 argument_list[2].long_reference));
8227             }
8228           if (attribute_flag[3] != 0)
8229             {
8230               (void) QueryColorDatabase(argument_list[3].string_reference,
8231                 &draw_info->stroke,exception);
8232               if (argument_list[3].image_reference != (Image *) NULL)
8233                 draw_info->stroke_pattern=CloneImage(
8234                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8235             }
8236           if (attribute_flag[4] != 0)
8237             {
8238               (void) QueryColorDatabase(argument_list[4].string_reference,
8239                 &draw_info->fill,exception);
8240               if (argument_list[4].image_reference != (Image *) NULL)
8241                 draw_info->fill_pattern=CloneImage(
8242                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8243             }
8244           if (attribute_flag[5] != 0)
8245             draw_info->stroke_width=argument_list[5].real_reference;
8246           if (attribute_flag[6] != 0)
8247             (void) CloneString(&draw_info->font,
8248               argument_list[6].string_reference);
8249           if (attribute_flag[7] != 0)
8250             (void) QueryColorDatabase(argument_list[7].string_reference,
8251               &draw_info->border_color,exception);
8252           if (attribute_flag[8] != 0)
8253             draw_info->affine.tx=argument_list[8].real_reference;
8254           if (attribute_flag[9] != 0)
8255             draw_info->affine.ty=argument_list[9].real_reference;
8256           if (attribute_flag[20] != 0)
8257             {
8258               AV
8259                 *av;
8260
8261               av=(AV *) argument_list[20].array_reference;
8262               if ((av_len(av) != 3) && (av_len(av) != 5))
8263                 {
8264                   ThrowPerlException(exception,OptionError,
8265                     "affine matrix must have 4 or 6 elements",PackageName);
8266                   goto PerlException;
8267                 }
8268               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8269               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8270               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8271               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8272               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8273                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8274                 {
8275                   ThrowPerlException(exception,OptionError,
8276                     "affine matrix is singular",PackageName);
8277                    goto PerlException;
8278                 }
8279               if (av_len(av) == 5)
8280                 {
8281                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8282                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8283                 }
8284             }
8285           for (j=10; j < 15; j++)
8286           {
8287             if (attribute_flag[j] == 0)
8288               continue;
8289             value=argument_list[j].string_reference;
8290             angle=argument_list[j].real_reference;
8291             current=draw_info->affine;
8292             GetAffineMatrix(&affine);
8293             switch (j)
8294             {
8295               case 10:
8296               {
8297                 /*
8298                   Translate.
8299                 */
8300                 flags=ParseGeometry(value,&geometry_info);
8301                 affine.tx=geometry_info.xi;
8302                 affine.ty=geometry_info.psi;
8303                 if ((flags & PsiValue) == 0)
8304                   affine.ty=affine.tx;
8305                 break;
8306               }
8307               case 11:
8308               {
8309                 /*
8310                   Scale.
8311                 */
8312                 flags=ParseGeometry(value,&geometry_info);
8313                 affine.sx=geometry_info.rho;
8314                 affine.sy=geometry_info.sigma;
8315                 if ((flags & SigmaValue) == 0)
8316                   affine.sy=affine.sx;
8317                 break;
8318               }
8319               case 12:
8320               {
8321                 /*
8322                   Rotate.
8323                 */
8324                 if (angle == 0.0)
8325                   break;
8326                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8327                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8328                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8329                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8330                 break;
8331               }
8332               case 13:
8333               {
8334                 /*
8335                   SkewX.
8336                 */
8337                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8338                 break;
8339               }
8340               case 14:
8341               {
8342                 /*
8343                   SkewY.
8344                 */
8345                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8346                 break;
8347               }
8348             }
8349             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8350             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8351             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8352             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8353             draw_info->affine.tx=
8354               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8355             draw_info->affine.ty=
8356               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8357           }
8358           if (attribute_flag[15] != 0)
8359             draw_info->fill_pattern=CloneImage(
8360               argument_list[15].image_reference,0,0,MagickTrue,exception);
8361           if (attribute_flag[16] != 0)
8362             draw_info->pointsize=argument_list[16].real_reference;
8363           if (attribute_flag[17] != 0)
8364             {
8365               draw_info->stroke_antialias=argument_list[17].long_reference != 0
8366                 ? MagickTrue : MagickFalse;
8367               draw_info->text_antialias=draw_info->stroke_antialias;
8368             }
8369           if (attribute_flag[18] != 0)
8370             (void) CloneString(&draw_info->density,
8371               argument_list[18].string_reference);
8372           if (attribute_flag[19] != 0)
8373             draw_info->stroke_width=argument_list[19].real_reference;
8374           if (attribute_flag[21] != 0)
8375             draw_info->dash_offset=argument_list[21].real_reference;
8376           if (attribute_flag[22] != 0)
8377             {
8378               AV
8379                 *av;
8380
8381               av=(AV *) argument_list[22].array_reference;
8382               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8383                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8384               if (draw_info->dash_pattern != (double *) NULL)
8385                 {
8386                   for (i=0; i <= av_len(av); i++)
8387                     draw_info->dash_pattern[i]=(double)
8388                       SvNV(*(av_fetch(av,i,0)));
8389                   draw_info->dash_pattern[i]=0.0;
8390                 }
8391             }
8392           if (attribute_flag[23] != 0)
8393             image->interpolate=(InterpolatePixelMethod)
8394               argument_list[23].long_reference;
8395           if ((attribute_flag[24] != 0) &&
8396               (draw_info->fill_pattern != (Image *) NULL))
8397             flags=ParsePageGeometry(draw_info->fill_pattern,
8398               argument_list[24].string_reference,
8399               &draw_info->fill_pattern->tile_offset,exception);
8400           if (attribute_flag[25] != 0)
8401             {
8402               (void) ConcatenateString(&draw_info->primitive," '");
8403               (void) ConcatenateString(&draw_info->primitive,
8404                 argument_list[25].string_reference);
8405               (void) ConcatenateString(&draw_info->primitive,"'");
8406             }
8407           if (attribute_flag[26] != 0)
8408             draw_info->fill_pattern=CloneImage(
8409               argument_list[26].image_reference,0,0,MagickTrue,exception);
8410           if (attribute_flag[27] != 0)
8411             draw_info->stroke_pattern=CloneImage(
8412               argument_list[27].image_reference,0,0,MagickTrue,exception);
8413           if (attribute_flag[28] != 0)
8414             (void) CloneString(&draw_info->primitive,
8415               argument_list[28].string_reference);
8416           if (attribute_flag[29] != 0)
8417             draw_info->kerning=argument_list[29].real_reference;
8418           if (attribute_flag[30] != 0)
8419             draw_info->interline_spacing=argument_list[30].real_reference;
8420           if (attribute_flag[31] != 0)
8421             draw_info->interword_spacing=argument_list[31].real_reference;
8422           DrawImage(image,draw_info);
8423           draw_info=DestroyDrawInfo(draw_info);
8424           break;
8425         }
8426         case 39:  /* Equalize */
8427         {
8428           if (attribute_flag[0] != 0)
8429             channel=(ChannelType) argument_list[0].long_reference;
8430           EqualizeImageChannel(image,channel);
8431           break;
8432         }
8433         case 40:  /* Gamma */
8434         {
8435           if (attribute_flag[1] != 0)
8436             channel=(ChannelType) argument_list[1].long_reference;
8437           if (attribute_flag[2] == 0)
8438             argument_list[2].real_reference=1.0;
8439           if (attribute_flag[3] == 0)
8440             argument_list[3].real_reference=1.0;
8441           if (attribute_flag[4] == 0)
8442             argument_list[4].real_reference=1.0;
8443           if (attribute_flag[0] == 0)
8444             {
8445               (void) FormatMagickString(message,MaxTextExtent,
8446                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8447                 (double) argument_list[3].real_reference,
8448                 (double) argument_list[4].real_reference);
8449               argument_list[0].string_reference=message;
8450             }
8451           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8452             (void) GammaImage(image,argument_list[0].string_reference);
8453           else
8454             (void) GammaImageChannel(image,channel,
8455               StringToDouble(argument_list[0].string_reference));
8456           break;
8457         }
8458         case 41:  /* Map */
8459         {
8460           QuantizeInfo
8461             *quantize_info;
8462
8463           if (attribute_flag[0] == 0)
8464             {
8465               ThrowPerlException(exception,OptionError,"MapImageRequired",
8466                 PackageName);
8467               goto PerlException;
8468             }
8469           quantize_info=AcquireQuantizeInfo(info->image_info);
8470           if (attribute_flag[1] != 0)
8471             quantize_info->dither=(MagickBooleanType)
8472               argument_list[1].long_reference;
8473           if (attribute_flag[2] != 0)
8474             quantize_info->dither_method=(DitherMethod)
8475               argument_list[2].long_reference;
8476           (void) RemapImages(quantize_info,image,
8477             argument_list[0].image_reference);
8478           quantize_info=DestroyQuantizeInfo(quantize_info);
8479           break;
8480         }
8481         case 42:  /* MatteFloodfill */
8482         {
8483           DrawInfo
8484             *draw_info;
8485
8486           MagickBooleanType
8487             invert;
8488
8489           MagickPixelPacket
8490             target;
8491
8492           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8493             (DrawInfo *) NULL);
8494           if (attribute_flag[0] != 0)
8495           if (attribute_flag[0] != 0)
8496             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8497               &geometry,exception);
8498           if (attribute_flag[1] != 0)
8499             geometry.x=argument_list[1].long_reference;
8500           if (attribute_flag[2] != 0)
8501             geometry.y=argument_list[2].long_reference;
8502           if (image->matte == MagickFalse)
8503             (void) SetImageOpacity(image,OpaqueOpacity);
8504           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8505             exception);
8506           if (attribute_flag[4] != 0)
8507             QueryMagickColor(argument_list[4].string_reference,&target,
8508               exception);
8509           if (attribute_flag[3] != 0)
8510             target.opacity=SiPrefixToDouble(argument_list[3].string_reference,
8511               QuantumRange);
8512           if (attribute_flag[5] != 0)
8513             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8514               QuantumRange);
8515           invert=MagickFalse;
8516           if (attribute_flag[6] != 0)
8517             invert=(MagickBooleanType) argument_list[6].long_reference;
8518           (void) FloodfillPaintImage(image,OpacityChannel,draw_info,&target,
8519             geometry.x,geometry.y,invert);
8520           draw_info=DestroyDrawInfo(draw_info);
8521           break;
8522         }
8523         case 43:  /* Modulate */
8524         {
8525           char
8526             modulate[MaxTextExtent];
8527
8528           ColorspaceType
8529             colorspace;
8530
8531           colorspace=image->colorspace;
8532           geometry_info.rho=100.0;
8533           geometry_info.sigma=100.0;
8534           geometry_info.xi=100.0;
8535           if (attribute_flag[0] != 0)
8536             (void)ParseGeometry(argument_list[0].string_reference,
8537               &geometry_info);
8538           if (attribute_flag[1] != 0)
8539             geometry_info.xi=argument_list[1].real_reference;
8540           if (attribute_flag[2] != 0)
8541             geometry_info.sigma=argument_list[2].real_reference;
8542           if (attribute_flag[3] != 0)
8543             {
8544               (void) SetImageColorspace(image,HWBColorspace);
8545               geometry_info.sigma=argument_list[3].real_reference;
8546             }
8547           if (attribute_flag[4] != 0)
8548             geometry_info.rho=argument_list[4].real_reference;
8549           if (attribute_flag[5] != 0)
8550             {
8551               (void) SetImageColorspace(image,HSLColorspace);
8552               geometry_info.sigma=argument_list[5].real_reference;
8553             }
8554           if (attribute_flag[6] != 0)
8555             {
8556               (void) SetImageColorspace(image,HWBColorspace);
8557               geometry_info.rho=argument_list[6].real_reference;
8558             }
8559           (void) FormatMagickString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8560             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8561           (void) ModulateImage(image,modulate);
8562           (void) SetImageColorspace(image,colorspace);
8563           break;
8564         }
8565         case 44:  /* Negate */
8566         {
8567           if (attribute_flag[0] == 0)
8568             argument_list[0].long_reference=0;
8569           if (attribute_flag[1] != 0)
8570             channel=(ChannelType) argument_list[1].long_reference;
8571           (void) NegateImageChannel(image,channel,
8572             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse);
8573           break;
8574         }
8575         case 45:  /* Normalize */
8576         {
8577           if (attribute_flag[0] != 0)
8578             channel=(ChannelType) argument_list[0].long_reference;
8579           NormalizeImageChannel(image,channel);
8580           break;
8581         }
8582         case 46:  /* NumberColors */
8583           break;
8584         case 47:  /* Opaque */
8585         {
8586           MagickBooleanType
8587             invert;
8588
8589           MagickPixelPacket
8590             fill_color,
8591             target;
8592
8593           (void) QueryMagickColor("none",&target,exception);
8594           (void) QueryMagickColor("none",&fill_color,exception);
8595           if (attribute_flag[0] != 0)
8596             (void) QueryMagickColor(argument_list[0].string_reference,
8597               &target,exception);
8598           if (attribute_flag[1] != 0)
8599             (void) QueryMagickColor(argument_list[1].string_reference,
8600               &fill_color,exception);
8601           if (attribute_flag[2] != 0)
8602             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8603               QuantumRange);
8604           if (attribute_flag[3] != 0)
8605             channel=(ChannelType) argument_list[3].long_reference;
8606           invert=MagickFalse;
8607           if (attribute_flag[4] != 0)
8608             invert=(MagickBooleanType) argument_list[4].long_reference;
8609           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8610             invert);
8611           break;
8612         }
8613         case 48:  /* Quantize */
8614         {
8615           QuantizeInfo
8616             *quantize_info;
8617
8618           quantize_info=AcquireQuantizeInfo(info->image_info);
8619           if (attribute_flag[0] != 0)
8620             quantize_info->number_colors=(unsigned long)
8621               argument_list[0].long_reference;
8622           if (attribute_flag[1] != 0)
8623             quantize_info->tree_depth=(unsigned long)
8624               argument_list[1].long_reference;
8625           if (attribute_flag[2] != 0)
8626             quantize_info->colorspace=(ColorspaceType)
8627               argument_list[2].long_reference;
8628           if (attribute_flag[3] != 0)
8629             quantize_info->dither=argument_list[3].long_reference != 0 ?
8630               MagickTrue : MagickFalse;
8631           if (attribute_flag[4] != 0)
8632             quantize_info->measure_error=
8633               argument_list[4].long_reference != 0 ? MagickTrue : MagickFalse;
8634           if (attribute_flag[5] != 0)
8635             (void) QueryColorDatabase(argument_list[5].string_reference,
8636               &image->transparent_color,exception);
8637           if (attribute_flag[5] && argument_list[5].long_reference)
8638             {
8639               (void) QuantizeImages(quantize_info,image);
8640               goto PerlException;
8641             }
8642           if (attribute_flag[6] != 0)
8643             quantize_info->dither_method=(DitherMethod)
8644               argument_list[6].long_reference;
8645           if ((image->storage_class == DirectClass) ||
8646               (image->colors > quantize_info->number_colors) ||
8647               (quantize_info->colorspace == GRAYColorspace))
8648             (void) QuantizeImage(quantize_info,image);
8649           else
8650             CompressImageColormap(image);
8651           quantize_info=DestroyQuantizeInfo(quantize_info);
8652           break;
8653         }
8654         case 49:  /* Raise */
8655         {
8656           if (attribute_flag[0] != 0)
8657             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8658               &geometry,exception);
8659           if (attribute_flag[1] != 0)
8660             geometry.width=argument_list[1].long_reference;
8661           if (attribute_flag[2] != 0)
8662             geometry.height=argument_list[2].long_reference;
8663           if (attribute_flag[3] == 0)
8664             argument_list[3].long_reference=1;
8665           (void) RaiseImage(image,&geometry,argument_list[3].long_reference !=
8666             0 ? MagickTrue : MagickFalse);
8667           break;
8668         }
8669         case 50:  /* Segment */
8670         {
8671           ColorspaceType
8672             colorspace;
8673
8674           double
8675             cluster_threshold,
8676             smoothing_threshold;
8677
8678           MagickBooleanType
8679             verbose;
8680
8681           cluster_threshold=1.0;
8682           smoothing_threshold=1.5;
8683           colorspace=RGBColorspace;
8684           verbose=MagickFalse;
8685           if (attribute_flag[0] != 0)
8686             {
8687               flags=ParseGeometry(argument_list[0].string_reference,
8688                 &geometry_info);
8689               cluster_threshold=geometry_info.rho;
8690               if (flags & SigmaValue)
8691                 smoothing_threshold=geometry_info.sigma;
8692             }
8693           if (attribute_flag[1] != 0)
8694             cluster_threshold=argument_list[1].real_reference;
8695           if (attribute_flag[2] != 0)
8696             smoothing_threshold=argument_list[2].real_reference;
8697           if (attribute_flag[3] != 0)
8698             colorspace=(ColorspaceType) argument_list[3].long_reference;
8699           if (attribute_flag[4] != 0)
8700             verbose=argument_list[4].long_reference != 0 ?
8701               MagickTrue : MagickFalse;
8702           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8703             smoothing_threshold);
8704           break;
8705         }
8706         case 51:  /* Signature */
8707         {
8708           (void) SignatureImage(image);
8709           break;
8710         }
8711         case 52:  /* Solarize */
8712         {
8713           geometry_info.rho=QuantumRange/2.0;
8714           if (attribute_flag[0] != 0)
8715             flags=ParseGeometry(argument_list[0].string_reference,
8716               &geometry_info);
8717           if (attribute_flag[1] != 0)
8718             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8719              QuantumRange);
8720           (void) SolarizeImage(image,geometry_info.rho);
8721           break;
8722         }
8723         case 53:  /* Sync */
8724         {
8725           (void) SyncImage(image);
8726           break;
8727         }
8728         case 54:  /* Texture */
8729         {
8730           if (attribute_flag[0] == 0)
8731             break;
8732           TextureImage(image,argument_list[0].image_reference);
8733           break;
8734         }
8735         case 55:  /* Evalute */
8736         {
8737           MagickEvaluateOperator
8738             op;
8739
8740           op=SetEvaluateOperator;
8741           if (attribute_flag[0] == MagickFalse)
8742             argument_list[0].real_reference=0.0;
8743           if (attribute_flag[1] != MagickFalse)
8744             op=(MagickEvaluateOperator) argument_list[1].long_reference;
8745           if (attribute_flag[2] != MagickFalse)
8746             channel=(ChannelType) argument_list[2].long_reference;
8747           (void) EvaluateImageChannel(image,channel,op,
8748             argument_list[0].real_reference,exception);
8749           break;
8750         }
8751         case 56:  /* Transparent */
8752         {
8753           double
8754             opacity;
8755
8756           MagickBooleanType
8757             invert;
8758
8759           MagickPixelPacket
8760             target;
8761
8762           (void) QueryMagickColor("none",&target,exception);
8763           if (attribute_flag[0] != 0)
8764             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8765               exception);
8766           opacity=TransparentOpacity;
8767           if (attribute_flag[1] != 0)
8768             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8769               QuantumRange);
8770           if (attribute_flag[2] != 0)
8771             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8772               QuantumRange);
8773           if (attribute_flag[3] == 0)
8774             argument_list[3].long_reference=0;
8775           invert=MagickFalse;
8776           if (attribute_flag[3] != 0)
8777             invert=(MagickBooleanType) argument_list[3].long_reference;
8778           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8779             invert);
8780           break;
8781         }
8782         case 57:  /* Threshold */
8783         {
8784           double
8785             threshold;
8786
8787           if (attribute_flag[0] == 0)
8788             argument_list[0].string_reference="50%";
8789           if (attribute_flag[1] != 0)
8790             channel=(ChannelType) argument_list[1].long_reference;
8791           threshold=SiPrefixToDouble(argument_list[0].string_reference,
8792             QuantumRange);
8793           (void) BilevelImageChannel(image,channel,threshold);
8794           break;
8795         }
8796         case 58:  /* Charcoal */
8797         {
8798           if (attribute_flag[0] != 0)
8799             {
8800               flags=ParseGeometry(argument_list[0].string_reference,
8801                 &geometry_info);
8802               if ((flags & SigmaValue) == 0)
8803                 geometry_info.sigma=1.0;
8804             }
8805           if (attribute_flag[1] != 0)
8806             geometry_info.rho=argument_list[1].real_reference;
8807           if (attribute_flag[2] != 0)
8808             geometry_info.sigma=argument_list[2].real_reference;
8809           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
8810             exception);
8811           break;
8812         }
8813         case 59:  /* Trim */
8814         {
8815           if (attribute_flag[0] != 0)
8816             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
8817               QuantumRange);
8818           image=TrimImage(image,exception);
8819           break;
8820         }
8821         case 60:  /* Wave */
8822         {
8823           if (attribute_flag[0] != 0)
8824             {
8825               flags=ParseGeometry(argument_list[0].string_reference,
8826                 &geometry_info);
8827               if ((flags & SigmaValue) == 0)
8828                 geometry_info.sigma=1.0;
8829             }
8830           if (attribute_flag[1] != 0)
8831             geometry_info.rho=argument_list[1].real_reference;
8832           if (attribute_flag[2] != 0)
8833             geometry_info.sigma=argument_list[2].real_reference;
8834           if (attribute_flag[3] != 0)
8835             image->interpolate=(InterpolatePixelMethod)
8836               argument_list[3].long_reference;
8837           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
8838             exception);
8839           break;
8840         }
8841         case 61:  /* Separate */
8842         {
8843           if (attribute_flag[0] != 0)
8844             channel=(ChannelType) argument_list[0].long_reference;
8845           (void) SeparateImageChannel(image,channel);
8846           break;
8847         }
8848         case 63:  /* Stereo */
8849         {
8850           if (attribute_flag[0] == 0)
8851             {
8852               ThrowPerlException(exception,OptionError,"StereoImageRequired",
8853                 PackageName);
8854               goto PerlException;
8855             }
8856           if (attribute_flag[1] != 0)
8857             geometry.x=argument_list[1].long_reference;
8858           if (attribute_flag[2] != 0)
8859             geometry.y=argument_list[2].long_reference;
8860           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
8861             geometry.x,geometry.y,exception);
8862           break;
8863         }
8864         case 64:  /* Stegano */
8865         {
8866           if (attribute_flag[0] == 0)
8867             {
8868               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
8869                 PackageName);
8870               goto PerlException;
8871             }
8872           if (attribute_flag[1] == 0)
8873             argument_list[1].long_reference=0;
8874           image->offset=argument_list[1].long_reference;
8875           image=SteganoImage(image,argument_list[0].image_reference,exception);
8876           break;
8877         }
8878         case 65:  /* Deconstruct */
8879         {
8880           image=DeconstructImages(image,exception);
8881           break;
8882         }
8883         case 66:  /* GaussianBlur */
8884         {
8885           if (attribute_flag[0] != 0)
8886             {
8887               flags=ParseGeometry(argument_list[0].string_reference,
8888                 &geometry_info);
8889               if ((flags & SigmaValue) == 0)
8890                 geometry_info.sigma=1.0;
8891             }
8892           if (attribute_flag[1] != 0)
8893             geometry_info.rho=argument_list[1].real_reference;
8894           if (attribute_flag[2] != 0)
8895             geometry_info.sigma=argument_list[2].real_reference;
8896           if (attribute_flag[3] != 0)
8897             channel=(ChannelType) argument_list[3].long_reference;
8898           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
8899             geometry_info.sigma,exception);
8900           break;
8901         }
8902         case 67:  /* Convolve */
8903         {
8904           AV
8905             *av;
8906
8907           double
8908             *kernel;
8909
8910           unsigned long
8911             order;
8912
8913           if (attribute_flag[0] == 0)
8914             break;
8915           if (attribute_flag[1] != 0)
8916             channel=(ChannelType) argument_list[1].long_reference;
8917           if (attribute_flag[2] != 0)
8918             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
8919               QuantumRange);
8920           av=(AV *) argument_list[0].array_reference;
8921           order=(unsigned long) sqrt(av_len(av)+1);
8922           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
8923           if (kernel == (double *) NULL)
8924             {
8925               ThrowPerlException(exception,ResourceLimitFatalError,
8926                 "MemoryAllocationFailed",PackageName);
8927               goto PerlException;
8928             }
8929           for (j=0; (j < (long) (order*order)) && (j < (av_len(av)+1)); j++)
8930             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
8931           for ( ; j < (long) (order*order); j++)
8932             kernel[j]=0.0;
8933           image=ConvolveImageChannel(image,channel,order,kernel,exception);
8934           kernel=(double *) RelinquishMagickMemory(kernel);
8935           break;
8936         }
8937         case 68:  /* Profile */
8938         {
8939           const char
8940             *name;
8941
8942           Image
8943             *profile_image;
8944
8945           ImageInfo
8946             *profile_info;
8947
8948           StringInfo
8949             *profile;
8950
8951           name="*";
8952           if (attribute_flag[0] != 0)
8953             name=argument_list[0].string_reference;
8954           if (attribute_flag[2] != 0)
8955             image->rendering_intent=(RenderingIntent)
8956               argument_list[2].long_reference;
8957           if (attribute_flag[3] != 0)
8958             image->black_point_compensation=
8959               argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse;
8960           if (attribute_flag[1] != 0)
8961             {
8962               if (argument_list[1].length == 0)
8963                 {
8964                   /*
8965                     Remove a profile from the image.
8966                   */
8967                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
8968                     MagickTrue);
8969                   break;
8970                 }
8971               /*
8972                 Associate user supplied profile with the image.
8973               */
8974               profile=AcquireStringInfo(argument_list[1].length);
8975               SetStringInfoDatum(profile,(const unsigned char *)
8976                 argument_list[1].string_reference);
8977               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
8978                 (unsigned long) GetStringInfoLength(profile),MagickFalse);
8979               profile=DestroyStringInfo(profile);
8980               break;
8981             }
8982           /*
8983             Associate a profile with the image.
8984           */
8985           profile_info=
8986             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
8987           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
8988           profile_image=ReadImages(profile_info,&image->exception);
8989           if (profile_image == (Image *) NULL)
8990             break;
8991           ResetImageProfileIterator(profile_image);
8992           name=GetNextImageProfile(profile_image);
8993           while (name != (const char *) NULL)
8994           {
8995             const StringInfo
8996               *profile;
8997
8998             profile=GetImageProfile(profile_image,name);
8999             if (profile != (const StringInfo *) NULL)
9000               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9001                 (unsigned long) GetStringInfoLength(profile),MagickFalse);
9002             name=GetNextImageProfile(profile_image);
9003           }
9004           profile_image=DestroyImage(profile_image);
9005           profile_info=DestroyImageInfo(profile_info);
9006           break;
9007         }
9008         case 69:  /* UnsharpMask */
9009         {
9010           if (attribute_flag[0] != 0)
9011             {
9012               flags=ParseGeometry(argument_list[0].string_reference,
9013                 &geometry_info);
9014               if ((flags & SigmaValue) == 0)
9015                 geometry_info.sigma=1.0;
9016               if ((flags & XiValue) == 0)
9017                 geometry_info.xi=1.0;
9018               if ((flags & PsiValue) == 0)
9019                 geometry_info.psi=0.5;
9020             }
9021           if (attribute_flag[1] != 0)
9022             geometry_info.rho=argument_list[1].real_reference;
9023           if (attribute_flag[2] != 0)
9024             geometry_info.sigma=argument_list[2].real_reference;
9025           if (attribute_flag[3] != 0)
9026             geometry_info.xi=argument_list[3].real_reference;
9027           if (attribute_flag[4] != 0)
9028             geometry_info.psi=argument_list[4].real_reference;
9029           if (attribute_flag[5] != 0)
9030             channel=(ChannelType) argument_list[5].long_reference;
9031           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9032             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9033           break;
9034         }
9035         case 70:  /* MotionBlur */
9036         {
9037           if (attribute_flag[0] != 0)
9038             {
9039               flags=ParseGeometry(argument_list[0].string_reference,
9040                 &geometry_info);
9041               if ((flags & SigmaValue) == 0)
9042                 geometry_info.sigma=1.0;
9043               if ((flags & XiValue) == 0)
9044                 geometry_info.xi=1.0;
9045             }
9046           if (attribute_flag[1] != 0)
9047             geometry_info.rho=argument_list[1].real_reference;
9048           if (attribute_flag[2] != 0)
9049             geometry_info.sigma=argument_list[2].real_reference;
9050           if (attribute_flag[3] != 0)
9051             geometry_info.xi=argument_list[3].real_reference;
9052           if (attribute_flag[4] != 0)
9053             channel=(ChannelType) argument_list[4].long_reference;
9054           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9055             geometry_info.sigma,geometry_info.xi,exception);
9056           break;
9057         }
9058         case 71:  /* OrderedDither */
9059         {
9060           if (attribute_flag[0] == 0)
9061             argument_list[0].string_reference="o8x8";
9062           if (attribute_flag[1] != 0)
9063             channel=(ChannelType) argument_list[1].long_reference;
9064           (void) OrderedPosterizeImageChannel(image,channel,
9065             argument_list[0].string_reference,exception);
9066           break;
9067         }
9068         case 72:  /* Shave */
9069         {
9070           if (attribute_flag[0] != 0)
9071             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9072               &geometry,exception);
9073           if (attribute_flag[1] != 0)
9074             geometry.width=argument_list[1].long_reference;
9075           if (attribute_flag[2] != 0)
9076             geometry.height=argument_list[2].long_reference;
9077           image=ShaveImage(image,&geometry,exception);
9078           break;
9079         }
9080         case 73:  /* Level */
9081         {
9082           double
9083             black_point,
9084             gamma,
9085             white_point;
9086
9087           black_point=0.0;
9088           white_point=(MagickRealType) image->columns*image->rows;
9089           gamma=1.0;
9090           if (attribute_flag[0] != 0)
9091             {
9092               flags=ParseGeometry(argument_list[0].string_reference,
9093                 &geometry_info);
9094               black_point=geometry_info.rho;
9095               if ((flags & SigmaValue) != 0)
9096                 white_point=geometry_info.sigma;
9097               if ((flags & XiValue) != 0)
9098                 gamma=geometry_info.xi;
9099               if ((flags & PercentValue) != 0)
9100                 {
9101                   black_point*=(double) (QuantumRange/100.0);
9102                   white_point*=(double) (QuantumRange/100.0);
9103                 }
9104               if ((flags & SigmaValue) == 0)
9105                 white_point=(double) QuantumRange-black_point;
9106             }
9107           if (attribute_flag[1] != 0)
9108             black_point=argument_list[1].real_reference;
9109           if (attribute_flag[2] != 0)
9110             white_point=argument_list[2].real_reference;
9111           if (attribute_flag[3] != 0)
9112             gamma=argument_list[3].real_reference;
9113           if (attribute_flag[4] != 0)
9114             channel=(ChannelType) argument_list[4].long_reference;
9115           if (attribute_flag[5] != 0)
9116             {
9117               argument_list[0].real_reference=argument_list[5].real_reference;
9118               attribute_flag[0]=attribute_flag[5];
9119             }
9120           (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9121           break;
9122         }
9123         case 74:  /* Clip */
9124         {
9125           if (attribute_flag[0] == 0)
9126             argument_list[0].string_reference="#1";
9127           if (attribute_flag[1] == 0)
9128             argument_list[1].long_reference=MagickTrue;
9129           (void) ClipImagePath(image,argument_list[0].string_reference,
9130             argument_list[1].long_reference != 0 ? MagickTrue : MagickFalse);
9131           break;
9132         }
9133         case 75:  /* AffineTransform */
9134         {
9135           DrawInfo
9136             *draw_info;
9137
9138           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9139             (DrawInfo *) NULL);
9140           if (attribute_flag[0] != 0)
9141             {
9142               AV
9143                 *av;
9144
9145               av=(AV *) argument_list[0].array_reference;
9146               if ((av_len(av) != 3) && (av_len(av) != 5))
9147                 {
9148                   ThrowPerlException(exception,OptionError,
9149                     "affine matrix must have 4 or 6 elements",PackageName);
9150                   goto PerlException;
9151                 }
9152               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9153               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9154               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9155               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9156               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9157                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9158                 {
9159                   ThrowPerlException(exception,OptionError,
9160                     "affine matrix is singular",PackageName);
9161                    goto PerlException;
9162                 }
9163               if (av_len(av) == 5)
9164                 {
9165                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9166                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9167                 }
9168             }
9169           for (j=1; j < 6; j++)
9170           {
9171             if (attribute_flag[j] == 0)
9172               continue;
9173             value=argument_list[j].string_reference;
9174             angle=argument_list[j].real_reference;
9175             current=draw_info->affine;
9176             GetAffineMatrix(&affine);
9177             switch (j)
9178             {
9179               case 1:
9180               {
9181                 /*
9182                   Translate.
9183                 */
9184                 flags=ParseGeometry(value,&geometry_info);
9185                 affine.tx=geometry_info.xi;
9186                 affine.ty=geometry_info.psi;
9187                 if ((flags & PsiValue) == 0)
9188                   affine.ty=affine.tx;
9189                 break;
9190               }
9191               case 2:
9192               {
9193                 /*
9194                   Scale.
9195                 */
9196                 flags=ParseGeometry(value,&geometry_info);
9197                 affine.sx=geometry_info.rho;
9198                 affine.sy=geometry_info.sigma;
9199                 if ((flags & SigmaValue) == 0)
9200                   affine.sy=affine.sx;
9201                 break;
9202               }
9203               case 3:
9204               {
9205                 /*
9206                   Rotate.
9207                 */
9208                 if (angle == 0.0)
9209                   break;
9210                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9211                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9212                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9213                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9214                 break;
9215               }
9216               case 4:
9217               {
9218                 /*
9219                   SkewX.
9220                 */
9221                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9222                 break;
9223               }
9224               case 5:
9225               {
9226                 /*
9227                   SkewY.
9228                 */
9229                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9230                 break;
9231               }
9232             }
9233             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9234             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9235             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9236             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9237             draw_info->affine.tx=
9238               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9239             draw_info->affine.ty=
9240               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9241           }
9242           if (attribute_flag[6] != 0)
9243             image->interpolate=(InterpolatePixelMethod)
9244               argument_list[6].long_reference;
9245           if (attribute_flag[7] != 0)
9246             QueryColorDatabase(argument_list[7].string_reference,
9247               &image->background_color,exception);
9248           image=AffineTransformImage(image,&draw_info->affine,exception);
9249           draw_info=DestroyDrawInfo(draw_info);
9250           break;
9251         }
9252         case 76:  /* Difference */
9253         {
9254           if (attribute_flag[0] == 0)
9255             {
9256               ThrowPerlException(exception,OptionError,
9257                 "ReferenceImageRequired",PackageName);
9258               goto PerlException;
9259             }
9260           if (attribute_flag[1] != 0)
9261             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9262               QuantumRange);
9263           (void) IsImagesEqual(image,argument_list[0].image_reference);
9264           break;
9265         }
9266         case 77:  /* AdaptiveThreshold */
9267         {
9268           if (attribute_flag[0] != 0)
9269             {
9270               flags=ParseGeometry(argument_list[0].string_reference,
9271                 &geometry_info);
9272               if ((flags & PercentValue) != 0)
9273                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9274             }
9275           if (attribute_flag[1] != 0)
9276             geometry_info.rho=argument_list[1].long_reference;
9277           if (attribute_flag[2] != 0)
9278             geometry_info.sigma=argument_list[2].long_reference;
9279           if (attribute_flag[3] != 0)
9280             geometry_info.xi=argument_list[3].long_reference;;
9281           image=AdaptiveThresholdImage(image,(unsigned long) geometry_info.rho,
9282             (unsigned long) geometry_info.sigma,(long) geometry_info.xi,
9283             exception);
9284           break;
9285         }
9286         case 78:  /* Resample */
9287         {
9288           unsigned long
9289             height,
9290             width;
9291
9292           if (attribute_flag[0] != 0)
9293             {
9294               flags=ParseGeometry(argument_list[0].string_reference,
9295                 &geometry_info);
9296               if ((flags & SigmaValue) == 0)
9297                 geometry_info.sigma=geometry_info.rho;
9298             }
9299           if (attribute_flag[1] != 0)
9300             geometry_info.rho=argument_list[1].real_reference;
9301           if (attribute_flag[2] != 0)
9302             geometry_info.sigma=argument_list[2].real_reference;
9303           if (attribute_flag[3] == 0)
9304             argument_list[3].long_reference=(long) UndefinedFilter;
9305           if (attribute_flag[4] == 0)
9306             SetImageArtifact(image,"filter:support",
9307               argument_list[4].string_reference);
9308           if (attribute_flag[5] != 0)
9309             argument_list[5].real_reference=1.0;
9310           width=(unsigned long) (geometry_info.rho*image->columns/
9311             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9312           height=(unsigned long) (geometry_info.sigma*image->rows/
9313             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9314           image=ResizeImage(image,width,height,(FilterTypes)
9315             argument_list[3].long_reference,argument_list[5].real_reference,
9316             exception);
9317           if (image != (Image *) NULL)
9318             {
9319               image->x_resolution=geometry_info.rho;
9320               image->y_resolution=geometry_info.sigma;
9321             }
9322           break;
9323         }
9324         case 79:  /* Describe */
9325         {
9326           if (attribute_flag[0] == 0)
9327             argument_list[0].file_reference=(FILE *) NULL;
9328           if (attribute_flag[1] != 0)
9329             (void) SetImageArtifact(image,"identify:features",
9330               argument_list[1].string_reference);
9331           (void) IdentifyImage(image,argument_list[0].file_reference,
9332             MagickTrue);
9333           break;
9334         }
9335         case 80:  /* BlackThreshold */
9336         {
9337           if (attribute_flag[0] == 0)
9338             argument_list[0].string_reference="50%";
9339           if (attribute_flag[2] != 0)
9340             channel=(ChannelType) argument_list[2].long_reference;
9341           BlackThresholdImageChannel(image,channel,
9342             argument_list[0].string_reference,exception);
9343           break;
9344         }
9345         case 81:  /* WhiteThreshold */
9346         {
9347           if (attribute_flag[0] == 0)
9348             argument_list[0].string_reference="50%";
9349           if (attribute_flag[2] != 0)
9350             channel=(ChannelType) argument_list[2].long_reference;
9351           WhiteThresholdImageChannel(image,channel,
9352             argument_list[0].string_reference,exception);
9353           break;
9354         }
9355         case 82:  /* RadialBlur */
9356         {
9357           if (attribute_flag[0] != 0)
9358             {
9359               flags=ParseGeometry(argument_list[0].string_reference,
9360                 &geometry_info);
9361               if ((flags & SigmaValue) == 0)
9362                 geometry_info.sigma=1.0;
9363             }
9364           if (attribute_flag[1] != 0)
9365             geometry_info.rho=argument_list[1].real_reference;
9366           if (attribute_flag[2] != 0)
9367             channel=(ChannelType) argument_list[2].long_reference;
9368           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9369             exception);
9370           break;
9371         }
9372         case 83:  /* Thumbnail */
9373         {
9374           if (attribute_flag[0] != 0)
9375             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9376               &geometry,exception);
9377           if (attribute_flag[1] != 0)
9378             geometry.width=argument_list[1].long_reference;
9379           if (attribute_flag[2] != 0)
9380             geometry.height=argument_list[2].long_reference;
9381           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9382           break;
9383         }
9384         case 84:  /* Strip */
9385         {
9386           (void) StripImage(image);
9387           break;
9388         }
9389         case 85:  /* Tint */
9390         {
9391           PixelPacket
9392             target;
9393
9394           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9395           if (attribute_flag[0] != 0)
9396             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9397               exception);
9398           if (attribute_flag[1] == 0)
9399             argument_list[1].string_reference="100";
9400           image=TintImage(image,argument_list[1].string_reference,target,
9401             exception);
9402           break;
9403         }
9404         case 86:  /* Channel */
9405         {
9406           if (attribute_flag[0] != 0)
9407             channel=(ChannelType) argument_list[0].long_reference;
9408           (void) SeparateImageChannel(image,channel);
9409           break;
9410         }
9411         case 87:  /* Splice */
9412         {
9413           if (attribute_flag[0] != 0)
9414             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9415               &geometry,exception);
9416           if (attribute_flag[1] != 0)
9417             geometry.width=argument_list[1].long_reference;
9418           if (attribute_flag[2] != 0)
9419             geometry.height=argument_list[2].long_reference;
9420           if (attribute_flag[3] != 0)
9421             geometry.x=argument_list[3].long_reference;
9422           if (attribute_flag[4] != 0)
9423             geometry.y=argument_list[4].long_reference;
9424           if (attribute_flag[5] != 0)
9425             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9426               QuantumRange);
9427           if (attribute_flag[6] != 0)
9428             (void) QueryColorDatabase(argument_list[6].string_reference,
9429               &image->background_color,exception);
9430           if (attribute_flag[7] != 0)
9431             image->gravity=(GravityType) argument_list[7].long_reference;
9432           image=SpliceImage(image,&geometry,exception);
9433           break;
9434         }
9435         case 88:  /* Posterize */
9436         {
9437           if (attribute_flag[0] == 0)
9438             argument_list[0].long_reference=3;
9439           if (attribute_flag[1] == 0)
9440             argument_list[1].long_reference=0;
9441           (void) PosterizeImage(image,argument_list[0].long_reference,
9442             argument_list[1].long_reference ? MagickTrue : MagickFalse);
9443           break;
9444         }
9445         case 89:  /* Shadow */
9446         {
9447           if (attribute_flag[0] != 0)
9448             {
9449               flags=ParseGeometry(argument_list[0].string_reference,
9450                 &geometry_info);
9451               if ((flags & SigmaValue) == 0)
9452                 geometry_info.sigma=1.0;
9453               if ((flags & XiValue) == 0)
9454                 geometry_info.xi=4.0;
9455               if ((flags & PsiValue) == 0)
9456                 geometry_info.psi=4.0;
9457             }
9458           if (attribute_flag[1] != 0)
9459             geometry_info.rho=argument_list[1].real_reference;
9460           if (attribute_flag[2] != 0)
9461             geometry_info.sigma=argument_list[2].real_reference;
9462           if (attribute_flag[3] != 0)
9463             geometry_info.xi=argument_list[3].long_reference;
9464           if (attribute_flag[4] != 0)
9465             geometry_info.psi=argument_list[4].long_reference;
9466           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9467             (long) (geometry_info.xi+0.5),(long) (geometry_info.psi+0.5),
9468             exception);
9469           break;
9470         }
9471         case 90:  /* Identify */
9472         {
9473           if (attribute_flag[0] == 0)
9474             argument_list[0].file_reference=(FILE *) NULL;
9475           if (attribute_flag[1] != 0)
9476             (void) SetImageArtifact(image,"identify:features",
9477               argument_list[1].string_reference);
9478           if ((attribute_flag[2] != 0) &&
9479               (argument_list[2].long_reference != 0))
9480             (void) SetImageArtifact(image,"identify:unique","true");
9481           (void) IdentifyImage(image,argument_list[0].file_reference,
9482             MagickTrue);
9483           break;
9484         }
9485         case 91:  /* SepiaTone */
9486         {
9487           if (attribute_flag[0] == 0)
9488             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9489           image=SepiaToneImage(image,argument_list[0].real_reference,
9490             exception);
9491           break;
9492         }
9493         case 92:  /* SigmoidalContrast */
9494         {
9495           MagickBooleanType
9496             sharpen;
9497
9498           if (attribute_flag[0] != 0)
9499             {
9500               flags=ParseGeometry(argument_list[0].string_reference,
9501                 &geometry_info);
9502               if ((flags & SigmaValue) == 0)
9503                 geometry_info.sigma=QuantumRange/2.0;
9504               if ((flags & PercentValue) != 0)
9505                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9506             }
9507           if (attribute_flag[1] != 0)
9508             geometry_info.rho=argument_list[1].real_reference;
9509           if (attribute_flag[2] != 0)
9510             geometry_info.sigma=argument_list[2].real_reference;
9511           if (attribute_flag[3] != 0)
9512             channel=(ChannelType) argument_list[3].long_reference;
9513           sharpen=MagickTrue;
9514           if (attribute_flag[4] != 0)
9515             sharpen=argument_list[4].long_reference != 0 ? MagickTrue :
9516               MagickFalse;
9517           (void) SigmoidalContrastImageChannel(image,channel,sharpen,
9518             geometry_info.rho,geometry_info.sigma);
9519           break;
9520         }
9521         case 93:  /* Extent */
9522         {
9523           if (attribute_flag[7] != 0)
9524             image->gravity=(GravityType) argument_list[7].long_reference;
9525           if (attribute_flag[0] != 0)
9526             {
9527               int
9528                 flags;
9529
9530               flags=ParseGravityGeometry(image,
9531                 argument_list[0].string_reference,&geometry,exception);
9532               if (geometry.width == 0)
9533                 geometry.width=image->columns;
9534               if (geometry.height == 0)
9535                 geometry.height=image->rows;
9536               geometry.x=(-geometry.x);
9537               geometry.y=(-geometry.y);
9538             }
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           if (attribute_flag[3] != 0)
9544             geometry.x=argument_list[3].long_reference;
9545           if (attribute_flag[4] != 0)
9546             geometry.y=argument_list[4].long_reference;
9547           if (attribute_flag[5] != 0)
9548             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9549               QuantumRange);
9550           if (attribute_flag[6] != 0)
9551             (void) QueryColorDatabase(argument_list[6].string_reference,
9552               &image->background_color,exception);
9553           image=ExtentImage(image,&geometry,exception);
9554           break;
9555         }
9556         case 94:  /* Vignette */
9557         {
9558           if (attribute_flag[0] != 0)
9559             {
9560               flags=ParseGeometry(argument_list[0].string_reference,
9561                 &geometry_info);
9562               if ((flags & SigmaValue) == 0)
9563                 geometry_info.sigma=1.0;
9564               if ((flags & XiValue) == 0)
9565                 geometry_info.xi=0.1*image->columns;
9566               if ((flags & PsiValue) == 0)
9567                 geometry_info.psi=0.1*image->rows;
9568             }
9569           if (attribute_flag[1] != 0)
9570             geometry_info.rho=argument_list[1].real_reference;
9571           if (attribute_flag[2] != 0)
9572             geometry_info.sigma=argument_list[2].real_reference;
9573           if (attribute_flag[3] != 0)
9574             geometry_info.xi=argument_list[3].long_reference;
9575           if (attribute_flag[4] != 0)
9576             geometry_info.psi=argument_list[4].long_reference;
9577           if (attribute_flag[5] != 0)
9578             (void) QueryColorDatabase(argument_list[5].string_reference,
9579               &image->background_color,exception);
9580           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9581             (long) (geometry_info.xi+0.5),(long) (geometry_info.psi+0.5),
9582             exception);
9583           break;
9584         }
9585         case 95:  /* ContrastStretch */
9586         {
9587           double
9588             black_point,
9589             white_point;
9590
9591           black_point=0.0;
9592           white_point=(MagickRealType) image->columns*image->rows;
9593           if (attribute_flag[0] != 0)
9594             {
9595               flags=ParseGeometry(argument_list[0].string_reference,
9596                 &geometry_info);
9597               black_point=geometry_info.rho;
9598               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9599                 black_point;
9600               if ((flags & PercentValue) != 0)
9601                 {
9602                   black_point*=(double) image->columns*image->rows/100.0;
9603                   white_point*=(double) image->columns*image->rows/100.0;
9604                 }
9605               white_point=(MagickRealType) image->columns*image->rows-
9606                 white_point;
9607             }
9608           if (attribute_flag[1] != 0)
9609             black_point=argument_list[1].real_reference;
9610           if (attribute_flag[2] != 0)
9611             white_point=argument_list[2].real_reference;
9612           if (attribute_flag[4] != 0)
9613             channel=(ChannelType) argument_list[4].long_reference;
9614           (void) ContrastStretchImageChannel(image,channel,black_point,
9615             white_point);
9616           break;
9617         }
9618         case 96:  /* Sans0 */
9619         {
9620           break;
9621         }
9622         case 97:  /* Sans1 */
9623         {
9624           break;
9625         }
9626         case 98:  /* AdaptiveSharpen */
9627         {
9628           if (attribute_flag[0] != 0)
9629             {
9630               flags=ParseGeometry(argument_list[0].string_reference,
9631                 &geometry_info);
9632               if ((flags & SigmaValue) == 0)
9633                 geometry_info.sigma=1.0;
9634             }
9635           if (attribute_flag[1] != 0)
9636             geometry_info.rho=argument_list[1].real_reference;
9637           if (attribute_flag[2] != 0)
9638             geometry_info.sigma=argument_list[2].real_reference;
9639           if (attribute_flag[3] != 0)
9640             channel=(ChannelType) argument_list[3].long_reference;
9641           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9642             geometry_info.sigma,exception);
9643           break;
9644         }
9645         case 99:  /* Transpose */
9646         {
9647           image=TransposeImage(image,exception);
9648           break;
9649         }
9650         case 100:  /* Tranverse */
9651         {
9652           image=TransverseImage(image,exception);
9653           break;
9654         }
9655         case 101:  /* AutoOrient */
9656         {
9657           switch (image->orientation)
9658           {
9659             case TopRightOrientation:
9660             {
9661               image=FlopImage(image,exception);
9662               break;
9663             }
9664             case BottomRightOrientation:
9665             {
9666               image=RotateImage(image,180.0,exception);
9667               break;
9668             }
9669             case BottomLeftOrientation:
9670             {
9671               image=FlipImage(image,exception);
9672               break;
9673             }
9674             case LeftTopOrientation:
9675             {
9676               image=TransposeImage(image,exception);
9677               break;
9678             }
9679             case RightTopOrientation:
9680             {
9681               image=RotateImage(image,90.0,exception);
9682               break;
9683             }
9684             case RightBottomOrientation:
9685             {
9686               image=TransverseImage(image,exception);
9687               break;
9688             }
9689             case LeftBottomOrientation:
9690             {
9691               image=RotateImage(image,270.0,exception);
9692               break;
9693             }
9694             default:
9695               break;
9696           }
9697           break;
9698         }
9699         case 102:  /* AdaptiveBlur */
9700         {
9701           if (attribute_flag[0] != 0)
9702             {
9703               flags=ParseGeometry(argument_list[0].string_reference,
9704                 &geometry_info);
9705               if ((flags & SigmaValue) == 0)
9706                 geometry_info.sigma=1.0;
9707             }
9708           if (attribute_flag[1] != 0)
9709             geometry_info.rho=argument_list[1].real_reference;
9710           if (attribute_flag[2] != 0)
9711             geometry_info.sigma=argument_list[2].real_reference;
9712           if (attribute_flag[3] != 0)
9713             channel=(ChannelType) argument_list[3].long_reference;
9714           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
9715             geometry_info.sigma,exception);
9716           break;
9717         }
9718         case 103:  /* Sketch */
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=1.0;
9728             }
9729           if (attribute_flag[1] != 0)
9730             geometry_info.rho=argument_list[1].real_reference;
9731           if (attribute_flag[2] != 0)
9732             geometry_info.sigma=argument_list[2].real_reference;
9733           if (attribute_flag[3] != 0)
9734             geometry_info.xi=argument_list[3].real_reference;
9735           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
9736             geometry_info.xi,exception);
9737           break;
9738         }
9739         case 104:  /* UniqueColors */
9740         {
9741           image=UniqueImageColors(image,exception);
9742           break;
9743         }
9744         case 105:  /* AdaptiveResize */
9745         {
9746           if (attribute_flag[0] != 0)
9747             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9748               &geometry,exception);
9749           if (attribute_flag[1] != 0)
9750             geometry.width=argument_list[1].long_reference;
9751           if (attribute_flag[2] != 0)
9752             geometry.height=argument_list[2].long_reference;
9753           if (attribute_flag[3] != 0)
9754             image->filter=(FilterTypes) argument_list[4].long_reference;
9755           if (attribute_flag[4] != 0)
9756             SetImageArtifact(image,"filter:support",
9757               argument_list[4].string_reference);
9758           if (attribute_flag[5] != 0)
9759             image->blur=argument_list[5].real_reference;
9760           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
9761             exception);
9762           break;
9763         }
9764         case 106:  /* ClipMask */
9765         {
9766           if (attribute_flag[0] == 0)
9767             {
9768               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9769                 PackageName);
9770               goto PerlException;
9771             }
9772           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
9773             MagickTrue,exception);
9774           (void) NegateImage(image->clip_mask,MagickFalse);
9775           break;
9776         }
9777         case 107:  /* LinearStretch */
9778         {
9779            double
9780              black_point,
9781              white_point;
9782
9783            black_point=0.0;
9784            white_point=(MagickRealType) image->columns*image->rows;
9785            if (attribute_flag[0] != 0)
9786              {
9787                flags=ParseGeometry(argument_list[0].string_reference,
9788                  &geometry_info);
9789                if ((flags & SigmaValue) != 0)
9790                   white_point=geometry_info.sigma;
9791                if ((flags & PercentValue) != 0)
9792                  {
9793                    black_point*=(double) image->columns*image->rows/100.0;
9794                    white_point*=(double) image->columns*image->rows/100.0;
9795                  }
9796                if ((flags & SigmaValue) == 0)
9797                  white_point=(double) image->columns*image->rows-black_point;
9798              }
9799           if (attribute_flag[1] != 0)
9800             black_point=argument_list[1].real_reference;
9801           if (attribute_flag[2] != 0)
9802             white_point=argument_list[2].real_reference;
9803           (void) LinearStretchImage(image,black_point,white_point);
9804           break;
9805         }
9806         case 108:  /* Recolor */
9807         {
9808           AV
9809             *av;
9810
9811           double
9812             *color_matrix;
9813
9814           unsigned long
9815             order;
9816
9817           if (attribute_flag[0] == 0)
9818             break;
9819           av=(AV *) argument_list[0].array_reference;
9820           order=(unsigned long) sqrt(av_len(av)+1);
9821           color_matrix=(double *) AcquireQuantumMemory(order,order*
9822             sizeof(*color_matrix));
9823           if (color_matrix == (double *) NULL)
9824             {
9825               ThrowPerlException(exception,ResourceLimitFatalError,
9826                 "MemoryAllocationFailed",PackageName);
9827               goto PerlException;
9828             }
9829           for (j=0; (j < (long) (order*order)) && (j < (av_len(av)+1)); j++)
9830             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
9831           for ( ; j < (long) (order*order); j++)
9832             color_matrix[j]=0.0;
9833           image=RecolorImage(image,order,color_matrix,exception);
9834           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
9835           break;
9836         }
9837         case 109:  /* Mask */
9838         {
9839           if (attribute_flag[0] == 0)
9840             {
9841               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9842                 PackageName);
9843               goto PerlException;
9844             }
9845           image->mask=CloneImage(argument_list[0].image_reference,0,0,
9846             MagickTrue,exception);
9847           (void) NegateImage(image->mask,MagickFalse);
9848           break;
9849         }
9850         case 110:  /* Polaroid */
9851         {
9852           DrawInfo
9853             *draw_info;
9854
9855           double
9856             angle;
9857
9858           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9859             (DrawInfo *) NULL);
9860           if (attribute_flag[0] != 0)
9861             (void) SetImageProperty(image,"caption",InterpretImageProperties(
9862               info ? info->image_info : (ImageInfo *) NULL,image,
9863               argument_list[0].string_reference));
9864           angle=0.0;
9865           if (attribute_flag[1] != 0)
9866             angle=argument_list[1].real_reference;
9867           if (attribute_flag[2] != 0)
9868             (void) CloneString(&draw_info->font,
9869               argument_list[2].string_reference);
9870           if (attribute_flag[3] != 0)
9871             (void) QueryColorDatabase(argument_list[3].string_reference,
9872               &draw_info->stroke,exception);
9873           if (attribute_flag[4] != 0)
9874             (void) QueryColorDatabase(argument_list[4].string_reference,
9875               &draw_info->fill,exception);
9876           if (attribute_flag[5] != 0)
9877             draw_info->stroke_width=argument_list[5].real_reference;
9878           if (attribute_flag[6] != 0)
9879             draw_info->pointsize=argument_list[6].real_reference;
9880           if (attribute_flag[7] != 0)
9881             draw_info->gravity=(GravityType) argument_list[7].long_reference;
9882           if (attribute_flag[8] != 0)
9883             (void) QueryColorDatabase(argument_list[8].string_reference,
9884               &image->background_color,exception);
9885           image=PolaroidImage(image,draw_info,angle,exception);
9886           draw_info=DestroyDrawInfo(draw_info);
9887           break;
9888         }
9889         case 111:  /* FloodfillPaint */
9890         {
9891           DrawInfo
9892             *draw_info;
9893
9894           MagickBooleanType
9895             invert;
9896
9897           MagickPixelPacket
9898             target;
9899
9900           draw_info=CloneDrawInfo(info ? info->image_info :
9901             (ImageInfo *) NULL,(DrawInfo *) NULL);
9902           if (attribute_flag[0] != 0)
9903             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9904               &geometry,exception);
9905           if (attribute_flag[1] != 0)
9906             geometry.x=argument_list[1].long_reference;
9907           if (attribute_flag[2] != 0)
9908             geometry.y=argument_list[2].long_reference;
9909           if (attribute_flag[3] != 0)
9910             (void) QueryColorDatabase(argument_list[3].string_reference,
9911               &draw_info->fill,exception);
9912           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
9913             exception);
9914           if (attribute_flag[4] != 0)
9915             QueryMagickColor(argument_list[4].string_reference,&target,
9916               exception);
9917           if (attribute_flag[5] != 0)
9918             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9919               QuantumRange);
9920           if (attribute_flag[6] != 0)
9921             channel=(ChannelType) argument_list[6].long_reference;
9922           invert=MagickFalse;
9923           if (attribute_flag[7] != 0)
9924             invert=(MagickBooleanType) argument_list[7].long_reference;
9925           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
9926             geometry.y,invert);
9927           draw_info=DestroyDrawInfo(draw_info);
9928           break;
9929         }
9930         case 112:  /* Distort */
9931         {
9932           AV
9933             *av;
9934
9935           double
9936             *coordinates;
9937
9938           DistortImageMethod
9939             method;
9940
9941           unsigned long
9942             number_coordinates;
9943
9944           VirtualPixelMethod
9945             virtual_pixel;
9946
9947           if (attribute_flag[0] == 0)
9948             break;
9949           method=UndefinedDistortion;
9950           if (attribute_flag[1] != 0)
9951             method=(DistortImageMethod) argument_list[1].long_reference;
9952           av=(AV *) argument_list[0].array_reference;
9953           number_coordinates=(unsigned long) av_len(av)+1;
9954           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
9955             sizeof(*coordinates));
9956           if (coordinates == (double *) NULL)
9957             {
9958               ThrowPerlException(exception,ResourceLimitFatalError,
9959                 "MemoryAllocationFailed",PackageName);
9960               goto PerlException;
9961             }
9962           for (j=0; j < (long) number_coordinates; j++)
9963             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
9964           virtual_pixel=UndefinedVirtualPixelMethod;
9965           if (attribute_flag[2] != 0)
9966             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
9967               argument_list[2].long_reference);
9968           image=DistortImage(image,method,number_coordinates,coordinates,
9969             argument_list[3].long_reference != 0 ? MagickTrue : MagickFalse,
9970             exception);
9971           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
9972             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
9973           coordinates=(double *) RelinquishMagickMemory(coordinates);
9974           break;
9975         }
9976         case 113:  /* Clut */
9977         {
9978           if (attribute_flag[0] == 0)
9979             {
9980               ThrowPerlException(exception,OptionError,"ClutImageRequired",
9981                 PackageName);
9982               goto PerlException;
9983             }
9984           if (attribute_flag[1] != 0)
9985             channel=(ChannelType) argument_list[1].long_reference;
9986           (void) ClutImageChannel(image,channel,
9987             argument_list[0].image_reference);
9988           break;
9989         }
9990         case 114:  /* LiquidRescale */
9991         {
9992           if (attribute_flag[0] != 0)
9993             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9994               &geometry,exception);
9995           if (attribute_flag[1] != 0)
9996             geometry.width=argument_list[1].long_reference;
9997           if (attribute_flag[2] != 0)
9998             geometry.height=argument_list[2].long_reference;
9999           if (attribute_flag[3] == 0)
10000             argument_list[3].real_reference=1.0;
10001           if (attribute_flag[4] == 0)
10002             argument_list[4].real_reference=0.0;
10003           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10004             argument_list[3].real_reference,argument_list[4].real_reference,
10005             exception);
10006           break;
10007         }
10008         case 115:  /* EncipherImage */
10009         {
10010           (void) EncipherImage(image,argument_list[0].string_reference,
10011             exception);
10012           break;
10013         }
10014         case 116:  /* DecipherImage */
10015         {
10016           (void) DecipherImage(image,argument_list[0].string_reference,
10017             exception);
10018           break;
10019         }
10020         case 117:  /* Deskew */
10021         {
10022           geometry_info.rho=QuantumRange/2.0;
10023           if (attribute_flag[0] != 0)
10024             flags=ParseGeometry(argument_list[0].string_reference,
10025               &geometry_info);
10026           if (attribute_flag[1] != 0)
10027             geometry_info.rho=SiPrefixToDouble(
10028               argument_list[1].string_reference,QuantumRange);
10029           image=DeskewImage(image,geometry_info.rho,exception);
10030           break;
10031         }
10032         case 118:  /* Remap */
10033         {
10034           QuantizeInfo
10035             *quantize_info;
10036
10037           if (attribute_flag[0] == 0)
10038             {
10039               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10040                 PackageName);
10041               goto PerlException;
10042             }
10043           quantize_info=AcquireQuantizeInfo(info->image_info);
10044           if (attribute_flag[1] != 0)
10045             quantize_info->dither=(MagickBooleanType)
10046               argument_list[1].long_reference;
10047           if (attribute_flag[2] != 0)
10048             quantize_info->dither_method=(DitherMethod)
10049               argument_list[2].long_reference;
10050           (void) RemapImages(quantize_info,image,
10051             argument_list[0].image_reference);
10052           quantize_info=DestroyQuantizeInfo(quantize_info);
10053           break;
10054         }
10055         case 119:  /* SparseColor */
10056         {
10057           AV
10058             *av;
10059
10060           double
10061             *coordinates;
10062
10063           SparseColorMethod
10064             method;
10065
10066           unsigned long
10067             number_coordinates;
10068
10069           VirtualPixelMethod
10070             virtual_pixel;
10071
10072           if (attribute_flag[0] == 0)
10073             break;
10074           method=UndefinedColorInterpolate;
10075           if (attribute_flag[1] != 0)
10076             method=(SparseColorMethod) argument_list[1].long_reference;
10077           av=(AV *) argument_list[0].array_reference;
10078           number_coordinates=(unsigned long) av_len(av)+1;
10079           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10080             sizeof(*coordinates));
10081           if (coordinates == (double *) NULL)
10082             {
10083               ThrowPerlException(exception,ResourceLimitFatalError,
10084                 "MemoryAllocationFailed",PackageName);
10085               goto PerlException;
10086             }
10087           for (j=0; j < (long) number_coordinates; j++)
10088             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10089           virtual_pixel=UndefinedVirtualPixelMethod;
10090           if (attribute_flag[2] != 0)
10091             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10092               argument_list[2].long_reference);
10093           if (attribute_flag[3] != 0)
10094             channel=(ChannelType) argument_list[3].long_reference;
10095           image=SparseColorImage(image,channel,method,number_coordinates,
10096             coordinates,exception);
10097           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10098             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10099           coordinates=(double *) RelinquishMagickMemory(coordinates);
10100           break;
10101         }
10102         case 120:  /* Function */
10103         {
10104           AV
10105             *av;
10106
10107           double
10108             *parameters;
10109
10110           MagickFunction
10111             function;
10112
10113           unsigned long
10114             number_parameters;
10115
10116           VirtualPixelMethod
10117             virtual_pixel;
10118
10119           if (attribute_flag[0] == 0)
10120             break;
10121           function=UndefinedFunction;
10122           if (attribute_flag[1] != 0)
10123             function=(MagickFunction) argument_list[1].long_reference;
10124           av=(AV *) argument_list[0].array_reference;
10125           number_parameters=(unsigned long) av_len(av)+1;
10126           parameters=(double *) AcquireQuantumMemory(number_parameters,
10127             sizeof(*parameters));
10128           if (parameters == (double *) NULL)
10129             {
10130               ThrowPerlException(exception,ResourceLimitFatalError,
10131                 "MemoryAllocationFailed",PackageName);
10132               goto PerlException;
10133             }
10134           for (j=0; j < (long) number_parameters; j++)
10135             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10136           virtual_pixel=UndefinedVirtualPixelMethod;
10137           if (attribute_flag[2] != 0)
10138             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10139               argument_list[2].long_reference);
10140           (void) FunctionImage(image,function,number_parameters,parameters,
10141             exception);
10142           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10143             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10144           parameters=(double *) RelinquishMagickMemory(parameters);
10145           break;
10146         }
10147         case 121:  /* SelectiveBlur */
10148         {
10149           if (attribute_flag[0] != 0)
10150             {
10151               flags=ParseGeometry(argument_list[0].string_reference,
10152                 &geometry_info);
10153               if ((flags & SigmaValue) == 0)
10154                 geometry_info.sigma=1.0;
10155               if ((flags & PercentValue) != 0)
10156                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10157             }
10158           if (attribute_flag[1] != 0)
10159             geometry_info.rho=argument_list[1].real_reference;
10160           if (attribute_flag[2] != 0)
10161             geometry_info.sigma=argument_list[2].real_reference;
10162           if (attribute_flag[3] != 0)
10163             geometry_info.xi=argument_list[3].long_reference;;
10164           if (attribute_flag[4] != 0)
10165             channel=(ChannelType) argument_list[4].long_reference;
10166           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10167             geometry_info.sigma,geometry_info.xi,exception);
10168           break;
10169         }
10170         case 122:  /* HaldClut */
10171         {
10172           if (attribute_flag[0] == 0)
10173             {
10174               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10175                 PackageName);
10176               goto PerlException;
10177             }
10178           if (attribute_flag[1] != 0)
10179             channel=(ChannelType) argument_list[1].long_reference;
10180           (void) HaldClutImageChannel(image,channel,
10181             argument_list[0].image_reference);
10182           break;
10183         }
10184         case 123:  /* BlueShift */
10185         {
10186           if (attribute_flag[0] != 0)
10187             (void) ParseGeometry(argument_list[0].string_reference,
10188               &geometry_info);
10189           image=BlueShiftImage(image,geometry_info.rho,exception);
10190           break;
10191         }
10192         case 124:  /* ForwardFourierTransformImage */
10193         {
10194           image=ForwardFourierTransformImage(image,
10195             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse,
10196             exception);
10197           break;
10198         }
10199         case 125:  /* InverseFourierTransformImage */
10200         {
10201           image=InverseFourierTransformImage(image,image->next,
10202             argument_list[0].long_reference != 0 ? MagickTrue : MagickFalse,
10203             exception);
10204           break;
10205         }
10206         case 126:  /* ColorDecisionList */
10207         {
10208           if (attribute_flag[0] == 0)
10209             argument_list[0].string_reference=(char *) NULL;
10210           (void) ColorDecisionListImage(image,
10211             argument_list[0].string_reference);
10212           break;
10213         }
10214         case 127:  /* AutoGamma */
10215         {
10216           if (attribute_flag[0] != 0)
10217             channel=(ChannelType) argument_list[0].long_reference;
10218           (void) AutoGammaImageChannel(image,channel);
10219           break;
10220         }
10221         case 128:  /* AutoLevel */
10222         {
10223           if (attribute_flag[0] != 0)
10224             channel=(ChannelType) argument_list[0].long_reference;
10225           (void) AutoLevelImageChannel(image,channel);
10226           break;
10227         }
10228         case 129:  /* LevelColors */
10229         {
10230           MagickPixelPacket
10231             black_point,
10232             white_point;
10233
10234           (void) QueryMagickColor("#000000",&black_point,exception);
10235           (void) QueryMagickColor("#ffffff",&black_point,exception);
10236           if (attribute_flag[1] != 0)
10237              (void) QueryMagickColor(argument_list[1].string_reference,
10238                &black_point,exception);
10239           if (attribute_flag[2] != 0)
10240              (void) QueryMagickColor(argument_list[2].string_reference,
10241                &white_point,exception);
10242           if (attribute_flag[3] != 0)
10243             channel=(ChannelType) argument_list[3].long_reference;
10244           (void) LevelColorsImageChannel(image,channel,&black_point,
10245             &white_point,argument_list[0].long_reference != 0 ? MagickTrue :
10246             MagickFalse);
10247           break;
10248         }
10249         case 130:  /* Clamp */
10250         {
10251           if (attribute_flag[0] != 0)
10252             channel=(ChannelType) argument_list[0].long_reference;
10253           (void) ClampImageChannel(image,channel);
10254           break;
10255         }
10256         case 131:  /* Filter */
10257         {
10258           KernelInfo
10259             *kernel;
10260
10261           if (attribute_flag[0] == 0)
10262             break;
10263           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10264           if (kernel == (KernelInfo *) NULL)
10265             break;
10266           if (attribute_flag[1] != 0)
10267             channel=(ChannelType) argument_list[1].long_reference;
10268           if (attribute_flag[2] != 0)
10269             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10270               QuantumRange);
10271           image=FilterImageChannel(image,channel,kernel,exception);
10272           kernel=DestroyKernelInfo(kernel);
10273           break;
10274         }
10275         case 132:  /* BrightnessContrast */
10276         {
10277           double
10278             brightness,
10279             contrast;
10280
10281           brightness=0.0;
10282           contrast=0.0;
10283           if (attribute_flag[0] != 0)
10284             {
10285               flags=ParseGeometry(argument_list[0].string_reference,
10286                 &geometry_info);
10287               brightness=geometry_info.rho;
10288               if ((flags & SigmaValue) == 0)
10289                 contrast=geometry_info.sigma;
10290             }
10291           if (attribute_flag[1] != 0)
10292             brightness=argument_list[1].real_reference;
10293           if (attribute_flag[2] != 0)
10294             contrast=argument_list[2].real_reference;
10295           if (attribute_flag[4] != 0)
10296             channel=(ChannelType) argument_list[4].long_reference;
10297           (void) BrightnessContrastImageChannel(image,channel,brightness,
10298             contrast);
10299           break;
10300         }
10301         case 133:  /* Morphology */
10302         {
10303           KernelInfo
10304             *kernel;
10305
10306           MorphologyMethod
10307             method;
10308
10309           long
10310             iterations;
10311
10312           if (attribute_flag[0] == 0)
10313             break;
10314           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10315           if (kernel == (KernelInfo *) NULL)
10316             break;
10317           if (attribute_flag[1] != 0)
10318             channel=(ChannelType) argument_list[1].long_reference;
10319           method=UndefinedMorphology;
10320           if (attribute_flag[2] != 0)
10321             method=argument_list[2].long_reference;
10322           iterations=1;
10323           if (attribute_flag[3] != 0)
10324             iterations=argument_list[4].long_reference;
10325           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10326             exception);
10327           kernel=DestroyKernelInfo(kernel);
10328           break;
10329         }
10330       }
10331       if (next != (Image *) NULL)
10332         (void) CatchImageException(next);
10333       if (region_image != (Image *) NULL)
10334         {
10335           /*
10336             Composite region.
10337           */
10338           status=CompositeImage(region_image,CopyCompositeOp,image,
10339             region_info.x,region_info.y);
10340           (void) CatchImageException(region_image);
10341           image=DestroyImage(image);
10342           image=region_image;
10343         }
10344       if (image != (Image *) NULL)
10345         {
10346           number_images++;
10347           if (next && (next != image))
10348             {
10349               image->next=next->next;
10350               DeleteImageFromRegistry(*pv,next);
10351             }
10352           sv_setiv(*pv,(IV) image);
10353           next=image;
10354         }
10355       if (*pv)
10356         pv++;
10357     }
10358
10359   PerlException:
10360     if (reference_vector)
10361       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10362     InheritPerlException(exception,perl_exception);
10363     exception=DestroyExceptionInfo(exception);
10364     sv_setiv(perl_exception,(IV) number_images);
10365     SvPOK_on(perl_exception);
10366     ST(0)=sv_2mortal(perl_exception);
10367     XSRETURN(1);
10368   }
10369 \f
10370 #
10371 ###############################################################################
10372 #                                                                             #
10373 #                                                                             #
10374 #                                                                             #
10375 #   M o n t a g e                                                             #
10376 #                                                                             #
10377 #                                                                             #
10378 #                                                                             #
10379 ###############################################################################
10380 #
10381 #
10382 void
10383 Montage(ref,...)
10384   Image::Magick ref=NO_INIT
10385   ALIAS:
10386     MontageImage  = 1
10387     montage       = 2
10388     montageimage  = 3
10389   PPCODE:
10390   {
10391     AV
10392       *av;
10393
10394     char
10395       *attribute;
10396
10397     ExceptionInfo
10398       *exception;
10399
10400     HV
10401       *hv;
10402
10403     Image
10404       *image,
10405       *next;
10406
10407     long
10408       sp;
10409
10410     MagickPixelPacket
10411       transparent_color;
10412
10413     MontageInfo
10414       *montage_info;
10415
10416     register long
10417       i;
10418
10419     struct PackageInfo
10420       *info;
10421
10422     SV
10423       *av_reference,
10424       *perl_exception,
10425       *reference,
10426       *rv,
10427       *sv;
10428
10429     exception=AcquireExceptionInfo();
10430     perl_exception=newSVpv("",0);
10431     attribute=NULL;
10432     if (sv_isobject(ST(0)) == 0)
10433       {
10434         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10435           PackageName);
10436         goto PerlException;
10437       }
10438     reference=SvRV(ST(0));
10439     hv=SvSTASH(reference);
10440     av=newAV();
10441     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10442     SvREFCNT_dec(av);
10443     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10444     if (image == (Image *) NULL)
10445       {
10446         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10447           PackageName);
10448         goto PerlException;
10449       }
10450     /*
10451       Get options.
10452     */
10453     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10454     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10455     (void) QueryMagickColor("none",&transparent_color,exception);
10456     for (i=2; i < items; i+=2)
10457     {
10458       attribute=(char *) SvPV(ST(i-1),na);
10459       switch (*attribute)
10460       {
10461         case 'B':
10462         case 'b':
10463         {
10464           if (LocaleCompare(attribute,"background") == 0)
10465             {
10466               (void) QueryColorDatabase(SvPV(ST(i),na),
10467                 &montage_info->background_color,exception);
10468               for (next=image; next; next=next->next)
10469                 next->background_color=montage_info->background_color;
10470               break;
10471             }
10472           if (LocaleCompare(attribute,"border") == 0)
10473             {
10474               montage_info->border_width=SvIV(ST(i));
10475               break;
10476             }
10477           if (LocaleCompare(attribute,"bordercolor") == 0)
10478             {
10479               (void) QueryColorDatabase(SvPV(ST(i),na),
10480                 &montage_info->border_color,exception);
10481               for (next=image; next; next=next->next)
10482                 next->border_color=montage_info->border_color;
10483               break;
10484             }
10485           if (LocaleCompare(attribute,"borderwidth") == 0)
10486             {
10487               montage_info->border_width=SvIV(ST(i));
10488               break;
10489             }
10490           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10491             attribute);
10492           break;
10493         }
10494         case 'C':
10495         case 'c':
10496         {
10497           if (LocaleCompare(attribute,"compose") == 0)
10498             {
10499               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10500                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10501               if (sp < 0)
10502                 {
10503                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10504                     SvPV(ST(i),na));
10505                   break;
10506                 }
10507               for (next=image; next; next=next->next)
10508                 next->compose=(CompositeOperator) sp;
10509               break;
10510             }
10511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10512             attribute);
10513           break;
10514         }
10515         case 'F':
10516         case 'f':
10517         {
10518           if (LocaleCompare(attribute,"fill") == 0)
10519             {
10520               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10521                 exception);
10522               break;
10523             }
10524           if (LocaleCompare(attribute,"font") == 0)
10525             {
10526               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10527               break;
10528             }
10529           if (LocaleCompare(attribute,"frame") == 0)
10530             {
10531               char
10532                 *p;
10533
10534               p=SvPV(ST(i),na);
10535               if (IsGeometry(p) == MagickFalse)
10536                 {
10537                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10538                     p);
10539                   break;
10540                 }
10541               (void) CloneString(&montage_info->frame,p);
10542               if (*p == '\0')
10543                 montage_info->frame=(char *) NULL;
10544               break;
10545             }
10546           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10547             attribute);
10548           break;
10549         }
10550         case 'G':
10551         case 'g':
10552         {
10553           if (LocaleCompare(attribute,"geometry") == 0)
10554             {
10555               char
10556                 *p;
10557
10558               p=SvPV(ST(i),na);
10559               if (IsGeometry(p) == MagickFalse)
10560                 {
10561                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10562                     p);
10563                   break;
10564                 }
10565              (void) CloneString(&montage_info->geometry,p);
10566              if (*p == '\0')
10567                montage_info->geometry=(char *) NULL;
10568              break;
10569            }
10570          if (LocaleCompare(attribute,"gravity") == 0)
10571            {
10572              long
10573                in;
10574
10575              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10576                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10577              if (in < 0)
10578                {
10579                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10580                    SvPV(ST(i),na));
10581                  return;
10582                }
10583              montage_info->gravity=(GravityType) in;
10584              for (next=image; next; next=next->next)
10585                next->gravity=(GravityType) in;
10586              break;
10587            }
10588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10589             attribute);
10590           break;
10591         }
10592         case 'L':
10593         case 'l':
10594         {
10595           if (LocaleCompare(attribute,"label") == 0)
10596             {
10597               for (next=image; next; next=next->next)
10598                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10599                   info ? info->image_info : (ImageInfo *) NULL,next,
10600                   SvPV(ST(i),na)));
10601               break;
10602             }
10603           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10604             attribute);
10605           break;
10606         }
10607         case 'M':
10608         case 'm':
10609         {
10610           if (LocaleCompare(attribute,"mattecolor") == 0)
10611             {
10612               (void) QueryColorDatabase(SvPV(ST(i),na),
10613                 &montage_info->matte_color,exception);
10614               for (next=image; next; next=next->next)
10615                 next->matte_color=montage_info->matte_color;
10616               break;
10617             }
10618           if (LocaleCompare(attribute,"mode") == 0)
10619             {
10620               long
10621                 in;
10622
10623               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10624                 ParseMagickOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10625               switch (in)
10626               {
10627                 default:
10628                 {
10629                   ThrowPerlException(exception,OptionError,
10630                     "UnrecognizedModeType",SvPV(ST(i),na));
10631                   break;
10632                 }
10633                 case FrameMode:
10634                 {
10635                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10636                   montage_info->shadow=MagickTrue;
10637                   break;
10638                 }
10639                 case UnframeMode:
10640                 {
10641                   montage_info->frame=(char *) NULL;
10642                   montage_info->shadow=MagickFalse;
10643                   montage_info->border_width=0;
10644                   break;
10645                 }
10646                 case ConcatenateMode:
10647                 {
10648                   montage_info->frame=(char *) NULL;
10649                   montage_info->shadow=MagickFalse;
10650                   (void) CloneString(&montage_info->geometry,"+0+0");
10651                   montage_info->border_width=0;
10652                 }
10653               }
10654               break;
10655             }
10656           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10657             attribute);
10658           break;
10659         }
10660         case 'P':
10661         case 'p':
10662         {
10663           if (LocaleCompare(attribute,"pointsize") == 0)
10664             {
10665               montage_info->pointsize=SvIV(ST(i));
10666               break;
10667             }
10668           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10669             attribute);
10670           break;
10671         }
10672         case 'S':
10673         case 's':
10674         {
10675           if (LocaleCompare(attribute,"shadow") == 0)
10676             {
10677               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
10678                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
10679               if (sp < 0)
10680                 {
10681                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10682                     SvPV(ST(i),na));
10683                   break;
10684                 }
10685              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
10686              break;
10687             }
10688           if (LocaleCompare(attribute,"stroke") == 0)
10689             {
10690               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
10691                 exception);
10692               break;
10693             }
10694           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10695             attribute);
10696           break;
10697         }
10698         case 'T':
10699         case 't':
10700         {
10701           if (LocaleCompare(attribute,"texture") == 0)
10702             {
10703               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
10704               break;
10705             }
10706           if (LocaleCompare(attribute,"tile") == 0)
10707             {
10708               char *p=SvPV(ST(i),na);
10709               if (IsGeometry(p) == MagickFalse)
10710                 {
10711                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10712                     p);
10713                   break;
10714                 }
10715               (void) CloneString(&montage_info->tile,p);
10716               if (*p == '\0')
10717                 montage_info->tile=(char *) NULL;
10718               break;
10719             }
10720           if (LocaleCompare(attribute,"title") == 0)
10721             {
10722               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
10723               break;
10724             }
10725           if (LocaleCompare(attribute,"transparent") == 0)
10726             {
10727               MagickPixelPacket
10728                 transparent_color;
10729
10730               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
10731               for (next=image; next; next=next->next)
10732                 (void) TransparentPaintImage(next,&transparent_color,
10733                   TransparentOpacity,MagickFalse);
10734               break;
10735             }
10736           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10737             attribute);
10738           break;
10739         }
10740         default:
10741         {
10742           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10743             attribute);
10744           break;
10745         }
10746       }
10747     }
10748     image=MontageImageList(info->image_info,montage_info,image,exception);
10749     montage_info=DestroyMontageInfo(montage_info);
10750     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
10751       goto PerlException;
10752     if (transparent_color.opacity != TransparentOpacity)
10753       for (next=image; next; next=next->next)
10754         (void) TransparentPaintImage(next,&transparent_color,
10755           TransparentOpacity,MagickFalse);
10756     for (  ; image; image=image->next)
10757     {
10758       AddImageToRegistry(image);
10759       rv=newRV(sv);
10760       av_push(av,sv_bless(rv,hv));
10761       SvREFCNT_dec(sv);
10762     }
10763     exception=DestroyExceptionInfo(exception);
10764     ST(0)=av_reference;
10765     SvREFCNT_dec(perl_exception);
10766     XSRETURN(1);
10767
10768   PerlException:
10769     InheritPerlException(exception,perl_exception);
10770     exception=DestroyExceptionInfo(exception);
10771     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
10772     SvPOK_on(perl_exception);
10773     ST(0)=sv_2mortal(perl_exception);
10774     XSRETURN(1);
10775   }
10776 \f
10777 #
10778 ###############################################################################
10779 #                                                                             #
10780 #                                                                             #
10781 #                                                                             #
10782 #   M o r p h                                                                 #
10783 #                                                                             #
10784 #                                                                             #
10785 #                                                                             #
10786 ###############################################################################
10787 #
10788 #
10789 void
10790 Morph(ref,...)
10791   Image::Magick ref=NO_INIT
10792   ALIAS:
10793     MorphImage  = 1
10794     morph       = 2
10795     morphimage  = 3
10796   PPCODE:
10797   {
10798     AV
10799       *av;
10800
10801     char
10802       *attribute;
10803
10804     ExceptionInfo
10805       *exception;
10806
10807     HV
10808       *hv;
10809
10810     Image
10811       *image;
10812
10813     long
10814       number_frames;
10815
10816     register long
10817       i;
10818
10819     struct PackageInfo
10820       *info;
10821
10822     SV
10823       *av_reference,
10824       *perl_exception,
10825       *reference,
10826       *rv,
10827       *sv;
10828
10829     exception=AcquireExceptionInfo();
10830     perl_exception=newSVpv("",0);
10831     av=NULL;
10832     attribute=NULL;
10833     if (sv_isobject(ST(0)) == 0)
10834       {
10835         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10836           PackageName);
10837         goto PerlException;
10838       }
10839     reference=SvRV(ST(0));
10840     hv=SvSTASH(reference);
10841     av=newAV();
10842     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10843     SvREFCNT_dec(av);
10844     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10845     if (image == (Image *) NULL)
10846       {
10847         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10848           PackageName);
10849         goto PerlException;
10850       }
10851     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10852     /*
10853       Get attribute.
10854     */
10855     number_frames=30;
10856     for (i=2; i < items; i+=2)
10857     {
10858       attribute=(char *) SvPV(ST(i-1),na);
10859       switch (*attribute)
10860       {
10861         case 'F':
10862         case 'f':
10863         {
10864           if (LocaleCompare(attribute,"frames") == 0)
10865             {
10866               number_frames=SvIV(ST(i));
10867               break;
10868             }
10869           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10870             attribute);
10871           break;
10872         }
10873         default:
10874         {
10875           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10876             attribute);
10877           break;
10878         }
10879       }
10880     }
10881     image=MorphImages(image,number_frames,exception);
10882     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
10883       goto PerlException;
10884     for ( ; image; image=image->next)
10885     {
10886       AddImageToRegistry(image);
10887       rv=newRV(sv);
10888       av_push(av,sv_bless(rv,hv));
10889       SvREFCNT_dec(sv);
10890     }
10891     exception=DestroyExceptionInfo(exception);
10892     ST(0)=av_reference;
10893     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
10894     XSRETURN(1);
10895
10896   PerlException:
10897     InheritPerlException(exception,perl_exception);
10898     exception=DestroyExceptionInfo(exception);
10899     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
10900     SvPOK_on(perl_exception);
10901     ST(0)=sv_2mortal(perl_exception);
10902     XSRETURN(1);
10903   }
10904 \f
10905 #
10906 ###############################################################################
10907 #                                                                             #
10908 #                                                                             #
10909 #                                                                             #
10910 #   M o s a i c                                                               #
10911 #                                                                             #
10912 #                                                                             #
10913 #                                                                             #
10914 ###############################################################################
10915 #
10916 #
10917 void
10918 Mosaic(ref)
10919   Image::Magick ref=NO_INIT
10920   ALIAS:
10921     MosaicImage   = 1
10922     mosaic        = 2
10923     mosaicimage   = 3
10924   PPCODE:
10925   {
10926     AV
10927       *av;
10928
10929     ExceptionInfo
10930       *exception;
10931
10932     HV
10933       *hv;
10934
10935     Image
10936       *image;
10937
10938     struct PackageInfo
10939       *info;
10940
10941     SV
10942       *perl_exception,
10943       *reference,
10944       *rv,
10945       *sv;
10946
10947     exception=AcquireExceptionInfo();
10948     perl_exception=newSVpv("",0);
10949     if (sv_isobject(ST(0)) == 0)
10950       {
10951         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10952           PackageName);
10953         goto PerlException;
10954       }
10955     reference=SvRV(ST(0));
10956     hv=SvSTASH(reference);
10957     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10958     if (image == (Image *) NULL)
10959       {
10960         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10961           PackageName);
10962         goto PerlException;
10963       }
10964     image=MergeImageLayers(image,MosaicLayer,exception);
10965     /*
10966       Create blessed Perl array for the returned image.
10967     */
10968     av=newAV();
10969     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10970     SvREFCNT_dec(av);
10971     AddImageToRegistry(image);
10972     rv=newRV(sv);
10973     av_push(av,sv_bless(rv,hv));
10974     SvREFCNT_dec(sv);
10975     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10976     (void) CopyMagickString(image->filename,info->image_info->filename,
10977       MaxTextExtent);
10978     SetImageInfo(info->image_info,MagickFalse,&image->exception);
10979     exception=DestroyExceptionInfo(exception);
10980     SvREFCNT_dec(perl_exception);
10981     XSRETURN(1);
10982
10983   PerlException:
10984     InheritPerlException(exception,perl_exception);
10985     exception=DestroyExceptionInfo(exception);
10986     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
10987     SvPOK_on(perl_exception);  /* return messages in string context */
10988     ST(0)=sv_2mortal(perl_exception);
10989     XSRETURN(1);
10990   }
10991 \f
10992 #
10993 ###############################################################################
10994 #                                                                             #
10995 #                                                                             #
10996 #                                                                             #
10997 #   P i n g                                                                   #
10998 #                                                                             #
10999 #                                                                             #
11000 #                                                                             #
11001 ###############################################################################
11002 #
11003 #
11004 void
11005 Ping(ref,...)
11006   Image::Magick ref=NO_INIT
11007   ALIAS:
11008     PingImage  = 1
11009     ping       = 2
11010     pingimage  = 3
11011   PPCODE:
11012   {
11013     AV
11014       *av;
11015
11016     char
11017       **keep,
11018       **list;
11019
11020     ExceptionInfo
11021       *exception;
11022
11023     HV
11024       *hv;
11025
11026     Image
11027       *image,
11028       *next;
11029
11030     int
11031       n;
11032
11033     long
11034       ac;
11035
11036     MagickBooleanType
11037       status;
11038
11039     register char
11040       **p;
11041
11042     register long
11043       i;
11044
11045     STRLEN
11046       *length;
11047
11048     struct PackageInfo
11049       *info,
11050       *package_info;
11051
11052     SV
11053       *perl_exception,
11054       *reference;
11055
11056     unsigned long
11057       count;
11058
11059     exception=AcquireExceptionInfo();
11060     perl_exception=newSVpv("",0);
11061     package_info=(struct PackageInfo *) NULL;
11062     ac=(items < 2) ? 1 : items-1;
11063     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11064     keep=list;
11065     length=(STRLEN *) NULL;
11066     if (list == (char **) NULL)
11067       {
11068         ThrowPerlException(exception,ResourceLimitError,
11069           "MemoryAllocationFailed",PackageName);
11070         goto PerlException;
11071       }
11072     keep=list;
11073     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11074     if (length == (STRLEN *) NULL)
11075       {
11076         ThrowPerlException(exception,ResourceLimitError,
11077           "MemoryAllocationFailed",PackageName);
11078         goto PerlException;
11079       }
11080     if (sv_isobject(ST(0)) == 0)
11081       {
11082         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11083           PackageName);
11084         goto PerlException;
11085       }
11086     reference=SvRV(ST(0));
11087     hv=SvSTASH(reference);
11088     if (SvTYPE(reference) != SVt_PVAV)
11089       {
11090         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11091           PackageName);
11092         goto PerlException;
11093       }
11094     av=(AV *) reference;
11095     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11096       exception);
11097     package_info=ClonePackageInfo(info,exception);
11098     n=1;
11099     if (items <= 1)
11100       *list=(char *) (*package_info->image_info->filename ?
11101         package_info->image_info->filename : "XC:black");
11102     else
11103       for (n=0, i=0; i < ac; i++)
11104       {
11105         list[n]=(char *) SvPV(ST(i+1),length[n]);
11106         if ((items >= 3) && strEQcase(list[n],"blob"))
11107           {
11108             void
11109               *blob;
11110
11111             i++;
11112             blob=(void *) (SvPV(ST(i+1),length[n]));
11113             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11114           }
11115         if ((items >= 3) && strEQcase(list[n],"filename"))
11116           continue;
11117         if ((items >= 3) && strEQcase(list[n],"file"))
11118           {
11119             FILE
11120               *file;
11121
11122             PerlIO
11123               *io_info;
11124
11125             i++;
11126             io_info=IoIFP(sv_2io(ST(i+1)));
11127             if (io_info == (PerlIO *) NULL)
11128               {
11129                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11130                   PackageName);
11131                 continue;
11132               }
11133             file=PerlIO_findFILE(io_info);
11134             if (file == (FILE *) NULL)
11135               {
11136                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11137                   PackageName);
11138                 continue;
11139               }
11140             SetImageInfoFile(package_info->image_info,file);
11141           }
11142         if ((items >= 3) && strEQcase(list[n],"magick"))
11143           continue;
11144         n++;
11145       }
11146     list[n]=(char *) NULL;
11147     keep=list;
11148     status=ExpandFilenames(&n,&list);
11149     if (status == MagickFalse)
11150       {
11151         ThrowPerlException(exception,ResourceLimitError,
11152           "MemoryAllocationFailed",PackageName);
11153         goto PerlException;
11154       }
11155     count=0;
11156     for (i=0; i < n; i++)
11157     {
11158       (void) CopyMagickString(package_info->image_info->filename,list[i],
11159         MaxTextExtent);
11160       image=PingImage(package_info->image_info,exception);
11161       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11162         break;
11163       if ((package_info->image_info->file != (FILE *) NULL) ||
11164           (package_info->image_info->blob != (void *) NULL))
11165         DisassociateImageStream(image);
11166       count+=GetImageListLength(image);
11167       EXTEND(sp,4*count);
11168       for (next=image; next; next=next->next)
11169       {
11170         PUSHs(sv_2mortal(newSViv(next->columns)));
11171         PUSHs(sv_2mortal(newSViv(next->rows)));
11172         PUSHs(sv_2mortal(newSViv((unsigned long) GetBlobSize(next))));
11173         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11174       }
11175       image=DestroyImageList(image);
11176     }
11177     /*
11178       Free resources.
11179     */
11180     for (i=0; i < n; i++)
11181       if (list[i] != (char *) NULL)
11182         for (p=keep; list[i] != *p++; )
11183           if (*p == NULL)
11184             {
11185               list[i]=(char *) RelinquishMagickMemory(list[i]);
11186               break;
11187             }
11188
11189   PerlException:
11190     if (package_info != (struct PackageInfo *) NULL)
11191       DestroyPackageInfo(package_info);
11192     if (list && (list != keep))
11193       list=(char **) RelinquishMagickMemory(list);
11194     if (keep)
11195       keep=(char **) RelinquishMagickMemory(keep);
11196     if (length)
11197       length=(STRLEN *) RelinquishMagickMemory(length);
11198     InheritPerlException(exception,perl_exception);
11199     exception=DestroyExceptionInfo(exception);
11200     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11201   }
11202 \f
11203 #
11204 ###############################################################################
11205 #                                                                             #
11206 #                                                                             #
11207 #                                                                             #
11208 #   P r e v i e w                                                             #
11209 #                                                                             #
11210 #                                                                             #
11211 #                                                                             #
11212 ###############################################################################
11213 #
11214 #
11215 void
11216 Preview(ref,...)
11217   Image::Magick ref=NO_INIT
11218   ALIAS:
11219     PreviewImage = 1
11220     preview      = 2
11221     previewimage = 3
11222   PPCODE:
11223   {
11224     AV
11225       *av;
11226
11227     ExceptionInfo
11228       *exception;
11229
11230     HV
11231       *hv;
11232
11233     Image
11234       *image,
11235       *preview_image;
11236
11237     PreviewType
11238       preview_type;
11239
11240     struct PackageInfo
11241       *info;
11242
11243     SV
11244       *av_reference,
11245       *perl_exception,
11246       *reference,
11247       *rv,
11248       *sv;
11249
11250     exception=AcquireExceptionInfo();
11251     perl_exception=newSVpv("",0);
11252     av=NULL;
11253     if (sv_isobject(ST(0)) == 0)
11254       {
11255         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11256           PackageName);
11257         goto PerlException;
11258       }
11259     reference=SvRV(ST(0));
11260     hv=SvSTASH(reference);
11261     av=newAV();
11262     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11263     SvREFCNT_dec(av);
11264     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11265     if (image == (Image *) NULL)
11266       {
11267         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11268           PackageName);
11269         goto PerlException;
11270       }
11271     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11272     preview_type=GammaPreview;
11273     if (items > 1)
11274       preview_type=(PreviewType)
11275         ParseMagickOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11276     for ( ; image; image=image->next)
11277     {
11278       preview_image=PreviewImage(image,preview_type,exception);
11279       if (preview_image == (Image *) NULL)
11280         goto PerlException;
11281       AddImageToRegistry(preview_image);
11282       rv=newRV(sv);
11283       av_push(av,sv_bless(rv,hv));
11284       SvREFCNT_dec(sv);
11285     }
11286     exception=DestroyExceptionInfo(exception);
11287     ST(0)=av_reference;
11288     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11289     XSRETURN(1);
11290
11291   PerlException:
11292     InheritPerlException(exception,perl_exception);
11293     exception=DestroyExceptionInfo(exception);
11294     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11295     SvPOK_on(perl_exception);
11296     ST(0)=sv_2mortal(perl_exception);
11297     XSRETURN(1);
11298   }
11299 \f
11300 #
11301 ###############################################################################
11302 #                                                                             #
11303 #                                                                             #
11304 #                                                                             #
11305 #   Q u e r y C o l o r                                                       #
11306 #                                                                             #
11307 #                                                                             #
11308 #                                                                             #
11309 ###############################################################################
11310 #
11311 #
11312 void
11313 QueryColor(ref,...)
11314   Image::Magick ref=NO_INIT
11315   ALIAS:
11316     querycolor = 1
11317   PPCODE:
11318   {
11319     char
11320       *name;
11321
11322     ExceptionInfo
11323       *exception;
11324
11325     MagickPixelPacket
11326       color;
11327
11328     register long
11329       i;
11330
11331     SV
11332       *perl_exception;
11333
11334     exception=AcquireExceptionInfo();
11335     perl_exception=newSVpv("",0);
11336     if (items == 1)
11337       {
11338         const ColorInfo
11339           **colorlist;
11340
11341         unsigned long
11342           colors;
11343
11344         colorlist=GetColorInfoList("*",&colors,exception);
11345         EXTEND(sp,colors);
11346         for (i=0; i < (long) colors; i++)
11347         {
11348           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11349         }
11350         colorlist=(const ColorInfo **)
11351           RelinquishMagickMemory((ColorInfo **) colorlist);
11352         goto PerlException;
11353       }
11354     EXTEND(sp,5*items);
11355     for (i=1; i < items; i++)
11356     {
11357       name=(char *) SvPV(ST(i),na);
11358       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11359         {
11360           PUSHs(&sv_undef);
11361           continue;
11362         }
11363       PUSHs(sv_2mortal(newSViv((unsigned long) (color.red+0.5))));
11364       PUSHs(sv_2mortal(newSViv((unsigned long) (color.green+0.5))));
11365       PUSHs(sv_2mortal(newSViv((unsigned long) (color.blue+0.5))));
11366       if (color.matte != MagickFalse)
11367         PUSHs(sv_2mortal(newSViv((unsigned long) (color.opacity+0.5))));
11368       if (color.colorspace == CMYKColorspace)
11369         PUSHs(sv_2mortal(newSViv((unsigned long) (color.index+0.5))));
11370     }
11371
11372   PerlException:
11373     InheritPerlException(exception,perl_exception);
11374     exception=DestroyExceptionInfo(exception);
11375     SvREFCNT_dec(perl_exception);
11376   }
11377 \f
11378 #
11379 ###############################################################################
11380 #                                                                             #
11381 #                                                                             #
11382 #                                                                             #
11383 #   Q u e r y C o l o r N a m e                                               #
11384 #                                                                             #
11385 #                                                                             #
11386 #                                                                             #
11387 ###############################################################################
11388 #
11389 #
11390 void
11391 QueryColorname(ref,...)
11392   Image::Magick ref=NO_INIT
11393   ALIAS:
11394     querycolorname = 1
11395   PPCODE:
11396   {
11397     AV
11398       *av;
11399
11400     char
11401       message[MaxTextExtent];
11402
11403     ExceptionInfo
11404       *exception;
11405
11406     Image
11407       *image;
11408
11409     PixelPacket
11410       target_color;
11411
11412     register long
11413       i;
11414
11415     struct PackageInfo
11416       *info;
11417
11418     SV
11419       *perl_exception,
11420       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11421
11422     exception=AcquireExceptionInfo();
11423     perl_exception=newSVpv("",0);
11424     reference=SvRV(ST(0));
11425     av=(AV *) reference;
11426     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11427       exception);
11428     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11429     if (image == (Image *) NULL)
11430       {
11431         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11432           PackageName);
11433         goto PerlException;
11434       }
11435     EXTEND(sp,items);
11436     for (i=1; i < items; i++)
11437     {
11438       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11439       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11440         exception);
11441       PUSHs(sv_2mortal(newSVpv(message,0)));
11442     }
11443
11444   PerlException:
11445     InheritPerlException(exception,perl_exception);
11446     exception=DestroyExceptionInfo(exception);
11447     SvREFCNT_dec(perl_exception);
11448   }
11449 \f
11450 #
11451 ###############################################################################
11452 #                                                                             #
11453 #                                                                             #
11454 #                                                                             #
11455 #   Q u e r y F o n t                                                         #
11456 #                                                                             #
11457 #                                                                             #
11458 #                                                                             #
11459 ###############################################################################
11460 #
11461 #
11462 void
11463 QueryFont(ref,...)
11464   Image::Magick ref=NO_INIT
11465   ALIAS:
11466     queryfont = 1
11467   PPCODE:
11468   {
11469     char
11470       *name,
11471       message[MaxTextExtent];
11472
11473     ExceptionInfo
11474       *exception;
11475
11476     register long
11477       i;
11478
11479     SV
11480       *perl_exception;
11481
11482     volatile const TypeInfo
11483       *type_info;
11484
11485     exception=AcquireExceptionInfo();
11486     perl_exception=newSVpv("",0);
11487     if (items == 1)
11488       {
11489         const TypeInfo
11490           **typelist;
11491
11492         unsigned long
11493           types;
11494
11495         typelist=GetTypeInfoList("*",&types,exception);
11496         EXTEND(sp,types);
11497         for (i=0; i < (long) types; i++)
11498         {
11499           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11500         }
11501         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11502           typelist);
11503         goto PerlException;
11504       }
11505     EXTEND(sp,10*items);
11506     for (i=1; i < items; i++)
11507     {
11508       name=(char *) SvPV(ST(i),na);
11509       type_info=GetTypeInfo(name,exception);
11510       if (type_info == (TypeInfo *) NULL)
11511         {
11512           PUSHs(&sv_undef);
11513           continue;
11514         }
11515       if (type_info->name == (char *) NULL)
11516         PUSHs(&sv_undef);
11517       else
11518         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11519       if (type_info->description == (char *) NULL)
11520         PUSHs(&sv_undef);
11521       else
11522         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11523       if (type_info->family == (char *) NULL)
11524         PUSHs(&sv_undef);
11525       else
11526         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11527       if (type_info->style == UndefinedStyle)
11528         PUSHs(&sv_undef);
11529       else
11530         PUSHs(sv_2mortal(newSVpv(MagickOptionToMnemonic(MagickStyleOptions,
11531           type_info->style),0)));
11532       if (type_info->stretch == UndefinedStretch)
11533         PUSHs(&sv_undef);
11534       else
11535         PUSHs(sv_2mortal(newSVpv(MagickOptionToMnemonic(MagickStretchOptions,
11536           type_info->stretch),0)));
11537       (void) FormatMagickString(message,MaxTextExtent,"%lu",type_info->weight);
11538       PUSHs(sv_2mortal(newSVpv(message,0)));
11539       if (type_info->encoding == (char *) NULL)
11540         PUSHs(&sv_undef);
11541       else
11542         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11543       if (type_info->foundry == (char *) NULL)
11544         PUSHs(&sv_undef);
11545       else
11546         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11547       if (type_info->format == (char *) NULL)
11548         PUSHs(&sv_undef);
11549       else
11550         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11551       if (type_info->metrics == (char *) NULL)
11552         PUSHs(&sv_undef);
11553       else
11554         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11555       if (type_info->glyphs == (char *) NULL)
11556         PUSHs(&sv_undef);
11557       else
11558         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11559     }
11560
11561   PerlException:
11562     InheritPerlException(exception,perl_exception);
11563     exception=DestroyExceptionInfo(exception);
11564     SvREFCNT_dec(perl_exception);
11565   }
11566 \f
11567 #
11568 ###############################################################################
11569 #                                                                             #
11570 #                                                                             #
11571 #                                                                             #
11572 #   Q u e r y F o n t M e t r i c s                                           #
11573 #                                                                             #
11574 #                                                                             #
11575 #                                                                             #
11576 ###############################################################################
11577 #
11578 #
11579 void
11580 QueryFontMetrics(ref,...)
11581   Image::Magick ref=NO_INIT
11582   ALIAS:
11583     queryfontmetrics = 1
11584   PPCODE:
11585   {
11586     AffineMatrix
11587       affine,
11588       current;
11589
11590     AV
11591       *av;
11592
11593     char
11594       *attribute;
11595
11596     double
11597       x,
11598       y;
11599
11600     DrawInfo
11601       *draw_info;
11602
11603     ExceptionInfo
11604       *exception;
11605
11606     GeometryInfo
11607       geometry_info;
11608
11609     Image
11610       *image;
11611
11612     long
11613       type;
11614
11615     MagickBooleanType
11616       status;
11617
11618     MagickStatusType
11619       flags;
11620
11621     register long
11622       i;
11623
11624     struct PackageInfo
11625       *info,
11626       *package_info;
11627
11628     SV
11629       *perl_exception,
11630       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11631
11632     TypeMetric
11633       metrics;
11634
11635     exception=AcquireExceptionInfo();
11636     package_info=(struct PackageInfo *) NULL;
11637     perl_exception=newSVpv("",0);
11638     reference=SvRV(ST(0));
11639     av=(AV *) reference;
11640     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11641       exception);
11642     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11643     if (image == (Image *) NULL)
11644       {
11645         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11646           PackageName);
11647         goto PerlException;
11648       }
11649     package_info=ClonePackageInfo(info,exception);
11650     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
11651     CloneString(&draw_info->text,"");
11652     current=draw_info->affine;
11653     GetAffineMatrix(&affine);
11654     x=0.0;
11655     y=0.0;
11656     EXTEND(sp,7*items);
11657     for (i=2; i < items; i+=2)
11658     {
11659       attribute=(char *) SvPV(ST(i-1),na);
11660       switch (*attribute)
11661       {
11662         case 'A':
11663         case 'a':
11664         {
11665           if (LocaleCompare(attribute,"antialias") == 0)
11666             {
11667               type=ParseMagickOption(MagickBooleanOptions,MagickFalse,
11668                 SvPV(ST(i),na));
11669               if (type < 0)
11670                 {
11671                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11672                     SvPV(ST(i),na));
11673                   break;
11674                 }
11675               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
11676               break;
11677             }
11678           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11679             attribute);
11680           break;
11681         }
11682         case 'd':
11683         case 'D':
11684         {
11685           if (LocaleCompare(attribute,"density") == 0)
11686             {
11687               CloneString(&draw_info->density,SvPV(ST(i),na));
11688               break;
11689             }
11690           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11691             attribute);
11692           break;
11693         }
11694         case 'e':
11695         case 'E':
11696         {
11697           if (LocaleCompare(attribute,"encoding") == 0)
11698             {
11699               CloneString(&draw_info->encoding,SvPV(ST(i),na));
11700               break;
11701             }
11702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11703             attribute);
11704           break;
11705         }
11706         case 'f':
11707         case 'F':
11708         {
11709           if (LocaleCompare(attribute,"family") == 0)
11710             {
11711               CloneString(&draw_info->family,SvPV(ST(i),na));
11712               break;
11713             }
11714           if (LocaleCompare(attribute,"fill") == 0)
11715             {
11716               if (info)
11717                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
11718                   &image->exception);
11719               break;
11720             }
11721           if (LocaleCompare(attribute,"font") == 0)
11722             {
11723               CloneString(&draw_info->font,SvPV(ST(i),na));
11724               break;
11725             }
11726           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11727             attribute);
11728           break;
11729         }
11730         case 'g':
11731         case 'G':
11732         {
11733           if (LocaleCompare(attribute,"geometry") == 0)
11734             {
11735               CloneString(&draw_info->geometry,SvPV(ST(i),na));
11736               break;
11737             }
11738           if (LocaleCompare(attribute,"gravity") == 0)
11739             {
11740               draw_info->gravity=(GravityType) ParseMagickOption(
11741                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11742               break;
11743             }
11744           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11745             attribute);
11746           break;
11747         }
11748         case 'i':
11749         case 'I':
11750         {
11751           if (LocaleCompare(attribute,"interline-spacing") == 0)
11752             {
11753               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11754               draw_info->interline_spacing=geometry_info.rho;
11755               break;
11756             }
11757           if (LocaleCompare(attribute,"interword-spacing") == 0)
11758             {
11759               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11760               draw_info->interword_spacing=geometry_info.rho;
11761               break;
11762             }
11763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11764             attribute);
11765           break;
11766         }
11767         case 'k':
11768         case 'K':
11769         {
11770           if (LocaleCompare(attribute,"kerning") == 0)
11771             {
11772               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11773               draw_info->kerning=geometry_info.rho;
11774               break;
11775             }
11776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11777             attribute);
11778           break;
11779         }
11780         case 'p':
11781         case 'P':
11782         {
11783           if (LocaleCompare(attribute,"pointsize") == 0)
11784             {
11785               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11786               draw_info->pointsize=geometry_info.rho;
11787               break;
11788             }
11789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11790             attribute);
11791           break;
11792         }
11793         case 'r':
11794         case 'R':
11795         {
11796           if (LocaleCompare(attribute,"rotate") == 0)
11797             {
11798               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11799               affine.rx=geometry_info.rho;
11800               affine.ry=geometry_info.sigma;
11801               if ((flags & SigmaValue) == 0)
11802                 affine.ry=affine.rx;
11803               break;
11804             }
11805           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11806             attribute);
11807           break;
11808         }
11809         case 's':
11810         case 'S':
11811         {
11812           if (LocaleCompare(attribute,"scale") == 0)
11813             {
11814               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11815               affine.sx=geometry_info.rho;
11816               affine.sy=geometry_info.sigma;
11817               if ((flags & SigmaValue) == 0)
11818                 affine.sy=affine.sx;
11819               break;
11820             }
11821           if (LocaleCompare(attribute,"skew") == 0)
11822             {
11823               double
11824                 x_angle,
11825                 y_angle;
11826
11827               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11828               x_angle=geometry_info.rho;
11829               y_angle=geometry_info.sigma;
11830               if ((flags & SigmaValue) == 0)
11831                 y_angle=x_angle;
11832               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
11833               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
11834               break;
11835             }
11836           if (LocaleCompare(attribute,"stroke") == 0)
11837             {
11838               if (info)
11839                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
11840                   &image->exception);
11841               break;
11842             }
11843           if (LocaleCompare(attribute,"style") == 0)
11844             {
11845               type=ParseMagickOption(MagickStyleOptions,MagickFalse,
11846                 SvPV(ST(i),na));
11847               if (type < 0)
11848                 {
11849                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11850                     SvPV(ST(i),na));
11851                   break;
11852                 }
11853               draw_info->style=(StyleType) type;
11854               break;
11855             }
11856           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11857             attribute);
11858           break;
11859         }
11860         case 't':
11861         case 'T':
11862         {
11863           if (LocaleCompare(attribute,"text") == 0)
11864             {
11865               CloneString(&draw_info->text,SvPV(ST(i),na));
11866               break;
11867             }
11868           if (LocaleCompare(attribute,"translate") == 0)
11869             {
11870               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11871               affine.tx=geometry_info.rho;
11872               affine.ty=geometry_info.sigma;
11873               if ((flags & SigmaValue) == 0)
11874                 affine.ty=affine.tx;
11875               break;
11876             }
11877           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11878             attribute);
11879           break;
11880         }
11881         case 'w':
11882         case 'W':
11883         {
11884           if (LocaleCompare(attribute,"weight") == 0)
11885             {
11886               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11887               draw_info->weight=(unsigned long) geometry_info.rho;
11888               break;
11889             }
11890           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11891             attribute);
11892           break;
11893         }
11894         case 'x':
11895         case 'X':
11896         {
11897           if (LocaleCompare(attribute,"x") == 0)
11898             {
11899               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11900               x=geometry_info.rho;
11901               break;
11902             }
11903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11904             attribute);
11905           break;
11906         }
11907         case 'y':
11908         case 'Y':
11909         {
11910           if (LocaleCompare(attribute,"y") == 0)
11911             {
11912               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
11913               y=geometry_info.rho;
11914               break;
11915             }
11916           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11917             attribute);
11918           break;
11919         }
11920         default:
11921         {
11922           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11923             attribute);
11924           break;
11925         }
11926       }
11927     }
11928     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
11929     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
11930     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
11931     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
11932     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
11933     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
11934     if (draw_info->geometry == (char *) NULL)
11935       {
11936         draw_info->geometry=AcquireString((char *) NULL);
11937         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
11938           "%.15g,%.15g",x,y);
11939       }
11940     status=GetTypeMetrics(image,draw_info,&metrics);
11941     (void) CatchImageException(image);
11942     if (status == MagickFalse)
11943       PUSHs(&sv_undef);
11944     else
11945       {
11946         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
11947         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
11948         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
11949         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
11950         PUSHs(sv_2mortal(newSVnv(metrics.width)));
11951         PUSHs(sv_2mortal(newSVnv(metrics.height)));
11952         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
11953         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
11954         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
11955         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
11956         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
11957         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
11958         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
11959       }
11960     draw_info=DestroyDrawInfo(draw_info);
11961
11962   PerlException:
11963     if (package_info != (struct PackageInfo *) NULL)
11964       DestroyPackageInfo(package_info);
11965     InheritPerlException(exception,perl_exception);
11966     exception=DestroyExceptionInfo(exception);
11967     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11968   }
11969 \f
11970 #
11971 ###############################################################################
11972 #                                                                             #
11973 #                                                                             #
11974 #                                                                             #
11975 #   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                         #
11976 #                                                                             #
11977 #                                                                             #
11978 #                                                                             #
11979 ###############################################################################
11980 #
11981 #
11982 void
11983 QueryMultilineFontMetrics(ref,...)
11984   Image::Magick ref=NO_INIT
11985   ALIAS:
11986     querymultilinefontmetrics = 1
11987   PPCODE:
11988   {
11989     AffineMatrix
11990       affine,
11991       current;
11992
11993     AV
11994       *av;
11995
11996     char
11997       *attribute;
11998
11999     double
12000       x,
12001       y;
12002
12003     DrawInfo
12004       *draw_info;
12005
12006     ExceptionInfo
12007       *exception;
12008
12009     GeometryInfo
12010       geometry_info;
12011
12012     Image
12013       *image;
12014
12015     long
12016       type;
12017
12018     MagickBooleanType
12019       status;
12020
12021     MagickStatusType
12022       flags;
12023
12024     register long
12025       i;
12026
12027     struct PackageInfo
12028       *info,
12029       *package_info;
12030
12031     SV
12032       *perl_exception,
12033       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12034
12035     TypeMetric
12036       metrics;
12037
12038     exception=AcquireExceptionInfo();
12039     package_info=(struct PackageInfo *) NULL;
12040     perl_exception=newSVpv("",0);
12041     reference=SvRV(ST(0));
12042     av=(AV *) reference;
12043     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12044       exception);
12045     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12046     if (image == (Image *) NULL)
12047       {
12048         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12049           PackageName);
12050         goto PerlException;
12051       }
12052     package_info=ClonePackageInfo(info,exception);
12053     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12054     CloneString(&draw_info->text,"");
12055     current=draw_info->affine;
12056     GetAffineMatrix(&affine);
12057     x=0.0;
12058     y=0.0;
12059     EXTEND(sp,7*items);
12060     for (i=2; i < items; i+=2)
12061     {
12062       attribute=(char *) SvPV(ST(i-1),na);
12063       switch (*attribute)
12064       {
12065         case 'A':
12066         case 'a':
12067         {
12068           if (LocaleCompare(attribute,"antialias") == 0)
12069             {
12070               type=ParseMagickOption(MagickBooleanOptions,MagickFalse,
12071                 SvPV(ST(i),na));
12072               if (type < 0)
12073                 {
12074                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12075                     SvPV(ST(i),na));
12076                   break;
12077                 }
12078               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12079               break;
12080             }
12081           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12082             attribute);
12083           break;
12084         }
12085         case 'd':
12086         case 'D':
12087         {
12088           if (LocaleCompare(attribute,"density") == 0)
12089             {
12090               CloneString(&draw_info->density,SvPV(ST(i),na));
12091               break;
12092             }
12093           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12094             attribute);
12095           break;
12096         }
12097         case 'e':
12098         case 'E':
12099         {
12100           if (LocaleCompare(attribute,"encoding") == 0)
12101             {
12102               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12103               break;
12104             }
12105           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12106             attribute);
12107           break;
12108         }
12109         case 'f':
12110         case 'F':
12111         {
12112           if (LocaleCompare(attribute,"family") == 0)
12113             {
12114               CloneString(&draw_info->family,SvPV(ST(i),na));
12115               break;
12116             }
12117           if (LocaleCompare(attribute,"fill") == 0)
12118             {
12119               if (info)
12120                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12121                   &image->exception);
12122               break;
12123             }
12124           if (LocaleCompare(attribute,"font") == 0)
12125             {
12126               CloneString(&draw_info->font,SvPV(ST(i),na));
12127               break;
12128             }
12129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12130             attribute);
12131           break;
12132         }
12133         case 'g':
12134         case 'G':
12135         {
12136           if (LocaleCompare(attribute,"geometry") == 0)
12137             {
12138               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12139               break;
12140             }
12141           if (LocaleCompare(attribute,"gravity") == 0)
12142             {
12143               draw_info->gravity=(GravityType) ParseMagickOption(
12144                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12145               break;
12146             }
12147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12148             attribute);
12149           break;
12150         }
12151         case 'p':
12152         case 'P':
12153         {
12154           if (LocaleCompare(attribute,"pointsize") == 0)
12155             {
12156               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12157               draw_info->pointsize=geometry_info.rho;
12158               break;
12159             }
12160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12161             attribute);
12162           break;
12163         }
12164         case 'r':
12165         case 'R':
12166         {
12167           if (LocaleCompare(attribute,"rotate") == 0)
12168             {
12169               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12170               affine.rx=geometry_info.rho;
12171               affine.ry=geometry_info.sigma;
12172               if ((flags & SigmaValue) == 0)
12173                 affine.ry=affine.rx;
12174               break;
12175             }
12176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12177             attribute);
12178           break;
12179         }
12180         case 's':
12181         case 'S':
12182         {
12183           if (LocaleCompare(attribute,"scale") == 0)
12184             {
12185               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12186               affine.sx=geometry_info.rho;
12187               affine.sy=geometry_info.sigma;
12188               if ((flags & SigmaValue) == 0)
12189                 affine.sy=affine.sx;
12190               break;
12191             }
12192           if (LocaleCompare(attribute,"skew") == 0)
12193             {
12194               double
12195                 x_angle,
12196                 y_angle;
12197
12198               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12199               x_angle=geometry_info.rho;
12200               y_angle=geometry_info.sigma;
12201               if ((flags & SigmaValue) == 0)
12202                 y_angle=x_angle;
12203               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12204               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12205               break;
12206             }
12207           if (LocaleCompare(attribute,"stroke") == 0)
12208             {
12209               if (info)
12210                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12211                   &image->exception);
12212               break;
12213             }
12214           if (LocaleCompare(attribute,"style") == 0)
12215             {
12216               type=ParseMagickOption(MagickStyleOptions,MagickFalse,
12217                 SvPV(ST(i),na));
12218               if (type < 0)
12219                 {
12220                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12221                     SvPV(ST(i),na));
12222                   break;
12223                 }
12224               draw_info->style=(StyleType) type;
12225               break;
12226             }
12227           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12228             attribute);
12229           break;
12230         }
12231         case 't':
12232         case 'T':
12233         {
12234           if (LocaleCompare(attribute,"text") == 0)
12235             {
12236               CloneString(&draw_info->text,SvPV(ST(i),na));
12237               break;
12238             }
12239           if (LocaleCompare(attribute,"translate") == 0)
12240             {
12241               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12242               affine.tx=geometry_info.rho;
12243               affine.ty=geometry_info.sigma;
12244               if ((flags & SigmaValue) == 0)
12245                 affine.ty=affine.tx;
12246               break;
12247             }
12248           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12249             attribute);
12250           break;
12251         }
12252         case 'w':
12253         case 'W':
12254         {
12255           if (LocaleCompare(attribute,"weight") == 0)
12256             {
12257               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12258               draw_info->weight=(unsigned long) geometry_info.rho;
12259               break;
12260             }
12261           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12262             attribute);
12263           break;
12264         }
12265         case 'x':
12266         case 'X':
12267         {
12268           if (LocaleCompare(attribute,"x") == 0)
12269             {
12270               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12271               x=geometry_info.rho;
12272               break;
12273             }
12274           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12275             attribute);
12276           break;
12277         }
12278         case 'y':
12279         case 'Y':
12280         {
12281           if (LocaleCompare(attribute,"y") == 0)
12282             {
12283               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12284               y=geometry_info.rho;
12285               break;
12286             }
12287           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12288             attribute);
12289           break;
12290         }
12291         default:
12292         {
12293           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12294             attribute);
12295           break;
12296         }
12297       }
12298     }
12299     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12300     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12301     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12302     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12303     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12304     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12305     if (draw_info->geometry == (char *) NULL)
12306       {
12307         draw_info->geometry=AcquireString((char *) NULL);
12308         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
12309           "%.15g,%.15g",x,y);
12310       }
12311     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12312     (void) CatchImageException(image);
12313     if (status == MagickFalse)
12314       PUSHs(&sv_undef);
12315     else
12316       {
12317         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12318         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12319         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12320         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12321         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12322         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12323         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12324         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12325         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12326         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12327         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12328         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12329         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12330       }
12331     draw_info=DestroyDrawInfo(draw_info);
12332
12333   PerlException:
12334     if (package_info != (struct PackageInfo *) NULL)
12335       DestroyPackageInfo(package_info);
12336     InheritPerlException(exception,perl_exception);
12337     exception=DestroyExceptionInfo(exception);
12338     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12339   }
12340 \f
12341 #
12342 ###############################################################################
12343 #                                                                             #
12344 #                                                                             #
12345 #                                                                             #
12346 #   Q u e r y F o r m a t                                                     #
12347 #                                                                             #
12348 #                                                                             #
12349 #                                                                             #
12350 ###############################################################################
12351 #
12352 #
12353 void
12354 QueryFormat(ref,...)
12355   Image::Magick ref=NO_INIT
12356   ALIAS:
12357     queryformat = 1
12358   PPCODE:
12359   {
12360     char
12361       *name;
12362
12363     ExceptionInfo
12364       *exception;
12365
12366     register long
12367       i;
12368
12369     SV
12370       *perl_exception;
12371
12372     volatile const MagickInfo
12373       *magick_info;
12374
12375     exception=AcquireExceptionInfo();
12376     perl_exception=newSVpv("",0);
12377     if (items == 1)
12378       {
12379         char
12380           format[MaxTextExtent];
12381
12382         const MagickInfo
12383           **format_list;
12384
12385         unsigned long
12386           types;
12387
12388         format_list=GetMagickInfoList("*",&types,exception);
12389         EXTEND(sp,types);
12390         for (i=0; i < (long) types; i++)
12391         {
12392           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12393           LocaleLower(format);
12394           PUSHs(sv_2mortal(newSVpv(format,0)));
12395         }
12396         format_list=(const MagickInfo **)
12397           RelinquishMagickMemory((MagickInfo *) format_list);
12398         goto PerlException;
12399       }
12400     EXTEND(sp,8*items);
12401     for (i=1; i < items; i++)
12402     {
12403       name=(char *) SvPV(ST(i),na);
12404       magick_info=GetMagickInfo(name,exception);
12405       if (magick_info == (const MagickInfo *) NULL)
12406         {
12407           PUSHs(&sv_undef);
12408           continue;
12409         }
12410       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12411       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12412       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12413       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12414       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12415       if (magick_info->description == (char *) NULL)
12416         PUSHs(&sv_undef);
12417       else
12418         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12419       if (magick_info->module == (char *) NULL)
12420         PUSHs(&sv_undef);
12421       else
12422         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12423     }
12424
12425   PerlException:
12426     InheritPerlException(exception,perl_exception);
12427     exception=DestroyExceptionInfo(exception);
12428     SvREFCNT_dec(perl_exception);
12429   }
12430 \f
12431 #
12432 ###############################################################################
12433 #                                                                             #
12434 #                                                                             #
12435 #                                                                             #
12436 #   Q u e r y O p t i o n                                                     #
12437 #                                                                             #
12438 #                                                                             #
12439 #                                                                             #
12440 ###############################################################################
12441 #
12442 #
12443 void
12444 QueryOption(ref,...)
12445   Image::Magick ref=NO_INIT
12446   ALIAS:
12447     queryoption = 1
12448   PPCODE:
12449   {
12450     char
12451       **options;
12452
12453     ExceptionInfo
12454       *exception;
12455
12456     long
12457       j,
12458       option;
12459
12460     register long
12461       i;
12462
12463     SV
12464       *perl_exception;
12465
12466     exception=AcquireExceptionInfo();
12467     perl_exception=newSVpv("",0);
12468     EXTEND(sp,8*items);
12469     for (i=1; i < items; i++)
12470     {
12471       option=ParseMagickOption(MagickListOptions,MagickFalse,(char *)
12472         SvPV(ST(i),na));
12473       options=GetMagickOptions((MagickOption) option);
12474       if (options == (char **) NULL)
12475         PUSHs(&sv_undef);
12476       else
12477         {
12478           for (j=0; options[j] != (char *) NULL; j++)
12479             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12480           options=DestroyStringList(options);
12481         }
12482     }
12483
12484   PerlException:
12485     InheritPerlException(exception,perl_exception);
12486     exception=DestroyExceptionInfo(exception);
12487     SvREFCNT_dec(perl_exception);
12488   }
12489 \f
12490 #
12491 ###############################################################################
12492 #                                                                             #
12493 #                                                                             #
12494 #                                                                             #
12495 #   R e a d                                                                   #
12496 #                                                                             #
12497 #                                                                             #
12498 #                                                                             #
12499 ###############################################################################
12500 #
12501 #
12502 void
12503 Read(ref,...)
12504   Image::Magick ref=NO_INIT
12505   ALIAS:
12506     ReadImage  = 1
12507     read       = 2
12508     readimage  = 3
12509   PPCODE:
12510   {
12511     AV
12512       *av;
12513
12514     char
12515       **keep,
12516       **list;
12517
12518     ExceptionInfo
12519       *exception;
12520
12521     HV
12522       *hv;
12523
12524     Image
12525       *image;
12526
12527     int
12528       n;
12529
12530     long
12531       ac,
12532       number_images;
12533
12534     MagickBooleanType
12535       status;
12536
12537     register char
12538       **p;
12539
12540     register long
12541       i;
12542
12543     STRLEN
12544       *length;
12545
12546     struct PackageInfo
12547       *info,
12548       *package_info;
12549
12550     SV
12551       *perl_exception,  /* Perl variable for storing messages */
12552       *reference,
12553       *rv,
12554       *sv;
12555
12556     exception=AcquireExceptionInfo();
12557     perl_exception=newSVpv("",0);
12558     package_info=(struct PackageInfo *) NULL;
12559     number_images=0;
12560     ac=(items < 2) ? 1 : items-1;
12561     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12562     keep=list;
12563     length=(STRLEN *) NULL;
12564     if (list == (char **) NULL)
12565       {
12566         ThrowPerlException(exception,ResourceLimitError,
12567           "MemoryAllocationFailed",PackageName);
12568         goto PerlException;
12569       }
12570     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12571     if (length == (STRLEN *) NULL)
12572       {
12573         ThrowPerlException(exception,ResourceLimitError,
12574           "MemoryAllocationFailed",PackageName);
12575         goto PerlException;
12576       }
12577     if (sv_isobject(ST(0)) == 0)
12578       {
12579         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12580           PackageName);
12581         goto PerlException;
12582       }
12583     reference=SvRV(ST(0));
12584     hv=SvSTASH(reference);
12585     if (SvTYPE(reference) != SVt_PVAV)
12586       {
12587         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12588           PackageName);
12589         goto PerlException;
12590       }
12591     av=(AV *) reference;
12592     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12593       exception);
12594     package_info=ClonePackageInfo(info,exception);
12595     n=1;
12596     if (items <= 1)
12597       *list=(char *) (*package_info->image_info->filename ?
12598         package_info->image_info->filename : "XC:black");
12599     else
12600       for (n=0, i=0; i < ac; i++)
12601       {
12602         list[n]=(char *) SvPV(ST(i+1),length[n]);
12603         if ((items >= 3) && strEQcase(list[n],"blob"))
12604           {
12605             void
12606               *blob;
12607
12608             i++;
12609             blob=(void *) (SvPV(ST(i+1),length[n]));
12610             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12611           }
12612         if ((items >= 3) && strEQcase(list[n],"filename"))
12613           continue;
12614         if ((items >= 3) && strEQcase(list[n],"file"))
12615           {
12616             FILE
12617               *file;
12618
12619             PerlIO
12620               *io_info;
12621
12622             i++;
12623             io_info=IoIFP(sv_2io(ST(i+1)));
12624             if (io_info == (PerlIO *) NULL)
12625               {
12626                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12627                   PackageName);
12628                 continue;
12629               }
12630             file=PerlIO_findFILE(io_info);
12631             if (file == (FILE *) NULL)
12632               {
12633                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12634                   PackageName);
12635                 continue;
12636               }
12637             SetImageInfoFile(package_info->image_info,file);
12638           }
12639         if ((items >= 3) && strEQcase(list[n],"magick"))
12640           continue;
12641         n++;
12642       }
12643     list[n]=(char *) NULL;
12644     keep=list;
12645     status=ExpandFilenames(&n,&list);
12646     if (status == MagickFalse)
12647       {
12648         ThrowPerlException(exception,ResourceLimitError,
12649           "MemoryAllocationFailed",PackageName);
12650         goto PerlException;
12651       }
12652     number_images=0;
12653     for (i=0; i < n; i++)
12654     {
12655       if ((package_info->image_info->file != (FILE *) NULL) ||
12656           (package_info->image_info->blob != (void *) NULL))
12657         {
12658           image=ReadImages(package_info->image_info,exception);
12659           if (image != (Image *) NULL)
12660             DisassociateImageStream(image);
12661         }
12662       else
12663         {
12664           (void) CopyMagickString(package_info->image_info->filename,list[i],
12665             MaxTextExtent);
12666           image=ReadImages(package_info->image_info,exception);
12667         }
12668       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
12669         break;
12670       for ( ; image; image=image->next)
12671       {
12672         AddImageToRegistry(image);
12673         rv=newRV(sv);
12674         av_push(av,sv_bless(rv,hv));
12675         SvREFCNT_dec(sv);
12676         number_images++;
12677       }
12678     }
12679     /*
12680       Free resources.
12681     */
12682     for (i=0; i < n; i++)
12683       if (list[i] != (char *) NULL)
12684         for (p=keep; list[i] != *p++; )
12685           if (*p == (char *) NULL)
12686             {
12687               list[i]=(char *) RelinquishMagickMemory(list[i]);
12688               break;
12689             }
12690
12691   PerlException:
12692     if (package_info != (struct PackageInfo *) NULL)
12693       DestroyPackageInfo(package_info);
12694     if (list && (list != keep))
12695       list=(char **) RelinquishMagickMemory(list);
12696     if (keep)
12697       keep=(char **) RelinquishMagickMemory(keep);
12698     if (length)
12699       length=(STRLEN *) RelinquishMagickMemory(length);
12700     InheritPerlException(exception,perl_exception);
12701     exception=DestroyExceptionInfo(exception);
12702     sv_setiv(perl_exception,(IV) number_images);
12703     SvPOK_on(perl_exception);
12704     ST(0)=sv_2mortal(perl_exception);
12705     XSRETURN(1);
12706   }
12707 \f
12708 #
12709 ###############################################################################
12710 #                                                                             #
12711 #                                                                             #
12712 #                                                                             #
12713 #   R e m o t e                                                               #
12714 #                                                                             #
12715 #                                                                             #
12716 #                                                                             #
12717 ###############################################################################
12718 #
12719 #
12720 void
12721 Remote(ref,...)
12722   Image::Magick ref=NO_INIT
12723   ALIAS:
12724     RemoteCommand  = 1
12725     remote         = 2
12726     remoteCommand  = 3
12727   PPCODE:
12728   {
12729     AV
12730       *av;
12731
12732     ExceptionInfo
12733       *exception;
12734
12735     register long
12736       i;
12737
12738     SV
12739       *perl_exception,
12740       *reference;
12741
12742     struct PackageInfo
12743       *info;
12744
12745     exception=AcquireExceptionInfo();
12746     perl_exception=newSVpv("",0);
12747     reference=SvRV(ST(0));
12748     av=(AV *) reference;
12749     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12750       exception);
12751     for (i=1; i < items; i++)
12752       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
12753         SvPV(ST(i),na),exception);
12754     InheritPerlException(exception,perl_exception);
12755     exception=DestroyExceptionInfo(exception);
12756     SvREFCNT_dec(perl_exception);    /* throw away all errors */
12757   }
12758 \f
12759 #
12760 ###############################################################################
12761 #                                                                             #
12762 #                                                                             #
12763 #                                                                             #
12764 #   S e t                                                                     #
12765 #                                                                             #
12766 #                                                                             #
12767 #                                                                             #
12768 ###############################################################################
12769 #
12770 #
12771 void
12772 Set(ref,...)
12773   Image::Magick ref=NO_INIT
12774   ALIAS:
12775     SetAttributes  = 1
12776     SetAttribute   = 2
12777     set            = 3
12778     setattributes  = 4
12779     setattribute   = 5
12780   PPCODE:
12781   {
12782     ExceptionInfo
12783       *exception;
12784
12785     Image
12786       *image;
12787
12788     register long
12789       i;
12790
12791     struct PackageInfo
12792       *info;
12793
12794     SV
12795       *perl_exception,
12796       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12797
12798     exception=AcquireExceptionInfo();
12799     perl_exception=newSVpv("",0);
12800     if (sv_isobject(ST(0)) == 0)
12801       {
12802         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12803           PackageName);
12804         goto PerlException;
12805       }
12806     reference=SvRV(ST(0));
12807     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12808     if (items == 2)
12809       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
12810     else
12811       for (i=2; i < items; i+=2)
12812         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
12813
12814   PerlException:
12815     InheritPerlException(exception,perl_exception);
12816     exception=DestroyExceptionInfo(exception);
12817     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
12818     SvPOK_on(perl_exception);
12819     ST(0)=sv_2mortal(perl_exception);
12820     XSRETURN(1);
12821   }
12822 \f
12823 #
12824 ###############################################################################
12825 #                                                                             #
12826 #                                                                             #
12827 #                                                                             #
12828 #   S e t P i x e l                                                           #
12829 #                                                                             #
12830 #                                                                             #
12831 #                                                                             #
12832 ###############################################################################
12833 #
12834 #
12835 void
12836 SetPixel(ref,...)
12837   Image::Magick ref=NO_INIT
12838   ALIAS:
12839     setpixel = 1
12840     setPixel = 2
12841   PPCODE:
12842   {
12843     AV
12844       *av;
12845
12846     char
12847       *attribute;
12848
12849     ChannelType
12850       channel;
12851
12852     ExceptionInfo
12853       *exception;
12854
12855     Image
12856       *image;
12857
12858     long
12859       option;
12860
12861     MagickBooleanType
12862       normalize;
12863
12864     RectangleInfo
12865       region;
12866
12867     register IndexPacket
12868       *indexes;
12869
12870     register long
12871       i;
12872
12873     register PixelPacket
12874       *q;
12875
12876     struct PackageInfo
12877       *info;
12878
12879     SV
12880       *perl_exception,
12881       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12882
12883     exception=AcquireExceptionInfo();
12884     perl_exception=newSVpv("",0);
12885     reference=SvRV(ST(0));
12886     av=(AV *) reference;
12887     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12888       exception);
12889     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12890     if (image == (Image *) NULL)
12891       {
12892         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12893           PackageName);
12894         goto PerlException;
12895       }
12896     av=(AV *) NULL;
12897     channel=DefaultChannels;
12898     normalize=MagickTrue;
12899     region.x=0;
12900     region.y=0;
12901     region.width=image->columns;
12902     region.height=1;
12903     if (items == 1)
12904       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
12905     for (i=2; i < items; i+=2)
12906     {
12907       attribute=(char *) SvPV(ST(i-1),na);
12908       switch (*attribute)
12909       {
12910         case 'C':
12911         case 'c':
12912         {
12913           if (LocaleCompare(attribute,"channel") == 0)
12914             {
12915               long
12916                 option;
12917
12918               option=ParseChannelOption(SvPV(ST(i),na));
12919               if (option < 0)
12920                 {
12921                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12922                     SvPV(ST(i),na));
12923                   return;
12924                 }
12925                channel=(ChannelType) option;
12926               break;
12927             }
12928           if (LocaleCompare(attribute,"color") == 0)
12929             {
12930               if (SvTYPE(ST(i)) != SVt_RV)
12931                 {
12932                   char
12933                     message[MaxTextExtent];
12934
12935                   (void) FormatMagickString(message,MaxTextExtent,
12936                     "invalid %.60s value",attribute);
12937                   ThrowPerlException(exception,OptionError,message,
12938                     SvPV(ST(i),na));
12939                 }
12940               av=(AV *) SvRV(ST(i));
12941               break;
12942             }
12943           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12944             attribute);
12945           break;
12946         }
12947         case 'g':
12948         case 'G':
12949         {
12950           if (LocaleCompare(attribute,"geometry") == 0)
12951             {
12952               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
12953               break;
12954             }
12955           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12956             attribute);
12957           break;
12958         }
12959         case 'N':
12960         case 'n':
12961         {
12962           if (LocaleCompare(attribute,"normalize") == 0)
12963             {
12964               option=ParseMagickOption(MagickBooleanOptions,MagickFalse,
12965                 SvPV(ST(i),na));
12966               if (option < 0)
12967                 {
12968                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12969                     SvPV(ST(i),na));
12970                   break;
12971                 }
12972              normalize=option != 0 ? MagickTrue : MagickFalse;
12973              break;
12974             }
12975           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12976             attribute);
12977           break;
12978         }
12979         case 'x':
12980         case 'X':
12981         {
12982           if (LocaleCompare(attribute,"x") == 0)
12983             {
12984               region.x=SvIV(ST(i));
12985               break;
12986             }
12987           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12988             attribute);
12989           break;
12990         }
12991         case 'y':
12992         case 'Y':
12993         {
12994           if (LocaleCompare(attribute,"y") == 0)
12995             {
12996               region.y=SvIV(ST(i));
12997               break;
12998             }
12999           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13000             attribute);
13001           break;
13002         }
13003         default:
13004         {
13005           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13006             attribute);
13007           break;
13008         }
13009       }
13010     }
13011     (void) SetImageStorageClass(image,DirectClass);
13012     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13013     if ((q == (PixelPacket *) NULL) || (av == (AV *) NULL))
13014       PUSHs(&sv_undef);
13015     else
13016       {
13017         double
13018           scale;
13019
13020         register long
13021           i;
13022
13023         i=0;
13024         indexes=GetAuthenticIndexQueue(image);
13025         scale=1.0;
13026         if (normalize != MagickFalse)
13027           scale=QuantumRange;
13028         if (((channel & RedChannel) != 0) && (i <= av_len(av)))
13029           {
13030             q->red=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13031             i++;
13032           }
13033         if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
13034           {
13035             q->green=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13036             i++;
13037           }
13038         if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
13039           {
13040             q->blue=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13041             i++;
13042           }
13043         if ((((channel & IndexChannel) != 0) &&
13044             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13045           {
13046             *indexes=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13047             i++;
13048           }
13049         if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
13050           {
13051             q->opacity=ClampToQuantum(QuantumRange*SvNV(*(av_fetch(av,i,0))));
13052             i++;
13053           }
13054         (void) SyncAuthenticPixels(image,exception);
13055       }
13056
13057   PerlException:
13058     InheritPerlException(exception,perl_exception);
13059     exception=DestroyExceptionInfo(exception);
13060     SvREFCNT_dec(perl_exception);
13061   }
13062 \f
13063 #
13064 ###############################################################################
13065 #                                                                             #
13066 #                                                                             #
13067 #                                                                             #
13068 #   S t a t i s t i c s                                                       #
13069 #                                                                             #
13070 #                                                                             #
13071 #                                                                             #
13072 ###############################################################################
13073 #
13074 #
13075 void
13076 Statistics(ref,...)
13077   Image::Magick ref=NO_INIT
13078   ALIAS:
13079     StatisticsImage = 1
13080     statistics      = 2
13081     statisticsimage = 3
13082   PPCODE:
13083   {
13084 #define ChannelStatistics(channel) \
13085 { \
13086   (void) FormatMagickString(message,MaxTextExtent,"%lu", \
13087     channel_statistics[channel].depth); \
13088   PUSHs(sv_2mortal(newSVpv(message,0))); \
13089   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13090     channel_statistics[channel].minima/scale); \
13091   PUSHs(sv_2mortal(newSVpv(message,0))); \
13092   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13093     channel_statistics[channel].maxima/scale); \
13094   PUSHs(sv_2mortal(newSVpv(message,0))); \
13095   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13096     channel_statistics[channel].mean/scale); \
13097   PUSHs(sv_2mortal(newSVpv(message,0))); \
13098   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13099     channel_statistics[channel].standard_deviation/scale); \
13100   PUSHs(sv_2mortal(newSVpv(message,0))); \
13101   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13102     channel_statistics[channel].kurtosis); \
13103   PUSHs(sv_2mortal(newSVpv(message,0))); \
13104   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13105     channel_statistics[channel].skewness); \
13106   PUSHs(sv_2mortal(newSVpv(message,0))); \
13107 }
13108
13109     AV
13110       *av;
13111
13112     char
13113       message[MaxTextExtent];
13114
13115     ChannelStatistics
13116       *channel_statistics;
13117
13118     double
13119       scale;
13120
13121     ExceptionInfo
13122       *exception;
13123
13124     HV
13125       *hv;
13126
13127     Image
13128       *image;
13129
13130     ssize_t
13131       count;
13132
13133     struct PackageInfo
13134       *info;
13135
13136     SV
13137       *av_reference,
13138       *perl_exception,
13139       *reference;
13140
13141     exception=AcquireExceptionInfo();
13142     perl_exception=newSVpv("",0);
13143     av=NULL;
13144     if (sv_isobject(ST(0)) == 0)
13145       {
13146         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13147           PackageName);
13148         goto PerlException;
13149       }
13150     reference=SvRV(ST(0));
13151     hv=SvSTASH(reference);
13152     av=newAV();
13153     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13154     SvREFCNT_dec(av);
13155     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13156     if (image == (Image *) NULL)
13157       {
13158         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13159           PackageName);
13160         goto PerlException;
13161       }
13162     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13163     count=0;
13164     for ( ; image; image=image->next)
13165     {
13166       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13167       if (channel_statistics == (ChannelStatistics *) NULL)
13168         continue;
13169       count++;
13170       EXTEND(sp,35*count);
13171       scale=(double) QuantumRange;
13172       ChannelStatistics(RedChannel);
13173       ChannelStatistics(GreenChannel);
13174       ChannelStatistics(BlueChannel);
13175       if (image->colorspace == CMYKColorspace)
13176         ChannelStatistics(IndexChannel);
13177       if (image->matte != MagickFalse)
13178         ChannelStatistics(OpacityChannel);
13179       channel_statistics=(ChannelStatistics *)
13180         RelinquishMagickMemory(channel_statistics);
13181     }
13182
13183   PerlException:
13184     InheritPerlException(exception,perl_exception);
13185     exception=DestroyExceptionInfo(exception);
13186     SvREFCNT_dec(perl_exception);
13187   }
13188 \f
13189 #
13190 ###############################################################################
13191 #                                                                             #
13192 #                                                                             #
13193 #                                                                             #
13194 #   S y n c A u t h e n t i c P i x e l s                                     #
13195 #                                                                             #
13196 #                                                                             #
13197 #                                                                             #
13198 ###############################################################################
13199 #
13200 #
13201 void
13202 SyncAuthenticPixels(ref,...)
13203   Image::Magick ref = NO_INIT
13204   ALIAS:
13205     Syncauthenticpixels = 1
13206     SyncImagePixels = 2
13207     syncimagepixels = 3
13208   CODE:
13209   {
13210     ExceptionInfo
13211       *exception;
13212
13213     Image
13214       *image;
13215
13216     MagickBooleanType
13217       status;
13218
13219     struct PackageInfo
13220       *info;
13221
13222     SV
13223       *perl_exception,
13224       *reference;
13225
13226     exception=AcquireExceptionInfo();
13227     perl_exception=newSVpv("",0);
13228
13229     if (sv_isobject(ST(0)) == 0)
13230       {
13231         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13232           PackageName);
13233         goto PerlException;
13234       }
13235
13236     reference=SvRV(ST(0));
13237     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13238     if (image == (Image *) NULL)
13239       {
13240         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13241           PackageName);
13242         goto PerlException;
13243       }
13244
13245     status=SyncAuthenticPixels(image,exception);
13246     if (status != MagickFalse)
13247       return;
13248     InheritException(exception,&image->exception);
13249
13250   PerlException:
13251     InheritPerlException(exception,perl_exception);
13252     exception=DestroyExceptionInfo(exception);
13253     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13254   }
13255 \f
13256 #
13257 ###############################################################################
13258 #                                                                             #
13259 #                                                                             #
13260 #                                                                             #
13261 #   T r a n s f o r m                                                         #
13262 #                                                                             #
13263 #                                                                             #
13264 #                                                                             #
13265 ###############################################################################
13266 #
13267 #
13268 void
13269 Transform(ref,...)
13270   Image::Magick ref=NO_INIT
13271   ALIAS:
13272     TransformImage = 1
13273     transform      = 2
13274     transformimage = 3
13275   PPCODE:
13276   {
13277     AV
13278       *av;
13279
13280     char
13281       *attribute,
13282       *crop_geometry,
13283       *geometry;
13284
13285     ExceptionInfo
13286       *exception;
13287
13288     HV
13289       *hv;
13290
13291     Image
13292       *clone,
13293       *image;
13294
13295     register long
13296       i;
13297
13298     struct PackageInfo
13299       *info;
13300
13301     SV
13302       *av_reference,
13303       *perl_exception,
13304       *reference,
13305       *rv,
13306       *sv;
13307
13308     exception=AcquireExceptionInfo();
13309     perl_exception=newSVpv("",0);
13310     av=NULL;
13311     attribute=NULL;
13312     if (sv_isobject(ST(0)) == 0)
13313       {
13314         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13315           PackageName);
13316         goto PerlException;
13317       }
13318     reference=SvRV(ST(0));
13319     hv=SvSTASH(reference);
13320     av=newAV();
13321     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13322     SvREFCNT_dec(av);
13323     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13324     if (image == (Image *) NULL)
13325       {
13326         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13327           PackageName);
13328         goto PerlException;
13329       }
13330     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13331     /*
13332       Get attribute.
13333     */
13334     crop_geometry=(char *) NULL;
13335     geometry=(char *) NULL;
13336     for (i=2; i < items; i+=2)
13337     {
13338       attribute=(char *) SvPV(ST(i-1),na);
13339       switch (*attribute)
13340       {
13341         case 'c':
13342         case 'C':
13343         {
13344           if (LocaleCompare(attribute,"crop") == 0)
13345             {
13346               crop_geometry=SvPV(ST(i),na);
13347               break;
13348             }
13349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13350             attribute);
13351           break;
13352         }
13353         case 'g':
13354         case 'G':
13355         {
13356           if (LocaleCompare(attribute,"geometry") == 0)
13357             {
13358               geometry=SvPV(ST(i),na);
13359               break;
13360             }
13361          if (LocaleCompare(attribute,"gravity") == 0)
13362            {
13363              Image
13364                *next;
13365
13366              long
13367                in;
13368
13369              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseMagickOption(
13370                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13371              if (in < 0)
13372                {
13373                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13374                    SvPV(ST(i),na));
13375                  return;
13376                }
13377              for (next=image; next; next=next->next)
13378                next->gravity=(GravityType) in;
13379              break;
13380            }
13381           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13382             attribute);
13383           break;
13384         }
13385         default:
13386         {
13387           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13388             attribute);
13389           break;
13390         }
13391       }
13392     }
13393     for ( ; image; image=image->next)
13394     {
13395       clone=CloneImage(image,0,0,MagickTrue,exception);
13396       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13397         goto PerlException;
13398       TransformImage(&clone,crop_geometry,geometry);
13399       for ( ; clone; clone=clone->next)
13400       {
13401         AddImageToRegistry(clone);
13402         rv=newRV(sv);
13403         av_push(av,sv_bless(rv,hv));
13404         SvREFCNT_dec(sv);
13405       }
13406     }
13407     exception=DestroyExceptionInfo(exception);
13408     ST(0)=av_reference;
13409     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13410     XSRETURN(1);
13411
13412   PerlException:
13413     InheritPerlException(exception,perl_exception);
13414     exception=DestroyExceptionInfo(exception);
13415     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13416     SvPOK_on(perl_exception);
13417     ST(0)=sv_2mortal(perl_exception);
13418     XSRETURN(1);
13419   }
13420 \f
13421 #
13422 ###############################################################################
13423 #                                                                             #
13424 #                                                                             #
13425 #                                                                             #
13426 #   W r i t e                                                                 #
13427 #                                                                             #
13428 #                                                                             #
13429 #                                                                             #
13430 ###############################################################################
13431 #
13432 #
13433 void
13434 Write(ref,...)
13435   Image::Magick ref=NO_INIT
13436   ALIAS:
13437     WriteImage    = 1
13438     write         = 2
13439     writeimage    = 3
13440   PPCODE:
13441   {
13442     char
13443       filename[MaxTextExtent];
13444
13445     ExceptionInfo
13446       *exception;
13447
13448     Image
13449       *image,
13450       *next;
13451
13452     long
13453       number_images,
13454       scene;
13455
13456     register long
13457       i;
13458
13459     struct PackageInfo
13460       *info,
13461       *package_info;
13462
13463     SV
13464       *perl_exception,
13465       *reference;
13466
13467     exception=AcquireExceptionInfo();
13468     perl_exception=newSVpv("",0);
13469     number_images=0;
13470     package_info=(struct PackageInfo *) NULL;
13471     if (sv_isobject(ST(0)) == 0)
13472       {
13473         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13474           PackageName);
13475         goto PerlException;
13476       }
13477     reference=SvRV(ST(0));
13478     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13479     if (image == (Image *) NULL)
13480       {
13481         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13482           PackageName);
13483         goto PerlException;
13484       }
13485     package_info=ClonePackageInfo(info,exception);
13486     if (items == 2)
13487       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
13488     else
13489       if (items > 2)
13490         for (i=2; i < items; i+=2)
13491           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
13492             exception);
13493     (void) CopyMagickString(filename,package_info->image_info->filename,
13494       MaxTextExtent);
13495     scene=0;
13496     for (next=image; next; next=next->next)
13497     {
13498       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
13499       next->scene=scene++;
13500     }
13501     SetImageInfo(package_info->image_info,MagickTrue,&image->exception);
13502     for (next=image; next; next=next->next)
13503     {
13504       (void) WriteImage(package_info->image_info,next);
13505       if (next->exception.severity >= ErrorException)
13506         InheritException(exception,&next->exception);
13507       GetImageException(next,exception);
13508       number_images++;
13509       if (package_info->image_info->adjoin)
13510         break;
13511     }
13512
13513   PerlException:
13514     if (package_info != (struct PackageInfo *) NULL)
13515       DestroyPackageInfo(package_info);
13516     InheritPerlException(exception,perl_exception);
13517     exception=DestroyExceptionInfo(exception);
13518     sv_setiv(perl_exception,(IV) number_images);
13519     SvPOK_on(perl_exception);
13520     ST(0)=sv_2mortal(perl_exception);
13521     XSRETURN(1);
13522   }