]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv((IV) image); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   MagickRealType
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"bias", RealReference},
218       {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
251       {"color", StringReference}, {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"bias", RealReference},
260       {"channel", MagickChannelOptions} } },
261     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
262       {"y", RealReference}, { "fill", StringReference},
263       {"color", StringReference} } },
264     { "Spread", { {"radius", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Swirl", { {"degrees", RealReference},
267       {"interpolate", MagickInterpolateOptions} } },
268     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
269       {"height", IntegerReference}, {"filter", MagickFilterOptions},
270       {"support", StringReference }, {"blur", RealReference } } },
271     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
272       {"height", IntegerReference}, {"filter", MagickFilterOptions},
273       {"support", RealReference }, {"blur", RealReference } } },
274     { "Annotate", { {"text", StringReference}, {"font", StringReference},
275       {"pointsize", RealReference}, {"density", StringReference},
276       {"undercolor", StringReference}, {"stroke", StringReference},
277       {"fill", StringReference}, {"geometry", StringReference},
278       {"pen", StringReference}, {"x", RealReference},
279       {"y", RealReference}, {"gravity", MagickGravityOptions},
280       {"translate", StringReference}, {"scale", StringReference},
281       {"rotate", RealReference}, {"skewX", RealReference},
282       {"skewY", RealReference}, {"strokewidth", RealReference},
283       {"antialias", MagickBooleanOptions}, {"family", StringReference},
284       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
285       {"weight", IntegerReference}, {"align", MagickAlignOptions},
286       {"encoding", StringReference}, {"affine", ArrayReference},
287       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
288       {"tile", ImageReference}, {"kerning", RealReference},
289       {"interline-spacing", RealReference},
290       {"interword-spacing", RealReference},
291       {"direction", MagickDirectionOptions} } },
292     { "ColorFloodfill", { {"geometry", StringReference},
293       {"x", IntegerReference}, {"y", IntegerReference},
294       {"fill", StringReference}, {"bordercolor", StringReference},
295       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
296     { "Composite", { {"image", ImageReference},
297       {"compose", MagickComposeOptions}, {"geometry", StringReference},
298       {"x", IntegerReference}, {"y", IntegerReference},
299       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
300       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
301       {"color", StringReference}, {"mask", ImageReference},
302       {"channel", MagickChannelOptions},
303       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
304       {"blend", StringReference} } },
305     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
306     { "CycleColormap", { {"display", IntegerReference} } },
307     { "Draw", { {"primitive", MagickPrimitiveOptions},
308       {"points", StringReference}, {"method", MagickMethodOptions},
309       {"stroke", StringReference}, {"fill", StringReference},
310       {"strokewidth", RealReference}, {"font", StringReference},
311       {"bordercolor", StringReference}, {"x", RealReference},
312       {"y", RealReference}, {"translate", StringReference},
313       {"scale", StringReference}, {"rotate", RealReference},
314       {"skewX", RealReference}, {"skewY", RealReference},
315       {"tile", ImageReference}, {"pointsize", RealReference},
316       {"antialias", MagickBooleanOptions}, {"density", StringReference},
317       {"linewidth", RealReference}, {"affine", ArrayReference},
318       {"stroke-dashoffset", RealReference},
319       {"stroke-dasharray", ArrayReference},
320       {"interpolate", MagickInterpolateOptions},
321       {"origin", StringReference}, {"text", StringReference},
322       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
323       {"vector-graphics", StringReference}, {"kerning", RealReference},
324       {"interline-spacing", RealReference},
325       {"interword-spacing", RealReference},
326       {"direction", MagickDirectionOptions} } },
327     { "Equalize", { {"channel", MagickChannelOptions} } },
328     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
329       {"red", RealReference}, {"green", RealReference},
330       {"blue", RealReference} } },
331     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
332       {"dither-method", MagickDitherOptions} } },
333     { "MatteFloodfill", { {"geometry", StringReference},
334       {"x", IntegerReference}, {"y", IntegerReference},
335       {"opacity", StringReference}, {"bordercolor", StringReference},
336       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
337     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
338       {"saturation", RealReference}, {"whiteness", RealReference},
339       {"brightness", RealReference}, {"lightness", RealReference},
340       {"blackness", RealReference} } },
341     { "Negate", { {"gray", MagickBooleanOptions},
342       {"channel", MagickChannelOptions} } },
343     { "Normalize", { {"channel", MagickChannelOptions} } },
344     { "NumberColors", },
345     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
346       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
347       {"invert", MagickBooleanOptions} } },
348     { "Quantize", { {"colors", IntegerReference},
349       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
350       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
351       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
352       {"dither-method", MagickDitherOptions} } },
353     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
354       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
355     { "Segment", { {"geometry", StringReference},
356       {"cluster-threshold", RealReference},
357       {"smoothing-threshold", RealReference},
358       {"colorspace", MagickColorspaceOptions},
359       {"verbose", MagickBooleanOptions} } },
360     { "Signature", },
361     { "Solarize", { {"geometry", StringReference},
362       {"threshold", StringReference} } },
363     { "Sync", },
364     { "Texture", { {"texture", ImageReference} } },
365     { "Evaluate", { {"value", RealReference},
366       {"operator", MagickEvaluateOptions},
367       {"channel", MagickChannelOptions} } },
368     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
369       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
370     { "Threshold", { {"threshold", StringReference},
371       {"channel", MagickChannelOptions} } },
372     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
373       {"sigma", RealReference}, {"biabias", RealReference} } },
374     { "Trim", { {"fuzz", StringReference} } },
375     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
376       {"wavelength", RealReference},
377       {"interpolate", MagickInterpolateOptions} } },
378     { "Separate", { {"channel", MagickChannelOptions} } },
379     { "Condense", },
380     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
381       {"y", IntegerReference} } },
382     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
383     { "Deconstruct", },
384     { "GaussianBlur", { {"geometry", StringReference},
385       {"radius", RealReference}, {"sigma", RealReference},
386       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
387     { "Convolve", { {"coefficients", ArrayReference},
388       {"channel", MagickChannelOptions}, {"bias", StringReference},
389       {"kernel", StringReference} } },
390     { "Profile", { {"name", StringReference}, {"profile", StringReference},
391       { "rendering-intent", MagickIntentOptions},
392       { "black-point-compensation", MagickBooleanOptions} } },
393     { "UnsharpMask", { {"geometry", StringReference},
394       {"radius", RealReference}, {"sigma", RealReference},
395       {"amount", RealReference}, {"threshold", RealReference},
396       {"channel", MagickChannelOptions} } },
397     { "MotionBlur", { {"geometry", StringReference},
398       {"radius", RealReference}, {"sigma", RealReference},
399       {"angle", RealReference}, {"bias", RealReference},
400       {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"bias", RealReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference }, {"blur", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
427       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", },
431     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference}, {"bias", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference }, {"interpolate", MagickInterpolateOptions} } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "ColorMatrix", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference},
487       {"interpolate", MagickInterpolateOptions} } },
488     { "FloodfillPaint", { {"geometry", StringReference},
489       {"x", IntegerReference}, {"y", IntegerReference},
490       {"fill", StringReference}, {"bordercolor", StringReference},
491       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492       {"invert", MagickBooleanOptions} } },
493     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494       {"virtual-pixel", MagickVirtualPixelOptions},
495       {"best-fit", MagickBooleanOptions} } },
496     { "Clut", { {"image", ImageReference},
497       {"interpolate", MagickInterpolateOptions},
498       {"channel", MagickChannelOptions} } },
499     { "LiquidRescale", { {"geometry", StringReference},
500       {"width", IntegerReference}, {"height", IntegerReference},
501       {"delta-x", RealReference}, {"rigidity", RealReference } } },
502     { "Encipher", { {"passphrase", StringReference} } },
503     { "Decipher", { {"passphrase", StringReference} } },
504     { "Deskew", { {"geometry", StringReference},
505       {"threshold", StringReference} } },
506     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
507       {"dither-method", MagickDitherOptions} } },
508     { "SparseColor", { {"points", ArrayReference},
509       {"method", MagickSparseColorOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions},
511       {"channel", MagickChannelOptions} } },
512     { "Function", { {"parameters", ArrayReference},
513       {"function", MagickFunctionOptions},
514       {"virtual-pixel", MagickVirtualPixelOptions} } },
515     { "SelectiveBlur", { {"geometry", StringReference},
516       {"radius", RealReference}, {"sigma", RealReference},
517       {"threshold", RealReference}, {"bias", RealReference},
518       {"channel", MagickChannelOptions} } },
519     { "HaldClut", { {"image", ImageReference},
520       {"channel", MagickChannelOptions} } },
521     { "BlueShift", { {"factor", StringReference} } },
522     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
524     { "ColorDecisionList", {
525       {"color-correction-collection", StringReference} } },
526     { "AutoGamma", { {"channel", MagickChannelOptions} } },
527     { "AutoLevel", { {"channel", MagickChannelOptions} } },
528     { "LevelColors", { {"invert", MagickBooleanOptions},
529       {"black-point", StringReference}, {"white-point", StringReference},
530       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
531     { "Clamp", { {"channel", MagickChannelOptions} } },
532     { "BrightnessContrast", { {"levels", StringReference},
533       {"brightness", RealReference},{"contrast", RealReference},
534       {"channel", MagickChannelOptions} } },
535     { "Morphology", { {"kernel", StringReference},
536       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
537       {"iterations", IntegerReference} } },
538     { "Sans", { {"matrix", ArrayReference} } },
539     { "Color", { {"color", StringReference} } },
540     { "Mode", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions} } },
543     { "Statistic", { {"geometry", StringReference},
544       {"width", IntegerReference},{"height", IntegerReference},
545       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
546   };
547
548 static SplayTreeInfo
549   *magick_registry = (SplayTreeInfo *) NULL;
550 \f
551 /*
552   Forward declarations.
553 */
554 static Image
555   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
556
557 static ssize_t
558   strEQcase(const char *,const char *);
559 \f
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %                                                                             %
563 %                                                                             %
564 %                                                                             %
565 %   C l o n e P a c k a g e I n f o                                           %
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
572 %  a new one.
573 %
574 %  The format of the ClonePackageInfo routine is:
575 %
576 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
577 %        exception)
578 %
579 %  A description of each parameter follows:
580 %
581 %    o info: a structure of type info.
582 %
583 %    o exception: Return any errors or warnings in this structure.
584 %
585 */
586 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
587   ExceptionInfo *exception)
588 {
589   struct PackageInfo
590     *clone_info;
591
592   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
593   if (clone_info == (struct PackageInfo *) NULL)
594     {
595       ThrowPerlException(exception,ResourceLimitError,
596         "UnableToClonePackageInfo",PackageName);
597       return((struct PackageInfo *) NULL);
598     }
599   if (info == (struct PackageInfo *) NULL)
600     {
601       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
602       return(clone_info);
603     }
604   *clone_info=(*info);
605   clone_info->image_info=CloneImageInfo(info->image_info);
606   return(clone_info);
607 }
608 \f
609 /*
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %                                                                             %
612 %                                                                             %
613 %                                                                             %
614 %   c o n s t a n t                                                           %
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %
620 %  constant() returns a double value for the specified name.
621 %
622 %  The format of the constant routine is:
623 %
624 %      double constant(char *name,ssize_t sans)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o value: Method constant returns a double value for the specified name.
629 %
630 %    o name: The name of the constant.
631 %
632 %    o sans: This integer value is not used.
633 %
634 */
635 static double constant(char *name,ssize_t sans)
636 {
637   (void) sans;
638   errno=0;
639   switch (*name)
640   {
641     case 'B':
642     {
643       if (strEQ(name,"BlobError"))
644         return(BlobError);
645       if (strEQ(name,"BlobWarning"))
646         return(BlobWarning);
647       break;
648     }
649     case 'C':
650     {
651       if (strEQ(name,"CacheError"))
652         return(CacheError);
653       if (strEQ(name,"CacheWarning"))
654         return(CacheWarning);
655       if (strEQ(name,"CoderError"))
656         return(CoderError);
657       if (strEQ(name,"CoderWarning"))
658         return(CoderWarning);
659       if (strEQ(name,"ConfigureError"))
660         return(ConfigureError);
661       if (strEQ(name,"ConfigureWarning"))
662         return(ConfigureWarning);
663       if (strEQ(name,"CorruptImageError"))
664         return(CorruptImageError);
665       if (strEQ(name,"CorruptImageWarning"))
666         return(CorruptImageWarning);
667       break;
668     }
669     case 'D':
670     {
671       if (strEQ(name,"DelegateError"))
672         return(DelegateError);
673       if (strEQ(name,"DelegateWarning"))
674         return(DelegateWarning);
675       if (strEQ(name,"DrawError"))
676         return(DrawError);
677       if (strEQ(name,"DrawWarning"))
678         return(DrawWarning);
679       break;
680     }
681     case 'E':
682     {
683       if (strEQ(name,"ErrorException"))
684         return(ErrorException);
685       if (strEQ(name,"ExceptionError"))
686         return(CoderError);
687       if (strEQ(name,"ExceptionWarning"))
688         return(CoderWarning);
689       break;
690     }
691     case 'F':
692     {
693       if (strEQ(name,"FatalErrorException"))
694         return(FatalErrorException);
695       if (strEQ(name,"FileOpenError"))
696         return(FileOpenError);
697       if (strEQ(name,"FileOpenWarning"))
698         return(FileOpenWarning);
699       break;
700     }
701     case 'I':
702     {
703       if (strEQ(name,"ImageError"))
704         return(ImageError);
705       if (strEQ(name,"ImageWarning"))
706         return(ImageWarning);
707       break;
708     }
709     case 'M':
710     {
711       if (strEQ(name,"MaxRGB"))
712         return(QuantumRange);
713       if (strEQ(name,"MissingDelegateError"))
714         return(MissingDelegateError);
715       if (strEQ(name,"MissingDelegateWarning"))
716         return(MissingDelegateWarning);
717       if (strEQ(name,"ModuleError"))
718         return(ModuleError);
719       if (strEQ(name,"ModuleWarning"))
720         return(ModuleWarning);
721       break;
722     }
723     case 'O':
724     {
725       if (strEQ(name,"Opaque"))
726         return(OpaqueAlpha);
727       if (strEQ(name,"OptionError"))
728         return(OptionError);
729       if (strEQ(name,"OptionWarning"))
730         return(OptionWarning);
731       break;
732     }
733     case 'Q':
734     {
735       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumDepth"))
738         return(MAGICKCORE_QUANTUM_DEPTH);
739       if (strEQ(name,"QuantumRange"))
740         return(QuantumRange);
741       break;
742     }
743     case 'R':
744     {
745       if (strEQ(name,"ResourceLimitError"))
746         return(ResourceLimitError);
747       if (strEQ(name,"ResourceLimitWarning"))
748         return(ResourceLimitWarning);
749       if (strEQ(name,"RegistryError"))
750         return(RegistryError);
751       if (strEQ(name,"RegistryWarning"))
752         return(RegistryWarning);
753       break;
754     }
755     case 'S':
756     {
757       if (strEQ(name,"StreamError"))
758         return(StreamError);
759       if (strEQ(name,"StreamWarning"))
760         return(StreamWarning);
761       if (strEQ(name,"Success"))
762         return(0);
763       break;
764     }
765     case 'T':
766     {
767       if (strEQ(name,"Transparent"))
768         return(TransparentAlpha);
769       if (strEQ(name,"TypeError"))
770         return(TypeError);
771       if (strEQ(name,"TypeWarning"))
772         return(TypeWarning);
773       break;
774     }
775     case 'W':
776     {
777       if (strEQ(name,"WarningException"))
778         return(WarningException);
779       break;
780     }
781     case 'X':
782     {
783       if (strEQ(name,"XServerError"))
784         return(XServerError);
785       if (strEQ(name,"XServerWarning"))
786         return(XServerWarning);
787       break;
788     }
789   }
790   errno=EINVAL;
791   return(0);
792 }
793 \f
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %                                                                             %
797 %                                                                             %
798 %                                                                             %
799 %   D e s t r o y P a c k a g e I n f o                                       %
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 %  Method DestroyPackageInfo frees a previously created info structure.
806 %
807 %  The format of the DestroyPackageInfo routine is:
808 %
809 %      DestroyPackageInfo(struct PackageInfo *info)
810 %
811 %  A description of each parameter follows:
812 %
813 %    o info: a structure of type info.
814 %
815 */
816 static void DestroyPackageInfo(struct PackageInfo *info)
817 {
818   info->image_info=DestroyImageInfo(info->image_info);
819   info=(struct PackageInfo *) RelinquishMagickMemory(info);
820 }
821 \f
822 /*
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %                                                                             %
825 %                                                                             %
826 %                                                                             %
827 %   G e t L i s t                                                             %
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %
833 %  Method GetList is recursively called by SetupList to traverse the
834 %  Image__Magick reference.  If building an reference_vector (see SetupList),
835 %  *current is the current position in *reference_vector and *last is the final
836 %  entry in *reference_vector.
837 %
838 %  The format of the GetList routine is:
839 %
840 %      GetList(info)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o info: a structure of type info.
845 %
846 */
847 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
848   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
849 {
850   Image
851     *image;
852
853   if (reference == (SV *) NULL)
854     return(NULL);
855   switch (SvTYPE(reference))
856   {
857     case SVt_PVAV:
858     {
859       AV
860         *av;
861
862       Image
863         *head,
864         *previous;
865
866       register ssize_t
867         i;
868
869       ssize_t
870         n;
871
872       /*
873         Array of images.
874       */
875       previous=(Image *) NULL;
876       head=(Image *) NULL;
877       av=(AV *) reference;
878       n=av_len(av);
879       for (i=0; i <= n; i++)
880       {
881         SV
882           **rv;
883
884         rv=av_fetch(av,i,0);
885         if (rv && *rv && sv_isobject(*rv))
886           {
887             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
888               exception);
889             if (image == (Image *) NULL)
890               continue;
891             if (image == previous)
892               {
893                 image=CloneImage(image,0,0,MagickTrue,exception);
894                 if (image == (Image *) NULL)
895                   return(NULL);
896               }
897             image->previous=previous;
898             *(previous ? &previous->next : &head)=image;
899             for (previous=image; previous->next; previous=previous->next) ;
900           }
901       }
902       return(head);
903     }
904     case SVt_PVMG:
905     {
906       /*
907         Blessed scalar, one image.
908       */
909       image=(Image *) SvIV(reference);
910       if (image == (Image *) NULL)
911         return(NULL);
912       image->previous=(Image *) NULL;
913       image->next=(Image *) NULL;
914       if (reference_vector)
915         {
916           if (*current == *last)
917             {
918               *last+=256;
919               if (*reference_vector == (SV **) NULL)
920                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
921                   sizeof(*reference_vector));
922               else
923                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
924                   *last,sizeof(*reference_vector));
925             }
926           if (*reference_vector == (SV **) NULL)
927             {
928               ThrowPerlException(exception,ResourceLimitError,
929                 "MemoryAllocationFailed",PackageName);
930               return((Image *) NULL);
931             }
932           (*reference_vector)[*current]=reference;
933           (*reference_vector)[++(*current)]=NULL;
934         }
935       return(image);
936     }
937     default:
938       break;
939   }
940   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
941     (double) SvTYPE(reference));
942   return((Image *) NULL);
943 }
944 \f
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 %                                                                             %
948 %                                                                             %
949 %                                                                             %
950 %   G e t P a c k a g e I n f o                                               %
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 %  Method GetPackageInfo looks up or creates an info structure for the given
957 %  Image__Magick reference.  If it does create a new one, the information in
958 %  package_info is used to initialize it.
959 %
960 %  The format of the GetPackageInfo routine is:
961 %
962 %      struct PackageInfo *GetPackageInfo(void *reference,
963 %        struct PackageInfo *package_info,ExceptionInfo *exception)
964 %
965 %  A description of each parameter follows:
966 %
967 %    o info: a structure of type info.
968 %
969 %    o exception: Return any errors or warnings in this structure.
970 %
971 */
972 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
973   struct PackageInfo *package_info,ExceptionInfo *exception)
974 {
975   char
976     message[MaxTextExtent];
977
978   struct PackageInfo
979     *clone_info;
980
981   SV
982     *sv;
983
984   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
985     PackageName,XS_VERSION,reference);
986   sv=perl_get_sv(message,(TRUE | 0x02));
987   if (sv == (SV *) NULL)
988     {
989       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
990         message);
991       return(package_info);
992     }
993   if (SvREFCNT(sv) == 0)
994     (void) SvREFCNT_inc(sv);
995   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
996     return(clone_info);
997   clone_info=ClonePackageInfo(package_info,exception);
998   sv_setiv(sv,(IV) clone_info);
999   return(clone_info);
1000 }
1001 \f
1002 /*
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %                                                                             %
1005 %                                                                             %
1006 %                                                                             %
1007 %   S e t A t t r i b u t e                                                   %
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 %
1013 %  SetAttribute() sets the attribute to the value in sval.  This can change
1014 %  either or both of image or info.
1015 %
1016 %  The format of the SetAttribute routine is:
1017 %
1018 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1019 %        SV *sval,ExceptionInfo *exception)
1020 %
1021 %  A description of each parameter follows:
1022 %
1023 %    o list: a list of strings.
1024 %
1025 %    o string: a character string.
1026 %
1027 */
1028
1029 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1030 {
1031   char
1032     *q;
1033
1034   double
1035     value;
1036
1037   value=InterpretSiPrefixValue(string,&q);
1038   if (*q == '%')
1039     value*=interval/100.0;
1040   return(value);
1041 }
1042
1043 static inline double StringToDouble(const char *restrict string,
1044   char **restrict sentinal)
1045 {
1046   return(InterpretLocaleValue(string,sentinal));
1047 }
1048
1049 static double StringToDoubleInterval(const char *string,const double interval)
1050 {
1051   char
1052     *q;
1053
1054   double
1055     value;
1056
1057   value=InterpretLocaleValue(string,&q);
1058   if (*q == '%')
1059     value*=interval/100.0;
1060   return(value);
1061 }
1062
1063 static inline ssize_t StringToLong(const char *value)
1064 {
1065   return(strtol(value,(char **) NULL,10));
1066 }
1067
1068 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1069   const char *attribute,SV *sval,ExceptionInfo *exception)
1070 {
1071   GeometryInfo
1072     geometry_info;
1073
1074   long
1075     x,
1076     y;
1077
1078   PixelInfo
1079     pixel;
1080
1081   MagickStatusType
1082     flags;
1083
1084   PixelInfo
1085     *color,
1086     target_color;
1087
1088   ssize_t
1089     sp;
1090
1091   switch (*attribute)
1092   {
1093     case 'A':
1094     case 'a':
1095     {
1096       if (LocaleCompare(attribute,"adjoin") == 0)
1097         {
1098           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1099             SvPV(sval,na)) : SvIV(sval);
1100           if (sp < 0)
1101             {
1102               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1103                 SvPV(sval,na));
1104               break;
1105             }
1106           if (info)
1107             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1108           break;
1109         }
1110       if (LocaleCompare(attribute,"alpha") == 0)
1111         {
1112           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1113             SvPV(sval,na)) : SvIV(sval);
1114           if (sp < 0)
1115             {
1116               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1117                 SvPV(sval,na));
1118               break;
1119             }
1120           for ( ; image; image=image->next)
1121             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1122           break;
1123         }
1124       if (LocaleCompare(attribute,"antialias") == 0)
1125         {
1126           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1127             SvPV(sval,na)) : SvIV(sval);
1128           if (sp < 0)
1129             {
1130               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1131                 SvPV(sval,na));
1132               break;
1133             }
1134           if (info)
1135             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1136           break;
1137         }
1138       if (LocaleCompare(attribute,"area-limit") == 0)
1139         {
1140           MagickSizeType
1141             limit;
1142
1143           limit=MagickResourceInfinity;
1144           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1145             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1146               100.0);
1147           (void) SetMagickResourceLimit(AreaResource,limit);
1148           break;
1149         }
1150       if (LocaleCompare(attribute,"attenuate") == 0)
1151         {
1152           if (info)
1153             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1154           break;
1155         }
1156       if (LocaleCompare(attribute,"authenticate") == 0)
1157         {
1158           if (info)
1159             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1160           break;
1161         }
1162       if (info)
1163         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1164       for ( ; image; image=image->next)
1165         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1166       break;
1167     }
1168     case 'B':
1169     case 'b':
1170     {
1171       if (LocaleCompare(attribute,"background") == 0)
1172         {
1173           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1174             exception);
1175           if (info)
1176             info->image_info->background_color=target_color;
1177           for ( ; image; image=image->next)
1178             image->background_color=target_color;
1179           break;
1180         }
1181       if (LocaleCompare(attribute,"bias") == 0)
1182         {
1183           for ( ; image; image=image->next)
1184             image->bias=StringToDoubleInterval(SvPV(sval,na),(double)
1185               QuantumRange+1.0);
1186           break;
1187         }
1188       if (LocaleCompare(attribute,"blue-primary") == 0)
1189         {
1190           for ( ; image; image=image->next)
1191           {
1192             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1193             image->chromaticity.blue_primary.x=geometry_info.rho;
1194             image->chromaticity.blue_primary.y=geometry_info.sigma;
1195             if ((flags & SigmaValue) == 0)
1196               image->chromaticity.blue_primary.y=
1197                 image->chromaticity.blue_primary.x;
1198           }
1199           break;
1200         }
1201       if (LocaleCompare(attribute,"bordercolor") == 0)
1202         {
1203           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1204             exception);
1205           if (info)
1206             info->image_info->border_color=target_color;
1207           for ( ; image; image=image->next)
1208             image->border_color=target_color;
1209           break;
1210         }
1211       if (info)
1212         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1213       for ( ; image; image=image->next)
1214         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1215       break;
1216     }
1217     case 'C':
1218     case 'c':
1219     {
1220       if (LocaleCompare(attribute,"cache-threshold") == 0)
1221         {
1222           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1223             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1224           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1225             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1226           break;
1227         }
1228       if (LocaleCompare(attribute,"clip-mask") == 0)
1229         {
1230           Image
1231             *clip_mask;
1232
1233           clip_mask=(Image *) NULL;
1234           if (SvPOK(sval))
1235             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1236           for ( ; image; image=image->next)
1237             SetImageClipMask(image,clip_mask,exception);
1238           break;
1239         }
1240       if (LocaleNCompare(attribute,"colormap",8) == 0)
1241         {
1242           for ( ; image; image=image->next)
1243           {
1244             int
1245               items;
1246
1247             long
1248               i;
1249
1250             if (image->storage_class == DirectClass)
1251               continue;
1252             i=0;
1253             items=sscanf(attribute,"%*[^[][%ld",&i);
1254             (void) items;
1255             if (i > (ssize_t) image->colors)
1256               i%=image->colors;
1257             if ((strchr(SvPV(sval,na),',') == 0) ||
1258                 (strchr(SvPV(sval,na),')') != 0))
1259               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1260                 image->colormap+i,exception);
1261             else
1262               {
1263                 color=image->colormap+i;
1264                 pixel.red=color->red;
1265                 pixel.green=color->green;
1266                 pixel.blue=color->blue;
1267                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1268                 pixel.red=geometry_info.rho;
1269                 pixel.green=geometry_info.sigma;
1270                 pixel.blue=geometry_info.xi;
1271                 color->red=ClampToQuantum(pixel.red);
1272                 color->green=ClampToQuantum(pixel.green);
1273                 color->blue=ClampToQuantum(pixel.blue);
1274               }
1275           }
1276           break;
1277         }
1278       if (LocaleCompare(attribute,"colorspace") == 0)
1279         {
1280           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1281             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1282           if (sp < 0)
1283             {
1284               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1285                 SvPV(sval,na));
1286               break;
1287             }
1288           for ( ; image; image=image->next)
1289             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1290               exception);
1291           break;
1292         }
1293       if (LocaleCompare(attribute,"comment") == 0)
1294         {
1295           for ( ; image; image=image->next)
1296             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1297               info ? info->image_info : (ImageInfo *) NULL,image,
1298               SvPV(sval,na),exception),exception);
1299           break;
1300         }
1301       if (LocaleCompare(attribute,"compression") == 0)
1302         {
1303           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1304             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1305           if (sp < 0)
1306             {
1307               ThrowPerlException(exception,OptionError,
1308                 "UnrecognizedImageCompression",SvPV(sval,na));
1309               break;
1310             }
1311           if (info)
1312             info->image_info->compression=(CompressionType) sp;
1313           for ( ; image; image=image->next)
1314             image->compression=(CompressionType) sp;
1315           break;
1316         }
1317       if (info)
1318         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1319       for ( ; image; image=image->next)
1320         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1321       break;
1322     }
1323     case 'D':
1324     case 'd':
1325     {
1326       if (LocaleCompare(attribute,"debug") == 0)
1327         {
1328           SetLogEventMask(SvPV(sval,na));
1329           break;
1330         }
1331       if (LocaleCompare(attribute,"delay") == 0)
1332         {
1333           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1334           for ( ; image; image=image->next)
1335           {
1336             image->delay=(size_t) floor(geometry_info.rho+0.5);
1337             if ((flags & SigmaValue) != 0)
1338               image->ticks_per_second=(ssize_t)
1339                 floor(geometry_info.sigma+0.5);
1340           }
1341           break;
1342         }
1343       if (LocaleCompare(attribute,"disk-limit") == 0)
1344         {
1345           MagickSizeType
1346             limit;
1347
1348           limit=MagickResourceInfinity;
1349           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1350             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1351               100.0);
1352           (void) SetMagickResourceLimit(DiskResource,limit);
1353           break;
1354         }
1355       if (LocaleCompare(attribute,"density") == 0)
1356         {
1357           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1358             {
1359               ThrowPerlException(exception,OptionError,"MissingGeometry",
1360                 SvPV(sval,na));
1361               break;
1362             }
1363           if (info)
1364             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1365           for ( ; image; image=image->next)
1366           {
1367             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1368             image->resolution.x=geometry_info.rho;
1369             image->resolution.y=geometry_info.sigma;
1370             if ((flags & SigmaValue) == 0)
1371               image->resolution.y=image->resolution.x;
1372           }
1373           break;
1374         }
1375       if (LocaleCompare(attribute,"depth") == 0)
1376         {
1377           if (info)
1378             info->image_info->depth=SvIV(sval);
1379           for ( ; image; image=image->next)
1380             (void) SetImageDepth(image,SvIV(sval),exception);
1381           break;
1382         }
1383       if (LocaleCompare(attribute,"dispose") == 0)
1384         {
1385           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1386             SvPV(sval,na)) : SvIV(sval);
1387           if (sp < 0)
1388             {
1389               ThrowPerlException(exception,OptionError,
1390                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1391               break;
1392             }
1393           for ( ; image; image=image->next)
1394             image->dispose=(DisposeType) sp;
1395           break;
1396         }
1397       if (LocaleCompare(attribute,"dither") == 0)
1398         {
1399           if (info)
1400             {
1401               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1402                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1403               if (sp < 0)
1404                 {
1405                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1406                     SvPV(sval,na));
1407                   break;
1408                 }
1409               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1410             }
1411           break;
1412         }
1413       if (LocaleCompare(attribute,"display") == 0)
1414         {
1415           display:
1416           if (info)
1417             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1418           break;
1419         }
1420       if (info)
1421         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1422       for ( ; image; image=image->next)
1423         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1424       break;
1425     }
1426     case 'E':
1427     case 'e':
1428     {
1429       if (LocaleCompare(attribute,"endian") == 0)
1430         {
1431           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1432             SvPV(sval,na)) : SvIV(sval);
1433           if (sp < 0)
1434             {
1435               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1436                 SvPV(sval,na));
1437               break;
1438             }
1439           if (info)
1440             info->image_info->endian=(EndianType) sp;
1441           for ( ; image; image=image->next)
1442             image->endian=(EndianType) sp;
1443           break;
1444         }
1445       if (LocaleCompare(attribute,"extract") == 0)
1446         {
1447           /*
1448             Set image extract geometry.
1449           */
1450           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1451           break;
1452         }
1453       if (info)
1454         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1455       for ( ; image; image=image->next)
1456         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1457       break;
1458     }
1459     case 'F':
1460     case 'f':
1461     {
1462       if (LocaleCompare(attribute,"filename") == 0)
1463         {
1464           if (info)
1465             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1466               MaxTextExtent);
1467           for ( ; image; image=image->next)
1468             (void) CopyMagickString(image->filename,SvPV(sval,na),
1469               MaxTextExtent);
1470           break;
1471         }
1472       if (LocaleCompare(attribute,"file") == 0)
1473         {
1474           FILE
1475             *file;
1476
1477           PerlIO
1478             *io_info;
1479
1480           if (info == (struct PackageInfo *) NULL)
1481             break;
1482           io_info=IoIFP(sv_2io(sval));
1483           if (io_info == (PerlIO *) NULL)
1484             {
1485               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1486                 PackageName);
1487               break;
1488             }
1489           file=PerlIO_findFILE(io_info);
1490           if (file == (FILE *) NULL)
1491             {
1492               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1493                 PackageName);
1494               break;
1495             }
1496           SetImageInfoFile(info->image_info,file);
1497           break;
1498         }
1499       if (LocaleCompare(attribute,"fill") == 0)
1500         {
1501           if (info)
1502             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1503           break;
1504         }
1505       if (LocaleCompare(attribute,"font") == 0)
1506         {
1507           if (info)
1508             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1509           break;
1510         }
1511       if (LocaleCompare(attribute,"foreground") == 0)
1512         break;
1513       if (LocaleCompare(attribute,"fuzz") == 0)
1514         {
1515           if (info)
1516             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1517               QuantumRange+1.0);
1518           for ( ; image; image=image->next)
1519             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1520               QuantumRange+1.0);
1521           break;
1522         }
1523       if (info)
1524         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1525       for ( ; image; image=image->next)
1526         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1527       break;
1528     }
1529     case 'G':
1530     case 'g':
1531     {
1532       if (LocaleCompare(attribute,"gamma") == 0)
1533         {
1534           for ( ; image; image=image->next)
1535             image->gamma=SvNV(sval);
1536           break;
1537         }
1538       if (LocaleCompare(attribute,"gravity") == 0)
1539         {
1540           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1541             SvPV(sval,na)) : SvIV(sval);
1542           if (sp < 0)
1543             {
1544               ThrowPerlException(exception,OptionError,
1545                 "UnrecognizedGravityType",SvPV(sval,na));
1546               break;
1547             }
1548           if (info)
1549             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1550           for ( ; image; image=image->next)
1551             image->gravity=(GravityType) sp;
1552           break;
1553         }
1554       if (LocaleCompare(attribute,"green-primary") == 0)
1555         {
1556           for ( ; image; image=image->next)
1557           {
1558             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1559             image->chromaticity.green_primary.x=geometry_info.rho;
1560             image->chromaticity.green_primary.y=geometry_info.sigma;
1561             if ((flags & SigmaValue) == 0)
1562               image->chromaticity.green_primary.y=
1563                 image->chromaticity.green_primary.x;
1564           }
1565           break;
1566         }
1567       if (info)
1568         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1569       for ( ; image; image=image->next)
1570         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1571       break;
1572     }
1573     case 'I':
1574     case 'i':
1575     {
1576       if (LocaleNCompare(attribute,"index",5) == 0)
1577         {
1578           int
1579             items;
1580
1581           long
1582             index;
1583
1584           register Quantum
1585             *q;
1586
1587           CacheView
1588             *image_view;
1589
1590           for ( ; image; image=image->next)
1591           {
1592             if (image->storage_class != PseudoClass)
1593               continue;
1594             x=0;
1595             y=0;
1596             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1597             (void) items;
1598             image_view=AcquireCacheView(image);
1599             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1600             if (q != (Quantum *) NULL)
1601               {
1602                 items=sscanf(SvPV(sval,na),"%ld",&index);
1603                 if ((index >= 0) && (index < (ssize_t) image->colors))
1604                   SetPixelIndex(image,index,q);
1605                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1606               }
1607             image_view=DestroyCacheView(image_view);
1608           }
1609           break;
1610         }
1611       if (LocaleCompare(attribute,"iterations") == 0)
1612         {
1613   iterations:
1614           for ( ; image; image=image->next)
1615             image->iterations=SvIV(sval);
1616           break;
1617         }
1618       if (LocaleCompare(attribute,"interlace") == 0)
1619         {
1620           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1621             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1622           if (sp < 0)
1623             {
1624               ThrowPerlException(exception,OptionError,
1625                 "UnrecognizedInterlaceType",SvPV(sval,na));
1626               break;
1627             }
1628           if (info)
1629             info->image_info->interlace=(InterlaceType) sp;
1630           for ( ; image; image=image->next)
1631             image->interlace=(InterlaceType) sp;
1632           break;
1633         }
1634       if (info)
1635         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1636       for ( ; image; image=image->next)
1637         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1638       break;
1639     }
1640     case 'L':
1641     case 'l':
1642     {
1643       if (LocaleCompare(attribute,"label") == 0)
1644         {
1645           for ( ; image; image=image->next)
1646             (void) SetImageProperty(image,"label",InterpretImageProperties(
1647               info ? info->image_info : (ImageInfo *) NULL,image,
1648               SvPV(sval,na),exception),exception);
1649           break;
1650         }
1651       if (LocaleCompare(attribute,"loop") == 0)
1652         goto iterations;
1653       if (info)
1654         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1655       for ( ; image; image=image->next)
1656         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1657       break;
1658     }
1659     case 'M':
1660     case 'm':
1661     {
1662       if (LocaleCompare(attribute,"magick") == 0)
1663         {
1664           if (info)
1665             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1666               "%s:",SvPV(sval,na));
1667           for ( ; image; image=image->next)
1668             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1669           break;
1670         }
1671       if (LocaleCompare(attribute,"map-limit") == 0)
1672         {
1673           MagickSizeType
1674             limit;
1675
1676           limit=MagickResourceInfinity;
1677           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1678             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1679               100.0);
1680           (void) SetMagickResourceLimit(MapResource,limit);
1681           break;
1682         }
1683       if (LocaleCompare(attribute,"mask") == 0)
1684         {
1685           Image
1686             *mask;
1687
1688           mask=(Image *) NULL;
1689           if (SvPOK(sval))
1690             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1691           for ( ; image; image=image->next)
1692             SetImageMask(image,mask,exception);
1693           break;
1694         }
1695       if (LocaleCompare(attribute,"mattecolor") == 0)
1696         {
1697           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1698             exception);
1699           if (info)
1700             info->image_info->matte_color=target_color;
1701           for ( ; image; image=image->next)
1702             image->matte_color=target_color;
1703           break;
1704         }
1705       if (LocaleCompare(attribute,"matte") == 0)
1706         {
1707           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1708             SvPV(sval,na)) : SvIV(sval);
1709           if (sp < 0)
1710             {
1711               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1712                 SvPV(sval,na));
1713               break;
1714             }
1715           for ( ; image; image=image->next)
1716             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1717           break;
1718         }
1719       if (LocaleCompare(attribute,"memory-limit") == 0)
1720         {
1721           MagickSizeType
1722             limit;
1723
1724           limit=MagickResourceInfinity;
1725           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1726             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1727               100.0);
1728           (void) SetMagickResourceLimit(MemoryResource,limit);
1729           break;
1730         }
1731       if (LocaleCompare(attribute,"monochrome") == 0)
1732         {
1733           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1734             SvPV(sval,na)) : SvIV(sval);
1735           if (sp < 0)
1736             {
1737               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1738                 SvPV(sval,na));
1739               break;
1740             }
1741           if (info)
1742             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1743           for ( ; image; image=image->next)
1744             (void) SetImageType(image,BilevelType,exception);
1745           break;
1746         }
1747       if (info)
1748         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1749       for ( ; image; image=image->next)
1750         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1751       break;
1752     }
1753     case 'O':
1754     case 'o':
1755     {
1756       if (LocaleCompare(attribute,"option") == 0)
1757         {
1758           if (info)
1759             DefineImageOption(info->image_info,SvPV(sval,na));
1760           break;
1761         }
1762       if (LocaleCompare(attribute,"orientation") == 0)
1763         {
1764           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1765             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1766           if (sp < 0)
1767             {
1768               ThrowPerlException(exception,OptionError,
1769                 "UnrecognizedOrientationType",SvPV(sval,na));
1770               break;
1771             }
1772           if (info)
1773             info->image_info->orientation=(OrientationType) sp;
1774           for ( ; image; image=image->next)
1775             image->orientation=(OrientationType) sp;
1776           break;
1777         }
1778       if (info)
1779         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1780       for ( ; image; image=image->next)
1781         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1782       break;
1783     }
1784     case 'P':
1785     case 'p':
1786     {
1787       if (LocaleCompare(attribute,"page") == 0)
1788         {
1789           char
1790             *geometry;
1791
1792           geometry=GetPageGeometry(SvPV(sval,na));
1793           if (info)
1794             (void) CloneString(&info->image_info->page,geometry);
1795           for ( ; image; image=image->next)
1796             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1797           geometry=(char *) RelinquishMagickMemory(geometry);
1798           break;
1799         }
1800       if (LocaleCompare(attribute,"pen") == 0)
1801         {
1802           if (info)
1803             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1804           break;
1805         }
1806       if (LocaleNCompare(attribute,"pixel",5) == 0)
1807         {
1808           int
1809             items;
1810
1811           PixelInfo
1812             pixel;
1813
1814           register Quantum
1815             *q;
1816
1817           CacheView
1818             *image_view;
1819
1820           for ( ; image; image=image->next)
1821           {
1822             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1823               break;
1824             x=0;
1825             y=0;
1826             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1827             (void) items;
1828             image_view=AcquireCacheView(image);
1829             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1830             if (q != (Quantum *) NULL)
1831               {
1832                 if ((strchr(SvPV(sval,na),',') == 0) ||
1833                     (strchr(SvPV(sval,na),')') != 0))
1834                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1835                     &pixel,exception);
1836                 else
1837                   {
1838                     GetPixelInfo(image,&pixel);
1839                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1840                     pixel.red=geometry_info.rho;
1841                     if ((flags & SigmaValue) != 0)
1842                       pixel.green=geometry_info.sigma;
1843                     if ((flags & XiValue) != 0)
1844                       pixel.blue=geometry_info.xi;
1845                     if ((flags & PsiValue) != 0)
1846                       pixel.alpha=geometry_info.psi;
1847                     if ((flags & ChiValue) != 0)
1848                       pixel.black=geometry_info.chi;
1849                   }
1850                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1851                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1852                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1853                 if (image->colorspace == CMYKColorspace)
1854                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1855                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1856                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1857               }
1858             image_view=DestroyCacheView(image_view);
1859           }
1860           break;
1861         }
1862       if (LocaleCompare(attribute,"pointsize") == 0)
1863         {
1864           if (info)
1865             {
1866               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1867               info->image_info->pointsize=geometry_info.rho;
1868             }
1869           break;
1870         }
1871       if (LocaleCompare(attribute,"preview") == 0)
1872         {
1873           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1874             SvPV(sval,na)) : SvIV(sval);
1875           if (sp < 0)
1876             {
1877               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1878                 SvPV(sval,na));
1879               break;
1880             }
1881           if (info)
1882             info->image_info->preview_type=(PreviewType) sp;
1883           break;
1884         }
1885       if (info)
1886         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1887       for ( ; image; image=image->next)
1888         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1889       break;
1890     }
1891     case 'Q':
1892     case 'q':
1893     {
1894       if (LocaleCompare(attribute,"quality") == 0)
1895         {
1896           if (info)
1897             info->image_info->quality=SvIV(sval);
1898           for ( ; image; image=image->next)
1899             image->quality=SvIV(sval);
1900           break;
1901         }
1902       if (info)
1903         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1904       for ( ; image; image=image->next)
1905         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1906       break;
1907     }
1908     case 'R':
1909     case 'r':
1910     {
1911       if (LocaleCompare(attribute,"red-primary") == 0)
1912         {
1913           for ( ; image; image=image->next)
1914           {
1915             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1916             image->chromaticity.red_primary.x=geometry_info.rho;
1917             image->chromaticity.red_primary.y=geometry_info.sigma;
1918             if ((flags & SigmaValue) == 0)
1919               image->chromaticity.red_primary.y=
1920                 image->chromaticity.red_primary.x;
1921           }
1922           break;
1923         }
1924       if (LocaleCompare(attribute,"render") == 0)
1925         {
1926           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1927             SvPV(sval,na)) : SvIV(sval);
1928           if (sp < 0)
1929             {
1930               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1931                 SvPV(sval,na));
1932               break;
1933             }
1934          for ( ; image; image=image->next)
1935            image->rendering_intent=(RenderingIntent) sp;
1936          break;
1937        }
1938       if (LocaleCompare(attribute,"repage") == 0)
1939         {
1940           RectangleInfo
1941             geometry;
1942
1943           for ( ; image; image=image->next)
1944           {
1945             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1946             if ((flags & WidthValue) != 0)
1947               {
1948                 if ((flags & HeightValue) == 0)
1949                   geometry.height=geometry.width;
1950                 image->page.width=geometry.width;
1951                 image->page.height=geometry.height;
1952               }
1953             if ((flags & AspectValue) != 0)
1954               {
1955                 if ((flags & XValue) != 0)
1956                   image->page.x+=geometry.x;
1957                 if ((flags & YValue) != 0)
1958                   image->page.y+=geometry.y;
1959               }
1960             else
1961               {
1962                 if ((flags & XValue) != 0)
1963                   {
1964                     image->page.x=geometry.x;
1965                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1966                       image->page.width=image->columns+geometry.x;
1967                   }
1968                 if ((flags & YValue) != 0)
1969                   {
1970                     image->page.y=geometry.y;
1971                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1972                       image->page.height=image->rows+geometry.y;
1973                   }
1974               }
1975           }
1976           break;
1977         }
1978       if (info)
1979         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1980       for ( ; image; image=image->next)
1981         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1982       break;
1983     }
1984     case 'S':
1985     case 's':
1986     {
1987       if (LocaleCompare(attribute,"sampling-factor") == 0)
1988         {
1989           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1990             {
1991               ThrowPerlException(exception,OptionError,"MissingGeometry",
1992                 SvPV(sval,na));
1993               break;
1994             }
1995           if (info)
1996             (void) CloneString(&info->image_info->sampling_factor,
1997               SvPV(sval,na));
1998           break;
1999         }
2000       if (LocaleCompare(attribute,"scene") == 0)
2001         {
2002           for ( ; image; image=image->next)
2003             image->scene=SvIV(sval);
2004           break;
2005         }
2006       if (LocaleCompare(attribute,"server") == 0)
2007         goto display;
2008       if (LocaleCompare(attribute,"size") == 0)
2009         {
2010           if (info)
2011             {
2012               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2013                 {
2014                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2015                     SvPV(sval,na));
2016                   break;
2017                 }
2018               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2019             }
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"stroke") == 0)
2023         {
2024           if (info)
2025             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2026           break;
2027         }
2028       if (info)
2029         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2030       for ( ; image; image=image->next)
2031         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2032       break;
2033     }
2034     case 'T':
2035     case 't':
2036     {
2037       if (LocaleCompare(attribute,"texture") == 0)
2038         {
2039           if (info)
2040             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2041           break;
2042         }
2043       if (LocaleCompare(attribute,"thread-limit") == 0)
2044         {
2045           MagickSizeType
2046             limit;
2047
2048           limit=MagickResourceInfinity;
2049           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2050             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2051               100.0);
2052           (void) SetMagickResourceLimit(ThreadResource,limit);
2053           break;
2054         }
2055       if (LocaleCompare(attribute,"tile-offset") == 0)
2056         {
2057           char
2058             *geometry;
2059
2060           geometry=GetPageGeometry(SvPV(sval,na));
2061           if (info)
2062             (void) CloneString(&info->image_info->page,geometry);
2063           for ( ; image; image=image->next)
2064             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2065               exception);
2066           geometry=(char *) RelinquishMagickMemory(geometry);
2067           break;
2068         }
2069       if (LocaleCompare(attribute,"time-limit") == 0)
2070         {
2071           MagickSizeType
2072             limit;
2073
2074           limit=MagickResourceInfinity;
2075           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2076             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2077               100.0);
2078           (void) SetMagickResourceLimit(TimeResource,limit);
2079           break;
2080         }
2081       if (LocaleCompare(attribute,"transparent-color") == 0)
2082         {
2083           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2084             exception);
2085           if (info)
2086             info->image_info->transparent_color=target_color;
2087           for ( ; image; image=image->next)
2088             image->transparent_color=target_color;
2089           break;
2090         }
2091       if (LocaleCompare(attribute,"type") == 0)
2092         {
2093           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2094             SvPV(sval,na)) : SvIV(sval);
2095           if (sp < 0)
2096             {
2097               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2098                 SvPV(sval,na));
2099               break;
2100             }
2101           if (info)
2102             info->image_info->type=(ImageType) sp;
2103           for ( ; image; image=image->next)
2104             SetImageType(image,(ImageType) sp,exception);
2105           break;
2106         }
2107       if (info)
2108         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2109       for ( ; image; image=image->next)
2110         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2111       break;
2112     }
2113     case 'U':
2114     case 'u':
2115     {
2116       if (LocaleCompare(attribute,"units") == 0)
2117         {
2118           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2119             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2120           if (sp < 0)
2121             {
2122               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2123                 SvPV(sval,na));
2124               break;
2125             }
2126           if (info)
2127             info->image_info->units=(ResolutionType) sp;
2128           for ( ; image; image=image->next)
2129           {
2130             ResolutionType
2131               units;
2132
2133             units=(ResolutionType) sp;
2134             if (image->units != units)
2135               switch (image->units)
2136               {
2137                 case UndefinedResolution:
2138                 case PixelsPerInchResolution:
2139                 {
2140                   if (units == PixelsPerCentimeterResolution)
2141                     {
2142                       image->resolution.x*=2.54;
2143                       image->resolution.y*=2.54;
2144                     }
2145                   break;
2146                 }
2147                 case PixelsPerCentimeterResolution:
2148                 {
2149                   if (units == PixelsPerInchResolution)
2150                     {
2151                       image->resolution.x/=2.54;
2152                       image->resolution.y/=2.54;
2153                     }
2154                   break;
2155                 }
2156               }
2157             image->units=units;
2158           }
2159           break;
2160         }
2161       if (info)
2162         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2163       for ( ; image; image=image->next)
2164         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2165       break;
2166     }
2167     case 'V':
2168     case 'v':
2169     {
2170       if (LocaleCompare(attribute,"verbose") == 0)
2171         {
2172           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2173             SvPV(sval,na)) : SvIV(sval);
2174           if (sp < 0)
2175             {
2176               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2177                 SvPV(sval,na));
2178               break;
2179             }
2180           if (info)
2181             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2182           break;
2183         }
2184       if (LocaleCompare(attribute,"view") == 0)
2185         {
2186           if (info)
2187             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2188           break;
2189         }
2190       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2191         {
2192           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2193             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2194           if (sp < 0)
2195             {
2196               ThrowPerlException(exception,OptionError,
2197                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2198               break;
2199             }
2200           if (info)
2201             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2202           for ( ; image; image=image->next)
2203             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2204           break;
2205         }
2206       if (info)
2207         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2208       for ( ; image; image=image->next)
2209         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2210       break;
2211     }
2212     case 'W':
2213     case 'w':
2214     {
2215       if (LocaleCompare(attribute,"white-point") == 0)
2216         {
2217           for ( ; image; image=image->next)
2218           {
2219             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2220             image->chromaticity.white_point.x=geometry_info.rho;
2221             image->chromaticity.white_point.y=geometry_info.sigma;
2222             if ((flags & SigmaValue) == 0)
2223               image->chromaticity.white_point.y=
2224                 image->chromaticity.white_point.x;
2225           }
2226           break;
2227         }
2228       if (info)
2229         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2230       for ( ; image; image=image->next)
2231         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2232       break;
2233     }
2234     default:
2235     {
2236       if (info)
2237         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2238       for ( ; image; image=image->next)
2239         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2240       break;
2241     }
2242   }
2243 }
2244 \f
2245 /*
2246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2247 %                                                                             %
2248 %                                                                             %
2249 %                                                                             %
2250 %   S e t u p L i s t                                                         %
2251 %                                                                             %
2252 %                                                                             %
2253 %                                                                             %
2254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2255 %
2256 %  Method SetupList returns the list of all the images linked by their
2257 %  image->next and image->previous link lists for use with ImageMagick.  If
2258 %  info is non-NULL, an info structure is returned in *info.  If
2259 %  reference_vector is non-NULL,an array of SV* are returned in
2260 %  *reference_vector.  Reference_vector is used when the images are going to be
2261 %  replaced with new Image*'s.
2262 %
2263 %  The format of the SetupList routine is:
2264 %
2265 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2266 %        SV ***reference_vector,ExceptionInfo *exception)
2267 %
2268 %  A description of each parameter follows:
2269 %
2270 %    o list: a list of strings.
2271 %
2272 %    o string: a character string.
2273 %
2274 %    o exception: Return any errors or warnings in this structure.
2275 %
2276 */
2277 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2278   SV ***reference_vector,ExceptionInfo *exception)
2279 {
2280   Image
2281     *image;
2282
2283   ssize_t
2284     current,
2285     last;
2286
2287   if (reference_vector)
2288     *reference_vector=NULL;
2289   if (info)
2290     *info=NULL;
2291   current=0;
2292   last=0;
2293   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2294   if (info && (SvTYPE(reference) == SVt_PVAV))
2295     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2296       exception);
2297   return(image);
2298 }
2299 \f
2300 /*
2301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2302 %                                                                             %
2303 %                                                                             %
2304 %                                                                             %
2305 %   s t r E Q c a s e                                                         %
2306 %                                                                             %
2307 %                                                                             %
2308 %                                                                             %
2309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2310 %
2311 %  strEQcase() compares two strings and returns 0 if they are the
2312 %  same or if the second string runs out first.  The comparison is case
2313 %  insensitive.
2314 %
2315 %  The format of the strEQcase routine is:
2316 %
2317 %      ssize_t strEQcase(const char *p,const char *q)
2318 %
2319 %  A description of each parameter follows:
2320 %
2321 %    o p: a character string.
2322 %
2323 %    o q: a character string.
2324 %
2325 %
2326 */
2327 static ssize_t strEQcase(const char *p,const char *q)
2328 {
2329   char
2330     c;
2331
2332   register ssize_t
2333     i;
2334
2335   for (i=0 ; (c=(*q)) != 0; i++)
2336   {
2337     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2338         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2339       return(0);
2340     p++;
2341     q++;
2342   }
2343   return(((*q == 0) && (*p == 0)) ? i : 0);
2344 }
2345 \f
2346 /*
2347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2348 %                                                                             %
2349 %                                                                             %
2350 %                                                                             %
2351 %   I m a g e : : M a g i c k                                                 %
2352 %                                                                             %
2353 %                                                                             %
2354 %                                                                             %
2355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2356 %
2357 %
2358 */
2359 MODULE = Image::Magick PACKAGE = Image::Magick
2360
2361 PROTOTYPES: ENABLE
2362
2363 BOOT:
2364   MagickCoreGenesis("PerlMagick",MagickFalse);
2365   SetWarningHandler(NULL);
2366   SetErrorHandler(NULL);
2367   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2368     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2369
2370 void
2371 UNLOAD()
2372   PPCODE:
2373   {
2374     if (magick_registry != (SplayTreeInfo *) NULL)
2375       magick_registry=DestroySplayTree(magick_registry);
2376     MagickCoreTerminus();
2377   }
2378
2379 double
2380 constant(name,argument)
2381   char *name
2382   ssize_t argument
2383 \f
2384 #
2385 ###############################################################################
2386 #                                                                             #
2387 #                                                                             #
2388 #                                                                             #
2389 #   A n i m a t e                                                             #
2390 #                                                                             #
2391 #                                                                             #
2392 #                                                                             #
2393 ###############################################################################
2394 #
2395 #
2396 void
2397 Animate(ref,...)
2398   Image::Magick ref=NO_INIT
2399   ALIAS:
2400     AnimateImage  = 1
2401     animate       = 2
2402     animateimage  = 3
2403   PPCODE:
2404   {
2405     ExceptionInfo
2406       *exception;
2407
2408     Image
2409       *image;
2410
2411     register ssize_t
2412       i;
2413
2414     struct PackageInfo
2415       *info,
2416       *package_info;
2417
2418     SV
2419       *perl_exception,
2420       *reference;
2421
2422     PERL_UNUSED_VAR(ref);
2423     PERL_UNUSED_VAR(ix);
2424     exception=AcquireExceptionInfo();
2425     perl_exception=newSVpv("",0);
2426     package_info=(struct PackageInfo *) NULL;
2427     if (sv_isobject(ST(0)) == 0)
2428       {
2429         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2430           PackageName);
2431         goto PerlException;
2432       }
2433     reference=SvRV(ST(0));
2434     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2435     if (image == (Image *) NULL)
2436       {
2437         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2438           PackageName);
2439         goto PerlException;
2440       }
2441     package_info=ClonePackageInfo(info,exception);
2442     if (items == 2)
2443       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2444     else
2445       if (items > 2)
2446         for (i=2; i < items; i+=2)
2447           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2448             exception);
2449     (void) AnimateImages(package_info->image_info,image,exception);
2450     (void) CatchImageException(image);
2451
2452   PerlException:
2453     if (package_info != (struct PackageInfo *) NULL)
2454       DestroyPackageInfo(package_info);
2455     InheritPerlException(exception,perl_exception);
2456     exception=DestroyExceptionInfo(exception);
2457     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2458     SvPOK_on(perl_exception);
2459     ST(0)=sv_2mortal(perl_exception);
2460     XSRETURN(1);
2461   }
2462 \f
2463 #
2464 ###############################################################################
2465 #                                                                             #
2466 #                                                                             #
2467 #                                                                             #
2468 #   A p p e n d                                                               #
2469 #                                                                             #
2470 #                                                                             #
2471 #                                                                             #
2472 ###############################################################################
2473 #
2474 #
2475 void
2476 Append(ref,...)
2477   Image::Magick ref=NO_INIT
2478   ALIAS:
2479     AppendImage  = 1
2480     append       = 2
2481     appendimage  = 3
2482   PPCODE:
2483   {
2484     AV
2485       *av;
2486
2487     char
2488       *attribute;
2489
2490     ExceptionInfo
2491       *exception;
2492
2493     HV
2494       *hv;
2495
2496     Image
2497       *image;
2498
2499     register ssize_t
2500       i;
2501
2502     ssize_t
2503       stack;
2504
2505     struct PackageInfo
2506       *info;
2507
2508     SV
2509       *av_reference,
2510       *perl_exception,
2511       *reference,
2512       *rv,
2513       *sv;
2514
2515     PERL_UNUSED_VAR(ref);
2516     PERL_UNUSED_VAR(ix);
2517     exception=AcquireExceptionInfo();
2518     perl_exception=newSVpv("",0);
2519     sv=NULL;
2520     attribute=NULL;
2521     av=NULL;
2522     if (sv_isobject(ST(0)) == 0)
2523       {
2524         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2525           PackageName);
2526         goto PerlException;
2527       }
2528     reference=SvRV(ST(0));
2529     hv=SvSTASH(reference);
2530     av=newAV();
2531     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2532     SvREFCNT_dec(av);
2533     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2534     if (image == (Image *) NULL)
2535       {
2536         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2537           PackageName);
2538         goto PerlException;
2539       }
2540     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2541     /*
2542       Get options.
2543     */
2544     stack=MagickTrue;
2545     for (i=2; i < items; i+=2)
2546     {
2547       attribute=(char *) SvPV(ST(i-1),na);
2548       switch (*attribute)
2549       {
2550         case 'S':
2551         case 's':
2552         {
2553           if (LocaleCompare(attribute,"stack") == 0)
2554             {
2555               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2556                 SvPV(ST(i),na));
2557               if (stack < 0)
2558                 {
2559                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2560                     SvPV(ST(i),na));
2561                   return;
2562                 }
2563               break;
2564             }
2565           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2566             attribute);
2567           break;
2568         }
2569         default:
2570         {
2571           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2572             attribute);
2573           break;
2574         }
2575       }
2576     }
2577     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2578     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2579       goto PerlException;
2580     for ( ; image; image=image->next)
2581     {
2582       AddImageToRegistry(sv,image);
2583       rv=newRV(sv);
2584       av_push(av,sv_bless(rv,hv));
2585       SvREFCNT_dec(sv);
2586     }
2587     exception=DestroyExceptionInfo(exception);
2588     ST(0)=av_reference;
2589     SvREFCNT_dec(perl_exception);
2590     XSRETURN(1);
2591
2592   PerlException:
2593     InheritPerlException(exception,perl_exception);
2594     exception=DestroyExceptionInfo(exception);
2595     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2596     SvPOK_on(perl_exception);
2597     ST(0)=sv_2mortal(perl_exception);
2598     XSRETURN(1);
2599   }
2600 \f
2601 #
2602 ###############################################################################
2603 #                                                                             #
2604 #                                                                             #
2605 #                                                                             #
2606 #   A v e r a g e                                                             #
2607 #                                                                             #
2608 #                                                                             #
2609 #                                                                             #
2610 ###############################################################################
2611 #
2612 #
2613 void
2614 Average(ref)
2615   Image::Magick ref=NO_INIT
2616   ALIAS:
2617     AverageImage   = 1
2618     average        = 2
2619     averageimage   = 3
2620   PPCODE:
2621   {
2622     AV
2623       *av;
2624
2625     char
2626       *p;
2627
2628     ExceptionInfo
2629       *exception;
2630
2631     HV
2632       *hv;
2633
2634     Image
2635       *image;
2636
2637     struct PackageInfo
2638       *info;
2639
2640     SV
2641       *perl_exception,
2642       *reference,
2643       *rv,
2644       *sv;
2645
2646     PERL_UNUSED_VAR(ref);
2647     PERL_UNUSED_VAR(ix);
2648     exception=AcquireExceptionInfo();
2649     perl_exception=newSVpv("",0);
2650     sv=NULL;
2651     if (sv_isobject(ST(0)) == 0)
2652       {
2653         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2654           PackageName);
2655         goto PerlException;
2656       }
2657     reference=SvRV(ST(0));
2658     hv=SvSTASH(reference);
2659     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2660     if (image == (Image *) NULL)
2661       {
2662         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2663           PackageName);
2664         goto PerlException;
2665       }
2666     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2667     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2668       goto PerlException;
2669     /*
2670       Create blessed Perl array for the returned image.
2671     */
2672     av=newAV();
2673     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2674     SvREFCNT_dec(av);
2675     AddImageToRegistry(sv,image);
2676     rv=newRV(sv);
2677     av_push(av,sv_bless(rv,hv));
2678     SvREFCNT_dec(sv);
2679     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2680     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2681       "average-%.*s",(int) (MaxTextExtent-9),
2682       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2683     (void) CopyMagickString(image->filename,info->image_info->filename,
2684       MaxTextExtent);
2685     SetImageInfo(info->image_info,0,exception);
2686     exception=DestroyExceptionInfo(exception);
2687     SvREFCNT_dec(perl_exception);
2688     XSRETURN(1);
2689
2690   PerlException:
2691     InheritPerlException(exception,perl_exception);
2692     exception=DestroyExceptionInfo(exception);
2693     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2694     SvPOK_on(perl_exception);
2695     ST(0)=sv_2mortal(perl_exception);
2696     XSRETURN(1);
2697   }
2698 \f
2699 #
2700 ###############################################################################
2701 #                                                                             #
2702 #                                                                             #
2703 #                                                                             #
2704 #   B l o b T o I m a g e                                                     #
2705 #                                                                             #
2706 #                                                                             #
2707 #                                                                             #
2708 ###############################################################################
2709 #
2710 #
2711 void
2712 BlobToImage(ref,...)
2713   Image::Magick ref=NO_INIT
2714   ALIAS:
2715     BlobToImage  = 1
2716     blobtoimage  = 2
2717     blobto       = 3
2718   PPCODE:
2719   {
2720     AV
2721       *av;
2722
2723     char
2724       **keep,
2725       **list;
2726
2727     ExceptionInfo
2728       *exception;
2729
2730     HV
2731       *hv;
2732
2733     Image
2734       *image;
2735
2736     register char
2737       **p;
2738
2739     register ssize_t
2740       i;
2741
2742     ssize_t
2743       ac,
2744       n,
2745       number_images;
2746
2747     STRLEN
2748       *length;
2749
2750     struct PackageInfo
2751       *info;
2752
2753     SV
2754       *perl_exception,
2755       *reference,
2756       *rv,
2757       *sv;
2758
2759     PERL_UNUSED_VAR(ref);
2760     PERL_UNUSED_VAR(ix);
2761     exception=AcquireExceptionInfo();
2762     perl_exception=newSVpv("",0);
2763     sv=NULL;
2764     number_images=0;
2765     ac=(items < 2) ? 1 : items-1;
2766     length=(STRLEN *) NULL;
2767     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2768     if (list == (char **) NULL)
2769       {
2770         ThrowPerlException(exception,ResourceLimitError,
2771           "MemoryAllocationFailed",PackageName);
2772         goto PerlException;
2773       }
2774     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2775     if (length == (STRLEN *) NULL)
2776       {
2777         ThrowPerlException(exception,ResourceLimitError,
2778           "MemoryAllocationFailed",PackageName);
2779         goto PerlException;
2780       }
2781     if (sv_isobject(ST(0)) == 0)
2782       {
2783         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2784           PackageName);
2785         goto PerlException;
2786       }
2787     reference=SvRV(ST(0));
2788     hv=SvSTASH(reference);
2789     if (SvTYPE(reference) != SVt_PVAV)
2790       {
2791         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2792           PackageName);
2793         goto PerlException;
2794       }
2795     av=(AV *) reference;
2796     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2797       exception);
2798     n=1;
2799     if (items <= 1)
2800       {
2801         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2802         goto PerlException;
2803       }
2804     for (n=0, i=0; i < ac; i++)
2805     {
2806       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2807       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2808         {
2809           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2810           continue;
2811         }
2812       n++;
2813     }
2814     list[n]=(char *) NULL;
2815     keep=list;
2816     for (i=number_images=0; i < n; i++)
2817     {
2818       image=BlobToImage(info->image_info,list[i],length[i],exception);
2819       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2820         break;
2821       for ( ; image; image=image->next)
2822       {
2823         AddImageToRegistry(sv,image);
2824         rv=newRV(sv);
2825         av_push(av,sv_bless(rv,hv));
2826         SvREFCNT_dec(sv);
2827         number_images++;
2828       }
2829     }
2830     /*
2831       Free resources.
2832     */
2833     for (i=0; i < n; i++)
2834       if (list[i] != (char *) NULL)
2835         for (p=keep; list[i] != *p++; )
2836           if (*p == (char *) NULL)
2837             {
2838               list[i]=(char *) RelinquishMagickMemory(list[i]);
2839               break;
2840             }
2841
2842   PerlException:
2843     if (list)
2844       list=(char **) RelinquishMagickMemory(list);
2845     if (length)
2846       length=(STRLEN *) RelinquishMagickMemory(length);
2847     InheritPerlException(exception,perl_exception);
2848     exception=DestroyExceptionInfo(exception);
2849     sv_setiv(perl_exception,(IV) number_images);
2850     SvPOK_on(perl_exception);
2851     ST(0)=sv_2mortal(perl_exception);
2852     XSRETURN(1);
2853   }
2854 \f
2855 #
2856 ###############################################################################
2857 #                                                                             #
2858 #                                                                             #
2859 #                                                                             #
2860 #   C l o n e                                                                 #
2861 #                                                                             #
2862 #                                                                             #
2863 #                                                                             #
2864 ###############################################################################
2865 #
2866 #
2867 void
2868 Clone(ref)
2869   Image::Magick ref=NO_INIT
2870   ALIAS:
2871     CopyImage   = 1
2872     copy        = 2
2873     copyimage   = 3
2874     CloneImage  = 4
2875     clone       = 5
2876     cloneimage  = 6
2877     Clone       = 7
2878   PPCODE:
2879   {
2880     AV
2881       *av;
2882
2883     ExceptionInfo
2884       *exception;
2885
2886     HV
2887       *hv;
2888
2889     Image
2890       *clone,
2891       *image;
2892
2893     struct PackageInfo
2894       *info;
2895
2896     SV
2897       *perl_exception,
2898       *reference,
2899       *rv,
2900       *sv;
2901
2902     PERL_UNUSED_VAR(ref);
2903     PERL_UNUSED_VAR(ix);
2904     exception=AcquireExceptionInfo();
2905     perl_exception=newSVpv("",0);
2906     sv=NULL;
2907     if (sv_isobject(ST(0)) == 0)
2908       {
2909         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2910           PackageName);
2911         goto PerlException;
2912       }
2913     reference=SvRV(ST(0));
2914     hv=SvSTASH(reference);
2915     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2916     if (image == (Image *) NULL)
2917       {
2918         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2919           PackageName);
2920         goto PerlException;
2921       }
2922     /*
2923       Create blessed Perl array for the returned image.
2924     */
2925     av=newAV();
2926     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2927     SvREFCNT_dec(av);
2928     for ( ; image; image=image->next)
2929     {
2930       clone=CloneImage(image,0,0,MagickTrue,exception);
2931       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2932         break;
2933       AddImageToRegistry(sv,clone);
2934       rv=newRV(sv);
2935       av_push(av,sv_bless(rv,hv));
2936       SvREFCNT_dec(sv);
2937     }
2938     exception=DestroyExceptionInfo(exception);
2939     SvREFCNT_dec(perl_exception);
2940     XSRETURN(1);
2941
2942   PerlException:
2943     InheritPerlException(exception,perl_exception);
2944     exception=DestroyExceptionInfo(exception);
2945     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2946     SvPOK_on(perl_exception);
2947     ST(0)=sv_2mortal(perl_exception);
2948     XSRETURN(1);
2949   }
2950 \f
2951 #
2952 ###############################################################################
2953 #                                                                             #
2954 #                                                                             #
2955 #                                                                             #
2956 #   C L O N E                                                                 #
2957 #                                                                             #
2958 #                                                                             #
2959 #                                                                             #
2960 ###############################################################################
2961 #
2962 #
2963 void
2964 CLONE(ref,...)
2965   SV *ref;
2966   CODE:
2967   {
2968     PERL_UNUSED_VAR(ref);
2969     if (magick_registry != (SplayTreeInfo *) NULL)
2970       {
2971         register Image
2972           *p;
2973
2974         ResetSplayTreeIterator(magick_registry);
2975         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2976         while (p != (Image *) NULL)
2977         {
2978           ReferenceImage(p);
2979           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2980         }
2981       }
2982   }
2983 \f
2984 #
2985 ###############################################################################
2986 #                                                                             #
2987 #                                                                             #
2988 #                                                                             #
2989 #   C o a l e s c e                                                           #
2990 #                                                                             #
2991 #                                                                             #
2992 #                                                                             #
2993 ###############################################################################
2994 #
2995 #
2996 void
2997 Coalesce(ref)
2998   Image::Magick ref=NO_INIT
2999   ALIAS:
3000     CoalesceImage   = 1
3001     coalesce        = 2
3002     coalesceimage   = 3
3003   PPCODE:
3004   {
3005     AV
3006       *av;
3007
3008     ExceptionInfo
3009       *exception;
3010
3011     HV
3012       *hv;
3013
3014     Image
3015       *image;
3016
3017     struct PackageInfo
3018       *info;
3019
3020     SV
3021       *av_reference,
3022       *perl_exception,
3023       *reference,
3024       *rv,
3025       *sv;
3026
3027     PERL_UNUSED_VAR(ref);
3028     PERL_UNUSED_VAR(ix);
3029     exception=AcquireExceptionInfo();
3030     perl_exception=newSVpv("",0);
3031     sv=NULL;
3032     if (sv_isobject(ST(0)) == 0)
3033       {
3034         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3035           PackageName);
3036         goto PerlException;
3037       }
3038     reference=SvRV(ST(0));
3039     hv=SvSTASH(reference);
3040     av=newAV();
3041     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3042     SvREFCNT_dec(av);
3043     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3044     if (image == (Image *) NULL)
3045       {
3046         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3047           PackageName);
3048         goto PerlException;
3049       }
3050     image=CoalesceImages(image,exception);
3051     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3052       goto PerlException;
3053     for ( ; image; image=image->next)
3054     {
3055       AddImageToRegistry(sv,image);
3056       rv=newRV(sv);
3057       av_push(av,sv_bless(rv,hv));
3058       SvREFCNT_dec(sv);
3059     }
3060     exception=DestroyExceptionInfo(exception);
3061     ST(0)=av_reference;
3062     SvREFCNT_dec(perl_exception);
3063     XSRETURN(1);
3064
3065   PerlException:
3066     InheritPerlException(exception,perl_exception);
3067     exception=DestroyExceptionInfo(exception);
3068     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3069     SvPOK_on(perl_exception);
3070     ST(0)=sv_2mortal(perl_exception);
3071     XSRETURN(1);
3072   }
3073 \f
3074 #
3075 ###############################################################################
3076 #                                                                             #
3077 #                                                                             #
3078 #                                                                             #
3079 #   C o m p a r e                                                             #
3080 #                                                                             #
3081 #                                                                             #
3082 #                                                                             #
3083 ###############################################################################
3084 #
3085 #
3086 void
3087 Compare(ref,...)
3088   Image::Magick ref=NO_INIT
3089   ALIAS:
3090     CompareImages = 1
3091     compare      = 2
3092     compareimage = 3
3093   PPCODE:
3094   {
3095     AV
3096       *av;
3097
3098     char
3099       *attribute;
3100
3101     double
3102       distortion;
3103
3104     ExceptionInfo
3105       *exception;
3106
3107     HV
3108       *hv;
3109
3110     Image
3111       *difference_image,
3112       *image,
3113       *reconstruct_image;
3114
3115     MetricType
3116       metric;
3117
3118     register ssize_t
3119       i;
3120
3121     ssize_t
3122       option;
3123
3124     struct PackageInfo
3125       *info;
3126
3127     SV
3128       *av_reference,
3129       *perl_exception,
3130       *reference,
3131       *rv,
3132       *sv;
3133
3134     PERL_UNUSED_VAR(ref);
3135     PERL_UNUSED_VAR(ix);
3136     exception=AcquireExceptionInfo();
3137     perl_exception=newSVpv("",0);
3138     sv=NULL;
3139     av=NULL;
3140     attribute=NULL;
3141     if (sv_isobject(ST(0)) == 0)
3142       {
3143         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3144           PackageName);
3145         goto PerlException;
3146       }
3147     reference=SvRV(ST(0));
3148     hv=SvSTASH(reference);
3149     av=newAV();
3150     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3151     SvREFCNT_dec(av);
3152     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3153     if (image == (Image *) NULL)
3154       {
3155         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3156           PackageName);
3157         goto PerlException;
3158       }
3159     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3160     /*
3161       Get attribute.
3162     */
3163     reconstruct_image=image;
3164     metric=RootMeanSquaredErrorMetric;
3165     for (i=2; i < items; i+=2)
3166     {
3167       attribute=(char *) SvPV(ST(i-1),na);
3168       switch (*attribute)
3169       {
3170         case 'C':
3171         case 'c':
3172         {
3173           if (LocaleCompare(attribute,"channel") == 0)
3174             {
3175               ssize_t
3176                 option;
3177
3178               option=ParseChannelOption(SvPV(ST(i),na));
3179               if (option < 0)
3180                 {
3181                   ThrowPerlException(exception,OptionError,
3182                     "UnrecognizedType",SvPV(ST(i),na));
3183                   return;
3184                 }
3185               SetPixelChannelMapMask(image,(ChannelType) option);
3186               break;
3187             }
3188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3189             attribute);
3190           break;
3191         }
3192         case 'F':
3193         case 'f':
3194         {
3195           if (LocaleCompare(attribute,"fuzz") == 0)
3196             {
3197               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3198               break;
3199             }
3200           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3201             attribute);
3202           break;
3203         }
3204         case 'I':
3205         case 'i':
3206         {
3207           if (LocaleCompare(attribute,"image") == 0)
3208             {
3209               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3210                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3211               break;
3212             }
3213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3214             attribute);
3215           break;
3216         }
3217         case 'M':
3218         case 'm':
3219         {
3220           if (LocaleCompare(attribute,"metric") == 0)
3221             {
3222               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3223                 SvPV(ST(i),na));
3224               if (option < 0)
3225                 {
3226                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3227                     SvPV(ST(i),na));
3228                   break;
3229                 }
3230               metric=(MetricType) option;
3231               break;
3232             }
3233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3234             attribute);
3235           break;
3236         }
3237         default:
3238         {
3239           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3240             attribute);
3241           break;
3242         }
3243       }
3244     }
3245     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3246       exception);
3247     if (difference_image != (Image *) NULL)
3248       {
3249         difference_image->error.mean_error_per_pixel=distortion;
3250         AddImageToRegistry(sv,difference_image);
3251         rv=newRV(sv);
3252         av_push(av,sv_bless(rv,hv));
3253         SvREFCNT_dec(sv);
3254       }
3255     exception=DestroyExceptionInfo(exception);
3256     ST(0)=av_reference;
3257     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3258     XSRETURN(1);
3259
3260   PerlException:
3261     InheritPerlException(exception,perl_exception);
3262     exception=DestroyExceptionInfo(exception);
3263     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3264     SvPOK_on(perl_exception);
3265     ST(0)=sv_2mortal(perl_exception);
3266     XSRETURN(1);
3267   }
3268 \f
3269 #
3270 ###############################################################################
3271 #                                                                             #
3272 #                                                                             #
3273 #                                                                             #
3274 #   C o m p a r e L a y e r s                                                 #
3275 #                                                                             #
3276 #                                                                             #
3277 #                                                                             #
3278 ###############################################################################
3279 #
3280 #
3281 void
3282 CompareLayers(ref)
3283   Image::Magick ref=NO_INIT
3284   ALIAS:
3285     CompareImagesLayers   = 1
3286     comparelayers        = 2
3287     compareimagelayers   = 3
3288   PPCODE:
3289   {
3290     AV
3291       *av;
3292
3293     char
3294       *attribute;
3295
3296     ExceptionInfo
3297       *exception;
3298
3299     HV
3300       *hv;
3301
3302     Image
3303       *image;
3304
3305     ImageLayerMethod
3306       method;
3307
3308     register ssize_t
3309       i;
3310
3311     ssize_t
3312       option;
3313
3314     struct PackageInfo
3315       *info;
3316
3317     SV
3318       *av_reference,
3319       *perl_exception,
3320       *reference,
3321       *rv,
3322       *sv;
3323
3324     PERL_UNUSED_VAR(ref);
3325     PERL_UNUSED_VAR(ix);
3326     exception=AcquireExceptionInfo();
3327     perl_exception=newSVpv("",0);
3328     sv=NULL;
3329     if (sv_isobject(ST(0)) == 0)
3330       {
3331         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3332           PackageName);
3333         goto PerlException;
3334       }
3335     reference=SvRV(ST(0));
3336     hv=SvSTASH(reference);
3337     av=newAV();
3338     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3339     SvREFCNT_dec(av);
3340     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3341     if (image == (Image *) NULL)
3342       {
3343         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3344           PackageName);
3345         goto PerlException;
3346       }
3347     method=CompareAnyLayer;
3348     for (i=2; i < items; i+=2)
3349     {
3350       attribute=(char *) SvPV(ST(i-1),na);
3351       switch (*attribute)
3352       {
3353         case 'M':
3354         case 'm':
3355         {
3356           if (LocaleCompare(attribute,"method") == 0)
3357             {
3358               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3359                 SvPV(ST(i),na));
3360               if (option < 0)
3361                 {
3362                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3363                     SvPV(ST(i),na));
3364                   break;
3365                 }
3366                method=(ImageLayerMethod) option;
3367               break;
3368             }
3369           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3370             attribute);
3371           break;
3372         }
3373         default:
3374         {
3375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3376             attribute);
3377           break;
3378         }
3379       }
3380     }
3381     image=CompareImagesLayers(image,method,exception);
3382     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3383       goto PerlException;
3384     for ( ; image; image=image->next)
3385     {
3386       AddImageToRegistry(sv,image);
3387       rv=newRV(sv);
3388       av_push(av,sv_bless(rv,hv));
3389       SvREFCNT_dec(sv);
3390     }
3391     exception=DestroyExceptionInfo(exception);
3392     ST(0)=av_reference;
3393     SvREFCNT_dec(perl_exception);
3394     XSRETURN(1);
3395
3396   PerlException:
3397     InheritPerlException(exception,perl_exception);
3398     exception=DestroyExceptionInfo(exception);
3399     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3400     SvPOK_on(perl_exception);
3401     ST(0)=sv_2mortal(perl_exception);
3402     XSRETURN(1);
3403   }
3404 \f
3405 #
3406 ###############################################################################
3407 #                                                                             #
3408 #                                                                             #
3409 #                                                                             #
3410 #   D e s t r o y                                                             #
3411 #                                                                             #
3412 #                                                                             #
3413 #                                                                             #
3414 ###############################################################################
3415 #
3416 #
3417 void
3418 DESTROY(ref)
3419   Image::Magick ref=NO_INIT
3420   PPCODE:
3421   {
3422     SV
3423       *reference;
3424
3425     PERL_UNUSED_VAR(ref);
3426     if (sv_isobject(ST(0)) == 0)
3427       croak("ReferenceIsNotMyType");
3428     reference=SvRV(ST(0));
3429     switch (SvTYPE(reference))
3430     {
3431       case SVt_PVAV:
3432       {
3433         char
3434           message[MaxTextExtent];
3435
3436         const SV
3437           *key;
3438
3439         HV
3440           *hv;
3441
3442         GV
3443           **gvp;
3444
3445         struct PackageInfo
3446           *info;
3447
3448         SV
3449           *sv;
3450
3451         /*
3452           Array (AV *) reference
3453         */
3454         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3455           XS_VERSION,reference);
3456         hv=gv_stashpv(PackageName, FALSE);
3457         if (!hv)
3458           break;
3459         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3460         if (!gvp)
3461           break;
3462         sv=GvSV(*gvp);
3463         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3464           {
3465             info=(struct PackageInfo *) SvIV(sv);
3466             DestroyPackageInfo(info);
3467           }
3468         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3469         (void) key;
3470         break;
3471       }
3472       case SVt_PVMG:
3473       {
3474         Image
3475           *image;
3476
3477         /*
3478           Blessed scalar = (Image *) SvIV(reference)
3479         */
3480         image=(Image *) SvIV(reference);
3481         if (image != (Image *) NULL)
3482           DeleteImageFromRegistry(reference,image);
3483         break;
3484       }
3485       default:
3486         break;
3487     }
3488   }
3489 \f
3490 #
3491 ###############################################################################
3492 #                                                                             #
3493 #                                                                             #
3494 #                                                                             #
3495 #   D i s p l a y                                                             #
3496 #                                                                             #
3497 #                                                                             #
3498 #                                                                             #
3499 ###############################################################################
3500 #
3501 #
3502 void
3503 Display(ref,...)
3504   Image::Magick ref=NO_INIT
3505   ALIAS:
3506     DisplayImage  = 1
3507     display       = 2
3508     displayimage  = 3
3509   PPCODE:
3510   {
3511     ExceptionInfo
3512       *exception;
3513
3514     Image
3515       *image;
3516
3517     register ssize_t
3518       i;
3519
3520     struct PackageInfo
3521       *info,
3522       *package_info;
3523
3524     SV
3525       *perl_exception,
3526       *reference;
3527
3528     PERL_UNUSED_VAR(ref);
3529     PERL_UNUSED_VAR(ix);
3530     exception=AcquireExceptionInfo();
3531     perl_exception=newSVpv("",0);
3532     package_info=(struct PackageInfo *) NULL;
3533     if (sv_isobject(ST(0)) == 0)
3534       {
3535         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3536           PackageName);
3537         goto PerlException;
3538       }
3539     reference=SvRV(ST(0));
3540     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3541     if (image == (Image *) NULL)
3542       {
3543         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3544           PackageName);
3545         goto PerlException;
3546       }
3547     package_info=ClonePackageInfo(info,exception);
3548     if (items == 2)
3549       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3550     else
3551       if (items > 2)
3552         for (i=2; i < items; i+=2)
3553           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3554             exception);
3555     (void) DisplayImages(package_info->image_info,image,exception);
3556     (void) CatchImageException(image);
3557
3558   PerlException:
3559     if (package_info != (struct PackageInfo *) NULL)
3560       DestroyPackageInfo(package_info);
3561     InheritPerlException(exception,perl_exception);
3562     exception=DestroyExceptionInfo(exception);
3563     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3564     SvPOK_on(perl_exception);
3565     ST(0)=sv_2mortal(perl_exception);
3566     XSRETURN(1);
3567   }
3568 \f
3569 #
3570 ###############################################################################
3571 #                                                                             #
3572 #                                                                             #
3573 #                                                                             #
3574 #   E v a l u a t e I m a g e s                                               #
3575 #                                                                             #
3576 #                                                                             #
3577 #                                                                             #
3578 ###############################################################################
3579 #
3580 #
3581 void
3582 EvaluateImages(ref)
3583   Image::Magick ref=NO_INIT
3584   ALIAS:
3585     EvaluateImages   = 1
3586     evaluateimages   = 2
3587   PPCODE:
3588   {
3589     AV
3590       *av;
3591
3592     char
3593       *attribute,
3594       *p;
3595
3596     ExceptionInfo
3597       *exception;
3598
3599     HV
3600       *hv;
3601
3602     Image
3603       *image;
3604
3605     MagickEvaluateOperator
3606       op;
3607
3608     register ssize_t
3609       i;
3610
3611     struct PackageInfo
3612       *info;
3613
3614     SV
3615       *perl_exception,
3616       *reference,
3617       *rv,
3618       *sv;
3619
3620     PERL_UNUSED_VAR(ref);
3621     PERL_UNUSED_VAR(ix);
3622     exception=AcquireExceptionInfo();
3623     perl_exception=newSVpv("",0);
3624     sv=NULL;
3625     if (sv_isobject(ST(0)) == 0)
3626       {
3627         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3628           PackageName);
3629         goto PerlException;
3630       }
3631     reference=SvRV(ST(0));
3632     hv=SvSTASH(reference);
3633     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3634     if (image == (Image *) NULL)
3635       {
3636         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3637           PackageName);
3638         goto PerlException;
3639       }
3640     op=MeanEvaluateOperator;
3641     if (items == 2)
3642       {
3643         ssize_t
3644           in;
3645
3646         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3647           SvPV(ST(1),na));
3648         if (in < 0)
3649           {
3650             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3651               SvPV(ST(1),na));
3652             return;
3653           }
3654         op=(MagickEvaluateOperator) in;
3655       }
3656     else
3657       for (i=2; i < items; i+=2)
3658       {
3659         attribute=(char *) SvPV(ST(i-1),na);
3660         switch (*attribute)
3661         {
3662           case 'O':
3663           case 'o':
3664           {
3665             if (LocaleCompare(attribute,"operator") == 0)
3666               {
3667                 ssize_t
3668                   in;
3669
3670                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3671                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3672                 if (in < 0)
3673                   {
3674                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3675                       SvPV(ST(i),na));
3676                     return;
3677                   }
3678                 op=(MagickEvaluateOperator) in;
3679                 break;
3680               }
3681             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3682               attribute);
3683             break;
3684           }
3685           default:
3686           {
3687             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3688               attribute);
3689             break;
3690           }
3691         }
3692       }
3693     image=EvaluateImages(image,op,exception);
3694     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3695       goto PerlException;
3696     /*
3697       Create blessed Perl array for the returned image.
3698     */
3699     av=newAV();
3700     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3701     SvREFCNT_dec(av);
3702     AddImageToRegistry(sv,image);
3703     rv=newRV(sv);
3704     av_push(av,sv_bless(rv,hv));
3705     SvREFCNT_dec(sv);
3706     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3707     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3708       "evaluate-%.*s",(int) (MaxTextExtent-9),
3709       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3710     (void) CopyMagickString(image->filename,info->image_info->filename,
3711       MaxTextExtent);
3712     SetImageInfo(info->image_info,0,exception);
3713     exception=DestroyExceptionInfo(exception);
3714     SvREFCNT_dec(perl_exception);
3715     XSRETURN(1);
3716
3717   PerlException:
3718     InheritPerlException(exception,perl_exception);
3719     exception=DestroyExceptionInfo(exception);
3720     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3721     SvPOK_on(perl_exception);
3722     ST(0)=sv_2mortal(perl_exception);
3723     XSRETURN(1);
3724   }
3725 \f
3726 #
3727 ###############################################################################
3728 #                                                                             #
3729 #                                                                             #
3730 #                                                                             #
3731 #   F e a t u r e s                                                           #
3732 #                                                                             #
3733 #                                                                             #
3734 #                                                                             #
3735 ###############################################################################
3736 #
3737 #
3738 void
3739 Features(ref,...)
3740   Image::Magick ref=NO_INIT
3741   ALIAS:
3742     FeaturesImage = 1
3743     features      = 2
3744     featuresimage = 3
3745   PPCODE:
3746   {
3747 #define ChannelFeatures(channel,direction) \
3748 { \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].angular_second_moment[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].contrast[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].contrast[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].variance_sum_of_squares[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].inverse_difference_moment[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].sum_average[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].sum_variance[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3771     channel_features[channel].sum_entropy[direction]); \
3772   PUSHs(sv_2mortal(newSVpv(message,0))); \
3773   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3774     channel_features[channel].entropy[direction]); \
3775   PUSHs(sv_2mortal(newSVpv(message,0))); \
3776   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3777     channel_features[channel].difference_variance[direction]); \
3778   PUSHs(sv_2mortal(newSVpv(message,0))); \
3779   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3780     channel_features[channel].difference_entropy[direction]); \
3781   PUSHs(sv_2mortal(newSVpv(message,0))); \
3782   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3783     channel_features[channel].measure_of_correlation_1[direction]); \
3784   PUSHs(sv_2mortal(newSVpv(message,0))); \
3785   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3786     channel_features[channel].measure_of_correlation_2[direction]); \
3787   PUSHs(sv_2mortal(newSVpv(message,0))); \
3788   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3789     channel_features[channel].maximum_correlation_coefficient[direction]); \
3790   PUSHs(sv_2mortal(newSVpv(message,0))); \
3791 }
3792
3793     AV
3794       *av;
3795
3796     char
3797       *attribute,
3798       message[MaxTextExtent];
3799
3800     ChannelFeatures
3801       *channel_features;
3802
3803     double
3804       distance;
3805
3806     ExceptionInfo
3807       *exception;
3808
3809     Image
3810       *image;
3811
3812     register ssize_t
3813       i;
3814
3815     ssize_t
3816       count;
3817
3818     struct PackageInfo
3819       *info;
3820
3821     SV
3822       *perl_exception,
3823       *reference;
3824
3825     PERL_UNUSED_VAR(ref);
3826     PERL_UNUSED_VAR(ix);
3827     exception=AcquireExceptionInfo();
3828     perl_exception=newSVpv("",0);
3829     av=NULL;
3830     if (sv_isobject(ST(0)) == 0)
3831       {
3832         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3833           PackageName);
3834         goto PerlException;
3835       }
3836     reference=SvRV(ST(0));
3837     av=newAV();
3838     SvREFCNT_dec(av);
3839     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3840     if (image == (Image *) NULL)
3841       {
3842         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3843           PackageName);
3844         goto PerlException;
3845       }
3846     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3847     distance=1;
3848     for (i=2; i < items; i+=2)
3849     {
3850       attribute=(char *) SvPV(ST(i-1),na);
3851       switch (*attribute)
3852       {
3853         case 'D':
3854         case 'd':
3855         {
3856           if (LocaleCompare(attribute,"distance") == 0)
3857             {
3858               distance=StringToLong((char *) SvPV(ST(1),na));
3859               break;
3860             }
3861           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3862             attribute);
3863           break;
3864         }
3865         default:
3866         {
3867           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3868             attribute);
3869           break;
3870         }
3871       }
3872     }
3873     count=0;
3874     for ( ; image; image=image->next)
3875     {
3876       channel_features=GetImageFeatures(image,distance,exception);
3877       if (channel_features == (ChannelFeatures *) NULL)
3878         continue;
3879       count++;
3880       EXTEND(sp,75*count);
3881       for (i=0; i < 4; i++)
3882       {
3883         ChannelFeatures(RedChannel,i);
3884         ChannelFeatures(GreenChannel,i);
3885         ChannelFeatures(BlueChannel,i);
3886         if (image->colorspace == CMYKColorspace)
3887           ChannelFeatures(BlackChannel,i);
3888         if (image->matte != MagickFalse)
3889           ChannelFeatures(AlphaChannel,i);
3890       }
3891       channel_features=(ChannelFeatures *)
3892         RelinquishMagickMemory(channel_features);
3893     }
3894
3895   PerlException:
3896     InheritPerlException(exception,perl_exception);
3897     exception=DestroyExceptionInfo(exception);
3898     SvREFCNT_dec(perl_exception);
3899   }
3900 \f
3901 #
3902 ###############################################################################
3903 #                                                                             #
3904 #                                                                             #
3905 #                                                                             #
3906 #   F l a t t e n                                                             #
3907 #                                                                             #
3908 #                                                                             #
3909 #                                                                             #
3910 ###############################################################################
3911 #
3912 #
3913 void
3914 Flatten(ref)
3915   Image::Magick ref=NO_INIT
3916   ALIAS:
3917     FlattenImage   = 1
3918     flatten        = 2
3919     flattenimage   = 3
3920   PPCODE:
3921   {
3922     AV
3923       *av;
3924
3925     char
3926       *attribute,
3927       *p;
3928
3929     ExceptionInfo
3930       *exception;
3931
3932     HV
3933       *hv;
3934
3935     Image
3936       *image;
3937
3938     PixelInfo
3939       background_color;
3940
3941     register ssize_t
3942       i;
3943
3944     struct PackageInfo
3945       *info;
3946
3947     SV
3948       *perl_exception,
3949       *reference,
3950       *rv,
3951       *sv;
3952
3953     PERL_UNUSED_VAR(ref);
3954     PERL_UNUSED_VAR(ix);
3955     exception=AcquireExceptionInfo();
3956     perl_exception=newSVpv("",0);
3957     sv=NULL;
3958     if (sv_isobject(ST(0)) == 0)
3959       {
3960         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3961           PackageName);
3962         goto PerlException;
3963       }
3964     reference=SvRV(ST(0));
3965     hv=SvSTASH(reference);
3966     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3967     if (image == (Image *) NULL)
3968       {
3969         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3970           PackageName);
3971         goto PerlException;
3972       }
3973     background_color=image->background_color;
3974     if (items == 2)
3975       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
3976         &background_color,exception);
3977     else
3978       for (i=2; i < items; i+=2)
3979       {
3980         attribute=(char *) SvPV(ST(i-1),na);
3981         switch (*attribute)
3982         {
3983           case 'B':
3984           case 'b':
3985           {
3986             if (LocaleCompare(attribute,"background") == 0)
3987               {
3988                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
3989                   AllCompliance,&background_color,exception);
3990                 break;
3991               }
3992             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3993               attribute);
3994             break;
3995           }
3996           default:
3997           {
3998             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3999               attribute);
4000             break;
4001           }
4002         }
4003       }
4004     image->background_color=background_color;
4005     image=MergeImageLayers(image,FlattenLayer,exception);
4006     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4007       goto PerlException;
4008     /*
4009       Create blessed Perl array for the returned image.
4010     */
4011     av=newAV();
4012     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4013     SvREFCNT_dec(av);
4014     AddImageToRegistry(sv,image);
4015     rv=newRV(sv);
4016     av_push(av,sv_bless(rv,hv));
4017     SvREFCNT_dec(sv);
4018     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4019     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4020       "flatten-%.*s",(int) (MaxTextExtent-9),
4021       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4022     (void) CopyMagickString(image->filename,info->image_info->filename,
4023       MaxTextExtent);
4024     SetImageInfo(info->image_info,0,exception);
4025     exception=DestroyExceptionInfo(exception);
4026     SvREFCNT_dec(perl_exception);
4027     XSRETURN(1);
4028
4029   PerlException:
4030     InheritPerlException(exception,perl_exception);
4031     exception=DestroyExceptionInfo(exception);
4032     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4033     SvPOK_on(perl_exception);  /* return messages in string context */
4034     ST(0)=sv_2mortal(perl_exception);
4035     XSRETURN(1);
4036   }
4037 \f
4038 #
4039 ###############################################################################
4040 #                                                                             #
4041 #                                                                             #
4042 #                                                                             #
4043 #   F x                                                                       #
4044 #                                                                             #
4045 #                                                                             #
4046 #                                                                             #
4047 ###############################################################################
4048 #
4049 #
4050 void
4051 Fx(ref,...)
4052   Image::Magick ref=NO_INIT
4053   ALIAS:
4054     FxImage  = 1
4055     fx       = 2
4056     fximage  = 3
4057   PPCODE:
4058   {
4059     AV
4060       *av;
4061
4062     char
4063       *attribute,
4064       expression[MaxTextExtent];
4065
4066     ChannelType
4067       channel,
4068       channel_mask;
4069
4070     ExceptionInfo
4071       *exception;
4072
4073     HV
4074       *hv;
4075
4076     Image
4077       *image;
4078
4079     register ssize_t
4080       i;
4081
4082     struct PackageInfo
4083       *info;
4084
4085     SV
4086       *av_reference,
4087       *perl_exception,
4088       *reference,
4089       *rv,
4090       *sv;
4091
4092     PERL_UNUSED_VAR(ref);
4093     PERL_UNUSED_VAR(ix);
4094     exception=AcquireExceptionInfo();
4095     perl_exception=newSVpv("",0);
4096     sv=NULL;
4097     attribute=NULL;
4098     av=NULL;
4099     if (sv_isobject(ST(0)) == 0)
4100       {
4101         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4102           PackageName);
4103         goto PerlException;
4104       }
4105     reference=SvRV(ST(0));
4106     hv=SvSTASH(reference);
4107     av=newAV();
4108     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4109     SvREFCNT_dec(av);
4110     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4111     if (image == (Image *) NULL)
4112       {
4113         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4114           PackageName);
4115         goto PerlException;
4116       }
4117     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4118     /*
4119       Get options.
4120     */
4121     channel=DefaultChannels;
4122     (void) CopyMagickString(expression,"u",MaxTextExtent);
4123     if (items == 2)
4124       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4125     else
4126       for (i=2; i < items; i+=2)
4127       {
4128         attribute=(char *) SvPV(ST(i-1),na);
4129         switch (*attribute)
4130         {
4131           case 'C':
4132           case 'c':
4133           {
4134             if (LocaleCompare(attribute,"channel") == 0)
4135               {
4136                 ssize_t
4137                   option;
4138
4139                 option=ParseChannelOption(SvPV(ST(i),na));
4140                 if (option < 0)
4141                   {
4142                     ThrowPerlException(exception,OptionError,
4143                       "UnrecognizedType",SvPV(ST(i),na));
4144                     return;
4145                   }
4146                 channel=(ChannelType) option;
4147                 break;
4148               }
4149             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4150               attribute);
4151             break;
4152           }
4153           case 'E':
4154           case 'e':
4155           {
4156             if (LocaleCompare(attribute,"expression") == 0)
4157               {
4158                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4159                   MaxTextExtent);
4160                 break;
4161               }
4162             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4163               attribute);
4164             break;
4165           }
4166           default:
4167           {
4168             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4169               attribute);
4170             break;
4171           }
4172         }
4173       }
4174     channel_mask=SetPixelChannelMask(image,channel);
4175     image=FxImage(image,expression,exception);
4176     if (image != (Image *) NULL)
4177       (void) SetPixelChannelMask(image,channel_mask);
4178     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4179       goto PerlException;
4180     for ( ; image; image=image->next)
4181     {
4182       AddImageToRegistry(sv,image);
4183       rv=newRV(sv);
4184       av_push(av,sv_bless(rv,hv));
4185       SvREFCNT_dec(sv);
4186     }
4187     exception=DestroyExceptionInfo(exception);
4188     ST(0)=av_reference;
4189     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4190     XSRETURN(1);
4191
4192   PerlException:
4193     InheritPerlException(exception,perl_exception);
4194     exception=DestroyExceptionInfo(exception);
4195     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4196     SvPOK_on(perl_exception);
4197     ST(0)=sv_2mortal(perl_exception);
4198     XSRETURN(1);
4199   }
4200 \f
4201 #
4202 ###############################################################################
4203 #                                                                             #
4204 #                                                                             #
4205 #                                                                             #
4206 #   G e t                                                                     #
4207 #                                                                             #
4208 #                                                                             #
4209 #                                                                             #
4210 ###############################################################################
4211 #
4212 #
4213 void
4214 Get(ref,...)
4215   Image::Magick ref=NO_INIT
4216   ALIAS:
4217     GetAttributes = 1
4218     GetAttribute  = 2
4219     get           = 3
4220     getattributes = 4
4221     getattribute  = 5
4222   PPCODE:
4223   {
4224     char
4225       *attribute,
4226       color[MaxTextExtent];
4227
4228     const char
4229       *value;
4230
4231     ExceptionInfo
4232       *exception;
4233
4234     Image
4235       *image;
4236
4237     long
4238       j;
4239
4240     register ssize_t
4241       i;
4242
4243     struct PackageInfo
4244       *info;
4245
4246     SV
4247       *perl_exception,
4248       *reference,
4249       *s;
4250
4251     PERL_UNUSED_VAR(ref);
4252     PERL_UNUSED_VAR(ix);
4253     exception=AcquireExceptionInfo();
4254     perl_exception=newSVpv("",0);
4255     if (sv_isobject(ST(0)) == 0)
4256       {
4257         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4258           PackageName);
4259         XSRETURN_EMPTY;
4260       }
4261     reference=SvRV(ST(0));
4262     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4263     if (image == (Image *) NULL && !info)
4264       XSRETURN_EMPTY;
4265     EXTEND(sp,items);
4266     for (i=1; i < items; i++)
4267     {
4268       attribute=(char *) SvPV(ST(i),na);
4269       s=NULL;
4270       switch (*attribute)
4271       {
4272         case 'A':
4273         case 'a':
4274         {
4275           if (LocaleCompare(attribute,"adjoin") == 0)
4276             {
4277               if (info)
4278                 s=newSViv((ssize_t) info->image_info->adjoin);
4279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4280               continue;
4281             }
4282           if (LocaleCompare(attribute,"antialias") == 0)
4283             {
4284               if (info)
4285                 s=newSViv((ssize_t) info->image_info->antialias);
4286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4287               continue;
4288             }
4289           if (LocaleCompare(attribute,"area") == 0)
4290             {
4291               s=newSViv(GetMagickResource(AreaResource));
4292               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4293               continue;
4294             }
4295           if (LocaleCompare(attribute,"attenuate") == 0)
4296             {
4297               const char
4298                 *value;
4299
4300               value=GetImageProperty(image,attribute,exception);
4301               if (value != (const char *) NULL)
4302                 s=newSVpv(value,0);
4303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4304               continue;
4305             }
4306           if (LocaleCompare(attribute,"authenticate") == 0)
4307             {
4308               if (info)
4309                 {
4310                   const char
4311                     *option;
4312
4313                   option=GetImageOption(info->image_info,attribute);
4314                   if (option != (const char *) NULL)
4315                     s=newSVpv(option,0);
4316                 }
4317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4318               continue;
4319             }
4320           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4321             attribute);
4322           break;
4323         }
4324         case 'B':
4325         case 'b':
4326         {
4327           if (LocaleCompare(attribute,"background") == 0)
4328             {
4329               if (image == (Image *) NULL)
4330                 break;
4331               (void) FormatLocaleString(color,MaxTextExtent,
4332                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4333                 image->background_color.green,image->background_color.blue,
4334                 image->background_color.alpha);
4335               s=newSVpv(color,0);
4336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4337               continue;
4338             }
4339           if (LocaleCompare(attribute,"base-columns") == 0)
4340             {
4341               if (image != (Image *) NULL)
4342                 s=newSViv((ssize_t) image->magick_columns);
4343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4344               continue;
4345             }
4346           if (LocaleCompare(attribute,"base-filename") == 0)
4347             {
4348               if (image != (Image *) NULL)
4349                 s=newSVpv(image->magick_filename,0);
4350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4351               continue;
4352             }
4353           if (LocaleCompare(attribute,"base-height") == 0)
4354             {
4355               if (image != (Image *) NULL)
4356                 s=newSViv((ssize_t) image->magick_rows);
4357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4358               continue;
4359             }
4360           if (LocaleCompare(attribute,"base-rows") == 0)
4361             {
4362               if (image != (Image *) NULL)
4363                 s=newSViv((ssize_t) image->magick_rows);
4364               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4365               continue;
4366             }
4367           if (LocaleCompare(attribute,"base-width") == 0)
4368             {
4369               if (image != (Image *) NULL)
4370                 s=newSViv((ssize_t) image->magick_columns);
4371               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4372               continue;
4373             }
4374           if (LocaleCompare(attribute,"bias") == 0)
4375             {
4376               if (image != (Image *) NULL)
4377                 s=newSVnv(image->bias);
4378               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4379               continue;
4380             }
4381           if (LocaleCompare(attribute,"blue-primary") == 0)
4382             {
4383               if (image == (Image *) NULL)
4384                 break;
4385               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4386                 image->chromaticity.blue_primary.x,
4387                 image->chromaticity.blue_primary.y);
4388               s=newSVpv(color,0);
4389               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4390               continue;
4391             }
4392           if (LocaleCompare(attribute,"bordercolor") == 0)
4393             {
4394               if (image == (Image *) NULL)
4395                 break;
4396               (void) FormatLocaleString(color,MaxTextExtent,
4397                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4398                 image->border_color.green,image->border_color.blue,
4399                 image->border_color.alpha);
4400               s=newSVpv(color,0);
4401               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4402               continue;
4403             }
4404           if (LocaleCompare(attribute,"bounding-box") == 0)
4405             {
4406               char
4407                 geometry[MaxTextExtent];
4408
4409               RectangleInfo
4410                 page;
4411
4412               if (image == (Image *) NULL)
4413                 break;
4414               page=GetImageBoundingBox(image,exception);
4415               (void) FormatLocaleString(geometry,MaxTextExtent,
4416                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4417                 page.height,(double) page.x,(double) page.y);
4418               s=newSVpv(geometry,0);
4419               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4420               continue;
4421             }
4422           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4423             attribute);
4424           break;
4425         }
4426         case 'C':
4427         case 'c':
4428         {
4429           if (LocaleCompare(attribute,"class") == 0)
4430             {
4431               if (image == (Image *) NULL)
4432                 break;
4433               s=newSViv(image->storage_class);
4434               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4435                 image->storage_class));
4436               SvIOK_on(s);
4437               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4438               continue;
4439             }
4440           if (LocaleCompare(attribute,"clip-mask") == 0)
4441             {
4442               if (image != (Image *) NULL)
4443                 {
4444                   SV
4445                     *sv;
4446
4447                   sv=NULL;
4448                   if (image->mask == (Image *) NULL)
4449                     ClipImage(image,exception);
4450                   if (image->mask != (Image *) NULL)
4451                     {
4452                       AddImageToRegistry(sv,image->mask);
4453                       s=sv_bless(newRV(sv),SvSTASH(reference));
4454                     }
4455                 }
4456               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4457               continue;
4458             }
4459           if (LocaleCompare(attribute,"clip-path") == 0)
4460             {
4461               if (image != (Image *) NULL)
4462                 {
4463                   SV
4464                     *sv;
4465
4466                   sv=NULL;
4467                   if (image->clip_mask == (Image *) NULL)
4468                     ClipImage(image,exception);
4469                   if (image->clip_mask != (Image *) NULL)
4470                     {
4471                       AddImageToRegistry(sv,image->clip_mask);
4472                       s=sv_bless(newRV(sv),SvSTASH(reference));
4473                     }
4474                 }
4475               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4476               continue;
4477             }
4478           if (LocaleCompare(attribute,"compression") == 0)
4479             {
4480               j=info ? info->image_info->compression : image ?
4481                 image->compression : UndefinedCompression;
4482               if (info)
4483                 if (info->image_info->compression == UndefinedCompression)
4484                   j=image->compression;
4485               s=newSViv(j);
4486               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4487                 j));
4488               SvIOK_on(s);
4489               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4490               continue;
4491             }
4492           if (LocaleCompare(attribute,"colorspace") == 0)
4493             {
4494               j=image ? image->colorspace : RGBColorspace;
4495               s=newSViv(j);
4496               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4497                 j));
4498               SvIOK_on(s);
4499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4500               continue;
4501             }
4502           if (LocaleCompare(attribute,"colors") == 0)
4503             {
4504               if (image != (Image *) NULL)
4505                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4506                   exception));
4507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4508               continue;
4509             }
4510           if (LocaleNCompare(attribute,"colormap",8) == 0)
4511             {
4512               int
4513                 items;
4514
4515               if (image == (Image *) NULL || !image->colormap)
4516                 break;
4517               j=0;
4518               items=sscanf(attribute,"%*[^[][%ld",&j);
4519               (void) items;
4520               if (j > (ssize_t) image->colors)
4521                 j%=image->colors;
4522               (void) FormatLocaleString(color,MaxTextExtent,
4523                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4524                 image->colormap[j].green,image->colormap[j].blue,
4525                 image->colormap[j].alpha);
4526               s=newSVpv(color,0);
4527               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4528               continue;
4529             }
4530           if (LocaleCompare(attribute,"columns") == 0)
4531             {
4532               if (image != (Image *) NULL)
4533                 s=newSViv((ssize_t) image->columns);
4534               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4535               continue;
4536             }
4537           if (LocaleCompare(attribute,"comment") == 0)
4538             {
4539               const char
4540                 *value;
4541
4542               value=GetImageProperty(image,attribute,exception);
4543               if (value != (const char *) NULL)
4544                 s=newSVpv(value,0);
4545               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4546               continue;
4547             }
4548           if (LocaleCompare(attribute,"copyright") == 0)
4549             {
4550               s=newSVpv(GetMagickCopyright(),0);
4551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4552               continue;
4553             }
4554           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4555             attribute);
4556           break;
4557         }
4558         case 'D':
4559         case 'd':
4560         {
4561           if (LocaleCompare(attribute,"density") == 0)
4562             {
4563               char
4564                 geometry[MaxTextExtent];
4565
4566               if (image == (Image *) NULL)
4567                 break;
4568               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4569                 image->resolution.x,image->resolution.y);
4570               s=newSVpv(geometry,0);
4571               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4572               continue;
4573             }
4574           if (LocaleCompare(attribute,"delay") == 0)
4575             {
4576               if (image != (Image *) NULL)
4577                 s=newSViv((ssize_t) image->delay);
4578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4579               continue;
4580             }
4581           if (LocaleCompare(attribute,"depth") == 0)
4582             {
4583               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4584               if (image != (Image *) NULL)
4585                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4586               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4587               continue;
4588             }
4589           if (LocaleCompare(attribute,"directory") == 0)
4590             {
4591               if (image && image->directory)
4592                 s=newSVpv(image->directory,0);
4593               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4594               continue;
4595             }
4596           if (LocaleCompare(attribute,"dispose") == 0)
4597             {
4598               if (image == (Image *) NULL)
4599                 break;
4600
4601               s=newSViv(image->dispose);
4602               (void) sv_setpv(s,
4603                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4604               SvIOK_on(s);
4605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4606               continue;
4607             }
4608           if (LocaleCompare(attribute,"disk") == 0)
4609             {
4610               s=newSViv(GetMagickResource(DiskResource));
4611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4612               continue;
4613             }
4614           if (LocaleCompare(attribute,"dither") == 0)
4615             {
4616               if (info)
4617                 s=newSViv((ssize_t) info->image_info->dither);
4618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619               continue;
4620             }
4621           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4622             {
4623               if (info && info->image_info->server_name)
4624                 s=newSVpv(info->image_info->server_name,0);
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4629             attribute);
4630           break;
4631         }
4632         case 'E':
4633         case 'e':
4634         {
4635           if (LocaleCompare(attribute,"elapsed-time") == 0)
4636             {
4637               if (image != (Image *) NULL)
4638                 s=newSVnv(GetElapsedTime(&image->timer));
4639               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4640               continue;
4641             }
4642           if (LocaleCompare(attribute,"endian") == 0)
4643             {
4644               j=info ? info->image_info->endian : image ? image->endian :
4645                 UndefinedEndian;
4646               s=newSViv(j);
4647               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4648               SvIOK_on(s);
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"error") == 0)
4653             {
4654               if (image != (Image *) NULL)
4655                 s=newSVnv(image->error.mean_error_per_pixel);
4656               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4657               continue;
4658             }
4659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4660             attribute);
4661           break;
4662         }
4663         case 'F':
4664         case 'f':
4665         {
4666           if (LocaleCompare(attribute,"filesize") == 0)
4667             {
4668               if (image != (Image *) NULL)
4669                 s=newSViv((ssize_t) GetBlobSize(image));
4670               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4671               continue;
4672             }
4673           if (LocaleCompare(attribute,"filename") == 0)
4674             {
4675               if (info && info->image_info->filename &&
4676                   *info->image_info->filename)
4677                 s=newSVpv(info->image_info->filename,0);
4678               if (image != (Image *) NULL)
4679                 s=newSVpv(image->filename,0);
4680               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4681               continue;
4682             }
4683           if (LocaleCompare(attribute,"filter") == 0)
4684             {
4685               s=image ? newSViv(image->filter) : newSViv(0);
4686               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4687                 image->filter));
4688               SvIOK_on(s);
4689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690               continue;
4691             }
4692           if (LocaleCompare(attribute,"font") == 0)
4693             {
4694               if (info && info->image_info->font)
4695                 s=newSVpv(info->image_info->font,0);
4696               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4697               continue;
4698             }
4699           if (LocaleCompare(attribute,"foreground") == 0)
4700             continue;
4701           if (LocaleCompare(attribute,"format") == 0)
4702             {
4703               const MagickInfo
4704                 *magick_info;
4705
4706               magick_info=(const MagickInfo *) NULL;
4707               if (info && (*info->image_info->magick != '\0'))
4708                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4709               if (image != (Image *) NULL)
4710                 magick_info=GetMagickInfo(image->magick,exception);
4711               if ((magick_info != (const MagickInfo *) NULL) &&
4712                   (*magick_info->description != '\0'))
4713                 s=newSVpv((char *) magick_info->description,0);
4714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715               continue;
4716             }
4717           if (LocaleCompare(attribute,"fuzz") == 0)
4718             {
4719               if (info)
4720                 s=newSVnv(info->image_info->fuzz);
4721               if (image != (Image *) NULL)
4722                 s=newSVnv(image->fuzz);
4723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4724               continue;
4725             }
4726           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4727             attribute);
4728           break;
4729         }
4730         case 'G':
4731         case 'g':
4732         {
4733           if (LocaleCompare(attribute,"gamma") == 0)
4734             {
4735               if (image != (Image *) NULL)
4736                 s=newSVnv(image->gamma);
4737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4738               continue;
4739             }
4740           if (LocaleCompare(attribute,"geometry") == 0)
4741             {
4742               if (image && image->geometry)
4743                 s=newSVpv(image->geometry,0);
4744               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4745               continue;
4746             }
4747           if (LocaleCompare(attribute,"gravity") == 0)
4748             {
4749               s=image ? newSViv(image->gravity) : newSViv(0);
4750               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4751                 image->gravity));
4752               SvIOK_on(s);
4753               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4754               continue;
4755             }
4756           if (LocaleCompare(attribute,"green-primary") == 0)
4757             {
4758               if (image == (Image *) NULL)
4759                 break;
4760               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4761                 image->chromaticity.green_primary.x,
4762                 image->chromaticity.green_primary.y);
4763               s=newSVpv(color,0);
4764               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4765               continue;
4766             }
4767           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4768             attribute);
4769           break;
4770         }
4771         case 'H':
4772         case 'h':
4773         {
4774           if (LocaleCompare(attribute,"height") == 0)
4775             {
4776               if (image != (Image *) NULL)
4777                 s=newSViv((ssize_t) image->rows);
4778               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4779               continue;
4780             }
4781           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4782             attribute);
4783           break;
4784         }
4785         case 'I':
4786         case 'i':
4787         {
4788           if (LocaleCompare(attribute,"icc") == 0)
4789             {
4790               if (image != (Image *) NULL)
4791                 {
4792                   const StringInfo
4793                     *profile;
4794
4795                   profile=GetImageProfile(image,"icc");
4796                   if (profile != (StringInfo *) NULL)
4797                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4798                       GetStringInfoLength(profile));
4799                 }
4800               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4801               continue;
4802             }
4803           if (LocaleCompare(attribute,"icm") == 0)
4804             {
4805               if (image != (Image *) NULL)
4806                 {
4807                   const StringInfo
4808                     *profile;
4809
4810                   profile=GetImageProfile(image,"icm");
4811                   if (profile != (const StringInfo *) NULL)
4812                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4813                       GetStringInfoLength(profile));
4814                 }
4815               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4816               continue;
4817             }
4818           if (LocaleCompare(attribute,"id") == 0)
4819             {
4820               if (image != (Image *) NULL)
4821                 {
4822                   char
4823                     key[MaxTextExtent];
4824
4825                   MagickBooleanType
4826                     status;
4827
4828                   static ssize_t
4829                     id = 0;
4830
4831                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4832                     id);
4833                   status=SetImageRegistry(ImageRegistryType,key,image,
4834                     exception);
4835                   (void) status;
4836                   s=newSViv(id++);
4837                 }
4838               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4839               continue;
4840             }
4841           if (LocaleNCompare(attribute,"index",5) == 0)
4842             {
4843               char
4844                 name[MaxTextExtent];
4845
4846               int
4847                 items;
4848
4849               long
4850                 x,
4851                 y;
4852
4853               register const Quantum
4854                 *p;
4855
4856               CacheView
4857                 *image_view;
4858
4859               if (image == (Image *) NULL)
4860                 break;
4861               if (image->storage_class != PseudoClass)
4862                 break;
4863               x=0;
4864               y=0;
4865               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4866               (void) items;
4867               image_view=AcquireCacheView(image);
4868               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
4869               if (p != (const Quantum *) NULL)
4870                 {
4871                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4872                     GetPixelIndex(image,p));
4873                   s=newSVpv(name,0);
4874                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4875                 }
4876               image_view=DestroyCacheView(image_view);
4877               continue;
4878             }
4879           if (LocaleCompare(attribute,"iptc") == 0)
4880             {
4881               if (image != (Image *) NULL)
4882                 {
4883                   const StringInfo
4884                     *profile;
4885
4886                   profile=GetImageProfile(image,"iptc");
4887                   if (profile != (const StringInfo *) NULL)
4888                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4889                       GetStringInfoLength(profile));
4890                 }
4891               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4892               continue;
4893             }
4894           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4895             {
4896               if (image != (Image *) NULL)
4897                 s=newSViv((ssize_t) image->iterations);
4898               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4899               continue;
4900             }
4901           if (LocaleCompare(attribute,"interlace") == 0)
4902             {
4903               j=info ? info->image_info->interlace : image ? image->interlace :
4904                 UndefinedInterlace;
4905               s=newSViv(j);
4906               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4907                 j));
4908               SvIOK_on(s);
4909               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4910               continue;
4911             }
4912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4913             attribute);
4914           break;
4915         }
4916         case 'L':
4917         case 'l':
4918         {
4919           if (LocaleCompare(attribute,"label") == 0)
4920             {
4921               const char
4922                 *value;
4923
4924               if (image == (Image *) NULL)
4925                 break;
4926               value=GetImageProperty(image,"Label",exception);
4927               if (value != (const char *) NULL)
4928                 s=newSVpv(value,0);
4929               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4930               continue;
4931             }
4932           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4933             {
4934               if (image != (Image *) NULL)
4935                 s=newSViv((ssize_t) image->iterations);
4936               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4937               continue;
4938             }
4939           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4940             attribute);
4941           break;
4942         }
4943         case 'M':
4944         case 'm':
4945         {
4946           if (LocaleCompare(attribute,"magick") == 0)
4947             {
4948               if (info && *info->image_info->magick)
4949                 s=newSVpv(info->image_info->magick,0);
4950               if (image != (Image *) NULL)
4951                 s=newSVpv(image->magick,0);
4952               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4953               continue;
4954             }
4955           if (LocaleCompare(attribute,"map") == 0)
4956             {
4957               s=newSViv(GetMagickResource(MapResource));
4958               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959               continue;
4960             }
4961           if (LocaleCompare(attribute,"maximum-error") == 0)
4962             {
4963               if (image != (Image *) NULL)
4964                 s=newSVnv(image->error.normalized_maximum_error);
4965               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4966               continue;
4967             }
4968           if (LocaleCompare(attribute,"memory") == 0)
4969             {
4970               s=newSViv(GetMagickResource(MemoryResource));
4971               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972               continue;
4973             }
4974           if (LocaleCompare(attribute,"mean-error") == 0)
4975             {
4976               if (image != (Image *) NULL)
4977                 s=newSVnv(image->error.normalized_mean_error);
4978               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979               continue;
4980             }
4981           if (LocaleCompare(attribute,"mime") == 0)
4982             {
4983               if (info && *info->image_info->magick)
4984                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4985               if (image != (Image *) NULL)
4986                 s=newSVpv(MagickToMime(image->magick),0);
4987               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4988               continue;
4989             }
4990           if (LocaleCompare(attribute,"mattecolor") == 0)
4991             {
4992               if (image == (Image *) NULL)
4993                 break;
4994               (void) FormatLocaleString(color,MaxTextExtent,
4995                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
4996                 image->matte_color.green,image->matte_color.blue,
4997                 image->matte_color.alpha);
4998               s=newSVpv(color,0);
4999               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000               continue;
5001             }
5002           if (LocaleCompare(attribute,"matte") == 0)
5003             {
5004               if (image != (Image *) NULL)
5005                 s=newSViv((ssize_t) image->matte);
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           if (LocaleCompare(attribute,"mime") == 0)
5010             {
5011               const char
5012                 *magick;
5013
5014               magick=NULL;
5015               if (info && *info->image_info->magick)
5016                 magick=info->image_info->magick;
5017               if (image != (Image *) NULL)
5018                 magick=image->magick;
5019               if (magick)
5020                 {
5021                   char
5022                     *mime;
5023
5024                   mime=MagickToMime(magick);
5025                   s=newSVpv(mime,0);
5026                   mime=(char *) RelinquishMagickMemory(mime);
5027                 }
5028               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5029               continue;
5030             }
5031           if (LocaleCompare(attribute,"monochrome") == 0)
5032             {
5033               if (image == (Image *) NULL)
5034                 continue;
5035               j=info ? info->image_info->monochrome :
5036                 IsImageMonochrome(image,exception);
5037               s=newSViv(j);
5038               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5039               continue;
5040             }
5041           if (LocaleCompare(attribute,"montage") == 0)
5042             {
5043               if (image && image->montage)
5044                 s=newSVpv(image->montage,0);
5045               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5046               continue;
5047             }
5048           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5049             attribute);
5050           break;
5051         }
5052         case 'O':
5053         case 'o':
5054         {
5055           if (LocaleCompare(attribute,"orientation") == 0)
5056             {
5057               j=info ? info->image_info->orientation : image ?
5058                 image->orientation : UndefinedOrientation;
5059               s=newSViv(j);
5060               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5061                 j));
5062               SvIOK_on(s);
5063               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5064               continue;
5065             }
5066           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5067             attribute);
5068           break;
5069         }
5070         case 'P':
5071         case 'p':
5072         {
5073           if (LocaleCompare(attribute,"page") == 0)
5074             {
5075               if (info && info->image_info->page)
5076                 s=newSVpv(info->image_info->page,0);
5077               if (image != (Image *) NULL)
5078                 {
5079                   char
5080                     geometry[MaxTextExtent];
5081
5082                   (void) FormatLocaleString(geometry,MaxTextExtent,
5083                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5084                     (double) image->page.height,(double) image->page.x,(double)
5085                     image->page.y);
5086                   s=newSVpv(geometry,0);
5087                 }
5088               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5089               continue;
5090             }
5091           if (LocaleCompare(attribute,"page.x") == 0)
5092             {
5093               if (image != (Image *) NULL)
5094                 s=newSViv((ssize_t) image->page.x);
5095               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5096               continue;
5097             }
5098           if (LocaleCompare(attribute,"page.y") == 0)
5099             {
5100               if (image != (Image *) NULL)
5101                 s=newSViv((ssize_t) image->page.y);
5102               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5103               continue;
5104             }
5105           if (LocaleNCompare(attribute,"pixel",5) == 0)
5106             {
5107               char
5108                 tuple[MaxTextExtent];
5109
5110               int
5111                 items;
5112
5113               long
5114                 x,
5115                 y;
5116
5117               register const Quantum
5118                 *p;
5119
5120               if (image == (Image *) NULL)
5121                 break;
5122               x=0;
5123               y=0;
5124               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5125               (void) items;
5126               p=GetVirtualPixels(image,x,y,1,1,exception);
5127               if (image->colorspace != CMYKColorspace)
5128                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5129                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5130                   GetPixelRed(image,p),GetPixelGreen(image,p),
5131                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5132               else
5133                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5134                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5135                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5136                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5137                   GetPixelAlpha(image,p));
5138               s=newSVpv(tuple,0);
5139               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5140               continue;
5141             }
5142           if (LocaleCompare(attribute,"pointsize") == 0)
5143             {
5144               if (info)
5145                 s=newSViv((ssize_t) info->image_info->pointsize);
5146               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5147               continue;
5148             }
5149           if (LocaleCompare(attribute,"preview") == 0)
5150             {
5151               s=newSViv(info->image_info->preview_type);
5152               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5153                 info->image_info->preview_type));
5154               SvIOK_on(s);
5155               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5156               continue;
5157             }
5158           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5159             attribute);
5160           break;
5161         }
5162         case 'Q':
5163         case 'q':
5164         {
5165           if (LocaleCompare(attribute,"quality") == 0)
5166             {
5167               if (info)
5168                 s=newSViv((ssize_t) info->image_info->quality);
5169               if (image != (Image *) NULL)
5170                 s=newSViv((ssize_t) image->quality);
5171               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5172               continue;
5173             }
5174           if (LocaleCompare(attribute,"quantum") == 0)
5175             {
5176               if (info)
5177                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5178               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5179               continue;
5180             }
5181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5182             attribute);
5183           break;
5184         }
5185         case 'R':
5186         case 'r':
5187         {
5188           if (LocaleCompare(attribute,"rendering-intent") == 0)
5189             {
5190               s=newSViv(image->rendering_intent);
5191               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5192                 image->rendering_intent));
5193               SvIOK_on(s);
5194               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5195               continue;
5196             }
5197           if (LocaleCompare(attribute,"red-primary") == 0)
5198             {
5199               if (image == (Image *) NULL)
5200                 break;
5201               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5202                 image->chromaticity.red_primary.x,
5203                 image->chromaticity.red_primary.y);
5204               s=newSVpv(color,0);
5205               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5206               continue;
5207             }
5208           if (LocaleCompare(attribute,"rows") == 0)
5209             {
5210               if (image != (Image *) NULL)
5211                 s=newSViv((ssize_t) image->rows);
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5216             attribute);
5217           break;
5218         }
5219         case 'S':
5220         case 's':
5221         {
5222           if (LocaleCompare(attribute,"sampling-factor") == 0)
5223             {
5224               if (info && info->image_info->sampling_factor)
5225                 s=newSVpv(info->image_info->sampling_factor,0);
5226               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5230             {
5231               if (info && info->image_info->server_name)
5232                 s=newSVpv(info->image_info->server_name,0);
5233               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5234               continue;
5235             }
5236           if (LocaleCompare(attribute,"size") == 0)
5237             {
5238               if (info && info->image_info->size)
5239                 s=newSVpv(info->image_info->size,0);
5240               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5241               continue;
5242             }
5243           if (LocaleCompare(attribute,"scene") == 0)
5244             {
5245               if (image != (Image *) NULL)
5246                 s=newSViv((ssize_t) image->scene);
5247               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5248               continue;
5249             }
5250           if (LocaleCompare(attribute,"scenes") == 0)
5251             {
5252               if (image != (Image *) NULL)
5253                 s=newSViv((ssize_t) info->image_info->number_scenes);
5254               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5255               continue;
5256             }
5257           if (LocaleCompare(attribute,"signature") == 0)
5258             {
5259               const char
5260                 *value;
5261
5262               if (image == (Image *) NULL)
5263                 break;
5264               (void) SignatureImage(image,exception);
5265               value=GetImageProperty(image,"Signature",exception);
5266               if (value != (const char *) NULL)
5267                 s=newSVpv(value,0);
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5272             attribute);
5273           break;
5274         }
5275         case 'T':
5276         case 't':
5277         {
5278           if (LocaleCompare(attribute,"taint") == 0)
5279             {
5280               if (image != (Image *) NULL)
5281                 s=newSViv((ssize_t) IsTaintImage(image));
5282               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5283               continue;
5284             }
5285           if (LocaleCompare(attribute,"texture") == 0)
5286             {
5287               if (info && info->image_info->texture)
5288                 s=newSVpv(info->image_info->texture,0);
5289               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5290               continue;
5291             }
5292           if (LocaleCompare(attribute,"total-ink-density") == 0)
5293             {
5294               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5295               if (image != (Image *) NULL)
5296                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298               continue;
5299             }
5300           if (LocaleCompare(attribute,"transparent-color") == 0)
5301             {
5302               if (image == (Image *) NULL)
5303                 break;
5304               (void) FormatLocaleString(color,MaxTextExtent,
5305                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5306                 image->transparent_color.green,image->transparent_color.blue,
5307                 image->transparent_color.alpha);
5308               s=newSVpv(color,0);
5309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5310               continue;
5311             }
5312           if (LocaleCompare(attribute,"type") == 0)
5313             {
5314               if (image == (Image *) NULL)
5315                 break;
5316               j=(ssize_t) GetImageType(image,exception);
5317               s=newSViv(j);
5318               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5319               SvIOK_on(s);
5320               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5321               continue;
5322             }
5323           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5324             attribute);
5325           break;
5326         }
5327         case 'U':
5328         case 'u':
5329         {
5330           if (LocaleCompare(attribute,"units") == 0)
5331             {
5332               j=info ? info->image_info->units : image ? image->units :
5333                 UndefinedResolution;
5334               if (info && (info->image_info->units == UndefinedResolution))
5335                 if (image)
5336                   j=image->units;
5337               if (j == UndefinedResolution)
5338                 s=newSVpv("undefined units",0);
5339               else
5340                 if (j == PixelsPerInchResolution)
5341                   s=newSVpv("pixels / inch",0);
5342                 else
5343                   s=newSVpv("pixels / centimeter",0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"user-time") == 0)
5348             {
5349               if (image != (Image *) NULL)
5350                 s=newSVnv(GetUserTime(&image->timer));
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5355             attribute);
5356           break;
5357         }
5358         case 'V':
5359         case 'v':
5360         {
5361           if (LocaleCompare(attribute,"verbose") == 0)
5362             {
5363               if (info)
5364                 s=newSViv((ssize_t) info->image_info->verbose);
5365               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5366               continue;
5367             }
5368           if (LocaleCompare(attribute,"version") == 0)
5369             {
5370               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5371               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5372               continue;
5373             }
5374           if (LocaleCompare(attribute,"view") == 0)
5375             {
5376               if (info && info->image_info->view)
5377                 s=newSVpv(info->image_info->view,0);
5378               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5379               continue;
5380             }
5381           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5382             {
5383               if (image == (Image *) NULL)
5384                 break;
5385               j=(ssize_t) GetImageVirtualPixelMethod(image);
5386               s=newSViv(j);
5387               (void) sv_setpv(s,CommandOptionToMnemonic(
5388                 MagickVirtualPixelOptions,j));
5389               SvIOK_on(s);
5390               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5391               continue;
5392             }
5393           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5394             attribute);
5395           break;
5396         }
5397         case 'W':
5398         case 'w':
5399         {
5400           if (LocaleCompare(attribute,"white-point") == 0)
5401             {
5402               if (image == (Image *) NULL)
5403                 break;
5404               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5405                 image->chromaticity.white_point.x,
5406                 image->chromaticity.white_point.y);
5407               s=newSVpv(color,0);
5408               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5409               continue;
5410             }
5411           if (LocaleCompare(attribute,"width") == 0)
5412             {
5413               if (image != (Image *) NULL)
5414                 s=newSViv((ssize_t) image->columns);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419              attribute);
5420           break;
5421         }
5422         case 'X':
5423         case 'x':
5424         {
5425           if (LocaleCompare(attribute,"x-resolution") == 0)
5426             {
5427               if (image != (Image *) NULL)
5428                 s=newSVnv(image->resolution.x);
5429               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5430               continue;
5431             }
5432           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5433             attribute);
5434           break;
5435         }
5436         case 'Y':
5437         case 'y':
5438         {
5439           if (LocaleCompare(attribute,"y-resolution") == 0)
5440             {
5441               if (image != (Image *) NULL)
5442                 s=newSVnv(image->resolution.y);
5443               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5444               continue;
5445             }
5446           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5447             attribute);
5448           break;
5449         }
5450         default:
5451           break;
5452       }
5453       if (image == (Image *) NULL)
5454         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5455           attribute)
5456       else
5457         {
5458           value=GetImageProperty(image,attribute,exception);
5459           if (value != (const char *) NULL)
5460             {
5461               s=newSVpv(value,0);
5462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463             }
5464           else
5465             if (*attribute != '%')
5466               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5467                 attribute)
5468             else
5469               {
5470                  char
5471                    *meta;
5472
5473                  meta=InterpretImageProperties(info ? info->image_info :
5474                    (ImageInfo *) NULL,image,attribute,exception);
5475                  s=newSVpv(meta,0);
5476                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5477                  meta=(char *) RelinquishMagickMemory(meta);
5478               }
5479         }
5480     }
5481     exception=DestroyExceptionInfo(exception);
5482     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5483   }
5484 \f
5485 #
5486 ###############################################################################
5487 #                                                                             #
5488 #                                                                             #
5489 #                                                                             #
5490 #   G e t A u t h e n t i c P i x e l s                                       #
5491 #                                                                             #
5492 #                                                                             #
5493 #                                                                             #
5494 ###############################################################################
5495 #
5496 #
5497 void *
5498 GetAuthenticPixels(ref,...)
5499   Image::Magick ref = NO_INIT
5500   ALIAS:
5501     getauthenticpixels = 1
5502     GetImagePixels = 2
5503     getimagepixels = 3
5504   CODE:
5505   {
5506     char
5507       *attribute;
5508
5509     ExceptionInfo
5510       *exception;
5511
5512     Image
5513       *image;
5514
5515     RectangleInfo
5516       region;
5517
5518     ssize_t
5519       i;
5520
5521     struct PackageInfo
5522       *info;
5523
5524     SV
5525       *perl_exception,
5526       *reference;
5527
5528     void
5529       *blob = NULL;
5530
5531     PERL_UNUSED_VAR(ref);
5532     PERL_UNUSED_VAR(ix);
5533     exception=AcquireExceptionInfo();
5534     perl_exception=newSVpv("",0);
5535     if (sv_isobject(ST(0)) == 0)
5536       {
5537         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5538           PackageName);
5539         goto PerlException;
5540       }
5541     reference=SvRV(ST(0));
5542
5543     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5544     if (image == (Image *) NULL)
5545       {
5546         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5547           PackageName);
5548         goto PerlException;
5549       }
5550
5551     region.x=0;
5552     region.y=0;
5553     region.width=image->columns;
5554     region.height=1;
5555     if (items == 1)
5556       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5557     for (i=2; i < items; i+=2)
5558     {
5559       attribute=(char *) SvPV(ST(i-1),na);
5560       switch (*attribute)
5561       {
5562         case 'g':
5563         case 'G':
5564         {
5565           if (LocaleCompare(attribute,"geometry") == 0)
5566             {
5567               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5568               break;
5569             }
5570           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5571             attribute);
5572           break;
5573         }
5574         case 'H':
5575         case 'h':
5576         {
5577           if (LocaleCompare(attribute,"height") == 0)
5578             {
5579               region.height=SvIV(ST(i));
5580               continue;
5581             }
5582           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5583             attribute);
5584           break;
5585         }
5586         case 'X':
5587         case 'x':
5588         {
5589           if (LocaleCompare(attribute,"x") == 0)
5590             {
5591               region.x=SvIV(ST(i));
5592               continue;
5593             }
5594           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5595             attribute);
5596           break;
5597         }
5598         case 'Y':
5599         case 'y':
5600         {
5601           if (LocaleCompare(attribute,"y") == 0)
5602             {
5603               region.y=SvIV(ST(i));
5604               continue;
5605             }
5606           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5607             attribute);
5608           break;
5609         }
5610         case 'W':
5611         case 'w':
5612         {
5613           if (LocaleCompare(attribute,"width") == 0)
5614             {
5615               region.width=SvIV(ST(i));
5616               continue;
5617             }
5618           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5619             attribute);
5620           break;
5621         }
5622       }
5623     }
5624     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5625       region.height,exception);
5626     if (blob != (void *) NULL)
5627       goto PerlEnd;
5628
5629   PerlException:
5630     InheritPerlException(exception,perl_exception);
5631     exception=DestroyExceptionInfo(exception);
5632     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5633
5634   PerlEnd:
5635     RETVAL = blob;
5636   }
5637   OUTPUT:
5638     RETVAL
5639 \f
5640 #
5641 ###############################################################################
5642 #                                                                             #
5643 #                                                                             #
5644 #                                                                             #
5645 #   G e t V i r t u a l P i x e l s                                           #
5646 #                                                                             #
5647 #                                                                             #
5648 #                                                                             #
5649 ###############################################################################
5650 #
5651 #
5652 void *
5653 GetVirtualPixels(ref,...)
5654   Image::Magick ref = NO_INIT
5655   ALIAS:
5656     getvirtualpixels = 1
5657     AcquireImagePixels = 2
5658     acquireimagepixels = 3
5659   CODE:
5660   {
5661     char
5662       *attribute;
5663
5664     const void
5665       *blob = NULL;
5666
5667     ExceptionInfo
5668       *exception;
5669
5670     Image
5671       *image;
5672
5673     RectangleInfo
5674       region;
5675
5676     ssize_t
5677       i;
5678
5679     struct PackageInfo
5680       *info;
5681
5682     SV
5683       *perl_exception,
5684       *reference;
5685
5686     PERL_UNUSED_VAR(ref);
5687     PERL_UNUSED_VAR(ix);
5688     exception=AcquireExceptionInfo();
5689     perl_exception=newSVpv("",0);
5690     if (sv_isobject(ST(0)) == 0)
5691       {
5692         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5693           PackageName);
5694         goto PerlException;
5695       }
5696     reference=SvRV(ST(0));
5697
5698     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5699     if (image == (Image *) NULL)
5700       {
5701         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5702           PackageName);
5703         goto PerlException;
5704       }
5705
5706     region.x=0;
5707     region.y=0;
5708     region.width=image->columns;
5709     region.height=1;
5710     if (items == 1)
5711       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5712     for (i=2; i < items; i+=2)
5713     {
5714       attribute=(char *) SvPV(ST(i-1),na);
5715       switch (*attribute)
5716       {
5717         case 'g':
5718         case 'G':
5719         {
5720           if (LocaleCompare(attribute,"geometry") == 0)
5721             {
5722               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5723               break;
5724             }
5725           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5726             attribute);
5727           break;
5728         }
5729         case 'H':
5730         case 'h':
5731         {
5732           if (LocaleCompare(attribute,"height") == 0)
5733             {
5734               region.height=SvIV(ST(i));
5735               continue;
5736             }
5737           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5738             attribute);
5739           break;
5740         }
5741         case 'X':
5742         case 'x':
5743         {
5744           if (LocaleCompare(attribute,"x") == 0)
5745             {
5746               region.x=SvIV(ST(i));
5747               continue;
5748             }
5749           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5750             attribute);
5751           break;
5752         }
5753         case 'Y':
5754         case 'y':
5755         {
5756           if (LocaleCompare(attribute,"y") == 0)
5757             {
5758               region.y=SvIV(ST(i));
5759               continue;
5760             }
5761           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5762             attribute);
5763           break;
5764         }
5765         case 'W':
5766         case 'w':
5767         {
5768           if (LocaleCompare(attribute,"width") == 0)
5769             {
5770               region.width=SvIV(ST(i));
5771               continue;
5772             }
5773           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5774             attribute);
5775           break;
5776         }
5777       }
5778     }
5779     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5780       region.height,exception);
5781     if (blob != (void *) NULL)
5782       goto PerlEnd;
5783
5784   PerlException:
5785     InheritPerlException(exception,perl_exception);
5786     exception=DestroyExceptionInfo(exception);
5787     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5788
5789   PerlEnd:
5790     RETVAL = (void *) blob;
5791   }
5792   OUTPUT:
5793     RETVAL
5794 \f
5795 #
5796 ###############################################################################
5797 #                                                                             #
5798 #                                                                             #
5799 #                                                                             #
5800 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5801 #                                                                             #
5802 #                                                                             #
5803 #                                                                             #
5804 ###############################################################################
5805 #
5806 #
5807 void *
5808 GetAuthenticMetacontent(ref,...)
5809   Image::Magick ref = NO_INIT
5810   ALIAS:
5811     getauthenticmetacontent = 1
5812     GetMetacontent = 2
5813     getmetacontent = 3
5814   CODE:
5815   {
5816     ExceptionInfo
5817       *exception;
5818
5819     Image
5820       *image;
5821
5822     struct PackageInfo
5823       *info;
5824
5825     SV
5826       *perl_exception,
5827       *reference;
5828
5829     void
5830       *blob = NULL;
5831
5832     PERL_UNUSED_VAR(ref);
5833     PERL_UNUSED_VAR(ix);
5834     exception=AcquireExceptionInfo();
5835     perl_exception=newSVpv("",0);
5836     if (sv_isobject(ST(0)) == 0)
5837       {
5838         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5839           PackageName);
5840         goto PerlException;
5841       }
5842     reference=SvRV(ST(0));
5843
5844     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5845     if (image == (Image *) NULL)
5846       {
5847         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5848           PackageName);
5849         goto PerlException;
5850       }
5851
5852     blob=(void *) GetAuthenticMetacontent(image);
5853     if (blob != (void *) NULL)
5854       goto PerlEnd;
5855
5856   PerlException:
5857     InheritPerlException(exception,perl_exception);
5858     exception=DestroyExceptionInfo(exception);
5859     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5860
5861   PerlEnd:
5862     RETVAL = blob;
5863   }
5864   OUTPUT:
5865     RETVAL
5866 \f
5867 #
5868 ###############################################################################
5869 #                                                                             #
5870 #                                                                             #
5871 #                                                                             #
5872 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5873 #                                                                             #
5874 #                                                                             #
5875 #                                                                             #
5876 ###############################################################################
5877 #
5878 #
5879 void *
5880 GetVirtualMetacontent(ref,...)
5881   Image::Magick ref = NO_INIT
5882   ALIAS:
5883     getvirtualmetacontent = 1
5884   CODE:
5885   {
5886     ExceptionInfo
5887       *exception;
5888
5889     Image
5890       *image;
5891
5892     struct PackageInfo
5893       *info;
5894
5895     SV
5896       *perl_exception,
5897       *reference;
5898
5899     void
5900       *blob = NULL;
5901
5902     PERL_UNUSED_VAR(ref);
5903     PERL_UNUSED_VAR(ix);
5904     exception=AcquireExceptionInfo();
5905     perl_exception=newSVpv("",0);
5906     if (sv_isobject(ST(0)) == 0)
5907       {
5908         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5909           PackageName);
5910         goto PerlException;
5911       }
5912     reference=SvRV(ST(0));
5913
5914     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5915     if (image == (Image *) NULL)
5916       {
5917         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5918           PackageName);
5919         goto PerlException;
5920       }
5921
5922     blob=(void *) GetVirtualMetacontent(image);
5923     if (blob != (void *) NULL)
5924       goto PerlEnd;
5925
5926   PerlException:
5927     InheritPerlException(exception,perl_exception);
5928     exception=DestroyExceptionInfo(exception);
5929     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5930
5931   PerlEnd:
5932     RETVAL = blob;
5933   }
5934   OUTPUT:
5935     RETVAL
5936 \f
5937 #
5938 ###############################################################################
5939 #                                                                             #
5940 #                                                                             #
5941 #                                                                             #
5942 #   H i s t o g r a m                                                         #
5943 #                                                                             #
5944 #                                                                             #
5945 #                                                                             #
5946 ###############################################################################
5947 #
5948 #
5949 void
5950 Histogram(ref,...)
5951   Image::Magick ref=NO_INIT
5952   ALIAS:
5953     HistogramImage = 1
5954     histogram      = 2
5955     histogramimage = 3
5956   PPCODE:
5957   {
5958     AV
5959       *av;
5960
5961     char
5962       message[MaxTextExtent];
5963
5964     PixelInfo
5965       *histogram;
5966
5967     ExceptionInfo
5968       *exception;
5969
5970     Image
5971       *image;
5972
5973     register ssize_t
5974       i;
5975
5976     ssize_t
5977       count;
5978
5979     struct PackageInfo
5980       *info;
5981
5982     SV
5983       *perl_exception,
5984       *reference;
5985
5986     size_t
5987       number_colors;
5988
5989     PERL_UNUSED_VAR(ref);
5990     PERL_UNUSED_VAR(ix);
5991     exception=AcquireExceptionInfo();
5992     perl_exception=newSVpv("",0);
5993     av=NULL;
5994     if (sv_isobject(ST(0)) == 0)
5995       {
5996         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5997           PackageName);
5998         goto PerlException;
5999       }
6000     reference=SvRV(ST(0));
6001     av=newAV();
6002     SvREFCNT_dec(av);
6003     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6004     if (image == (Image *) NULL)
6005       {
6006         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6007           PackageName);
6008         goto PerlException;
6009       }
6010     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6011     count=0;
6012     for ( ; image; image=image->next)
6013     {
6014       histogram=GetImageHistogram(image,&number_colors,exception);
6015       if (histogram == (PixelInfo *) NULL)
6016         continue;
6017       count+=(ssize_t) number_colors;
6018       EXTEND(sp,6*count);
6019       for (i=0; i < (ssize_t) number_colors; i++)
6020       {
6021         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6022           histogram[i].red);
6023         PUSHs(sv_2mortal(newSVpv(message,0)));
6024         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6025           histogram[i].green);
6026         PUSHs(sv_2mortal(newSVpv(message,0)));
6027         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6028           histogram[i].blue);
6029         PUSHs(sv_2mortal(newSVpv(message,0)));
6030         if (image->colorspace == CMYKColorspace)
6031           {
6032             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6033               histogram[i].black);
6034             PUSHs(sv_2mortal(newSVpv(message,0)));
6035           }
6036         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6037           histogram[i].alpha);
6038         PUSHs(sv_2mortal(newSVpv(message,0)));
6039         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6040           histogram[i].count);
6041         PUSHs(sv_2mortal(newSVpv(message,0)));
6042       }
6043       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6044     }
6045
6046   PerlException:
6047     InheritPerlException(exception,perl_exception);
6048     exception=DestroyExceptionInfo(exception);
6049     SvREFCNT_dec(perl_exception);
6050   }
6051 \f
6052 #
6053 ###############################################################################
6054 #                                                                             #
6055 #                                                                             #
6056 #                                                                             #
6057 #   G e t P i x e l                                                           #
6058 #                                                                             #
6059 #                                                                             #
6060 #                                                                             #
6061 ###############################################################################
6062 #
6063 #
6064 void
6065 GetPixel(ref,...)
6066   Image::Magick ref=NO_INIT
6067   ALIAS:
6068     getpixel = 1
6069     getPixel = 2
6070   PPCODE:
6071   {
6072     AV
6073       *av;
6074
6075     char
6076       *attribute;
6077
6078     ExceptionInfo
6079       *exception;
6080
6081     Image
6082       *image;
6083
6084     MagickBooleanType
6085       normalize;
6086
6087     RectangleInfo
6088       region;
6089
6090     register const Quantum
6091       *p;
6092
6093     register ssize_t
6094       i;
6095
6096     ssize_t
6097       option;
6098
6099     struct PackageInfo
6100       *info;
6101
6102     SV
6103       *perl_exception,
6104       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6105
6106     PERL_UNUSED_VAR(ref);
6107     PERL_UNUSED_VAR(ix);
6108     exception=AcquireExceptionInfo();
6109     perl_exception=newSVpv("",0);
6110     reference=SvRV(ST(0));
6111     av=(AV *) reference;
6112     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6113       exception);
6114     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6115     if (image == (Image *) NULL)
6116       {
6117         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6118           PackageName);
6119         goto PerlException;
6120       }
6121     normalize=MagickTrue;
6122     region.x=0;
6123     region.y=0;
6124     region.width=image->columns;
6125     region.height=1;
6126     if (items == 1)
6127       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6128     for (i=2; i < items; i+=2)
6129     {
6130       attribute=(char *) SvPV(ST(i-1),na);
6131       switch (*attribute)
6132       {
6133         case 'C':
6134         case 'c':
6135         {
6136           if (LocaleCompare(attribute,"channel") == 0)
6137             {
6138               ssize_t
6139                 option;
6140
6141               option=ParseChannelOption(SvPV(ST(i),na));
6142               if (option < 0)
6143                 {
6144                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6145                     SvPV(ST(i),na));
6146                   return;
6147                 }
6148               SetPixelChannelMapMask(image,(ChannelType) option);
6149               break;
6150             }
6151           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6152             attribute);
6153           break;
6154         }
6155         case 'g':
6156         case 'G':
6157         {
6158           if (LocaleCompare(attribute,"geometry") == 0)
6159             {
6160               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6161               break;
6162             }
6163           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6164             attribute);
6165           break;
6166         }
6167         case 'N':
6168         case 'n':
6169         {
6170           if (LocaleCompare(attribute,"normalize") == 0)
6171             {
6172               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6173                 SvPV(ST(i),na));
6174               if (option < 0)
6175                 {
6176                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6177                     SvPV(ST(i),na));
6178                   break;
6179                 }
6180              normalize=option != 0 ? MagickTrue : MagickFalse;
6181              break;
6182             }
6183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6184             attribute);
6185           break;
6186         }
6187         case 'x':
6188         case 'X':
6189         {
6190           if (LocaleCompare(attribute,"x") == 0)
6191             {
6192               region.x=SvIV(ST(i));
6193               break;
6194             }
6195           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6196             attribute);
6197           break;
6198         }
6199         case 'y':
6200         case 'Y':
6201         {
6202           if (LocaleCompare(attribute,"y") == 0)
6203             {
6204               region.y=SvIV(ST(i));
6205               break;
6206             }
6207           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6208             attribute);
6209           break;
6210         }
6211         default:
6212         {
6213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6214             attribute);
6215           break;
6216         }
6217       }
6218     }
6219     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6220     if (p == (const Quantum *) NULL)
6221       PUSHs(&sv_undef);
6222     else
6223       {
6224         double
6225           scale;
6226
6227         scale=1.0;
6228         if (normalize != MagickFalse)
6229           scale=1.0/QuantumRange;
6230         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6231           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6232         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6233           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6234         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6235           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6236         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6237             (image->colorspace == CMYKColorspace))
6238           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6239         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6240           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6241       }
6242
6243   PerlException:
6244     InheritPerlException(exception,perl_exception);
6245     exception=DestroyExceptionInfo(exception);
6246     SvREFCNT_dec(perl_exception);
6247   }
6248 \f
6249 #
6250 ###############################################################################
6251 #                                                                             #
6252 #                                                                             #
6253 #                                                                             #
6254 #   G e t P i x e l s                                                         #
6255 #                                                                             #
6256 #                                                                             #
6257 #                                                                             #
6258 ###############################################################################
6259 #
6260 #
6261 void
6262 GetPixels(ref,...)
6263   Image::Magick ref=NO_INIT
6264   ALIAS:
6265     getpixels = 1
6266     getPixels = 2
6267   PPCODE:
6268   {
6269     AV
6270       *av;
6271
6272     char
6273       *attribute;
6274
6275     const char
6276       *map;
6277
6278     ExceptionInfo
6279       *exception;
6280
6281     Image
6282       *image;
6283
6284     MagickBooleanType
6285       normalize,
6286       status;
6287
6288     RectangleInfo
6289       region;
6290
6291     register ssize_t
6292       i;
6293
6294     ssize_t
6295       option;
6296
6297     struct PackageInfo
6298       *info;
6299
6300     SV
6301       *perl_exception,
6302       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6303
6304     PERL_UNUSED_VAR(ref);
6305     PERL_UNUSED_VAR(ix);
6306     exception=AcquireExceptionInfo();
6307     perl_exception=newSVpv("",0);
6308     reference=SvRV(ST(0));
6309     av=(AV *) reference;
6310     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6311       exception);
6312     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6313     if (image == (Image *) NULL)
6314       {
6315         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6316           PackageName);
6317         goto PerlException;
6318       }
6319     map="RGB";
6320     if (image->matte != MagickFalse)
6321       map="RGBA";
6322     if (image->colorspace == CMYKColorspace)
6323       {
6324         map="CMYK";
6325         if (image->matte != MagickFalse)
6326           map="CMYKA";
6327       }
6328     normalize=MagickFalse;
6329     region.x=0;
6330     region.y=0;
6331     region.width=image->columns;
6332     region.height=1;
6333     if (items == 1)
6334       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6335     for (i=2; i < items; i+=2)
6336     {
6337       attribute=(char *) SvPV(ST(i-1),na);
6338       switch (*attribute)
6339       {
6340         case 'g':
6341         case 'G':
6342         {
6343           if (LocaleCompare(attribute,"geometry") == 0)
6344             {
6345               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6346               break;
6347             }
6348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6349             attribute);
6350           break;
6351         }
6352         case 'H':
6353         case 'h':
6354         {
6355           if (LocaleCompare(attribute,"height") == 0)
6356             {
6357               region.height=SvIV(ST(i));
6358               break;
6359             }
6360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6361             attribute);
6362           break;
6363         }
6364         case 'M':
6365         case 'm':
6366         {
6367           if (LocaleCompare(attribute,"map") == 0)
6368             {
6369               map=SvPV(ST(i),na);
6370               break;
6371             }
6372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6373             attribute);
6374           break;
6375         }
6376         case 'N':
6377         case 'n':
6378         {
6379           if (LocaleCompare(attribute,"normalize") == 0)
6380             {
6381               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6382                 SvPV(ST(i),na));
6383               if (option < 0)
6384                 {
6385                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6386                     SvPV(ST(i),na));
6387                   break;
6388                 }
6389              normalize=option != 0 ? MagickTrue : MagickFalse;
6390              break;
6391             }
6392           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6393             attribute);
6394           break;
6395         }
6396         case 'W':
6397         case 'w':
6398         {
6399           if (LocaleCompare(attribute,"width") == 0)
6400             {
6401               region.width=SvIV(ST(i));
6402               break;
6403             }
6404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6405             attribute);
6406           break;
6407         }
6408         case 'x':
6409         case 'X':
6410         {
6411           if (LocaleCompare(attribute,"x") == 0)
6412             {
6413               region.x=SvIV(ST(i));
6414               break;
6415             }
6416           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6417             attribute);
6418           break;
6419         }
6420         case 'y':
6421         case 'Y':
6422         {
6423           if (LocaleCompare(attribute,"y") == 0)
6424             {
6425               region.y=SvIV(ST(i));
6426               break;
6427             }
6428           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6429             attribute);
6430           break;
6431         }
6432         default:
6433         {
6434           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6435             attribute);
6436           break;
6437         }
6438       }
6439     }
6440     if (normalize != MagickFalse)
6441       {
6442         float
6443           *pixels;
6444
6445         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6446           region.height*sizeof(*pixels));
6447         if (pixels == (float *) NULL)
6448           {
6449             ThrowPerlException(exception,ResourceLimitError,
6450               "MemoryAllocationFailed",PackageName);
6451             goto PerlException;
6452           }
6453         status=ExportImagePixels(image,region.x,region.y,region.width,
6454           region.height,map,FloatPixel,pixels,exception);
6455         if (status == MagickFalse)
6456           PUSHs(&sv_undef);
6457         else
6458           {
6459             EXTEND(sp,strlen(map)*region.width*region.height);
6460             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6461               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6462           }
6463         pixels=(float *) RelinquishMagickMemory(pixels);
6464       }
6465     else
6466       {
6467         Quantum
6468           *pixels;
6469
6470         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6471           region.height*sizeof(*pixels));
6472         if (pixels == (Quantum *) NULL)
6473           {
6474             ThrowPerlException(exception,ResourceLimitError,
6475               "MemoryAllocationFailed",PackageName);
6476             goto PerlException;
6477           }
6478         status=ExportImagePixels(image,region.x,region.y,region.width,
6479           region.height,map,QuantumPixel,pixels,exception);
6480         if (status == MagickFalse)
6481           PUSHs(&sv_undef);
6482         else
6483           {
6484             EXTEND(sp,strlen(map)*region.width*region.height);
6485             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6486               PUSHs(sv_2mortal(newSViv(pixels[i])));
6487           }
6488         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6489       }
6490
6491   PerlException:
6492     InheritPerlException(exception,perl_exception);
6493     exception=DestroyExceptionInfo(exception);
6494     SvREFCNT_dec(perl_exception);
6495   }
6496 \f
6497 #
6498 ###############################################################################
6499 #                                                                             #
6500 #                                                                             #
6501 #                                                                             #
6502 #   I m a g e T o B l o b                                                     #
6503 #                                                                             #
6504 #                                                                             #
6505 #                                                                             #
6506 ###############################################################################
6507 #
6508 #
6509 void
6510 ImageToBlob(ref,...)
6511   Image::Magick ref=NO_INIT
6512   ALIAS:
6513     ImageToBlob  = 1
6514     imagetoblob  = 2
6515     toblob       = 3
6516     blob         = 4
6517   PPCODE:
6518   {
6519     char
6520       filename[MaxTextExtent];
6521
6522     ExceptionInfo
6523       *exception;
6524
6525     Image
6526       *image,
6527       *next;
6528
6529     register ssize_t
6530       i;
6531
6532     struct PackageInfo
6533       *info,
6534       *package_info;
6535
6536     size_t
6537       length;
6538
6539     ssize_t
6540       scene;
6541
6542     SV
6543       *perl_exception,
6544       *reference;
6545
6546     void
6547       *blob;
6548
6549     PERL_UNUSED_VAR(ref);
6550     PERL_UNUSED_VAR(ix);
6551     exception=AcquireExceptionInfo();
6552     perl_exception=newSVpv("",0);
6553     package_info=(struct PackageInfo *) NULL;
6554     if (sv_isobject(ST(0)) == 0)
6555       {
6556         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6557           PackageName);
6558         goto PerlException;
6559       }
6560     reference=SvRV(ST(0));
6561     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6562     if (image == (Image *) NULL)
6563       {
6564         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6565           PackageName);
6566         goto PerlException;
6567       }
6568     package_info=ClonePackageInfo(info,exception);
6569     for (i=2; i < items; i+=2)
6570       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6571     (void) CopyMagickString(filename,package_info->image_info->filename,
6572       MaxTextExtent);
6573     scene=0;
6574     for (next=image; next; next=next->next)
6575     {
6576       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6577       next->scene=scene++;
6578     }
6579     SetImageInfo(package_info->image_info,(unsigned int)
6580       GetImageListLength(image),exception);
6581     EXTEND(sp,(ssize_t) GetImageListLength(image));
6582     for ( ; image; image=image->next)
6583     {
6584       length=0;
6585       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6586       if (blob != (char *) NULL)
6587         {
6588           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6589           blob=(unsigned char *) RelinquishMagickMemory(blob);
6590         }
6591       if (package_info->image_info->adjoin)
6592         break;
6593     }
6594
6595   PerlException:
6596     if (package_info != (struct PackageInfo *) NULL)
6597       DestroyPackageInfo(package_info);
6598     InheritPerlException(exception,perl_exception);
6599     exception=DestroyExceptionInfo(exception);
6600     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6601   }
6602 \f
6603 #
6604 ###############################################################################
6605 #                                                                             #
6606 #                                                                             #
6607 #                                                                             #
6608 #   L a y e r s                                                               #
6609 #                                                                             #
6610 #                                                                             #
6611 #                                                                             #
6612 ###############################################################################
6613 #
6614 #
6615 void
6616 Layers(ref,...)
6617   Image::Magick ref=NO_INIT
6618   ALIAS:
6619     Layers                = 1
6620     layers           = 2
6621     OptimizeImageLayers   = 3
6622     optimizelayers        = 4
6623     optimizeimagelayers   = 5
6624   PPCODE:
6625   {
6626     AV
6627       *av;
6628
6629     char
6630       *attribute;
6631
6632     CompositeOperator
6633       compose;
6634
6635     ExceptionInfo
6636       *exception;
6637
6638     HV
6639       *hv;
6640
6641     Image
6642       *image,
6643       *layers;
6644
6645     ImageLayerMethod
6646       method;
6647
6648     register ssize_t
6649       i;
6650
6651     ssize_t
6652       option,
6653       sp;
6654
6655     struct PackageInfo
6656       *info;
6657
6658     SV
6659       *av_reference,
6660       *perl_exception,
6661       *reference,
6662       *rv,
6663       *sv;
6664
6665     PERL_UNUSED_VAR(ref);
6666     PERL_UNUSED_VAR(ix);
6667     exception=AcquireExceptionInfo();
6668     perl_exception=newSVpv("",0);
6669     sv=NULL;
6670     if (sv_isobject(ST(0)) == 0)
6671       {
6672         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6673           PackageName);
6674         goto PerlException;
6675       }
6676     reference=SvRV(ST(0));
6677     hv=SvSTASH(reference);
6678     av=newAV();
6679     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6680     SvREFCNT_dec(av);
6681     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6682     if (image == (Image *) NULL)
6683       {
6684         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6685           PackageName);
6686         goto PerlException;
6687       }
6688     compose=image->compose;
6689     method=OptimizeLayer;
6690     for (i=2; i < items; i+=2)
6691     {
6692       attribute=(char *) SvPV(ST(i-1),na);
6693       switch (*attribute)
6694       {
6695         case 'C':
6696         case 'c':
6697         {
6698           if (LocaleCompare(attribute,"compose") == 0)
6699             {
6700               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6701                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6702               if (sp < 0)
6703                 {
6704                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6705                     SvPV(ST(i),na));
6706                   break;
6707                 }
6708               compose=(CompositeOperator) sp;
6709               break;
6710             }
6711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6712             attribute);
6713           break;
6714         }
6715         case 'M':
6716         case 'm':
6717         {
6718           if (LocaleCompare(attribute,"method") == 0)
6719             {
6720               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6721                 SvPV(ST(i),na));
6722               if (option < 0)
6723                 {
6724                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6725                     SvPV(ST(i),na));
6726                   break;
6727                 }
6728               method=(ImageLayerMethod) option;
6729               break;
6730             }
6731           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6732             attribute);
6733           break;
6734         }
6735         default:
6736         {
6737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6738             attribute);
6739           break;
6740         }
6741       }
6742     }
6743     layers=(Image *) NULL;
6744     switch (method)
6745     {
6746       case CompareAnyLayer:
6747       case CompareClearLayer:
6748       case CompareOverlayLayer:
6749       default:
6750       {
6751         layers=CompareImagesLayers(image,method,exception);
6752         break;
6753       }
6754       case MergeLayer:
6755       case FlattenLayer:
6756       case MosaicLayer:
6757       {
6758         layers=MergeImageLayers(image,method,exception);
6759         break;
6760       }
6761       case DisposeLayer:
6762       {
6763         layers=DisposeImages(image,exception);
6764         break;
6765       }
6766       case OptimizeImageLayer:
6767       {
6768         layers=OptimizeImageLayers(image,exception);
6769         break;
6770       }
6771       case OptimizePlusLayer:
6772       {
6773         layers=OptimizePlusImageLayers(image,exception);
6774         break;
6775       }
6776       case OptimizeTransLayer:
6777       {
6778         OptimizeImageTransparency(image,exception);
6779         break;
6780       }
6781       case RemoveDupsLayer:
6782       {
6783         RemoveDuplicateLayers(&image,exception);
6784         break;
6785       }
6786       case RemoveZeroLayer:
6787       {
6788         RemoveZeroDelayLayers(&image,exception);
6789         break;
6790       }
6791       case OptimizeLayer:
6792       {
6793         QuantizeInfo
6794           *quantize_info;
6795
6796         /*
6797           General Purpose, GIF Animation Optimizer.
6798         */
6799         layers=CoalesceImages(image,exception);
6800         if (layers == (Image *) NULL)
6801           break;
6802         image=layers;
6803         layers=OptimizeImageLayers(image,exception);
6804         if (layers == (Image *) NULL)
6805           break;
6806         image=DestroyImageList(image);
6807         image=layers;
6808         layers=(Image *) NULL;
6809         OptimizeImageTransparency(image,exception);
6810         quantize_info=AcquireQuantizeInfo(info->image_info);
6811         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6812         quantize_info=DestroyQuantizeInfo(quantize_info);
6813         break;
6814       }
6815       case CompositeLayer:
6816       {
6817         Image
6818           *source;
6819
6820         RectangleInfo
6821           geometry;
6822
6823         /*
6824           Split image sequence at the first 'NULL:' image.
6825         */
6826         source=image;
6827         while (source != (Image *) NULL)
6828         {
6829           source=GetNextImageInList(source);
6830           if ((source != (Image *) NULL) &&
6831               (LocaleCompare(source->magick,"NULL") == 0))
6832             break;
6833         }
6834         if (source != (Image *) NULL)
6835           {
6836             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6837                 (GetNextImageInList(source) == (Image *) NULL))
6838               source=(Image *) NULL;
6839             else
6840               {
6841                 /*
6842                   Separate the two lists, junk the null: image.
6843                 */
6844                 source=SplitImageList(source->previous);
6845                 DeleteImageFromList(&source);
6846               }
6847           }
6848         if (source == (Image *) NULL)
6849           {
6850             (void) ThrowMagickException(exception,GetMagickModule(),
6851               OptionError,"MissingNullSeparator","layers Composite");
6852             break;
6853           }
6854         /*
6855           Adjust offset with gravity and virtual canvas.
6856         */
6857         SetGeometry(image,&geometry);
6858         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6859         geometry.width=source->page.width != 0 ? source->page.width :
6860           source->columns;
6861         geometry.height=source->page.height != 0 ? source->page.height :
6862           source->rows;
6863         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6864           image->columns,image->page.height != 0 ? image->page.height :
6865           image->rows,image->gravity,&geometry);
6866         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6867         source=DestroyImageList(source);
6868         break;
6869       }
6870     }
6871     if (layers != (Image *) NULL)
6872       image=layers;
6873     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6874       goto PerlException;
6875     for ( ; image; image=image->next)
6876     {
6877       AddImageToRegistry(sv,image);
6878       rv=newRV(sv);
6879       av_push(av,sv_bless(rv,hv));
6880       SvREFCNT_dec(sv);
6881     }
6882     exception=DestroyExceptionInfo(exception);
6883     ST(0)=av_reference;
6884     SvREFCNT_dec(perl_exception);
6885     XSRETURN(1);
6886
6887   PerlException:
6888     InheritPerlException(exception,perl_exception);
6889     exception=DestroyExceptionInfo(exception);
6890     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6891     SvPOK_on(perl_exception);
6892     ST(0)=sv_2mortal(perl_exception);
6893     XSRETURN(1);
6894   }
6895 \f
6896 #
6897 ###############################################################################
6898 #                                                                             #
6899 #                                                                             #
6900 #                                                                             #
6901 #   M a g i c k T o M i m e                                                   #
6902 #                                                                             #
6903 #                                                                             #
6904 #                                                                             #
6905 ###############################################################################
6906 #
6907 #
6908 SV *
6909 MagickToMime(ref,name)
6910   Image::Magick ref=NO_INIT
6911   char *name
6912   ALIAS:
6913     magicktomime = 1
6914   CODE:
6915   {
6916     char
6917       *mime;
6918
6919     PERL_UNUSED_VAR(ref);
6920     PERL_UNUSED_VAR(ix);
6921     mime=MagickToMime(name);
6922     RETVAL=newSVpv(mime,0);
6923     mime=(char *) RelinquishMagickMemory(mime);
6924   }
6925   OUTPUT:
6926     RETVAL
6927 \f
6928 #
6929 ###############################################################################
6930 #                                                                             #
6931 #                                                                             #
6932 #                                                                             #
6933 #   M o g r i f y                                                             #
6934 #                                                                             #
6935 #                                                                             #
6936 #                                                                             #
6937 ###############################################################################
6938 #
6939 #
6940 void
6941 Mogrify(ref,...)
6942   Image::Magick ref=NO_INIT
6943   ALIAS:
6944     Comment            =   1
6945     CommentImage       =   2
6946     Label              =   3
6947     LabelImage         =   4
6948     AddNoise           =   5
6949     AddNoiseImage      =   6
6950     Colorize           =   7
6951     ColorizeImage      =   8
6952     Border             =   9
6953     BorderImage        =  10
6954     Blur               =  11
6955     BlurImage          =  12
6956     Chop               =  13
6957     ChopImage          =  14
6958     Crop               =  15
6959     CropImage          =  16
6960     Despeckle          =  17
6961     DespeckleImage     =  18
6962     Edge               =  19
6963     EdgeImage          =  20
6964     Emboss             =  21
6965     EmbossImage        =  22
6966     Enhance            =  23
6967     EnhanceImage       =  24
6968     Flip               =  25
6969     FlipImage          =  26
6970     Flop               =  27
6971     FlopImage          =  28
6972     Frame              =  29
6973     FrameImage         =  30
6974     Implode            =  31
6975     ImplodeImage       =  32
6976     Magnify            =  33
6977     MagnifyImage       =  34
6978     MedianFilter       =  35
6979     MedianConvolveImage  =  36
6980     Minify             =  37
6981     MinifyImage        =  38
6982     OilPaint           =  39
6983     OilPaintImage      =  40
6984     ReduceNoise        =  41
6985     ReduceNoiseImage   =  42
6986     Roll               =  43
6987     RollImage          =  44
6988     Rotate             =  45
6989     RotateImage        =  46
6990     Sample             =  47
6991     SampleImage        =  48
6992     Scale              =  49
6993     ScaleImage         =  50
6994     Shade              =  51
6995     ShadeImage         =  52
6996     Sharpen            =  53
6997     SharpenImage       =  54
6998     Shear              =  55
6999     ShearImage         =  56
7000     Spread             =  57
7001     SpreadImage        =  58
7002     Swirl              =  59
7003     SwirlImage         =  60
7004     Resize             =  61
7005     ResizeImage        =  62
7006     Zoom               =  63
7007     ZoomImage          =  64
7008     Annotate           =  65
7009     AnnotateImage      =  66
7010     ColorFloodfill     =  67
7011     ColorFloodfillImage=  68
7012     Composite          =  69
7013     CompositeImage     =  70
7014     Contrast           =  71
7015     ContrastImage      =  72
7016     CycleColormap      =  73
7017     CycleColormapImage =  74
7018     Draw               =  75
7019     DrawImage          =  76
7020     Equalize           =  77
7021     EqualizeImage      =  78
7022     Gamma              =  79
7023     GammaImage         =  80
7024     Map                =  81
7025     MapImage           =  82
7026     MatteFloodfill     =  83
7027     MatteFloodfillImage=  84
7028     Modulate           =  85
7029     ModulateImage      =  86
7030     Negate             =  87
7031     NegateImage        =  88
7032     Normalize          =  89
7033     NormalizeImage     =  90
7034     NumberColors       =  91
7035     NumberColorsImage  =  92
7036     Opaque             =  93
7037     OpaqueImage        =  94
7038     Quantize           =  95
7039     QuantizeImage      =  96
7040     Raise              =  97
7041     RaiseImage         =  98
7042     Segment            =  99
7043     SegmentImage       = 100
7044     Signature          = 101
7045     SignatureImage     = 102
7046     Solarize           = 103
7047     SolarizeImage      = 104
7048     Sync               = 105
7049     SyncImage          = 106
7050     Texture            = 107
7051     TextureImage       = 108
7052     Evaluate           = 109
7053     EvaluateImage      = 110
7054     Transparent        = 111
7055     TransparentImage   = 112
7056     Threshold          = 113
7057     ThresholdImage     = 114
7058     Charcoal           = 115
7059     CharcoalImage      = 116
7060     Trim               = 117
7061     TrimImage          = 118
7062     Wave               = 119
7063     WaveImage          = 120
7064     Separate           = 121
7065     SeparateImage      = 122
7066     Stereo             = 125
7067     StereoImage        = 126
7068     Stegano            = 127
7069     SteganoImage       = 128
7070     Deconstruct        = 129
7071     DeconstructImage   = 130
7072     GaussianBlur       = 131
7073     GaussianBlurImage  = 132
7074     Convolve           = 133
7075     ConvolveImage      = 134
7076     Profile            = 135
7077     ProfileImage       = 136
7078     UnsharpMask        = 137
7079     UnsharpMaskImage   = 138
7080     MotionBlur         = 139
7081     MotionBlurImage    = 140
7082     OrderedDither      = 141
7083     OrderedDitherImage = 142
7084     Shave              = 143
7085     ShaveImage         = 144
7086     Level              = 145
7087     LevelImage         = 146
7088     Clip               = 147
7089     ClipImage          = 148
7090     AffineTransform    = 149
7091     AffineTransformImage = 150
7092     Difference         = 151
7093     DifferenceImage    = 152
7094     AdaptiveThreshold  = 153
7095     AdaptiveThresholdImage = 154
7096     Resample           = 155
7097     ResampleImage      = 156
7098     Describe           = 157
7099     DescribeImage      = 158
7100     BlackThreshold     = 159
7101     BlackThresholdImage= 160
7102     WhiteThreshold     = 161
7103     WhiteThresholdImage= 162
7104     RadialBlur         = 163
7105     RadialBlurImage    = 164
7106     Thumbnail          = 165
7107     ThumbnailImage     = 166
7108     Strip              = 167
7109     StripImage         = 168
7110     Tint               = 169
7111     TintImage          = 170
7112     Channel            = 171
7113     ChannelImage       = 172
7114     Splice             = 173
7115     SpliceImage        = 174
7116     Posterize          = 175
7117     PosterizeImage     = 176
7118     Shadow             = 177
7119     ShadowImage        = 178
7120     Identify           = 179
7121     IdentifyImage      = 180
7122     SepiaTone          = 181
7123     SepiaToneImage     = 182
7124     SigmoidalContrast  = 183
7125     SigmoidalContrastImage = 184
7126     Extent             = 185
7127     ExtentImage        = 186
7128     Vignette           = 187
7129     VignetteImage      = 188
7130     ContrastStretch    = 189
7131     ContrastStretchImage = 190
7132     Sans0              = 191
7133     Sans0Image         = 192
7134     Sans1              = 193
7135     Sans1Image         = 194
7136     AdaptiveSharpen    = 195
7137     AdaptiveSharpenImage = 196
7138     Transpose          = 197
7139     TransposeImage     = 198
7140     Transverse         = 199
7141     TransverseImage    = 200
7142     AutoOrient         = 201
7143     AutoOrientImage    = 202
7144     AdaptiveBlur       = 203
7145     AdaptiveBlurImage  = 204
7146     Sketch             = 205
7147     SketchImage        = 206
7148     UniqueColors       = 207
7149     UniqueColorsImage  = 208
7150     AdaptiveResize     = 209
7151     AdaptiveResizeImage= 210
7152     ClipMask           = 211
7153     ClipMaskImage      = 212
7154     LinearStretch      = 213
7155     LinearStretchImage = 214
7156     ColorMatrix        = 215
7157     ColorMatrixImage   = 216
7158     Mask               = 217
7159     MaskImage          = 218
7160     Polaroid           = 219
7161     PolaroidImage      = 220
7162     FloodfillPaint     = 221
7163     FloodfillPaintImage= 222
7164     Distort            = 223
7165     DistortImage       = 224
7166     Clut               = 225
7167     ClutImage          = 226
7168     LiquidRescale      = 227
7169     LiquidRescaleImage = 228
7170     Encipher           = 229
7171     EncipherImage      = 230
7172     Decipher           = 231
7173     DecipherImage      = 232
7174     Deskew             = 233
7175     DeskewImage        = 234
7176     Remap              = 235
7177     RemapImage         = 236
7178     SparseColor        = 237
7179     SparseColorImage   = 238
7180     Function           = 239
7181     FunctionImage      = 240
7182     SelectiveBlur      = 241
7183     SelectiveBlurImage = 242
7184     HaldClut           = 243
7185     HaldClutImage      = 244
7186     BlueShift          = 245
7187     BlueShiftImage     = 246
7188     ForwardFourierTransform  = 247
7189     ForwardFourierTransformImage = 248
7190     InverseFourierTransform = 249
7191     InverseFourierTransformImage = 250
7192     ColorDecisionList  = 251
7193     ColorDecisionListImage = 252
7194     AutoGamma          = 253
7195     AutoGammaImage     = 254
7196     AutoLevel          = 255
7197     AutoLevelImage     = 256
7198     LevelColors        = 257
7199     LevelImageColors   = 258
7200     Clamp              = 259
7201     ClampImage         = 260
7202     BrightnessContrast = 261
7203     BrightnessContrastImage = 262
7204     Morphology         = 263
7205     MorphologyImage    = 264
7206     Color              = 265
7207     ColorImage         = 266
7208     Mode               = 267
7209     ModeImage          = 268
7210     Statistic          = 269
7211     StatisticImage     = 270
7212     MogrifyRegion      = 666
7213   PPCODE:
7214   {
7215     AffineMatrix
7216       affine,
7217       current;
7218
7219     char
7220       attribute_flag[MaxArguments],
7221       message[MaxTextExtent];
7222
7223     ChannelType
7224       channel,
7225       channel_mask;
7226
7227     CompositeOperator
7228       compose;
7229
7230     const char
7231       *attribute,
7232       *value;
7233
7234     double
7235       angle;
7236
7237     ExceptionInfo
7238       *exception;
7239
7240     GeometryInfo
7241       geometry_info;
7242
7243     Image
7244       *image,
7245       *next,
7246       *region_image;
7247
7248     MagickBooleanType
7249       status;
7250
7251     MagickStatusType
7252       flags;
7253
7254     PixelInfo
7255       fill_color;
7256
7257     RectangleInfo
7258       geometry,
7259       region_info;
7260
7261     register ssize_t
7262       i;
7263
7264     ssize_t
7265       base,
7266       j,
7267       number_images;
7268
7269     struct Methods
7270       *rp;
7271
7272     struct PackageInfo
7273       *info;
7274
7275     SV
7276       *perl_exception,
7277       **pv,
7278       *reference,
7279       **reference_vector;
7280
7281     struct ArgumentList
7282       argument_list[MaxArguments];
7283
7284     PERL_UNUSED_VAR(ref);
7285     PERL_UNUSED_VAR(ix);
7286     exception=AcquireExceptionInfo();
7287     perl_exception=newSVpv("",0);
7288     reference_vector=NULL;
7289     region_image=NULL;
7290     number_images=0;
7291     base=2;
7292     if (sv_isobject(ST(0)) == 0)
7293       {
7294         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7295           PackageName);
7296         goto PerlException;
7297       }
7298     reference=SvRV(ST(0));
7299     region_info.width=0;
7300     region_info.height=0;
7301     region_info.x=0;
7302     region_info.y=0;
7303     region_image=(Image *) NULL;
7304     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7305     if (ix && (ix != 666))
7306       {
7307         /*
7308           Called as Method(...)
7309         */
7310         ix=(ix+1)/2;
7311         rp=(&Methods[ix-1]);
7312         attribute=rp->name;
7313       }
7314     else
7315       {
7316         /*
7317           Called as Mogrify("Method",...)
7318         */
7319         attribute=(char *) SvPV(ST(1),na);
7320         if (ix)
7321           {
7322             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7323             attribute=(char *) SvPV(ST(2),na);
7324             base++;
7325           }
7326         for (rp=Methods; ; rp++)
7327         {
7328           if (rp >= EndOf(Methods))
7329             {
7330               ThrowPerlException(exception,OptionError,
7331                 "UnrecognizedPerlMagickMethod",attribute);
7332               goto PerlException;
7333             }
7334           if (strEQcase(attribute,rp->name))
7335             break;
7336         }
7337         ix=rp-Methods+1;
7338         base++;
7339       }
7340     if (image == (Image *) NULL)
7341       {
7342         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7343         goto PerlException;
7344       }
7345     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7346     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7347     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7348     {
7349       Arguments
7350         *pp,
7351         *qq;
7352
7353       ssize_t
7354         ssize_test;
7355
7356       struct ArgumentList
7357         *al;
7358
7359       SV
7360         *sv;
7361
7362       sv=NULL;
7363       ssize_test=0;
7364       pp=(Arguments *) NULL;
7365       qq=rp->arguments;
7366       if (i == items)
7367         {
7368           pp=rp->arguments,
7369           sv=ST(i-1);
7370         }
7371       else
7372         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7373         {
7374           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7375             break;
7376           if (strEQcase(attribute,qq->method) > ssize_test)
7377             {
7378               pp=qq;
7379               ssize_test=strEQcase(attribute,qq->method);
7380             }
7381         }
7382       if (pp == (Arguments *) NULL)
7383         {
7384           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7385             attribute);
7386           goto continue_outer_loop;
7387         }
7388       al=(&argument_list[pp-rp->arguments]);
7389       switch (pp->type)
7390       {
7391         case ArrayReference:
7392         {
7393           if (SvTYPE(sv) != SVt_RV)
7394             {
7395               (void) FormatLocaleString(message,MaxTextExtent,
7396                 "invalid %.60s value",pp->method);
7397               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7398               goto continue_outer_loop;
7399             }
7400           al->array_reference=SvRV(sv);
7401           break;
7402         }
7403         case RealReference:
7404         {
7405           al->real_reference=SvNV(sv);
7406           break;
7407         }
7408         case FileReference:
7409         {
7410           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7411           break;
7412         }
7413         case ImageReference:
7414         {
7415           if (!sv_isobject(sv) ||
7416               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7417                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7418             {
7419               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7420                 PackageName);
7421               goto PerlException;
7422             }
7423           break;
7424         }
7425         case IntegerReference:
7426         {
7427           al->integer_reference=SvIV(sv);
7428           break;
7429         }
7430         case StringReference:
7431         {
7432           al->string_reference=(char *) SvPV(sv,al->length);
7433           if (sv_isobject(sv))
7434             al->image_reference=SetupList(aTHX_ SvRV(sv),
7435               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7436           break;
7437         }
7438         default:
7439         {
7440           /*
7441             Is a string; look up name.
7442           */
7443           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7444             {
7445               al->string_reference=(char *) SvPV(sv,al->length);
7446               al->integer_reference=(-1);
7447               break;
7448             }
7449           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7450             MagickFalse,SvPV(sv,na));
7451           if (pp->type == MagickChannelOptions)
7452             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7453           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7454             {
7455               (void) FormatLocaleString(message,MaxTextExtent,
7456                 "invalid %.60s value",pp->method);
7457               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7458               goto continue_outer_loop;
7459             }
7460           break;
7461         }
7462       }
7463       attribute_flag[pp-rp->arguments]++;
7464       continue_outer_loop: ;
7465     }
7466     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7467     pv=reference_vector;
7468     SetGeometryInfo(&geometry_info);
7469     channel=DefaultChannels;
7470     for (next=image; next; next=next->next)
7471     {
7472       image=next;
7473       SetGeometry(image,&geometry);
7474       if ((region_info.width*region_info.height) != 0)
7475         {
7476           region_image=image;
7477           image=CropImage(image,&region_info,exception);
7478         }
7479       switch (ix)
7480       {
7481         default:
7482         {
7483           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7484           ThrowPerlException(exception,OptionError,
7485             "UnrecognizedPerlMagickMethod",message);
7486           goto PerlException;
7487         }
7488         case 1:  /* Comment */
7489         {
7490           if (attribute_flag[0] == 0)
7491             argument_list[0].string_reference=(char *) NULL;
7492           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7493             info ? info->image_info : (ImageInfo *) NULL,image,
7494             argument_list[0].string_reference,exception),exception);
7495           break;
7496         }
7497         case 2:  /* Label */
7498         {
7499           if (attribute_flag[0] == 0)
7500             argument_list[0].string_reference=(char *) NULL;
7501           (void) SetImageProperty(image,"label",InterpretImageProperties(
7502             info ? info->image_info : (ImageInfo *) NULL,image,
7503             argument_list[0].string_reference,exception),exception);
7504           break;
7505         }
7506         case 3:  /* AddNoise */
7507         {
7508           double
7509             attenuate;
7510
7511           if (attribute_flag[0] == 0)
7512             argument_list[0].integer_reference=UniformNoise;
7513           attenuate=1.0;
7514           if (attribute_flag[1] != 0)
7515             attenuate=argument_list[1].real_reference;
7516           if (attribute_flag[2] != 0)
7517             channel=(ChannelType) argument_list[2].integer_reference;
7518           channel_mask=SetPixelChannelMask(image,channel);
7519           image=AddNoiseImage(image,(NoiseType)
7520             argument_list[0].integer_reference,attenuate,exception);
7521           if (image != (Image *) NULL)
7522             (void) SetPixelChannelMask(image,channel_mask);
7523           break;
7524         }
7525         case 4:  /* Colorize */
7526         {
7527           PixelInfo
7528             target;
7529
7530           Quantum
7531             virtual_pixel[MaxPixelChannels];
7532
7533           GetPixelInfo(image,&target);
7534           (void) GetOneVirtualPixel(image,0,0,virtual_pixel,exception);
7535           target.red=virtual_pixel[RedPixelChannel];
7536           target.green=virtual_pixel[GreenPixelChannel];
7537           target.blue=virtual_pixel[BluePixelChannel];
7538           target.alpha=virtual_pixel[AlphaPixelChannel];
7539           if (attribute_flag[0] != 0)
7540             (void) QueryColorCompliance(argument_list[0].string_reference,
7541               AllCompliance,&target,exception);
7542           if (attribute_flag[1] == 0)
7543             argument_list[1].string_reference="100%";
7544           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7545             exception);
7546           break;
7547         }
7548         case 5:  /* Border */
7549         {
7550           CompositeOperator
7551             compose;
7552
7553           geometry.width=0;
7554           geometry.height=0;
7555           if (attribute_flag[0] != 0)
7556             {
7557               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7558                 &geometry,exception);
7559               if ((flags & HeightValue) == 0)
7560                 geometry.height=geometry.width;
7561             }
7562           if (attribute_flag[1] != 0)
7563             geometry.width=argument_list[1].integer_reference;
7564           if (attribute_flag[2] != 0)
7565             geometry.height=argument_list[2].integer_reference;
7566           if (attribute_flag[3] != 0)
7567             QueryColorCompliance(argument_list[3].string_reference,
7568               AllCompliance,&image->border_color,exception);
7569           if (attribute_flag[4] != 0)
7570             QueryColorCompliance(argument_list[4].string_reference,
7571               AllCompliance,&image->border_color,exception);
7572           if (attribute_flag[5] != 0)
7573             QueryColorCompliance(argument_list[5].string_reference,
7574               AllCompliance,&image->border_color,exception);
7575           compose=image->compose;
7576           if (attribute_flag[6] != 0)
7577             compose=(CompositeOperator) argument_list[6].integer_reference;
7578           image=BorderImage(image,&geometry,compose,exception);
7579           break;
7580         }
7581         case 6:  /* Blur */
7582         {
7583           if (attribute_flag[0] != 0)
7584             {
7585               flags=ParseGeometry(argument_list[0].string_reference,
7586                 &geometry_info);
7587               if ((flags & SigmaValue) == 0)
7588                 geometry_info.sigma=1.0;
7589             }
7590           if (attribute_flag[1] != 0)
7591             geometry_info.rho=argument_list[1].real_reference;
7592           if (attribute_flag[2] != 0)
7593             geometry_info.sigma=argument_list[2].real_reference;
7594           if (attribute_flag[3] != 0)
7595             geometry_info.xi=argument_list[3].real_reference;
7596           if (attribute_flag[4] != 0)
7597             channel=(ChannelType) argument_list[4].integer_reference;
7598           channel_mask=SetPixelChannelMask(image,channel);
7599           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7600             geometry_info.xi,exception);
7601           if (image != (Image *) NULL)
7602             (void) SetPixelChannelMask(image,channel_mask);
7603           break;
7604         }
7605         case 7:  /* Chop */
7606         {
7607           if (attribute_flag[0] != 0)
7608             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7609               &geometry,exception);
7610           if (attribute_flag[1] != 0)
7611             geometry.width=argument_list[1].integer_reference;
7612           if (attribute_flag[2] != 0)
7613             geometry.height=argument_list[2].integer_reference;
7614           if (attribute_flag[3] != 0)
7615             geometry.x=argument_list[3].integer_reference;
7616           if (attribute_flag[4] != 0)
7617             geometry.y=argument_list[4].integer_reference;
7618           image=ChopImage(image,&geometry,exception);
7619           break;
7620         }
7621         case 8:  /* Crop */
7622         {
7623           if (attribute_flag[6] != 0)
7624             image->gravity=(GravityType) argument_list[6].integer_reference;
7625           if (attribute_flag[0] != 0)
7626             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7627               &geometry,exception);
7628           if (attribute_flag[1] != 0)
7629             geometry.width=argument_list[1].integer_reference;
7630           if (attribute_flag[2] != 0)
7631             geometry.height=argument_list[2].integer_reference;
7632           if (attribute_flag[3] != 0)
7633             geometry.x=argument_list[3].integer_reference;
7634           if (attribute_flag[4] != 0)
7635             geometry.y=argument_list[4].integer_reference;
7636           if (attribute_flag[5] != 0)
7637             image->fuzz=StringToDoubleInterval(
7638               argument_list[5].string_reference,(double) QuantumRange+1.0);
7639           image=CropImage(image,&geometry,exception);
7640           break;
7641         }
7642         case 9:  /* Despeckle */
7643         {
7644           image=DespeckleImage(image,exception);
7645           break;
7646         }
7647         case 10:  /* Edge */
7648         {
7649           if (attribute_flag[0] != 0)
7650             geometry_info.rho=argument_list[0].real_reference;
7651           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7652             exception);
7653           break;
7654         }
7655         case 11:  /* Emboss */
7656         {
7657           if (attribute_flag[0] != 0)
7658             {
7659               flags=ParseGeometry(argument_list[0].string_reference,
7660                 &geometry_info);
7661               if ((flags & SigmaValue) == 0)
7662                 geometry_info.sigma=1.0;
7663             }
7664           if (attribute_flag[1] != 0)
7665             geometry_info.rho=argument_list[1].real_reference;
7666           if (attribute_flag[2] != 0)
7667             geometry_info.sigma=argument_list[2].real_reference;
7668           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7669             exception);
7670           break;
7671         }
7672         case 12:  /* Enhance */
7673         {
7674           image=EnhanceImage(image,exception);
7675           break;
7676         }
7677         case 13:  /* Flip */
7678         {
7679           image=FlipImage(image,exception);
7680           break;
7681         }
7682         case 14:  /* Flop */
7683         {
7684           image=FlopImage(image,exception);
7685           break;
7686         }
7687         case 15:  /* Frame */
7688         {
7689           CompositeOperator
7690             compose;
7691
7692           FrameInfo
7693             frame_info;
7694
7695           if (attribute_flag[0] != 0)
7696             {
7697               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7698                 &geometry,exception);
7699               if ((flags & HeightValue) == 0)
7700                 geometry.height=geometry.width;
7701               frame_info.width=geometry.width;
7702               frame_info.height=geometry.height;
7703               frame_info.outer_bevel=geometry.x;
7704               frame_info.inner_bevel=geometry.y;
7705             }
7706           if (attribute_flag[1] != 0)
7707             frame_info.width=argument_list[1].integer_reference;
7708           if (attribute_flag[2] != 0)
7709             frame_info.height=argument_list[2].integer_reference;
7710           if (attribute_flag[3] != 0)
7711             frame_info.inner_bevel=argument_list[3].integer_reference;
7712           if (attribute_flag[4] != 0)
7713             frame_info.outer_bevel=argument_list[4].integer_reference;
7714           if (attribute_flag[5] != 0)
7715             QueryColorCompliance(argument_list[5].string_reference,
7716               AllCompliance,&fill_color,exception);
7717           if (attribute_flag[6] != 0)
7718             QueryColorCompliance(argument_list[6].string_reference,
7719               AllCompliance,&fill_color,exception);
7720           frame_info.x=(ssize_t) frame_info.width;
7721           frame_info.y=(ssize_t) frame_info.height;
7722           frame_info.width=image->columns+2*frame_info.x;
7723           frame_info.height=image->rows+2*frame_info.y;
7724           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7725             image->matte_color=fill_color;
7726           compose=image->compose;
7727           if (attribute_flag[7] != 0)
7728             compose=(CompositeOperator) argument_list[7].integer_reference;
7729           image=FrameImage(image,&frame_info,compose,exception);
7730           break;
7731         }
7732         case 16:  /* Implode */
7733         {
7734           PixelInterpolateMethod
7735             method;
7736
7737           if (attribute_flag[0] == 0)
7738             argument_list[0].real_reference=0.5;
7739           method=UndefinedInterpolatePixel;
7740           if (attribute_flag[1] != 0)
7741             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7742           image=ImplodeImage(image,argument_list[0].real_reference,
7743             method,exception);
7744           break;
7745         }
7746         case 17:  /* Magnify */
7747         {
7748           image=MagnifyImage(image,exception);
7749           break;
7750         }
7751         case 18:  /* MedianFilter */
7752         {
7753           if (attribute_flag[0] != 0)
7754             {
7755               flags=ParseGeometry(argument_list[0].string_reference,
7756                 &geometry_info);
7757               if ((flags & SigmaValue) == 0)
7758                 geometry_info.sigma=geometry_info.rho;
7759             }
7760           if (attribute_flag[1] != 0)
7761             geometry_info.rho=argument_list[1].real_reference;
7762           if (attribute_flag[2] != 0)
7763             geometry_info.sigma=argument_list[2].real_reference;
7764           if (attribute_flag[3] != 0)
7765             channel=(ChannelType) argument_list[3].integer_reference;
7766           channel_mask=SetPixelChannelMask(image,channel);
7767           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7768             (size_t) geometry_info.sigma,exception);
7769           if (image != (Image *) NULL)
7770             (void) SetPixelChannelMask(image,channel_mask);
7771           break;
7772         }
7773         case 19:  /* Minify */
7774         {
7775           image=MinifyImage(image,exception);
7776           break;
7777         }
7778         case 20:  /* OilPaint */
7779         {
7780           if (attribute_flag[0] == 0)
7781             argument_list[0].real_reference=0.0;
7782           if (attribute_flag[1] == 0)
7783             argument_list[1].real_reference=1.0;
7784           image=OilPaintImage(image,argument_list[0].real_reference,
7785             argument_list[1].real_reference,exception);
7786           break;
7787         }
7788         case 21:  /* ReduceNoise */
7789         {
7790           if (attribute_flag[0] != 0)
7791             {
7792               flags=ParseGeometry(argument_list[0].string_reference,
7793                 &geometry_info);
7794               if ((flags & SigmaValue) == 0)
7795                 geometry_info.sigma=1.0;
7796             }
7797           if (attribute_flag[1] != 0)
7798             geometry_info.rho=argument_list[1].real_reference;
7799           if (attribute_flag[2] != 0)
7800             geometry_info.sigma=argument_list[2].real_reference;
7801           if (attribute_flag[3] != 0)
7802             channel=(ChannelType) argument_list[3].integer_reference;
7803           channel_mask=SetPixelChannelMask(image,channel);
7804           image=StatisticImage(image,NonpeakStatistic,(size_t)
7805             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7806           if (image != (Image *) NULL)
7807             (void) SetPixelChannelMask(image,channel_mask);
7808           break;
7809         }
7810         case 22:  /* Roll */
7811         {
7812           if (attribute_flag[0] != 0)
7813             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7814               &geometry,exception);
7815           if (attribute_flag[1] != 0)
7816             geometry.x=argument_list[1].integer_reference;
7817           if (attribute_flag[2] != 0)
7818             geometry.y=argument_list[2].integer_reference;
7819           image=RollImage(image,geometry.x,geometry.y,exception);
7820           break;
7821         }
7822         case 23:  /* Rotate */
7823         {
7824           if (attribute_flag[0] == 0)
7825             argument_list[0].real_reference=90.0;
7826           if (attribute_flag[1] != 0)
7827             QueryColorCompliance(argument_list[1].string_reference,
7828               AllCompliance,&image->background_color,exception);
7829           if (attribute_flag[2] != 0)
7830             QueryColorCompliance(argument_list[2].string_reference,
7831               AllCompliance,&image->background_color,exception);
7832           if (attribute_flag[3] != 0)
7833             QueryColorCompliance(argument_list[3].string_reference,
7834               AllCompliance,&image->background_color,exception);
7835           image=RotateImage(image,argument_list[0].real_reference,exception);
7836           break;
7837         }
7838         case 24:  /* Sample */
7839         {
7840           if (attribute_flag[0] != 0)
7841             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7842               &geometry,exception);
7843           if (attribute_flag[1] != 0)
7844             geometry.width=argument_list[1].integer_reference;
7845           if (attribute_flag[2] != 0)
7846             geometry.height=argument_list[2].integer_reference;
7847           image=SampleImage(image,geometry.width,geometry.height,exception);
7848           break;
7849         }
7850         case 25:  /* Scale */
7851         {
7852           if (attribute_flag[0] != 0)
7853             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7854               &geometry,exception);
7855           if (attribute_flag[1] != 0)
7856             geometry.width=argument_list[1].integer_reference;
7857           if (attribute_flag[2] != 0)
7858             geometry.height=argument_list[2].integer_reference;
7859           image=ScaleImage(image,geometry.width,geometry.height,exception);
7860           break;
7861         }
7862         case 26:  /* Shade */
7863         {
7864           if (attribute_flag[0] != 0)
7865             {
7866               flags=ParseGeometry(argument_list[0].string_reference,
7867                 &geometry_info);
7868               if ((flags & SigmaValue) == 0)
7869                 geometry_info.sigma=0.0;
7870             }
7871           if (attribute_flag[1] != 0)
7872             geometry_info.rho=argument_list[1].real_reference;
7873           if (attribute_flag[2] != 0)
7874             geometry_info.sigma=argument_list[2].real_reference;
7875           image=ShadeImage(image,
7876             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7877             geometry_info.rho,geometry_info.sigma,exception);
7878           break;
7879         }
7880         case 27:  /* Sharpen */
7881         {
7882           if (attribute_flag[0] != 0)
7883             {
7884               flags=ParseGeometry(argument_list[0].string_reference,
7885                 &geometry_info);
7886               if ((flags & SigmaValue) == 0)
7887                 geometry_info.sigma=1.0;
7888             }
7889           if (attribute_flag[1] != 0)
7890             geometry_info.rho=argument_list[1].real_reference;
7891           if (attribute_flag[2] != 0)
7892             geometry_info.sigma=argument_list[2].real_reference;
7893           if (attribute_flag[3] != 0)
7894             geometry_info.xi=argument_list[3].real_reference;
7895           if (attribute_flag[4] != 0)
7896             channel=(ChannelType) argument_list[4].integer_reference;
7897           channel_mask=SetPixelChannelMask(image,channel);
7898           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7899             geometry_info.xi,exception);
7900           if (image != (Image *) NULL)
7901             (void) SetPixelChannelMask(image,channel_mask);
7902           break;
7903         }
7904         case 28:  /* Shear */
7905         {
7906           if (attribute_flag[0] != 0)
7907             {
7908               flags=ParseGeometry(argument_list[0].string_reference,
7909                 &geometry_info);
7910               if ((flags & SigmaValue) == 0)
7911                 geometry_info.sigma=geometry_info.rho;
7912             }
7913           if (attribute_flag[1] != 0)
7914             geometry_info.rho=argument_list[1].real_reference;
7915           if (attribute_flag[2] != 0)
7916             geometry_info.sigma=argument_list[2].real_reference;
7917           if (attribute_flag[3] != 0)
7918             QueryColorCompliance(argument_list[3].string_reference,
7919               AllCompliance,&image->background_color,exception);
7920           if (attribute_flag[4] != 0)
7921             QueryColorCompliance(argument_list[4].string_reference,
7922               AllCompliance,&image->background_color,exception);
7923           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7924             exception);
7925           break;
7926         }
7927         case 29:  /* Spread */
7928         {
7929           PixelInterpolateMethod
7930             method;
7931
7932           if (attribute_flag[0] == 0)
7933             argument_list[0].real_reference=1.0;
7934           method=UndefinedInterpolatePixel;
7935           if (attribute_flag[1] != 0)
7936             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7937           image=SpreadImage(image,argument_list[0].real_reference,method,
7938             exception);
7939           break;
7940         }
7941         case 30:  /* Swirl */
7942         {
7943           PixelInterpolateMethod
7944             method;
7945
7946           if (attribute_flag[0] == 0)
7947             argument_list[0].real_reference=50.0;
7948           method=UndefinedInterpolatePixel;
7949           if (attribute_flag[1] != 0)
7950             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7951           image=SwirlImage(image,argument_list[0].real_reference,
7952             method,exception);
7953           break;
7954         }
7955         case 31:  /* Resize */
7956         case 32:  /* Zoom */
7957         {
7958           if (attribute_flag[0] != 0)
7959             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7960               &geometry,exception);
7961           if (attribute_flag[1] != 0)
7962             geometry.width=argument_list[1].integer_reference;
7963           if (attribute_flag[2] != 0)
7964             geometry.height=argument_list[2].integer_reference;
7965           if (attribute_flag[3] == 0)
7966             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7967           if (attribute_flag[4] != 0)
7968             SetImageArtifact(image,"filter:support",
7969               argument_list[4].string_reference);
7970           if (attribute_flag[5] == 0)
7971             argument_list[5].real_reference=1.0;
7972           image=ResizeImage(image,geometry.width,geometry.height,
7973             (FilterTypes) argument_list[3].integer_reference,
7974             argument_list[5].real_reference,exception);
7975           break;
7976         }
7977         case 33:  /* Annotate */
7978         {
7979           DrawInfo
7980             *draw_info;
7981
7982           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7983             (DrawInfo *) NULL);
7984           if (attribute_flag[0] != 0)
7985             {
7986               char
7987                 *text;
7988
7989               text=InterpretImageProperties(info ? info->image_info :
7990                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7991                 exception);
7992               (void) CloneString(&draw_info->text,text);
7993               text=DestroyString(text);
7994             }
7995           if (attribute_flag[1] != 0)
7996             (void) CloneString(&draw_info->font,
7997               argument_list[1].string_reference);
7998           if (attribute_flag[2] != 0)
7999             draw_info->pointsize=argument_list[2].real_reference;
8000           if (attribute_flag[3] != 0)
8001             (void) CloneString(&draw_info->density,
8002               argument_list[3].string_reference);
8003           if (attribute_flag[4] != 0)
8004             (void) QueryColorCompliance(argument_list[4].string_reference,
8005               AllCompliance,&draw_info->undercolor,exception);
8006           if (attribute_flag[5] != 0)
8007             {
8008               (void) QueryColorCompliance(argument_list[5].string_reference,
8009                 AllCompliance,&draw_info->stroke,exception);
8010               if (argument_list[5].image_reference != (Image *) NULL)
8011                 draw_info->stroke_pattern=CloneImage(
8012                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8013             }
8014           if (attribute_flag[6] != 0)
8015             {
8016               (void) QueryColorCompliance(argument_list[6].string_reference,
8017                 AllCompliance,&draw_info->fill,exception);
8018               if (argument_list[6].image_reference != (Image *) NULL)
8019                 draw_info->fill_pattern=CloneImage(
8020                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8021             }
8022           if (attribute_flag[7] != 0)
8023             {
8024               (void) CloneString(&draw_info->geometry,
8025                 argument_list[7].string_reference);
8026               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8027                 &geometry,exception);
8028               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8029                 geometry_info.sigma=geometry_info.xi;
8030             }
8031           if (attribute_flag[8] != 0)
8032             (void) QueryColorCompliance(argument_list[8].string_reference,
8033               AllCompliance,&draw_info->fill,exception);
8034           if (attribute_flag[11] != 0)
8035             draw_info->gravity=(GravityType)
8036               argument_list[11].integer_reference;
8037           if (attribute_flag[25] != 0)
8038             {
8039               AV
8040                 *av;
8041
8042               av=(AV *) argument_list[25].array_reference;
8043               if ((av_len(av) != 3) && (av_len(av) != 5))
8044                 {
8045                   ThrowPerlException(exception,OptionError,
8046                     "affine matrix must have 4 or 6 elements",PackageName);
8047                   goto PerlException;
8048                 }
8049               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8050               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8051               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8052               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8053               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8054                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8055                 {
8056                   ThrowPerlException(exception,OptionError,
8057                     "affine matrix is singular",PackageName);
8058                    goto PerlException;
8059                 }
8060               if (av_len(av) == 5)
8061                 {
8062                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8063                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8064                 }
8065             }
8066           for (j=12; j < 17; j++)
8067           {
8068             if (attribute_flag[j] == 0)
8069               continue;
8070             value=argument_list[j].string_reference;
8071             angle=argument_list[j].real_reference;
8072             current=draw_info->affine;
8073             GetAffineMatrix(&affine);
8074             switch (j)
8075             {
8076               case 12:
8077               {
8078                 /*
8079                   Translate.
8080                 */
8081                 flags=ParseGeometry(value,&geometry_info);
8082                 affine.tx=geometry_info.xi;
8083                 affine.ty=geometry_info.psi;
8084                 if ((flags & PsiValue) == 0)
8085                   affine.ty=affine.tx;
8086                 break;
8087               }
8088               case 13:
8089               {
8090                 /*
8091                   Scale.
8092                 */
8093                 flags=ParseGeometry(value,&geometry_info);
8094                 affine.sx=geometry_info.rho;
8095                 affine.sy=geometry_info.sigma;
8096                 if ((flags & SigmaValue) == 0)
8097                   affine.sy=affine.sx;
8098                 break;
8099               }
8100               case 14:
8101               {
8102                 /*
8103                   Rotate.
8104                 */
8105                 if (angle == 0.0)
8106                   break;
8107                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8108                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8109                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8110                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8111                 break;
8112               }
8113               case 15:
8114               {
8115                 /*
8116                   SkewX.
8117                 */
8118                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8119                 break;
8120               }
8121               case 16:
8122               {
8123                 /*
8124                   SkewY.
8125                 */
8126                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8127                 break;
8128               }
8129             }
8130             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8131             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8132             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8133             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8134             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8135               current.tx;
8136             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8137               current.ty;
8138           }
8139           if (attribute_flag[9] == 0)
8140             argument_list[9].real_reference=0.0;
8141           if (attribute_flag[10] == 0)
8142             argument_list[10].real_reference=0.0;
8143           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8144             {
8145               char
8146                 geometry[MaxTextExtent];
8147
8148               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8149                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8150                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8151               (void) CloneString(&draw_info->geometry,geometry);
8152             }
8153           if (attribute_flag[17] != 0)
8154             draw_info->stroke_width=argument_list[17].real_reference;
8155           if (attribute_flag[18] != 0)
8156             {
8157               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8158                 MagickTrue : MagickFalse;
8159               draw_info->stroke_antialias=draw_info->text_antialias;
8160             }
8161           if (attribute_flag[19] != 0)
8162             (void) CloneString(&draw_info->family,
8163               argument_list[19].string_reference);
8164           if (attribute_flag[20] != 0)
8165             draw_info->style=(StyleType) argument_list[20].integer_reference;
8166           if (attribute_flag[21] != 0)
8167             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8168           if (attribute_flag[22] != 0)
8169             draw_info->weight=argument_list[22].integer_reference;
8170           if (attribute_flag[23] != 0)
8171             draw_info->align=(AlignType) argument_list[23].integer_reference;
8172           if (attribute_flag[24] != 0)
8173             (void) CloneString(&draw_info->encoding,
8174               argument_list[24].string_reference);
8175           if (attribute_flag[25] != 0)
8176             draw_info->fill_pattern=CloneImage(
8177               argument_list[25].image_reference,0,0,MagickTrue,exception);
8178           if (attribute_flag[26] != 0)
8179             draw_info->fill_pattern=CloneImage(
8180               argument_list[26].image_reference,0,0,MagickTrue,exception);
8181           if (attribute_flag[27] != 0)
8182             draw_info->stroke_pattern=CloneImage(
8183               argument_list[27].image_reference,0,0,MagickTrue,exception);
8184           if (attribute_flag[29] != 0)
8185             draw_info->kerning=argument_list[29].real_reference;
8186           if (attribute_flag[30] != 0)
8187             draw_info->interline_spacing=argument_list[30].real_reference;
8188           if (attribute_flag[31] != 0)
8189             draw_info->interword_spacing=argument_list[31].real_reference;
8190           if (attribute_flag[32] != 0)
8191             draw_info->direction=(DirectionType)
8192               argument_list[32].integer_reference;
8193           (void) AnnotateImage(image,draw_info,exception);
8194           draw_info=DestroyDrawInfo(draw_info);
8195           break;
8196         }
8197         case 34:  /* ColorFloodfill */
8198         {
8199           DrawInfo
8200             *draw_info;
8201
8202           MagickBooleanType
8203             invert;
8204
8205           PixelInfo
8206             target;
8207
8208           Quantum
8209             virtual_pixel[MaxPixelChannels];
8210
8211           draw_info=CloneDrawInfo(info ? info->image_info :
8212             (ImageInfo *) NULL,(DrawInfo *) NULL);
8213           if (attribute_flag[0] != 0)
8214             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8215               &geometry,exception);
8216           if (attribute_flag[1] != 0)
8217             geometry.x=argument_list[1].integer_reference;
8218           if (attribute_flag[2] != 0)
8219             geometry.y=argument_list[2].integer_reference;
8220           if (attribute_flag[3] != 0)
8221             (void) QueryColorCompliance(argument_list[3].string_reference,
8222               AllCompliance,&draw_info->fill,exception);
8223           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
8224             exception);
8225           target.red=virtual_pixel[RedPixelChannel];
8226           target.green=virtual_pixel[GreenPixelChannel];
8227           target.blue=virtual_pixel[BluePixelChannel];
8228           target.alpha=virtual_pixel[AlphaPixelChannel];
8229           invert=MagickFalse;
8230           if (attribute_flag[4] != 0)
8231             {
8232               QueryColorCompliance(argument_list[4].string_reference,
8233                 AllCompliance,&target,exception);
8234               invert=MagickTrue;
8235             }
8236           if (attribute_flag[5] != 0)
8237             image->fuzz=StringToDoubleInterval(
8238               argument_list[5].string_reference,(double) QuantumRange+1.0);
8239           if (attribute_flag[6] != 0)
8240             invert=(MagickBooleanType) argument_list[6].integer_reference;
8241           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8242             geometry.y,invert,exception);
8243           draw_info=DestroyDrawInfo(draw_info);
8244           break;
8245         }
8246         case 35:  /* Composite */
8247         {
8248           char
8249             composite_geometry[MaxTextExtent];
8250
8251           Image
8252             *composite_image,
8253             *rotate_image;
8254
8255           compose=OverCompositeOp;
8256           if (attribute_flag[0] != 0)
8257             composite_image=argument_list[0].image_reference;
8258           else
8259             {
8260               ThrowPerlException(exception,OptionError,
8261                 "CompositeImageRequired",PackageName);
8262               goto PerlException;
8263             }
8264           /*
8265             Parameter Handling used for BOTH normal and tiled composition.
8266           */
8267           if (attribute_flag[1] != 0) /* compose */
8268             compose=(CompositeOperator) argument_list[1].integer_reference;
8269           if (attribute_flag[6] != 0) /* opacity  */
8270             {
8271               if (compose != DissolveCompositeOp)
8272                 (void) SetImageAlpha(composite_image,(Quantum)
8273                   StringToDoubleInterval(argument_list[6].string_reference,
8274                   (double) QuantumRange+1.0),exception);
8275               else
8276                 {
8277                   CacheView
8278                     *composite_view;
8279
8280                   double
8281                     opacity;
8282
8283                   MagickBooleanType
8284                     sync;
8285
8286                   register ssize_t
8287                     x;
8288
8289                   register Quantum
8290                     *q;
8291
8292                   ssize_t
8293                     y;
8294
8295                   /*
8296                     Handle dissolve composite operator (patch by
8297                     Kevin A. McGrail).
8298                   */
8299                   (void) CloneString(&image->geometry,
8300                     argument_list[6].string_reference);
8301                   opacity=(Quantum) StringToDoubleInterval(
8302                     argument_list[6].string_reference,(double) QuantumRange+
8303                     1.0);
8304                   if (composite_image->matte != MagickTrue)
8305                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8306                   composite_view=AcquireCacheView(composite_image);
8307                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8308                   {
8309                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8310                       composite_image->columns,1,exception);
8311                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8312                     {
8313                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8314                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8315                           q);
8316                       q+=GetPixelChannels(composite_image);
8317                     }
8318                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8319                     if (sync == MagickFalse)
8320                       break;
8321                   }
8322                   composite_view=DestroyCacheView(composite_view);
8323                 }
8324             }
8325           if (attribute_flag[9] != 0)    /* "color=>" */
8326             QueryColorCompliance(argument_list[9].string_reference,
8327               AllCompliance,&composite_image->background_color,exception);
8328           if (attribute_flag[12] != 0) /* "interpolate=>" */
8329             image->interpolate=(PixelInterpolateMethod)
8330               argument_list[12].integer_reference;
8331           if (attribute_flag[13] != 0)   /* "args=>" */
8332             (void) SetImageArtifact(composite_image,"compose:args",
8333               argument_list[13].string_reference);
8334           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8335             (void) SetImageArtifact(composite_image,"compose:args",
8336               argument_list[14].string_reference);
8337           /*
8338             Tiling Composition (with orthogonal rotate).
8339           */
8340           rotate_image=(Image *) NULL;
8341           if (attribute_flag[8] != 0)   /* "rotate=>" */
8342             {
8343                /*
8344                  Rotate image.
8345                */
8346                rotate_image=RotateImage(composite_image,
8347                  argument_list[8].real_reference,exception);
8348                if (rotate_image == (Image *) NULL)
8349                  break;
8350             }
8351           if ((attribute_flag[7] != 0) &&
8352               (argument_list[7].integer_reference != 0)) /* tile */
8353             {
8354               ssize_t
8355                 x,
8356                 y;
8357
8358               /*
8359                 Tile the composite image.
8360               */
8361              if (attribute_flag[8] != 0)   /* "tile=>" */
8362                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8363                  "false");
8364              else
8365                (void) SetImageArtifact(composite_image,
8366                  "compose:outside-overlay","false");
8367              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8368                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8369                 {
8370                   if (attribute_flag[8] != 0) /* rotate */
8371                     (void) CompositeImage(image,compose,rotate_image,x,y,
8372                       exception);
8373                   else
8374                     (void) CompositeImage(image,compose,composite_image,x,y,
8375                       exception);
8376                 }
8377               if (attribute_flag[8] != 0) /* rotate */
8378                 rotate_image=DestroyImage(rotate_image);
8379               break;
8380             }
8381           /*
8382             Parameter Handling used used ONLY for normal composition.
8383           */
8384           if (attribute_flag[5] != 0) /* gravity */
8385             image->gravity=(GravityType) argument_list[5].integer_reference;
8386           if (attribute_flag[2] != 0) /* geometry offset */
8387             {
8388               SetGeometry(image,&geometry);
8389               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8390                 &geometry);
8391               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8392                 &geometry);
8393             }
8394           if (attribute_flag[3] != 0) /* x offset */
8395             geometry.x=argument_list[3].integer_reference;
8396           if (attribute_flag[4] != 0) /* y offset */
8397             geometry.y=argument_list[4].integer_reference;
8398           if (attribute_flag[10] != 0) /* mask */
8399             {
8400               if ((image->compose == DisplaceCompositeOp) ||
8401                   (image->compose == DistortCompositeOp))
8402                 {
8403                   /*
8404                     Merge Y displacement into X displacement image.
8405                   */
8406                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8407                     exception);
8408                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8409                     argument_list[10].image_reference,0,0,exception);
8410                 }
8411               else
8412                 {
8413                   /*
8414                     Set a blending mask for the composition.
8415                   */
8416                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8417                     MagickTrue,exception);
8418                   (void) NegateImage(image->mask,MagickFalse,exception);
8419                 }
8420             }
8421           if (attribute_flag[11] != 0) /* channel */
8422             channel=(ChannelType) argument_list[11].integer_reference;
8423           /*
8424             Composite two images (normal composition).
8425           */
8426           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8427             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8428             (double) composite_image->rows,(double) geometry.x,(double)
8429             geometry.y);
8430           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8431             exception);
8432           channel_mask=SetPixelChannelMask(image,channel);
8433           if (attribute_flag[8] == 0) /* no rotate */
8434             CompositeImage(image,compose,composite_image,geometry.x,geometry.y,
8435               exception);
8436           else
8437             {
8438               /*
8439                 Position adjust rotated image then composite.
8440               */
8441               geometry.x-=(ssize_t) (rotate_image->columns-
8442                 composite_image->columns)/2;
8443               geometry.y-=(ssize_t) (rotate_image->rows-
8444                 composite_image->rows)/2;
8445               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y,
8446                 exception);
8447               rotate_image=DestroyImage(rotate_image);
8448             }
8449           if (attribute_flag[10] != 0) /* mask */
8450             {
8451               if ((image->compose == DisplaceCompositeOp) ||
8452                   (image->compose == DistortCompositeOp))
8453                 composite_image=DestroyImage(composite_image);
8454               else
8455                 image->mask=DestroyImage(image->mask);
8456             }
8457           (void) SetPixelChannelMask(image,channel_mask);
8458           break;
8459         }
8460         case 36:  /* Contrast */
8461         {
8462           if (attribute_flag[0] == 0)
8463             argument_list[0].integer_reference=0;
8464           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8465             MagickTrue : MagickFalse,exception);
8466           break;
8467         }
8468         case 37:  /* CycleColormap */
8469         {
8470           if (attribute_flag[0] == 0)
8471             argument_list[0].integer_reference=6;
8472           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8473             exception);
8474           break;
8475         }
8476         case 38:  /* Draw */
8477         {
8478           DrawInfo
8479             *draw_info;
8480
8481           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8482             (DrawInfo *) NULL);
8483           (void) CloneString(&draw_info->primitive,"point");
8484           if (attribute_flag[0] != 0)
8485             {
8486               if (argument_list[0].integer_reference < 0)
8487                 (void) CloneString(&draw_info->primitive,
8488                   argument_list[0].string_reference);
8489               else
8490                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8491                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8492             }
8493           if (attribute_flag[1] != 0)
8494             {
8495               if (LocaleCompare(draw_info->primitive,"path") == 0)
8496                 {
8497                   (void) ConcatenateString(&draw_info->primitive," '");
8498                   ConcatenateString(&draw_info->primitive,
8499                     argument_list[1].string_reference);
8500                   (void) ConcatenateString(&draw_info->primitive,"'");
8501                 }
8502               else
8503                 {
8504                   (void) ConcatenateString(&draw_info->primitive," ");
8505                   ConcatenateString(&draw_info->primitive,
8506                     argument_list[1].string_reference);
8507                 }
8508             }
8509           if (attribute_flag[2] != 0)
8510             {
8511               (void) ConcatenateString(&draw_info->primitive," ");
8512               (void) ConcatenateString(&draw_info->primitive,
8513                 CommandOptionToMnemonic(MagickMethodOptions,
8514                 argument_list[2].integer_reference));
8515             }
8516           if (attribute_flag[3] != 0)
8517             {
8518               (void) QueryColorCompliance(argument_list[3].string_reference,
8519                 AllCompliance,&draw_info->stroke,exception);
8520               if (argument_list[3].image_reference != (Image *) NULL)
8521                 draw_info->stroke_pattern=CloneImage(
8522                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8523             }
8524           if (attribute_flag[4] != 0)
8525             {
8526               (void) QueryColorCompliance(argument_list[4].string_reference,
8527                 AllCompliance,&draw_info->fill,exception);
8528               if (argument_list[4].image_reference != (Image *) NULL)
8529                 draw_info->fill_pattern=CloneImage(
8530                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8531             }
8532           if (attribute_flag[5] != 0)
8533             draw_info->stroke_width=argument_list[5].real_reference;
8534           if (attribute_flag[6] != 0)
8535             (void) CloneString(&draw_info->font,
8536               argument_list[6].string_reference);
8537           if (attribute_flag[7] != 0)
8538             (void) QueryColorCompliance(argument_list[7].string_reference,
8539               AllCompliance,&draw_info->border_color,exception);
8540           if (attribute_flag[8] != 0)
8541             draw_info->affine.tx=argument_list[8].real_reference;
8542           if (attribute_flag[9] != 0)
8543             draw_info->affine.ty=argument_list[9].real_reference;
8544           if (attribute_flag[20] != 0)
8545             {
8546               AV
8547                 *av;
8548
8549               av=(AV *) argument_list[20].array_reference;
8550               if ((av_len(av) != 3) && (av_len(av) != 5))
8551                 {
8552                   ThrowPerlException(exception,OptionError,
8553                     "affine matrix must have 4 or 6 elements",PackageName);
8554                   goto PerlException;
8555                 }
8556               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8557               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8558               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8559               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8560               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8561                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8562                 {
8563                   ThrowPerlException(exception,OptionError,
8564                     "affine matrix is singular",PackageName);
8565                    goto PerlException;
8566                 }
8567               if (av_len(av) == 5)
8568                 {
8569                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8570                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8571                 }
8572             }
8573           for (j=10; j < 15; j++)
8574           {
8575             if (attribute_flag[j] == 0)
8576               continue;
8577             value=argument_list[j].string_reference;
8578             angle=argument_list[j].real_reference;
8579             current=draw_info->affine;
8580             GetAffineMatrix(&affine);
8581             switch (j)
8582             {
8583               case 10:
8584               {
8585                 /*
8586                   Translate.
8587                 */
8588                 flags=ParseGeometry(value,&geometry_info);
8589                 affine.tx=geometry_info.xi;
8590                 affine.ty=geometry_info.psi;
8591                 if ((flags & PsiValue) == 0)
8592                   affine.ty=affine.tx;
8593                 break;
8594               }
8595               case 11:
8596               {
8597                 /*
8598                   Scale.
8599                 */
8600                 flags=ParseGeometry(value,&geometry_info);
8601                 affine.sx=geometry_info.rho;
8602                 affine.sy=geometry_info.sigma;
8603                 if ((flags & SigmaValue) == 0)
8604                   affine.sy=affine.sx;
8605                 break;
8606               }
8607               case 12:
8608               {
8609                 /*
8610                   Rotate.
8611                 */
8612                 if (angle == 0.0)
8613                   break;
8614                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8615                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8616                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8617                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8618                 break;
8619               }
8620               case 13:
8621               {
8622                 /*
8623                   SkewX.
8624                 */
8625                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8626                 break;
8627               }
8628               case 14:
8629               {
8630                 /*
8631                   SkewY.
8632                 */
8633                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8634                 break;
8635               }
8636             }
8637             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8638             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8639             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8640             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8641             draw_info->affine.tx=
8642               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8643             draw_info->affine.ty=
8644               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8645           }
8646           if (attribute_flag[15] != 0)
8647             draw_info->fill_pattern=CloneImage(
8648               argument_list[15].image_reference,0,0,MagickTrue,exception);
8649           if (attribute_flag[16] != 0)
8650             draw_info->pointsize=argument_list[16].real_reference;
8651           if (attribute_flag[17] != 0)
8652             {
8653               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8654                 ? MagickTrue : MagickFalse;
8655               draw_info->text_antialias=draw_info->stroke_antialias;
8656             }
8657           if (attribute_flag[18] != 0)
8658             (void) CloneString(&draw_info->density,
8659               argument_list[18].string_reference);
8660           if (attribute_flag[19] != 0)
8661             draw_info->stroke_width=argument_list[19].real_reference;
8662           if (attribute_flag[21] != 0)
8663             draw_info->dash_offset=argument_list[21].real_reference;
8664           if (attribute_flag[22] != 0)
8665             {
8666               AV
8667                 *av;
8668
8669               av=(AV *) argument_list[22].array_reference;
8670               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8671                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8672               if (draw_info->dash_pattern != (double *) NULL)
8673                 {
8674                   for (i=0; i <= av_len(av); i++)
8675                     draw_info->dash_pattern[i]=(double)
8676                       SvNV(*(av_fetch(av,i,0)));
8677                   draw_info->dash_pattern[i]=0.0;
8678                 }
8679             }
8680           if (attribute_flag[23] != 0)
8681             image->interpolate=(PixelInterpolateMethod)
8682               argument_list[23].integer_reference;
8683           if ((attribute_flag[24] != 0) &&
8684               (draw_info->fill_pattern != (Image *) NULL))
8685             flags=ParsePageGeometry(draw_info->fill_pattern,
8686               argument_list[24].string_reference,
8687               &draw_info->fill_pattern->tile_offset,exception);
8688           if (attribute_flag[25] != 0)
8689             {
8690               (void) ConcatenateString(&draw_info->primitive," '");
8691               (void) ConcatenateString(&draw_info->primitive,
8692                 argument_list[25].string_reference);
8693               (void) ConcatenateString(&draw_info->primitive,"'");
8694             }
8695           if (attribute_flag[26] != 0)
8696             draw_info->fill_pattern=CloneImage(
8697               argument_list[26].image_reference,0,0,MagickTrue,exception);
8698           if (attribute_flag[27] != 0)
8699             draw_info->stroke_pattern=CloneImage(
8700               argument_list[27].image_reference,0,0,MagickTrue,exception);
8701           if (attribute_flag[28] != 0)
8702             (void) CloneString(&draw_info->primitive,
8703               argument_list[28].string_reference);
8704           if (attribute_flag[29] != 0)
8705             draw_info->kerning=argument_list[29].real_reference;
8706           if (attribute_flag[30] != 0)
8707             draw_info->interline_spacing=argument_list[30].real_reference;
8708           if (attribute_flag[31] != 0)
8709             draw_info->interword_spacing=argument_list[31].real_reference;
8710           if (attribute_flag[32] != 0)
8711             draw_info->direction=(DirectionType)
8712               argument_list[32].integer_reference;
8713           DrawImage(image,draw_info,exception);
8714           draw_info=DestroyDrawInfo(draw_info);
8715           break;
8716         }
8717         case 39:  /* Equalize */
8718         {
8719           if (attribute_flag[0] != 0)
8720             channel=(ChannelType) argument_list[0].integer_reference;
8721           channel_mask=SetPixelChannelMask(image,channel);
8722           EqualizeImage(image,exception);
8723           (void) SetPixelChannelMask(image,channel_mask);
8724           break;
8725         }
8726         case 40:  /* Gamma */
8727         {
8728           if (attribute_flag[1] != 0)
8729             channel=(ChannelType) argument_list[1].integer_reference;
8730           if (attribute_flag[2] == 0)
8731             argument_list[2].real_reference=1.0;
8732           if (attribute_flag[3] == 0)
8733             argument_list[3].real_reference=1.0;
8734           if (attribute_flag[4] == 0)
8735             argument_list[4].real_reference=1.0;
8736           if (attribute_flag[0] == 0)
8737             {
8738               (void) FormatLocaleString(message,MaxTextExtent,
8739                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8740                 (double) argument_list[3].real_reference,
8741                 (double) argument_list[4].real_reference);
8742               argument_list[0].string_reference=message;
8743             }
8744           (void) GammaImage(image,StringToDouble(
8745             argument_list[0].string_reference,(char **) NULL),exception);
8746           break;
8747         }
8748         case 41:  /* Map */
8749         {
8750           QuantizeInfo
8751             *quantize_info;
8752
8753           if (attribute_flag[0] == 0)
8754             {
8755               ThrowPerlException(exception,OptionError,"MapImageRequired",
8756                 PackageName);
8757               goto PerlException;
8758             }
8759           quantize_info=AcquireQuantizeInfo(info->image_info);
8760           if (attribute_flag[1] != 0)
8761             quantize_info->dither=(MagickBooleanType)
8762               argument_list[1].integer_reference;
8763           if (attribute_flag[2] != 0)
8764             quantize_info->dither_method=(DitherMethod)
8765               argument_list[2].integer_reference;
8766           (void) RemapImages(quantize_info,image,
8767             argument_list[0].image_reference,exception);
8768           quantize_info=DestroyQuantizeInfo(quantize_info);
8769           break;
8770         }
8771         case 42:  /* MatteFloodfill */
8772         {
8773           DrawInfo
8774             *draw_info;
8775
8776           MagickBooleanType
8777             invert;
8778
8779           PixelInfo
8780             target;
8781
8782           Quantum
8783             virtual_pixel[MaxPixelChannels];
8784
8785           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8786             (DrawInfo *) NULL);
8787           if (attribute_flag[0] != 0)
8788             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8789               &geometry,exception);
8790           if (attribute_flag[1] != 0)
8791             geometry.x=argument_list[1].integer_reference;
8792           if (attribute_flag[2] != 0)
8793             geometry.y=argument_list[2].integer_reference;
8794           if (image->matte == MagickFalse)
8795             (void) SetImageAlpha(image,OpaqueAlpha,exception);
8796           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
8797             exception);
8798           target.red=virtual_pixel[RedPixelChannel];
8799           target.green=virtual_pixel[GreenPixelChannel];
8800           target.blue=virtual_pixel[BluePixelChannel];
8801           target.alpha=virtual_pixel[AlphaPixelChannel];
8802           if (attribute_flag[4] != 0)
8803             QueryColorCompliance(argument_list[4].string_reference,
8804               AllCompliance,&target,exception);
8805           if (attribute_flag[3] != 0)
8806             target.alpha=StringToDoubleInterval(
8807               argument_list[3].string_reference,(double) (double) QuantumRange+
8808               1.0);
8809           if (attribute_flag[5] != 0)
8810             image->fuzz=StringToDoubleInterval(
8811               argument_list[5].string_reference,(double) QuantumRange+1.0);
8812           invert=MagickFalse;
8813           if (attribute_flag[6] != 0)
8814             invert=(MagickBooleanType) argument_list[6].integer_reference;
8815           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8816           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8817             geometry.y,invert,exception);
8818           (void) SetPixelChannelMask(image,channel_mask);
8819           draw_info=DestroyDrawInfo(draw_info);
8820           break;
8821         }
8822         case 43:  /* Modulate */
8823         {
8824           char
8825             modulate[MaxTextExtent];
8826
8827           geometry_info.rho=100.0;
8828           geometry_info.sigma=100.0;
8829           geometry_info.xi=100.0;
8830           if (attribute_flag[0] != 0)
8831             (void)ParseGeometry(argument_list[0].string_reference,
8832               &geometry_info);
8833           if (attribute_flag[1] != 0)
8834             geometry_info.xi=argument_list[1].real_reference;
8835           if (attribute_flag[2] != 0)
8836             geometry_info.sigma=argument_list[2].real_reference;
8837           if (attribute_flag[3] != 0)
8838             {
8839               geometry_info.sigma=argument_list[3].real_reference;
8840               SetImageArtifact(image,"modulate:colorspace","HWB");
8841             }
8842           if (attribute_flag[4] != 0)
8843             {
8844               geometry_info.rho=argument_list[4].real_reference;
8845               SetImageArtifact(image,"modulate:colorspace","HSB");
8846             }
8847           if (attribute_flag[5] != 0)
8848             {
8849               geometry_info.sigma=argument_list[5].real_reference;
8850               SetImageArtifact(image,"modulate:colorspace","HSL");
8851             }
8852           if (attribute_flag[6] != 0)
8853             {
8854               geometry_info.rho=argument_list[6].real_reference;
8855               SetImageArtifact(image,"modulate:colorspace","HWB");
8856             }
8857           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8858             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8859           (void) ModulateImage(image,modulate,exception);
8860           break;
8861         }
8862         case 44:  /* Negate */
8863         {
8864           if (attribute_flag[0] == 0)
8865             argument_list[0].integer_reference=0;
8866           if (attribute_flag[1] != 0)
8867             channel=(ChannelType) argument_list[1].integer_reference;
8868           channel_mask=SetPixelChannelMask(image,channel);
8869           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8870             MagickTrue : MagickFalse,exception);
8871           (void) SetPixelChannelMask(image,channel_mask);
8872           break;
8873         }
8874         case 45:  /* Normalize */
8875         {
8876           if (attribute_flag[0] != 0)
8877             channel=(ChannelType) argument_list[0].integer_reference;
8878           channel_mask=SetPixelChannelMask(image,channel);
8879           NormalizeImage(image,exception);
8880           (void) SetPixelChannelMask(image,channel_mask);
8881           break;
8882         }
8883         case 46:  /* NumberColors */
8884           break;
8885         case 47:  /* Opaque */
8886         {
8887           MagickBooleanType
8888             invert;
8889
8890           PixelInfo
8891             fill_color,
8892             target;
8893
8894           (void) QueryColorCompliance("none",AllCompliance,&target,
8895              exception);
8896           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
8897             exception);
8898           if (attribute_flag[0] != 0)
8899             (void) QueryColorCompliance(argument_list[0].string_reference,
8900               AllCompliance,&target,exception);
8901           if (attribute_flag[1] != 0)
8902             (void) QueryColorCompliance(argument_list[1].string_reference,
8903               AllCompliance,&fill_color,exception);
8904           if (attribute_flag[2] != 0)
8905             image->fuzz=StringToDoubleInterval(
8906               argument_list[2].string_reference,(double) QuantumRange+1.0);
8907           if (attribute_flag[3] != 0)
8908             channel=(ChannelType) argument_list[3].integer_reference;
8909           invert=MagickFalse;
8910           if (attribute_flag[4] != 0)
8911             invert=(MagickBooleanType) argument_list[4].integer_reference;
8912           channel_mask=SetPixelChannelMask(image,channel);
8913           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8914           (void) SetPixelChannelMask(image,channel_mask);
8915           break;
8916         }
8917         case 48:  /* Quantize */
8918         {
8919           QuantizeInfo
8920             *quantize_info;
8921
8922           quantize_info=AcquireQuantizeInfo(info->image_info);
8923           if (attribute_flag[0] != 0)
8924             quantize_info->number_colors=(size_t)
8925               argument_list[0].integer_reference;
8926           if (attribute_flag[1] != 0)
8927             quantize_info->tree_depth=(size_t)
8928               argument_list[1].integer_reference;
8929           if (attribute_flag[2] != 0)
8930             quantize_info->colorspace=(ColorspaceType)
8931               argument_list[2].integer_reference;
8932           if (attribute_flag[3] != 0)
8933             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8934               MagickTrue : MagickFalse;
8935           if (attribute_flag[4] != 0)
8936             quantize_info->measure_error=
8937               argument_list[4].integer_reference != 0 ? MagickTrue :
8938               MagickFalse;
8939           if (attribute_flag[5] != 0)
8940             (void) QueryColorCompliance(argument_list[5].string_reference,
8941               AllCompliance,&image->transparent_color,exception);
8942           if (attribute_flag[5] && argument_list[5].integer_reference)
8943             {
8944               (void) QuantizeImages(quantize_info,image,exception);
8945               goto PerlException;
8946             }
8947           if (attribute_flag[6] != 0)
8948             quantize_info->dither_method=(DitherMethod)
8949               argument_list[6].integer_reference;
8950           if ((image->storage_class == DirectClass) ||
8951               (image->colors > quantize_info->number_colors) ||
8952               (quantize_info->colorspace == GRAYColorspace))
8953             (void) QuantizeImage(quantize_info,image,exception);
8954           else
8955             CompressImageColormap(image,exception);
8956           quantize_info=DestroyQuantizeInfo(quantize_info);
8957           break;
8958         }
8959         case 49:  /* Raise */
8960         {
8961           if (attribute_flag[0] != 0)
8962             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8963               &geometry,exception);
8964           if (attribute_flag[1] != 0)
8965             geometry.width=argument_list[1].integer_reference;
8966           if (attribute_flag[2] != 0)
8967             geometry.height=argument_list[2].integer_reference;
8968           if (attribute_flag[3] == 0)
8969             argument_list[3].integer_reference=1;
8970           (void) RaiseImage(image,&geometry,
8971             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8972             exception);
8973           break;
8974         }
8975         case 50:  /* Segment */
8976         {
8977           ColorspaceType
8978             colorspace;
8979
8980           double
8981             cluster_threshold,
8982             smoothing_threshold;
8983
8984           MagickBooleanType
8985             verbose;
8986
8987           cluster_threshold=1.0;
8988           smoothing_threshold=1.5;
8989           colorspace=RGBColorspace;
8990           verbose=MagickFalse;
8991           if (attribute_flag[0] != 0)
8992             {
8993               flags=ParseGeometry(argument_list[0].string_reference,
8994                 &geometry_info);
8995               cluster_threshold=geometry_info.rho;
8996               if (flags & SigmaValue)
8997                 smoothing_threshold=geometry_info.sigma;
8998             }
8999           if (attribute_flag[1] != 0)
9000             cluster_threshold=argument_list[1].real_reference;
9001           if (attribute_flag[2] != 0)
9002             smoothing_threshold=argument_list[2].real_reference;
9003           if (attribute_flag[3] != 0)
9004             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9005           if (attribute_flag[4] != 0)
9006             verbose=argument_list[4].integer_reference != 0 ?
9007               MagickTrue : MagickFalse;
9008           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9009             smoothing_threshold,exception);
9010           break;
9011         }
9012         case 51:  /* Signature */
9013         {
9014           (void) SignatureImage(image,exception);
9015           break;
9016         }
9017         case 52:  /* Solarize */
9018         {
9019           geometry_info.rho=QuantumRange/2.0;
9020           if (attribute_flag[0] != 0)
9021             flags=ParseGeometry(argument_list[0].string_reference,
9022               &geometry_info);
9023           if (attribute_flag[1] != 0)
9024             geometry_info.rho=StringToDoubleInterval(
9025               argument_list[1].string_reference,(double) QuantumRange+1.0);
9026           (void) SolarizeImage(image,geometry_info.rho,exception);
9027           break;
9028         }
9029         case 53:  /* Sync */
9030         {
9031           (void) SyncImage(image,exception);
9032           break;
9033         }
9034         case 54:  /* Texture */
9035         {
9036           if (attribute_flag[0] == 0)
9037             break;
9038           TextureImage(image,argument_list[0].image_reference,exception);
9039           break;
9040         }
9041         case 55:  /* Evalute */
9042         {
9043           MagickEvaluateOperator
9044             op;
9045
9046           op=SetEvaluateOperator;
9047           if (attribute_flag[0] == MagickFalse)
9048             argument_list[0].real_reference=0.0;
9049           if (attribute_flag[1] != MagickFalse)
9050             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9051           if (attribute_flag[2] != MagickFalse)
9052             channel=(ChannelType) argument_list[2].integer_reference;
9053           channel_mask=SetPixelChannelMask(image,channel);
9054           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9055             exception);
9056           (void) SetPixelChannelMask(image,channel_mask);
9057           break;
9058         }
9059         case 56:  /* Transparent */
9060         {
9061           double
9062             opacity;
9063
9064           MagickBooleanType
9065             invert;
9066
9067           PixelInfo
9068             target;
9069
9070           (void) QueryColorCompliance("none",AllCompliance,&target,
9071             exception);
9072           if (attribute_flag[0] != 0)
9073             (void) QueryColorCompliance(argument_list[0].string_reference,
9074               AllCompliance,&target,exception);
9075           opacity=TransparentAlpha;
9076           if (attribute_flag[1] != 0)
9077             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9078               (double) QuantumRange+1.0);
9079           if (attribute_flag[2] != 0)
9080             image->fuzz=StringToDoubleInterval(
9081               argument_list[2].string_reference,(double) QuantumRange+1.0);
9082           if (attribute_flag[3] == 0)
9083             argument_list[3].integer_reference=0;
9084           invert=MagickFalse;
9085           if (attribute_flag[3] != 0)
9086             invert=(MagickBooleanType) argument_list[3].integer_reference;
9087           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9088             invert,exception);
9089           break;
9090         }
9091         case 57:  /* Threshold */
9092         {
9093           double
9094             threshold;
9095
9096           if (attribute_flag[0] == 0)
9097             argument_list[0].string_reference="50%";
9098           if (attribute_flag[1] != 0)
9099             channel=(ChannelType) argument_list[1].integer_reference;
9100           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9101             (double) QuantumRange+1.0);
9102           channel_mask=SetPixelChannelMask(image,channel);
9103           (void) BilevelImage(image,threshold,exception);
9104           (void) SetPixelChannelMask(image,channel_mask);
9105           break;
9106         }
9107         case 58:  /* Charcoal */
9108         {
9109           if (attribute_flag[0] != 0)
9110             {
9111               flags=ParseGeometry(argument_list[0].string_reference,
9112                 &geometry_info);
9113               if ((flags & SigmaValue) == 0)
9114                 geometry_info.sigma=1.0;
9115             }
9116           if (attribute_flag[1] != 0)
9117             geometry_info.rho=argument_list[1].real_reference;
9118           if (attribute_flag[2] != 0)
9119             geometry_info.sigma=argument_list[2].real_reference;
9120           if (attribute_flag[3] != 0)
9121             geometry_info.xi=argument_list[3].real_reference;
9122           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9123             geometry_info.xi,exception);
9124           break;
9125         }
9126         case 59:  /* Trim */
9127         {
9128           if (attribute_flag[0] != 0)
9129             image->fuzz=StringToDoubleInterval(
9130               argument_list[0].string_reference,(double) QuantumRange+1.0);
9131           image=TrimImage(image,exception);
9132           break;
9133         }
9134         case 60:  /* Wave */
9135         {
9136           PixelInterpolateMethod
9137             method;
9138
9139           if (attribute_flag[0] != 0)
9140             {
9141               flags=ParseGeometry(argument_list[0].string_reference,
9142                 &geometry_info);
9143               if ((flags & SigmaValue) == 0)
9144                 geometry_info.sigma=1.0;
9145             }
9146           if (attribute_flag[1] != 0)
9147             geometry_info.rho=argument_list[1].real_reference;
9148           if (attribute_flag[2] != 0)
9149             geometry_info.sigma=argument_list[2].real_reference;
9150           method=UndefinedInterpolatePixel;
9151           if (attribute_flag[3] != 0)
9152             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9153           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9154             method,exception);
9155           break;
9156         }
9157         case 61:  /* Separate */
9158         {
9159           if (attribute_flag[0] != 0)
9160             channel=(ChannelType) argument_list[0].integer_reference;
9161           channel_mask=SetPixelChannelMask(image,channel);
9162           (void) SeparateImage(image,exception);
9163           (void) SetPixelChannelMask(image,channel_mask);
9164           break;
9165         }
9166         case 63:  /* Stereo */
9167         {
9168           if (attribute_flag[0] == 0)
9169             {
9170               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9171                 PackageName);
9172               goto PerlException;
9173             }
9174           if (attribute_flag[1] != 0)
9175             geometry.x=argument_list[1].integer_reference;
9176           if (attribute_flag[2] != 0)
9177             geometry.y=argument_list[2].integer_reference;
9178           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9179             geometry.x,geometry.y,exception);
9180           break;
9181         }
9182         case 64:  /* Stegano */
9183         {
9184           if (attribute_flag[0] == 0)
9185             {
9186               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9187                 PackageName);
9188               goto PerlException;
9189             }
9190           if (attribute_flag[1] == 0)
9191             argument_list[1].integer_reference=0;
9192           image->offset=argument_list[1].integer_reference;
9193           image=SteganoImage(image,argument_list[0].image_reference,exception);
9194           break;
9195         }
9196         case 65:  /* Deconstruct */
9197         {
9198           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9199           break;
9200         }
9201         case 66:  /* GaussianBlur */
9202         {
9203           if (attribute_flag[0] != 0)
9204             {
9205               flags=ParseGeometry(argument_list[0].string_reference,
9206                 &geometry_info);
9207               if ((flags & SigmaValue) == 0)
9208                 geometry_info.sigma=1.0;
9209             }
9210           if (attribute_flag[1] != 0)
9211             geometry_info.rho=argument_list[1].real_reference;
9212           if (attribute_flag[2] != 0)
9213             geometry_info.sigma=argument_list[2].real_reference;
9214           if (attribute_flag[3] != 0)
9215             geometry_info.xi=argument_list[3].real_reference;
9216           if (attribute_flag[4] != 0)
9217             channel=(ChannelType) argument_list[4].integer_reference;
9218           channel_mask=SetPixelChannelMask(image,channel);
9219           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9220             geometry_info.xi,exception);
9221           if (image != (Image *) NULL)
9222             (void) SetPixelChannelMask(image,channel_mask);
9223           break;
9224         }
9225         case 67:  /* Convolve */
9226         {
9227           KernelInfo
9228             *kernel;
9229
9230           kernel=(KernelInfo *) NULL;
9231           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9232             break;
9233           if (attribute_flag[0] != 0)
9234             {
9235               AV
9236                 *av;
9237
9238               size_t
9239                 order;
9240
9241               kernel=AcquireKernelInfo((const char *) NULL);
9242               if (kernel == (KernelInfo *) NULL)
9243                 break;
9244               av=(AV *) argument_list[0].array_reference;
9245               order=(size_t) sqrt(av_len(av)+1);
9246               kernel->width=order;
9247               kernel->height=order;
9248               kernel->values=(double *) AcquireAlignedMemory(order,order*
9249                 sizeof(*kernel->values));
9250               if (kernel->values == (double *) NULL)
9251                 {
9252                   kernel=DestroyKernelInfo(kernel);
9253                   ThrowPerlException(exception,ResourceLimitFatalError,
9254                     "MemoryAllocationFailed",PackageName);
9255                   goto PerlException;
9256                 }
9257               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9258                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9259               for ( ; j < (ssize_t) (order*order); j++)
9260                 kernel->values[j]=0.0;
9261             }
9262           if (attribute_flag[1] != 0)
9263             channel=(ChannelType) argument_list[1].integer_reference;
9264           if (attribute_flag[2] != 0)
9265             image->bias=StringToDoubleInterval(
9266               argument_list[2].string_reference,(double) QuantumRange+1.0);
9267           if (attribute_flag[3] != 0)
9268             {
9269               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9270               if (kernel == (KernelInfo *) NULL)
9271                 break;
9272             }
9273           channel_mask=SetPixelChannelMask(image,channel);
9274           kernel->bias=image->bias;
9275           image=ConvolveImage(image,kernel,exception);
9276           if (image != (Image *) NULL)
9277             (void) SetPixelChannelMask(image,channel_mask);
9278           kernel=DestroyKernelInfo(kernel);
9279           break;
9280         }
9281         case 68:  /* Profile */
9282         {
9283           const char
9284             *name;
9285
9286           Image
9287             *profile_image;
9288
9289           ImageInfo
9290             *profile_info;
9291
9292           StringInfo
9293             *profile;
9294
9295           name="*";
9296           if (attribute_flag[0] != 0)
9297             name=argument_list[0].string_reference;
9298           if (attribute_flag[2] != 0)
9299             image->rendering_intent=(RenderingIntent)
9300               argument_list[2].integer_reference;
9301           if (attribute_flag[3] != 0)
9302             image->black_point_compensation=
9303               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9304           if (attribute_flag[1] != 0)
9305             {
9306               if (argument_list[1].length == 0)
9307                 {
9308                   /*
9309                     Remove a profile from the image.
9310                   */
9311                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9312                     exception);
9313                   break;
9314                 }
9315               /*
9316                 Associate user supplied profile with the image.
9317               */
9318               profile=AcquireStringInfo(argument_list[1].length);
9319               SetStringInfoDatum(profile,(const unsigned char *)
9320                 argument_list[1].string_reference);
9321               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9322                 (size_t) GetStringInfoLength(profile),exception);
9323               profile=DestroyStringInfo(profile);
9324               break;
9325             }
9326           /*
9327             Associate a profile with the image.
9328           */
9329           profile_info=
9330             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9331           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9332           profile_image=ReadImages(profile_info,exception);
9333           if (profile_image == (Image *) NULL)
9334             break;
9335           ResetImageProfileIterator(profile_image);
9336           name=GetNextImageProfile(profile_image);
9337           while (name != (const char *) NULL)
9338           {
9339             const StringInfo
9340               *profile;
9341
9342             profile=GetImageProfile(profile_image,name);
9343             if (profile != (const StringInfo *) NULL)
9344               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9345                 (size_t) GetStringInfoLength(profile),exception);
9346             name=GetNextImageProfile(profile_image);
9347           }
9348           profile_image=DestroyImage(profile_image);
9349           profile_info=DestroyImageInfo(profile_info);
9350           break;
9351         }
9352         case 69:  /* UnsharpMask */
9353         {
9354           if (attribute_flag[0] != 0)
9355             {
9356               flags=ParseGeometry(argument_list[0].string_reference,
9357                 &geometry_info);
9358               if ((flags & SigmaValue) == 0)
9359                 geometry_info.sigma=1.0;
9360               if ((flags & XiValue) == 0)
9361                 geometry_info.xi=1.0;
9362               if ((flags & PsiValue) == 0)
9363                 geometry_info.psi=0.5;
9364             }
9365           if (attribute_flag[1] != 0)
9366             geometry_info.rho=argument_list[1].real_reference;
9367           if (attribute_flag[2] != 0)
9368             geometry_info.sigma=argument_list[2].real_reference;
9369           if (attribute_flag[3] != 0)
9370             geometry_info.xi=argument_list[3].real_reference;
9371           if (attribute_flag[4] != 0)
9372             geometry_info.psi=argument_list[4].real_reference;
9373           if (attribute_flag[5] != 0)
9374             channel=(ChannelType) argument_list[5].integer_reference;
9375           channel_mask=SetPixelChannelMask(image,channel);
9376           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9377             geometry_info.xi,geometry_info.psi,exception);
9378           if (image != (Image *) NULL)
9379             (void) SetPixelChannelMask(image,channel_mask);
9380           break;
9381         }
9382         case 70:  /* MotionBlur */
9383         {
9384           if (attribute_flag[0] != 0)
9385             {
9386               flags=ParseGeometry(argument_list[0].string_reference,
9387                 &geometry_info);
9388               if ((flags & SigmaValue) == 0)
9389                 geometry_info.sigma=1.0;
9390               if ((flags & XiValue) == 0)
9391                 geometry_info.xi=1.0;
9392             }
9393           if (attribute_flag[1] != 0)
9394             geometry_info.rho=argument_list[1].real_reference;
9395           if (attribute_flag[2] != 0)
9396             geometry_info.sigma=argument_list[2].real_reference;
9397           if (attribute_flag[3] != 0)
9398             geometry_info.xi=argument_list[3].real_reference;
9399           if (attribute_flag[4] != 0)
9400             geometry_info.psi=argument_list[4].real_reference;
9401           if (attribute_flag[5] != 0)
9402             channel=(ChannelType) argument_list[5].integer_reference;
9403           channel_mask=SetPixelChannelMask(image,channel);
9404           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9405             geometry_info.xi,geometry_info.psi,exception);
9406           if (image != (Image *) NULL)
9407             (void) SetPixelChannelMask(image,channel_mask);
9408           break;
9409         }
9410         case 71:  /* OrderedDither */
9411         {
9412           if (attribute_flag[0] == 0)
9413             argument_list[0].string_reference="o8x8";
9414           if (attribute_flag[1] != 0)
9415             channel=(ChannelType) argument_list[1].integer_reference;
9416           channel_mask=SetPixelChannelMask(image,channel);
9417           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9418             exception);
9419           (void) SetPixelChannelMask(image,channel_mask);
9420           break;
9421         }
9422         case 72:  /* Shave */
9423         {
9424           if (attribute_flag[0] != 0)
9425             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9426               &geometry,exception);
9427           if (attribute_flag[1] != 0)
9428             geometry.width=argument_list[1].integer_reference;
9429           if (attribute_flag[2] != 0)
9430             geometry.height=argument_list[2].integer_reference;
9431           image=ShaveImage(image,&geometry,exception);
9432           break;
9433         }
9434         case 73:  /* Level */
9435         {
9436           double
9437             black_point,
9438             gamma,
9439             white_point;
9440
9441           black_point=0.0;
9442           white_point=(MagickRealType) image->columns*image->rows;
9443           gamma=1.0;
9444           if (attribute_flag[0] != 0)
9445             {
9446               flags=ParseGeometry(argument_list[0].string_reference,
9447                 &geometry_info);
9448               black_point=geometry_info.rho;
9449               if ((flags & SigmaValue) != 0)
9450                 white_point=geometry_info.sigma;
9451               if ((flags & XiValue) != 0)
9452                 gamma=geometry_info.xi;
9453               if ((flags & PercentValue) != 0)
9454                 {
9455                   black_point*=(double) (QuantumRange/100.0);
9456                   white_point*=(double) (QuantumRange/100.0);
9457                 }
9458               if ((flags & SigmaValue) == 0)
9459                 white_point=(double) QuantumRange-black_point;
9460             }
9461           if (attribute_flag[1] != 0)
9462             black_point=argument_list[1].real_reference;
9463           if (attribute_flag[2] != 0)
9464             white_point=argument_list[2].real_reference;
9465           if (attribute_flag[3] != 0)
9466             gamma=argument_list[3].real_reference;
9467           if (attribute_flag[4] != 0)
9468             channel=(ChannelType) argument_list[4].integer_reference;
9469           if (attribute_flag[5] != 0)
9470             {
9471               argument_list[0].real_reference=argument_list[5].real_reference;
9472               attribute_flag[0]=attribute_flag[5];
9473             }
9474           channel_mask=SetPixelChannelMask(image,channel);
9475           (void) LevelImage(image,black_point,white_point,gamma,exception);
9476           (void) SetPixelChannelMask(image,channel_mask);
9477           break;
9478         }
9479         case 74:  /* Clip */
9480         {
9481           if (attribute_flag[0] == 0)
9482             argument_list[0].string_reference="#1";
9483           if (attribute_flag[1] == 0)
9484             argument_list[1].integer_reference=MagickTrue;
9485           (void) ClipImagePath(image,argument_list[0].string_reference,
9486             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9487             exception);
9488           break;
9489         }
9490         case 75:  /* AffineTransform */
9491         {
9492           DrawInfo
9493             *draw_info;
9494
9495           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9496             (DrawInfo *) NULL);
9497           if (attribute_flag[0] != 0)
9498             {
9499               AV
9500                 *av;
9501
9502               av=(AV *) argument_list[0].array_reference;
9503               if ((av_len(av) != 3) && (av_len(av) != 5))
9504                 {
9505                   ThrowPerlException(exception,OptionError,
9506                     "affine matrix must have 4 or 6 elements",PackageName);
9507                   goto PerlException;
9508                 }
9509               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9510               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9511               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9512               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9513               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9514                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9515                 {
9516                   ThrowPerlException(exception,OptionError,
9517                     "affine matrix is singular",PackageName);
9518                    goto PerlException;
9519                 }
9520               if (av_len(av) == 5)
9521                 {
9522                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9523                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9524                 }
9525             }
9526           for (j=1; j < 6; j++)
9527           {
9528             if (attribute_flag[j] == 0)
9529               continue;
9530             value=argument_list[j].string_reference;
9531             angle=argument_list[j].real_reference;
9532             current=draw_info->affine;
9533             GetAffineMatrix(&affine);
9534             switch (j)
9535             {
9536               case 1:
9537               {
9538                 /*
9539                   Translate.
9540                 */
9541                 flags=ParseGeometry(value,&geometry_info);
9542                 affine.tx=geometry_info.xi;
9543                 affine.ty=geometry_info.psi;
9544                 if ((flags & PsiValue) == 0)
9545                   affine.ty=affine.tx;
9546                 break;
9547               }
9548               case 2:
9549               {
9550                 /*
9551                   Scale.
9552                 */
9553                 flags=ParseGeometry(value,&geometry_info);
9554                 affine.sx=geometry_info.rho;
9555                 affine.sy=geometry_info.sigma;
9556                 if ((flags & SigmaValue) == 0)
9557                   affine.sy=affine.sx;
9558                 break;
9559               }
9560               case 3:
9561               {
9562                 /*
9563                   Rotate.
9564                 */
9565                 if (angle == 0.0)
9566                   break;
9567                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9568                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9569                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9570                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9571                 break;
9572               }
9573               case 4:
9574               {
9575                 /*
9576                   SkewX.
9577                 */
9578                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9579                 break;
9580               }
9581               case 5:
9582               {
9583                 /*
9584                   SkewY.
9585                 */
9586                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9587                 break;
9588               }
9589             }
9590             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9591             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9592             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9593             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9594             draw_info->affine.tx=
9595               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9596             draw_info->affine.ty=
9597               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9598           }
9599           if (attribute_flag[6] != 0)
9600             image->interpolate=(PixelInterpolateMethod)
9601               argument_list[6].integer_reference;
9602           if (attribute_flag[7] != 0)
9603             QueryColorCompliance(argument_list[7].string_reference,
9604               AllCompliance,&image->background_color,exception);
9605           image=AffineTransformImage(image,&draw_info->affine,exception);
9606           draw_info=DestroyDrawInfo(draw_info);
9607           break;
9608         }
9609         case 76:  /* Difference */
9610         {
9611           if (attribute_flag[0] == 0)
9612             {
9613               ThrowPerlException(exception,OptionError,
9614                 "ReferenceImageRequired",PackageName);
9615               goto PerlException;
9616             }
9617           if (attribute_flag[1] != 0)
9618             image->fuzz=StringToDoubleInterval(
9619               argument_list[1].string_reference,(double) QuantumRange+1.0);
9620           (void) IsImagesEqual(image,argument_list[0].image_reference,
9621             exception);
9622           break;
9623         }
9624         case 77:  /* AdaptiveThreshold */
9625         {
9626           if (attribute_flag[0] != 0)
9627             {
9628               flags=ParseGeometry(argument_list[0].string_reference,
9629                 &geometry_info);
9630               if ((flags & PercentValue) != 0)
9631                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9632             }
9633           if (attribute_flag[1] != 0)
9634             geometry_info.rho=argument_list[1].integer_reference;
9635           if (attribute_flag[2] != 0)
9636             geometry_info.sigma=argument_list[2].integer_reference;
9637           if (attribute_flag[3] != 0)
9638             geometry_info.xi=argument_list[3].integer_reference;;
9639           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9640             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9641           break;
9642         }
9643         case 78:  /* Resample */
9644         {
9645           size_t
9646             height,
9647             width;
9648
9649           if (attribute_flag[0] != 0)
9650             {
9651               flags=ParseGeometry(argument_list[0].string_reference,
9652                 &geometry_info);
9653               if ((flags & SigmaValue) == 0)
9654                 geometry_info.sigma=geometry_info.rho;
9655             }
9656           if (attribute_flag[1] != 0)
9657             geometry_info.rho=argument_list[1].real_reference;
9658           if (attribute_flag[2] != 0)
9659             geometry_info.sigma=argument_list[2].real_reference;
9660           if (attribute_flag[3] == 0)
9661             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9662           if (attribute_flag[4] == 0)
9663             SetImageArtifact(image,"filter:support",
9664               argument_list[4].string_reference);
9665           if (attribute_flag[5] != 0)
9666             argument_list[5].real_reference=1.0;
9667           width=(size_t) (geometry_info.rho*image->columns/
9668             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9669           height=(size_t) (geometry_info.sigma*image->rows/
9670             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9671           image=ResizeImage(image,width,height,(FilterTypes)
9672             argument_list[3].integer_reference,argument_list[5].real_reference,
9673             exception);
9674           if (image != (Image *) NULL)
9675             {
9676               image->resolution.x=geometry_info.rho;
9677               image->resolution.y=geometry_info.sigma;
9678             }
9679           break;
9680         }
9681         case 79:  /* Describe */
9682         {
9683           if (attribute_flag[0] == 0)
9684             argument_list[0].file_reference=(FILE *) NULL;
9685           if (attribute_flag[1] != 0)
9686             (void) SetImageArtifact(image,"identify:features",
9687               argument_list[1].string_reference);
9688           (void) IdentifyImage(image,argument_list[0].file_reference,
9689             MagickTrue,exception);
9690           break;
9691         }
9692         case 80:  /* BlackThreshold */
9693         {
9694           if (attribute_flag[0] == 0)
9695             argument_list[0].string_reference="50%";
9696           if (attribute_flag[2] != 0)
9697             channel=(ChannelType) argument_list[2].integer_reference;
9698           channel_mask=SetPixelChannelMask(image,channel);
9699           BlackThresholdImage(image,argument_list[0].string_reference,
9700             exception);
9701           (void) SetPixelChannelMask(image,channel_mask);
9702           break;
9703         }
9704         case 81:  /* WhiteThreshold */
9705         {
9706           if (attribute_flag[0] == 0)
9707             argument_list[0].string_reference="50%";
9708           if (attribute_flag[2] != 0)
9709             channel=(ChannelType) argument_list[2].integer_reference;
9710           channel_mask=SetPixelChannelMask(image,channel);
9711           WhiteThresholdImage(image,argument_list[0].string_reference,
9712             exception);
9713           (void) SetPixelChannelMask(image,channel_mask);
9714           break;
9715         }
9716         case 82:  /* RadialBlur */
9717         {
9718           if (attribute_flag[0] != 0)
9719             {
9720               flags=ParseGeometry(argument_list[0].string_reference,
9721                 &geometry_info);
9722             }
9723           if (attribute_flag[1] != 0)
9724             geometry_info.rho=argument_list[1].real_reference;
9725           if (attribute_flag[2] != 0)
9726             geometry_info.sigma=argument_list[2].real_reference;
9727           if (attribute_flag[3] != 0)
9728             channel=(ChannelType) argument_list[3].integer_reference;
9729           channel_mask=SetPixelChannelMask(image,channel);
9730           image=RadialBlurImage(image,geometry_info.rho,geometry_info.sigma,
9731             exception);
9732           if (image != (Image *) NULL)
9733             (void) SetPixelChannelMask(image,channel_mask);
9734           break;
9735         }
9736         case 83:  /* Thumbnail */
9737         {
9738           if (attribute_flag[0] != 0)
9739             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9740               &geometry,exception);
9741           if (attribute_flag[1] != 0)
9742             geometry.width=argument_list[1].integer_reference;
9743           if (attribute_flag[2] != 0)
9744             geometry.height=argument_list[2].integer_reference;
9745           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9746           break;
9747         }
9748         case 84:  /* Strip */
9749         {
9750           (void) StripImage(image,exception);
9751           break;
9752         }
9753         case 85:  /* Tint */
9754         {
9755           PixelInfo
9756             tint;
9757
9758           GetPixelInfo(image,&tint);
9759           if (attribute_flag[0] != 0)
9760             (void) QueryColorCompliance(argument_list[0].string_reference,
9761               AllCompliance,&tint,exception);
9762           if (attribute_flag[1] == 0)
9763             argument_list[1].string_reference="100";
9764           image=TintImage(image,argument_list[1].string_reference,&tint,
9765             exception);
9766           break;
9767         }
9768         case 86:  /* Channel */
9769         {
9770           if (attribute_flag[0] != 0)
9771             channel=(ChannelType) argument_list[0].integer_reference;
9772           channel_mask=SetPixelChannelMask(image,channel);
9773           (void) SeparateImage(image,exception);
9774           (void) SetPixelChannelMask(image,channel_mask);
9775           break;
9776         }
9777         case 87:  /* Splice */
9778         {
9779           if (attribute_flag[0] != 0)
9780             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9781               &geometry,exception);
9782           if (attribute_flag[1] != 0)
9783             geometry.width=argument_list[1].integer_reference;
9784           if (attribute_flag[2] != 0)
9785             geometry.height=argument_list[2].integer_reference;
9786           if (attribute_flag[3] != 0)
9787             geometry.x=argument_list[3].integer_reference;
9788           if (attribute_flag[4] != 0)
9789             geometry.y=argument_list[4].integer_reference;
9790           if (attribute_flag[5] != 0)
9791             image->fuzz=StringToDoubleInterval(
9792               argument_list[5].string_reference,(double) QuantumRange+1.0);
9793           if (attribute_flag[6] != 0)
9794             (void) QueryColorCompliance(argument_list[6].string_reference,
9795               AllCompliance,&image->background_color,exception);
9796           if (attribute_flag[7] != 0)
9797             image->gravity=(GravityType) argument_list[7].integer_reference;
9798           image=SpliceImage(image,&geometry,exception);
9799           break;
9800         }
9801         case 88:  /* Posterize */
9802         {
9803           if (attribute_flag[0] == 0)
9804             argument_list[0].integer_reference=3;
9805           if (attribute_flag[1] == 0)
9806             argument_list[1].integer_reference=0;
9807           (void) PosterizeImage(image,argument_list[0].integer_reference,
9808             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9809             exception);
9810           break;
9811         }
9812         case 89:  /* Shadow */
9813         {
9814           if (attribute_flag[0] != 0)
9815             {
9816               flags=ParseGeometry(argument_list[0].string_reference,
9817                 &geometry_info);
9818               if ((flags & SigmaValue) == 0)
9819                 geometry_info.sigma=1.0;
9820               if ((flags & XiValue) == 0)
9821                 geometry_info.xi=4.0;
9822               if ((flags & PsiValue) == 0)
9823                 geometry_info.psi=4.0;
9824             }
9825           if (attribute_flag[1] != 0)
9826             geometry_info.rho=argument_list[1].real_reference;
9827           if (attribute_flag[2] != 0)
9828             geometry_info.sigma=argument_list[2].real_reference;
9829           if (attribute_flag[3] != 0)
9830             geometry_info.xi=argument_list[3].integer_reference;
9831           if (attribute_flag[4] != 0)
9832             geometry_info.psi=argument_list[4].integer_reference;
9833           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9834             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9835             0.5),exception);
9836           break;
9837         }
9838         case 90:  /* Identify */
9839         {
9840           if (attribute_flag[0] == 0)
9841             argument_list[0].file_reference=(FILE *) NULL;
9842           if (attribute_flag[1] != 0)
9843             (void) SetImageArtifact(image,"identify:features",
9844               argument_list[1].string_reference);
9845           if ((attribute_flag[2] != 0) &&
9846               (argument_list[2].integer_reference != 0))
9847             (void) SetImageArtifact(image,"identify:unique","true");
9848           (void) IdentifyImage(image,argument_list[0].file_reference,
9849             MagickTrue,exception);
9850           break;
9851         }
9852         case 91:  /* SepiaTone */
9853         {
9854           if (attribute_flag[0] == 0)
9855             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9856           image=SepiaToneImage(image,argument_list[0].real_reference,
9857             exception);
9858           break;
9859         }
9860         case 92:  /* SigmoidalContrast */
9861         {
9862           MagickBooleanType
9863             sharpen;
9864
9865           if (attribute_flag[0] != 0)
9866             {
9867               flags=ParseGeometry(argument_list[0].string_reference,
9868                 &geometry_info);
9869               if ((flags & SigmaValue) == 0)
9870                 geometry_info.sigma=QuantumRange/2.0;
9871               if ((flags & PercentValue) != 0)
9872                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9873             }
9874           if (attribute_flag[1] != 0)
9875             geometry_info.rho=argument_list[1].real_reference;
9876           if (attribute_flag[2] != 0)
9877             geometry_info.sigma=argument_list[2].real_reference;
9878           if (attribute_flag[3] != 0)
9879             channel=(ChannelType) argument_list[3].integer_reference;
9880           sharpen=MagickTrue;
9881           if (attribute_flag[4] != 0)
9882             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9883               MagickFalse;
9884           channel_mask=SetPixelChannelMask(image,channel);
9885           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9886             geometry_info.sigma,exception);
9887           (void) SetPixelChannelMask(image,channel_mask);
9888           break;
9889         }
9890         case 93:  /* Extent */
9891         {
9892           if (attribute_flag[7] != 0)
9893             image->gravity=(GravityType) argument_list[7].integer_reference;
9894           if (attribute_flag[0] != 0)
9895             {
9896               int
9897                 flags;
9898
9899               flags=ParseGravityGeometry(image,
9900                 argument_list[0].string_reference,&geometry,exception);
9901               (void) flags;
9902               if (geometry.width == 0)
9903                 geometry.width=image->columns;
9904               if (geometry.height == 0)
9905                 geometry.height=image->rows;
9906             }
9907           if (attribute_flag[1] != 0)
9908             geometry.width=argument_list[1].integer_reference;
9909           if (attribute_flag[2] != 0)
9910             geometry.height=argument_list[2].integer_reference;
9911           if (attribute_flag[3] != 0)
9912             geometry.x=argument_list[3].integer_reference;
9913           if (attribute_flag[4] != 0)
9914             geometry.y=argument_list[4].integer_reference;
9915           if (attribute_flag[5] != 0)
9916             image->fuzz=StringToDoubleInterval(
9917               argument_list[5].string_reference,(double) QuantumRange+1.0);
9918           if (attribute_flag[6] != 0)
9919             (void) QueryColorCompliance(argument_list[6].string_reference,
9920               AllCompliance,&image->background_color,exception);
9921           image=ExtentImage(image,&geometry,exception);
9922           break;
9923         }
9924         case 94:  /* Vignette */
9925         {
9926           if (attribute_flag[0] != 0)
9927             {
9928               flags=ParseGeometry(argument_list[0].string_reference,
9929                 &geometry_info);
9930               if ((flags & SigmaValue) == 0)
9931                 geometry_info.sigma=1.0;
9932               if ((flags & XiValue) == 0)
9933                 geometry_info.xi=0.1*image->columns;
9934               if ((flags & PsiValue) == 0)
9935                 geometry_info.psi=0.1*image->rows;
9936             }
9937           if (attribute_flag[1] != 0)
9938             geometry_info.rho=argument_list[1].real_reference;
9939           if (attribute_flag[2] != 0)
9940             geometry_info.sigma=argument_list[2].real_reference;
9941           if (attribute_flag[3] != 0)
9942             geometry_info.xi=argument_list[3].integer_reference;
9943           if (attribute_flag[4] != 0)
9944             geometry_info.psi=argument_list[4].integer_reference;
9945           if (attribute_flag[5] != 0)
9946             (void) QueryColorCompliance(argument_list[5].string_reference,
9947               AllCompliance,&image->background_color,exception);
9948           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9949             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9950             0.5),exception);
9951           break;
9952         }
9953         case 95:  /* ContrastStretch */
9954         {
9955           double
9956             black_point,
9957             white_point;
9958
9959           black_point=0.0;
9960           white_point=(MagickRealType) image->columns*image->rows;
9961           if (attribute_flag[0] != 0)
9962             {
9963               flags=ParseGeometry(argument_list[0].string_reference,
9964                 &geometry_info);
9965               black_point=geometry_info.rho;
9966               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9967                 black_point;
9968               if ((flags & PercentValue) != 0)
9969                 {
9970                   black_point*=(double) image->columns*image->rows/100.0;
9971                   white_point*=(double) image->columns*image->rows/100.0;
9972                 }
9973               white_point=(MagickRealType) image->columns*image->rows-
9974                 white_point;
9975             }
9976           if (attribute_flag[1] != 0)
9977             black_point=argument_list[1].real_reference;
9978           if (attribute_flag[2] != 0)
9979             white_point=argument_list[2].real_reference;
9980           if (attribute_flag[4] != 0)
9981             channel=(ChannelType) argument_list[4].integer_reference;
9982           channel_mask=SetPixelChannelMask(image,channel);
9983           (void) ContrastStretchImage(image,black_point,white_point,exception);
9984           (void) SetPixelChannelMask(image,channel_mask);
9985           break;
9986         }
9987         case 96:  /* Sans0 */
9988         {
9989           break;
9990         }
9991         case 97:  /* Sans1 */
9992         {
9993           break;
9994         }
9995         case 98:  /* AdaptiveSharpen */
9996         {
9997           if (attribute_flag[0] != 0)
9998             {
9999               flags=ParseGeometry(argument_list[0].string_reference,
10000                 &geometry_info);
10001               if ((flags & SigmaValue) == 0)
10002                 geometry_info.sigma=1.0;
10003               if ((flags & XiValue) == 0)
10004                 geometry_info.xi=0.0;
10005             }
10006           if (attribute_flag[1] != 0)
10007             geometry_info.rho=argument_list[1].real_reference;
10008           if (attribute_flag[2] != 0)
10009             geometry_info.sigma=argument_list[2].real_reference;
10010           if (attribute_flag[3] != 0)
10011             geometry_info.xi=argument_list[3].real_reference;
10012           if (attribute_flag[4] != 0)
10013             channel=(ChannelType) argument_list[4].integer_reference;
10014           channel_mask=SetPixelChannelMask(image,channel);
10015           image=AdaptiveSharpenImage(image,geometry_info.rho,
10016             geometry_info.sigma,geometry_info.xi,exception);
10017           if (image != (Image *) NULL)
10018             (void) SetPixelChannelMask(image,channel_mask);
10019           break;
10020         }
10021         case 99:  /* Transpose */
10022         {
10023           image=TransposeImage(image,exception);
10024           break;
10025         }
10026         case 100:  /* Tranverse */
10027         {
10028           image=TransverseImage(image,exception);
10029           break;
10030         }
10031         case 101:  /* AutoOrient */
10032         {
10033           switch (image->orientation)
10034           {
10035             case TopRightOrientation:
10036             {
10037               image=FlopImage(image,exception);
10038               break;
10039             }
10040             case BottomRightOrientation:
10041             {
10042               image=RotateImage(image,180.0,exception);
10043               break;
10044             }
10045             case BottomLeftOrientation:
10046             {
10047               image=FlipImage(image,exception);
10048               break;
10049             }
10050             case LeftTopOrientation:
10051             {
10052               image=TransposeImage(image,exception);
10053               break;
10054             }
10055             case RightTopOrientation:
10056             {
10057               image=RotateImage(image,90.0,exception);
10058               break;
10059             }
10060             case RightBottomOrientation:
10061             {
10062               image=TransverseImage(image,exception);
10063               break;
10064             }
10065             case LeftBottomOrientation:
10066             {
10067               image=RotateImage(image,270.0,exception);
10068               break;
10069             }
10070             default:
10071               break;
10072           }
10073           break;
10074         }
10075         case 102:  /* AdaptiveBlur */
10076         {
10077           if (attribute_flag[0] != 0)
10078             {
10079               flags=ParseGeometry(argument_list[0].string_reference,
10080                 &geometry_info);
10081               if ((flags & SigmaValue) == 0)
10082                 geometry_info.sigma=1.0;
10083               if ((flags & XiValue) == 0)
10084                 geometry_info.xi=0.0;
10085             }
10086           if (attribute_flag[1] != 0)
10087             geometry_info.rho=argument_list[1].real_reference;
10088           if (attribute_flag[2] != 0)
10089             geometry_info.sigma=argument_list[2].real_reference;
10090           if (attribute_flag[3] != 0)
10091             geometry_info.xi=argument_list[3].real_reference;
10092           if (attribute_flag[4] != 0)
10093             channel=(ChannelType) argument_list[4].integer_reference;
10094           channel_mask=SetPixelChannelMask(image,channel);
10095           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10096             geometry_info.xi,exception);
10097           if (image != (Image *) NULL)
10098             (void) SetPixelChannelMask(image,channel_mask);
10099           break;
10100         }
10101         case 103:  /* Sketch */
10102         {
10103           if (attribute_flag[0] != 0)
10104             {
10105               flags=ParseGeometry(argument_list[0].string_reference,
10106                 &geometry_info);
10107               if ((flags & SigmaValue) == 0)
10108                 geometry_info.sigma=1.0;
10109               if ((flags & XiValue) == 0)
10110                 geometry_info.xi=1.0;
10111             }
10112           if (attribute_flag[1] != 0)
10113             geometry_info.rho=argument_list[1].real_reference;
10114           if (attribute_flag[2] != 0)
10115             geometry_info.sigma=argument_list[2].real_reference;
10116           if (attribute_flag[3] != 0)
10117             geometry_info.xi=argument_list[3].real_reference;
10118           if (attribute_flag[4] != 0)
10119             geometry_info.psi=argument_list[4].real_reference;
10120           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10121             geometry_info.xi,geometry_info.psi,exception);
10122           break;
10123         }
10124         case 104:  /* UniqueColors */
10125         {
10126           image=UniqueImageColors(image,exception);
10127           break;
10128         }
10129         case 105:  /* AdaptiveResize */
10130         {
10131           PixelInterpolateMethod
10132             method;
10133
10134           if (attribute_flag[0] != 0)
10135             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10136               &geometry,exception);
10137           if (attribute_flag[1] != 0)
10138             geometry.width=argument_list[1].integer_reference;
10139           if (attribute_flag[2] != 0)
10140             geometry.height=argument_list[2].integer_reference;
10141           if (attribute_flag[3] != 0)
10142             image->filter=(FilterTypes) argument_list[4].integer_reference;
10143           if (attribute_flag[4] != 0)
10144             SetImageArtifact(image,"filter:support",
10145               argument_list[4].string_reference);
10146           if (attribute_flag[5] != 0)
10147             image->blur=argument_list[5].real_reference;
10148           method=UndefinedInterpolatePixel;
10149           if (attribute_flag[6] != 0)
10150             method=(PixelInterpolateMethod) argument_list[6].integer_reference;
10151           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10152             method,exception);
10153           break;
10154         }
10155         case 106:  /* ClipMask */
10156         {
10157           if (attribute_flag[0] == 0)
10158             {
10159               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10160                 PackageName);
10161               goto PerlException;
10162             }
10163           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10164             MagickTrue,exception);
10165           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10166           break;
10167         }
10168         case 107:  /* LinearStretch */
10169         {
10170            double
10171              black_point,
10172              white_point;
10173
10174            black_point=0.0;
10175            white_point=(MagickRealType) image->columns*image->rows;
10176            if (attribute_flag[0] != 0)
10177              {
10178                flags=ParseGeometry(argument_list[0].string_reference,
10179                  &geometry_info);
10180                if ((flags & SigmaValue) != 0)
10181                   white_point=geometry_info.sigma;
10182                if ((flags & PercentValue) != 0)
10183                  {
10184                    black_point*=(double) image->columns*image->rows/100.0;
10185                    white_point*=(double) image->columns*image->rows/100.0;
10186                  }
10187                if ((flags & SigmaValue) == 0)
10188                  white_point=(double) image->columns*image->rows-black_point;
10189              }
10190           if (attribute_flag[1] != 0)
10191             black_point=argument_list[1].real_reference;
10192           if (attribute_flag[2] != 0)
10193             white_point=argument_list[2].real_reference;
10194           (void) LinearStretchImage(image,black_point,white_point,exception);
10195           break;
10196         }
10197         case 108:  /* ColorMatrix */
10198         {
10199           AV
10200             *av;
10201
10202           double
10203             *color_matrix;
10204
10205           KernelInfo
10206             *kernel_info;
10207
10208           size_t
10209             order;
10210
10211           if (attribute_flag[0] == 0)
10212             break;
10213           av=(AV *) argument_list[0].array_reference;
10214           order=(size_t) sqrt(av_len(av)+1);
10215           color_matrix=(double *) AcquireQuantumMemory(order,order*
10216             sizeof(*color_matrix));
10217           if (color_matrix == (double *) NULL)
10218             {
10219               ThrowPerlException(exception,ResourceLimitFatalError,
10220                 "MemoryAllocationFailed",PackageName);
10221               goto PerlException;
10222            }
10223           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10224             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10225           for ( ; j < (ssize_t) (order*order); j++)
10226             color_matrix[j]=0.0;
10227           kernel_info=AcquireKernelInfo((const char *) NULL);
10228           if (kernel_info == (KernelInfo *) NULL)
10229             break;
10230           kernel_info->width=order;
10231           kernel_info->height=order;
10232           kernel_info->values=color_matrix;
10233           image=ColorMatrixImage(image,kernel_info,exception);
10234           kernel_info->values=(double *) NULL;
10235           kernel_info=DestroyKernelInfo(kernel_info);
10236           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10237           break;
10238         }
10239         case 109:  /* Mask */
10240         {
10241           if (attribute_flag[0] == 0)
10242             {
10243               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10244                 PackageName);
10245               goto PerlException;
10246             }
10247           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10248             MagickTrue,exception);
10249           (void) NegateImage(image->mask,MagickFalse,exception);
10250           break;
10251         }
10252         case 110:  /* Polaroid */
10253         {
10254           DrawInfo
10255             *draw_info;
10256
10257           double
10258             angle;
10259
10260           PixelInterpolateMethod
10261             method;
10262
10263           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10264             (DrawInfo *) NULL);
10265           if (attribute_flag[0] != 0)
10266             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10267               info ? info->image_info : (ImageInfo *) NULL,image,
10268               argument_list[0].string_reference,exception),exception);
10269           angle=0.0;
10270           if (attribute_flag[1] != 0)
10271             angle=argument_list[1].real_reference;
10272           if (attribute_flag[2] != 0)
10273             (void) CloneString(&draw_info->font,
10274               argument_list[2].string_reference);
10275           if (attribute_flag[3] != 0)
10276             (void) QueryColorCompliance(argument_list[3].string_reference,
10277               AllCompliance,&draw_info->stroke,exception);
10278           if (attribute_flag[4] != 0)
10279             (void) QueryColorCompliance(argument_list[4].string_reference,
10280               AllCompliance,&draw_info->fill,exception);
10281           if (attribute_flag[5] != 0)
10282             draw_info->stroke_width=argument_list[5].real_reference;
10283           if (attribute_flag[6] != 0)
10284             draw_info->pointsize=argument_list[6].real_reference;
10285           if (attribute_flag[7] != 0)
10286             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10287           if (attribute_flag[8] != 0)
10288             (void) QueryColorCompliance(argument_list[8].string_reference,
10289               AllCompliance,&image->background_color,exception);
10290           method=UndefinedInterpolatePixel;
10291           if (attribute_flag[9] != 0)
10292             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10293           image=PolaroidImage(image,draw_info,angle,method,exception);
10294           draw_info=DestroyDrawInfo(draw_info);
10295           break;
10296         }
10297         case 111:  /* FloodfillPaint */
10298         {
10299           DrawInfo
10300             *draw_info;
10301
10302           MagickBooleanType
10303             invert;
10304
10305           PixelInfo
10306             target;
10307
10308           Quantum
10309             virtual_pixel[MaxPixelChannels];
10310
10311           draw_info=CloneDrawInfo(info ? info->image_info :
10312             (ImageInfo *) NULL,(DrawInfo *) NULL);
10313           if (attribute_flag[0] != 0)
10314             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10315               &geometry,exception);
10316           if (attribute_flag[1] != 0)
10317             geometry.x=argument_list[1].integer_reference;
10318           if (attribute_flag[2] != 0)
10319             geometry.y=argument_list[2].integer_reference;
10320           if (attribute_flag[3] != 0)
10321             (void) QueryColorCompliance(argument_list[3].string_reference,
10322               AllCompliance,&draw_info->fill,exception);
10323           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
10324             exception);
10325           target.red=virtual_pixel[RedPixelChannel];
10326           target.green=virtual_pixel[GreenPixelChannel];
10327           target.blue=virtual_pixel[BluePixelChannel];
10328           target.alpha=virtual_pixel[AlphaPixelChannel];
10329           if (attribute_flag[4] != 0)
10330             QueryColorCompliance(argument_list[4].string_reference,
10331               AllCompliance,&target,exception);
10332           if (attribute_flag[5] != 0)
10333             image->fuzz=StringToDoubleInterval(
10334               argument_list[5].string_reference,(double) QuantumRange+1.0);
10335           if (attribute_flag[6] != 0)
10336             channel=(ChannelType) argument_list[6].integer_reference;
10337           invert=MagickFalse;
10338           if (attribute_flag[7] != 0)
10339             invert=(MagickBooleanType) argument_list[7].integer_reference;
10340           channel_mask=SetPixelChannelMask(image,channel);
10341           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10342             geometry.y,invert,exception);
10343           (void) SetPixelChannelMask(image,channel_mask);
10344           draw_info=DestroyDrawInfo(draw_info);
10345           break;
10346         }
10347         case 112:  /* Distort */
10348         {
10349           AV
10350             *av;
10351
10352           double
10353             *coordinates;
10354
10355           DistortImageMethod
10356             method;
10357
10358           size_t
10359             number_coordinates;
10360
10361           VirtualPixelMethod
10362             virtual_pixel;
10363
10364           if (attribute_flag[0] == 0)
10365             break;
10366           method=UndefinedDistortion;
10367           if (attribute_flag[1] != 0)
10368             method=(DistortImageMethod) argument_list[1].integer_reference;
10369           av=(AV *) argument_list[0].array_reference;
10370           number_coordinates=(size_t) av_len(av)+1;
10371           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10372             sizeof(*coordinates));
10373           if (coordinates == (double *) NULL)
10374             {
10375               ThrowPerlException(exception,ResourceLimitFatalError,
10376                 "MemoryAllocationFailed",PackageName);
10377               goto PerlException;
10378             }
10379           for (j=0; j < (ssize_t) number_coordinates; j++)
10380             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10381           virtual_pixel=UndefinedVirtualPixelMethod;
10382           if (attribute_flag[2] != 0)
10383             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10384               argument_list[2].integer_reference);
10385           image=DistortImage(image,method,number_coordinates,coordinates,
10386             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10387             exception);
10388           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10389             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10390           coordinates=(double *) RelinquishMagickMemory(coordinates);
10391           break;
10392         }
10393         case 113:  /* Clut */
10394         {
10395           PixelInterpolateMethod
10396             method;
10397
10398           if (attribute_flag[0] == 0)
10399             {
10400               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10401                 PackageName);
10402               goto PerlException;
10403             }
10404           method=UndefinedInterpolatePixel;
10405           if (attribute_flag[1] != 0)
10406             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10407           if (attribute_flag[2] != 0)
10408             channel=(ChannelType) argument_list[2].integer_reference;
10409           channel_mask=SetPixelChannelMask(image,channel);
10410           (void) ClutImage(image,argument_list[0].image_reference,method,
10411             exception);
10412           (void) SetPixelChannelMask(image,channel_mask);
10413           break;
10414         }
10415         case 114:  /* LiquidRescale */
10416         {
10417           if (attribute_flag[0] != 0)
10418             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10419               &geometry,exception);
10420           if (attribute_flag[1] != 0)
10421             geometry.width=argument_list[1].integer_reference;
10422           if (attribute_flag[2] != 0)
10423             geometry.height=argument_list[2].integer_reference;
10424           if (attribute_flag[3] == 0)
10425             argument_list[3].real_reference=1.0;
10426           if (attribute_flag[4] == 0)
10427             argument_list[4].real_reference=0.0;
10428           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10429             argument_list[3].real_reference,argument_list[4].real_reference,
10430             exception);
10431           break;
10432         }
10433         case 115:  /* EncipherImage */
10434         {
10435           (void) EncipherImage(image,argument_list[0].string_reference,
10436             exception);
10437           break;
10438         }
10439         case 116:  /* DecipherImage */
10440         {
10441           (void) DecipherImage(image,argument_list[0].string_reference,
10442             exception);
10443           break;
10444         }
10445         case 117:  /* Deskew */
10446         {
10447           geometry_info.rho=QuantumRange/2.0;
10448           if (attribute_flag[0] != 0)
10449             flags=ParseGeometry(argument_list[0].string_reference,
10450               &geometry_info);
10451           if (attribute_flag[1] != 0)
10452             geometry_info.rho=StringToDoubleInterval(
10453               argument_list[1].string_reference,(double) QuantumRange+1.0);
10454           image=DeskewImage(image,geometry_info.rho,exception);
10455           break;
10456         }
10457         case 118:  /* Remap */
10458         {
10459           QuantizeInfo
10460             *quantize_info;
10461
10462           if (attribute_flag[0] == 0)
10463             {
10464               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10465                 PackageName);
10466               goto PerlException;
10467             }
10468           quantize_info=AcquireQuantizeInfo(info->image_info);
10469           if (attribute_flag[1] != 0)
10470             quantize_info->dither=(MagickBooleanType)
10471               argument_list[1].integer_reference;
10472           if (attribute_flag[2] != 0)
10473             quantize_info->dither_method=(DitherMethod)
10474               argument_list[2].integer_reference;
10475           (void) RemapImages(quantize_info,image,
10476             argument_list[0].image_reference,exception);
10477           quantize_info=DestroyQuantizeInfo(quantize_info);
10478           break;
10479         }
10480         case 119:  /* SparseColor */
10481         {
10482           AV
10483             *av;
10484
10485           double
10486             *coordinates;
10487
10488           SparseColorMethod
10489             method;
10490
10491           size_t
10492             number_coordinates;
10493
10494           VirtualPixelMethod
10495             virtual_pixel;
10496
10497           if (attribute_flag[0] == 0)
10498             break;
10499           method=UndefinedColorInterpolate;
10500           if (attribute_flag[1] != 0)
10501             method=(SparseColorMethod) argument_list[1].integer_reference;
10502           av=(AV *) argument_list[0].array_reference;
10503           number_coordinates=(size_t) av_len(av)+1;
10504           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10505             sizeof(*coordinates));
10506           if (coordinates == (double *) NULL)
10507             {
10508               ThrowPerlException(exception,ResourceLimitFatalError,
10509                 "MemoryAllocationFailed",PackageName);
10510               goto PerlException;
10511             }
10512           for (j=0; j < (ssize_t) number_coordinates; j++)
10513             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10514           virtual_pixel=UndefinedVirtualPixelMethod;
10515           if (attribute_flag[2] != 0)
10516             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10517               argument_list[2].integer_reference);
10518           if (attribute_flag[3] != 0)
10519             channel=(ChannelType) argument_list[3].integer_reference;
10520           channel_mask=SetPixelChannelMask(image,channel);
10521           image=SparseColorImage(image,method,number_coordinates,coordinates,
10522             exception);
10523           if (image != (Image *) NULL)
10524             (void) SetPixelChannelMask(image,channel_mask);
10525           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10526             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10527           coordinates=(double *) RelinquishMagickMemory(coordinates);
10528           break;
10529         }
10530         case 120:  /* Function */
10531         {
10532           AV
10533             *av;
10534
10535           double
10536             *parameters;
10537
10538           MagickFunction
10539             function;
10540
10541           size_t
10542             number_parameters;
10543
10544           VirtualPixelMethod
10545             virtual_pixel;
10546
10547           if (attribute_flag[0] == 0)
10548             break;
10549           function=UndefinedFunction;
10550           if (attribute_flag[1] != 0)
10551             function=(MagickFunction) argument_list[1].integer_reference;
10552           av=(AV *) argument_list[0].array_reference;
10553           number_parameters=(size_t) av_len(av)+1;
10554           parameters=(double *) AcquireQuantumMemory(number_parameters,
10555             sizeof(*parameters));
10556           if (parameters == (double *) NULL)
10557             {
10558               ThrowPerlException(exception,ResourceLimitFatalError,
10559                 "MemoryAllocationFailed",PackageName);
10560               goto PerlException;
10561             }
10562           for (j=0; j < (ssize_t) number_parameters; j++)
10563             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10564           virtual_pixel=UndefinedVirtualPixelMethod;
10565           if (attribute_flag[2] != 0)
10566             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10567               argument_list[2].integer_reference);
10568           (void) FunctionImage(image,function,number_parameters,parameters,
10569             exception);
10570           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10571             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10572           parameters=(double *) RelinquishMagickMemory(parameters);
10573           break;
10574         }
10575         case 121:  /* SelectiveBlur */
10576         {
10577           if (attribute_flag[0] != 0)
10578             {
10579               flags=ParseGeometry(argument_list[0].string_reference,
10580                 &geometry_info);
10581               if ((flags & SigmaValue) == 0)
10582                 geometry_info.sigma=1.0;
10583               if ((flags & PercentValue) != 0)
10584                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10585             }
10586           if (attribute_flag[1] != 0)
10587             geometry_info.rho=argument_list[1].real_reference;
10588           if (attribute_flag[2] != 0)
10589             geometry_info.sigma=argument_list[2].real_reference;
10590           if (attribute_flag[3] != 0)
10591             geometry_info.xi=argument_list[3].integer_reference;;
10592           if (attribute_flag[4] != 0)
10593             geometry_info.psi=argument_list[4].integer_reference;;
10594           if (attribute_flag[5] != 0)
10595             channel=(ChannelType) argument_list[5].integer_reference;
10596           channel_mask=SetPixelChannelMask(image,channel);
10597           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10598             geometry_info.xi,geometry_info.psi,exception);
10599           if (image != (Image *) NULL)
10600             (void) SetPixelChannelMask(image,channel_mask);
10601           break;
10602         }
10603         case 122:  /* HaldClut */
10604         {
10605           if (attribute_flag[0] == 0)
10606             {
10607               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10608                 PackageName);
10609               goto PerlException;
10610             }
10611           if (attribute_flag[1] != 0)
10612             channel=(ChannelType) argument_list[1].integer_reference;
10613           channel_mask=SetPixelChannelMask(image,channel);
10614           (void) HaldClutImage(image,argument_list[0].image_reference,
10615             exception);
10616           (void) SetPixelChannelMask(image,channel_mask);
10617           break;
10618         }
10619         case 123:  /* BlueShift */
10620         {
10621           if (attribute_flag[0] != 0)
10622             (void) ParseGeometry(argument_list[0].string_reference,
10623               &geometry_info);
10624           image=BlueShiftImage(image,geometry_info.rho,exception);
10625           break;
10626         }
10627         case 124:  /* ForwardFourierTransformImage */
10628         {
10629           image=ForwardFourierTransformImage(image,
10630             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10631             exception);
10632           break;
10633         }
10634         case 125:  /* InverseFourierTransformImage */
10635         {
10636           image=InverseFourierTransformImage(image,image->next,
10637             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10638             exception);
10639           break;
10640         }
10641         case 126:  /* ColorDecisionList */
10642         {
10643           if (attribute_flag[0] == 0)
10644             argument_list[0].string_reference=(char *) NULL;
10645           (void) ColorDecisionListImage(image,
10646             argument_list[0].string_reference,exception);
10647           break;
10648         }
10649         case 127:  /* AutoGamma */
10650         {
10651           if (attribute_flag[0] != 0)
10652             channel=(ChannelType) argument_list[0].integer_reference;
10653           channel_mask=SetPixelChannelMask(image,channel);
10654           (void) AutoGammaImage(image,exception);
10655           (void) SetPixelChannelMask(image,channel_mask);
10656           break;
10657         }
10658         case 128:  /* AutoLevel */
10659         {
10660           if (attribute_flag[0] != 0)
10661             channel=(ChannelType) argument_list[0].integer_reference;
10662           channel_mask=SetPixelChannelMask(image,channel);
10663           (void) AutoLevelImage(image,exception);
10664           (void) SetPixelChannelMask(image,channel_mask);
10665           break;
10666         }
10667         case 129:  /* LevelColors */
10668         {
10669           PixelInfo
10670             black_point,
10671             white_point;
10672
10673           (void) QueryColorCompliance("#000000",AllCompliance,
10674             &black_point,exception);
10675           (void) QueryColorCompliance("#ffffff",AllCompliance,
10676             &white_point,exception);
10677           if (attribute_flag[1] != 0)
10678              (void) QueryColorCompliance(
10679                argument_list[1].string_reference,AllCompliance,&black_point,
10680                exception);
10681           if (attribute_flag[2] != 0)
10682              (void) QueryColorCompliance(
10683                argument_list[2].string_reference,AllCompliance,&white_point,
10684                exception);
10685           if (attribute_flag[3] != 0)
10686             channel=(ChannelType) argument_list[3].integer_reference;
10687           channel_mask=SetPixelChannelMask(image,channel);
10688           (void) LevelImageColors(image,&black_point,&white_point,
10689             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10690             exception);
10691           (void) SetPixelChannelMask(image,channel_mask);
10692           break;
10693         }
10694         case 130:  /* Clamp */
10695         {
10696           if (attribute_flag[0] != 0)
10697             channel=(ChannelType) argument_list[0].integer_reference;
10698           channel_mask=SetPixelChannelMask(image,channel);
10699           (void) ClampImage(image,exception);
10700           (void) SetPixelChannelMask(image,channel_mask);
10701           break;
10702         }
10703         case 131:  /* BrightnessContrast */
10704         {
10705           double
10706             brightness,
10707             contrast;
10708
10709           brightness=0.0;
10710           contrast=0.0;
10711           if (attribute_flag[0] != 0)
10712             {
10713               flags=ParseGeometry(argument_list[0].string_reference,
10714                 &geometry_info);
10715               brightness=geometry_info.rho;
10716               if ((flags & SigmaValue) == 0)
10717                 contrast=geometry_info.sigma;
10718             }
10719           if (attribute_flag[1] != 0)
10720             brightness=argument_list[1].real_reference;
10721           if (attribute_flag[2] != 0)
10722             contrast=argument_list[2].real_reference;
10723           if (attribute_flag[4] != 0)
10724             channel=(ChannelType) argument_list[4].integer_reference;
10725           channel_mask=SetPixelChannelMask(image,channel);
10726           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10727           (void) SetPixelChannelMask(image,channel_mask);
10728           break;
10729         }
10730         case 132:  /* Morphology */
10731         {
10732           KernelInfo
10733             *kernel;
10734
10735           MorphologyMethod
10736             method;
10737
10738           ssize_t
10739             iterations;
10740
10741           if (attribute_flag[0] == 0)
10742             break;
10743           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10744           if (kernel == (KernelInfo *) NULL)
10745             break;
10746           if (attribute_flag[1] != 0)
10747             channel=(ChannelType) argument_list[1].integer_reference;
10748           method=UndefinedMorphology;
10749           if (attribute_flag[2] != 0)
10750             method=argument_list[2].integer_reference;
10751           iterations=1;
10752           if (attribute_flag[3] != 0)
10753             iterations=argument_list[3].integer_reference;
10754           channel_mask=SetPixelChannelMask(image,channel);
10755           image=MorphologyImage(image,method,iterations,kernel,exception);
10756           if (image != (Image *) NULL)
10757             (void) SetPixelChannelMask(image,channel_mask);
10758           kernel=DestroyKernelInfo(kernel);
10759           break;
10760         }
10761         case 133:  /* Mode */
10762         {
10763           if (attribute_flag[0] != 0)
10764             {
10765               flags=ParseGeometry(argument_list[0].string_reference,
10766                 &geometry_info);
10767               if ((flags & SigmaValue) == 0)
10768                 geometry_info.sigma=1.0;
10769             }
10770           if (attribute_flag[1] != 0)
10771             geometry_info.rho=argument_list[1].real_reference;
10772           if (attribute_flag[2] != 0)
10773             geometry_info.sigma=argument_list[2].real_reference;
10774           if (attribute_flag[3] != 0)
10775             channel=(ChannelType) argument_list[3].integer_reference;
10776           channel_mask=SetPixelChannelMask(image,channel);
10777           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10778             (size_t) geometry_info.sigma,exception);
10779           if (image != (Image *) NULL)
10780             (void) SetPixelChannelMask(image,channel_mask);
10781           break;
10782         }
10783         case 134:  /* Statistic */
10784         {
10785           StatisticType
10786             statistic;
10787
10788           statistic=UndefinedStatistic;
10789           if (attribute_flag[0] != 0)
10790             {
10791               flags=ParseGeometry(argument_list[0].string_reference,
10792                 &geometry_info);
10793               if ((flags & SigmaValue) == 0)
10794                 geometry_info.sigma=1.0;
10795             }
10796           if (attribute_flag[1] != 0)
10797             geometry_info.rho=argument_list[1].real_reference;
10798           if (attribute_flag[2] != 0)
10799             geometry_info.sigma=argument_list[2].real_reference;
10800           if (attribute_flag[3] != 0)
10801             channel=(ChannelType) argument_list[3].integer_reference;
10802           if (attribute_flag[4] != 0)
10803             statistic=(StatisticType) argument_list[4].integer_reference;
10804           channel_mask=SetPixelChannelMask(image,channel);
10805           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10806             (size_t) geometry_info.sigma,exception);
10807           if (image != (Image *) NULL)
10808             (void) SetPixelChannelMask(image,channel_mask);
10809           break;
10810         }
10811       }
10812       if (next != (Image *) NULL)
10813         (void) CatchImageException(next);
10814       if (region_image != (Image *) NULL)
10815         {
10816           /*
10817             Composite region.
10818           */ 
10819           status=CompositeImage(region_image,CopyCompositeOp,image,
10820             region_info.x,region_info.y,exception);
10821           (void) status;
10822           (void) CatchImageException(region_image);
10823           image=DestroyImage(image);
10824           image=region_image;
10825         }
10826       if (image != (Image *) NULL)
10827         {
10828           number_images++;
10829           if (next && (next != image))
10830             {
10831               image->next=next->next;
10832               if (image->next != (Image *) NULL)
10833                 image->next->previous=image;
10834               DeleteImageFromRegistry(*pv,next);
10835             }
10836           sv_setiv(*pv,(IV) image);
10837           next=image;
10838         }
10839       if (*pv)
10840         pv++;
10841     }
10842
10843   PerlException:
10844     if (reference_vector)
10845       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10846     InheritPerlException(exception,perl_exception);
10847     exception=DestroyExceptionInfo(exception);
10848     sv_setiv(perl_exception,(IV) number_images);
10849     SvPOK_on(perl_exception);
10850     ST(0)=sv_2mortal(perl_exception);
10851     XSRETURN(1);
10852   }
10853 \f
10854 #
10855 ###############################################################################
10856 #                                                                             #
10857 #                                                                             #
10858 #                                                                             #
10859 #   M o n t a g e                                                             #
10860 #                                                                             #
10861 #                                                                             #
10862 #                                                                             #
10863 ###############################################################################
10864 #
10865 #
10866 void
10867 Montage(ref,...)
10868   Image::Magick ref=NO_INIT
10869   ALIAS:
10870     MontageImage  = 1
10871     montage       = 2
10872     montageimage  = 3
10873   PPCODE:
10874   {
10875     AV
10876       *av;
10877
10878     char
10879       *attribute;
10880
10881     ExceptionInfo
10882       *exception;
10883
10884     HV
10885       *hv;
10886
10887     Image
10888       *image,
10889       *next;
10890
10891     PixelInfo
10892       transparent_color;
10893
10894     MontageInfo
10895       *montage_info;
10896
10897     register ssize_t
10898       i;
10899
10900     ssize_t
10901       sp;
10902
10903     struct PackageInfo
10904       *info;
10905
10906     SV
10907       *av_reference,
10908       *perl_exception,
10909       *reference,
10910       *rv,
10911       *sv;
10912
10913     PERL_UNUSED_VAR(ref);
10914     PERL_UNUSED_VAR(ix);
10915     exception=AcquireExceptionInfo();
10916     perl_exception=newSVpv("",0);
10917     sv=NULL;
10918     attribute=NULL;
10919     if (sv_isobject(ST(0)) == 0)
10920       {
10921         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10922           PackageName);
10923         goto PerlException;
10924       }
10925     reference=SvRV(ST(0));
10926     hv=SvSTASH(reference);
10927     av=newAV();
10928     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10929     SvREFCNT_dec(av);
10930     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10931     if (image == (Image *) NULL)
10932       {
10933         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10934           PackageName);
10935         goto PerlException;
10936       }
10937     /*
10938       Get options.
10939     */
10940     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10941     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10942     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
10943       exception);
10944     for (i=2; i < items; i+=2)
10945     {
10946       attribute=(char *) SvPV(ST(i-1),na);
10947       switch (*attribute)
10948       {
10949         case 'B':
10950         case 'b':
10951         {
10952           if (LocaleCompare(attribute,"background") == 0)
10953             {
10954               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10955                 &montage_info->background_color,exception);
10956               for (next=image; next; next=next->next)
10957                 next->background_color=montage_info->background_color;
10958               break;
10959             }
10960           if (LocaleCompare(attribute,"border") == 0)
10961             {
10962               montage_info->border_width=SvIV(ST(i));
10963               break;
10964             }
10965           if (LocaleCompare(attribute,"bordercolor") == 0)
10966             {
10967               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10968                 &montage_info->border_color,exception);
10969               for (next=image; next; next=next->next)
10970                 next->border_color=montage_info->border_color;
10971               break;
10972             }
10973           if (LocaleCompare(attribute,"borderwidth") == 0)
10974             {
10975               montage_info->border_width=SvIV(ST(i));
10976               break;
10977             }
10978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10979             attribute);
10980           break;
10981         }
10982         case 'C':
10983         case 'c':
10984         {
10985           if (LocaleCompare(attribute,"compose") == 0)
10986             {
10987               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10988                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10989               if (sp < 0)
10990                 {
10991                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10992                     SvPV(ST(i),na));
10993                   break;
10994                 }
10995               for (next=image; next; next=next->next)
10996                 next->compose=(CompositeOperator) sp;
10997               break;
10998             }
10999           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11000             attribute);
11001           break;
11002         }
11003         case 'F':
11004         case 'f':
11005         {
11006           if (LocaleCompare(attribute,"fill") == 0)
11007             {
11008               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11009                 &montage_info->fill,exception);
11010               break;
11011             }
11012           if (LocaleCompare(attribute,"font") == 0)
11013             {
11014               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11015               break;
11016             }
11017           if (LocaleCompare(attribute,"frame") == 0)
11018             {
11019               char
11020                 *p;
11021
11022               p=SvPV(ST(i),na);
11023               if (IsGeometry(p) == MagickFalse)
11024                 {
11025                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11026                     p);
11027                   break;
11028                 }
11029               (void) CloneString(&montage_info->frame,p);
11030               if (*p == '\0')
11031                 montage_info->frame=(char *) NULL;
11032               break;
11033             }
11034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11035             attribute);
11036           break;
11037         }
11038         case 'G':
11039         case 'g':
11040         {
11041           if (LocaleCompare(attribute,"geometry") == 0)
11042             {
11043               char
11044                 *p;
11045
11046               p=SvPV(ST(i),na);
11047               if (IsGeometry(p) == MagickFalse)
11048                 {
11049                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11050                     p);
11051                   break;
11052                 }
11053              (void) CloneString(&montage_info->geometry,p);
11054              if (*p == '\0')
11055                montage_info->geometry=(char *) NULL;
11056              break;
11057            }
11058          if (LocaleCompare(attribute,"gravity") == 0)
11059            {
11060              ssize_t
11061                in;
11062
11063              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11064                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11065              if (in < 0)
11066                {
11067                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11068                    SvPV(ST(i),na));
11069                  return;
11070                }
11071              montage_info->gravity=(GravityType) in;
11072              for (next=image; next; next=next->next)
11073                next->gravity=(GravityType) in;
11074              break;
11075            }
11076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11077             attribute);
11078           break;
11079         }
11080         case 'L':
11081         case 'l':
11082         {
11083           if (LocaleCompare(attribute,"label") == 0)
11084             {
11085               for (next=image; next; next=next->next)
11086                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11087                   info ? info->image_info : (ImageInfo *) NULL,next,
11088                   SvPV(ST(i),na),exception),exception);
11089               break;
11090             }
11091           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11092             attribute);
11093           break;
11094         }
11095         case 'M':
11096         case 'm':
11097         {
11098           if (LocaleCompare(attribute,"mattecolor") == 0)
11099             {
11100               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11101                 &montage_info->matte_color,exception);
11102               for (next=image; next; next=next->next)
11103                 next->matte_color=montage_info->matte_color;
11104               break;
11105             }
11106           if (LocaleCompare(attribute,"mode") == 0)
11107             {
11108               ssize_t
11109                 in;
11110
11111               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11112                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11113               switch (in)
11114               {
11115                 default:
11116                 {
11117                   ThrowPerlException(exception,OptionError,
11118                     "UnrecognizedModeType",SvPV(ST(i),na));
11119                   break;
11120                 }
11121                 case FrameMode:
11122                 {
11123                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11124                   montage_info->shadow=MagickTrue;
11125                   break;
11126                 }
11127                 case UnframeMode:
11128                 {
11129                   montage_info->frame=(char *) NULL;
11130                   montage_info->shadow=MagickFalse;
11131                   montage_info->border_width=0;
11132                   break;
11133                 }
11134                 case ConcatenateMode:
11135                 {
11136                   montage_info->frame=(char *) NULL;
11137                   montage_info->shadow=MagickFalse;
11138                   (void) CloneString(&montage_info->geometry,"+0+0");
11139                   montage_info->border_width=0;
11140                 }
11141               }
11142               break;
11143             }
11144           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11145             attribute);
11146           break;
11147         }
11148         case 'P':
11149         case 'p':
11150         {
11151           if (LocaleCompare(attribute,"pointsize") == 0)
11152             {
11153               montage_info->pointsize=SvIV(ST(i));
11154               break;
11155             }
11156           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11157             attribute);
11158           break;
11159         }
11160         case 'S':
11161         case 's':
11162         {
11163           if (LocaleCompare(attribute,"shadow") == 0)
11164             {
11165               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11166                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11167               if (sp < 0)
11168                 {
11169                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11170                     SvPV(ST(i),na));
11171                   break;
11172                 }
11173              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11174              break;
11175             }
11176           if (LocaleCompare(attribute,"stroke") == 0)
11177             {
11178               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11179                 &montage_info->stroke,exception);
11180               break;
11181             }
11182           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11183             attribute);
11184           break;
11185         }
11186         case 'T':
11187         case 't':
11188         {
11189           if (LocaleCompare(attribute,"texture") == 0)
11190             {
11191               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11192               break;
11193             }
11194           if (LocaleCompare(attribute,"tile") == 0)
11195             {
11196               char *p=SvPV(ST(i),na);
11197               if (IsGeometry(p) == MagickFalse)
11198                 {
11199                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11200                     p);
11201                   break;
11202                 }
11203               (void) CloneString(&montage_info->tile,p);
11204               if (*p == '\0')
11205                 montage_info->tile=(char *) NULL;
11206               break;
11207             }
11208           if (LocaleCompare(attribute,"title") == 0)
11209             {
11210               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11211               break;
11212             }
11213           if (LocaleCompare(attribute,"transparent") == 0)
11214             {
11215               PixelInfo
11216                 transparent_color;
11217
11218               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11219                 &transparent_color,exception);
11220               for (next=image; next; next=next->next)
11221                 (void) TransparentPaintImage(next,&transparent_color,
11222                   TransparentAlpha,MagickFalse,exception);
11223               break;
11224             }
11225           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11226             attribute);
11227           break;
11228         }
11229         default:
11230         {
11231           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11232             attribute);
11233           break;
11234         }
11235       }
11236     }
11237     image=MontageImageList(info->image_info,montage_info,image,exception);
11238     montage_info=DestroyMontageInfo(montage_info);
11239     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11240       goto PerlException;
11241     if (transparent_color.alpha != TransparentAlpha)
11242       for (next=image; next; next=next->next)
11243         (void) TransparentPaintImage(next,&transparent_color,
11244           TransparentAlpha,MagickFalse,exception);
11245     for (  ; image; image=image->next)
11246     {
11247       AddImageToRegistry(sv,image);
11248       rv=newRV(sv);
11249       av_push(av,sv_bless(rv,hv));
11250       SvREFCNT_dec(sv);
11251     }
11252     exception=DestroyExceptionInfo(exception);
11253     ST(0)=av_reference;
11254     SvREFCNT_dec(perl_exception);
11255     XSRETURN(1);
11256
11257   PerlException:
11258     InheritPerlException(exception,perl_exception);
11259     exception=DestroyExceptionInfo(exception);
11260     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11261     SvPOK_on(perl_exception);
11262     ST(0)=sv_2mortal(perl_exception);
11263     XSRETURN(1);
11264   }
11265 \f
11266 #
11267 ###############################################################################
11268 #                                                                             #
11269 #                                                                             #
11270 #                                                                             #
11271 #   M o r p h                                                                 #
11272 #                                                                             #
11273 #                                                                             #
11274 #                                                                             #
11275 ###############################################################################
11276 #
11277 #
11278 void
11279 Morph(ref,...)
11280   Image::Magick ref=NO_INIT
11281   ALIAS:
11282     MorphImage  = 1
11283     morph       = 2
11284     morphimage  = 3
11285   PPCODE:
11286   {
11287     AV
11288       *av;
11289
11290     char
11291       *attribute;
11292
11293     ExceptionInfo
11294       *exception;
11295
11296     HV
11297       *hv;
11298
11299     Image
11300       *image;
11301
11302     register ssize_t
11303       i;
11304
11305     ssize_t
11306       number_frames;
11307
11308     struct PackageInfo
11309       *info;
11310
11311     SV
11312       *av_reference,
11313       *perl_exception,
11314       *reference,
11315       *rv,
11316       *sv;
11317
11318     PERL_UNUSED_VAR(ref);
11319     PERL_UNUSED_VAR(ix);
11320     exception=AcquireExceptionInfo();
11321     perl_exception=newSVpv("",0);
11322     sv=NULL;
11323     av=NULL;
11324     attribute=NULL;
11325     if (sv_isobject(ST(0)) == 0)
11326       {
11327         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11328           PackageName);
11329         goto PerlException;
11330       }
11331     reference=SvRV(ST(0));
11332     hv=SvSTASH(reference);
11333     av=newAV();
11334     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11335     SvREFCNT_dec(av);
11336     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11337     if (image == (Image *) NULL)
11338       {
11339         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11340           PackageName);
11341         goto PerlException;
11342       }
11343     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11344     /*
11345       Get attribute.
11346     */
11347     number_frames=30;
11348     for (i=2; i < items; i+=2)
11349     {
11350       attribute=(char *) SvPV(ST(i-1),na);
11351       switch (*attribute)
11352       {
11353         case 'F':
11354         case 'f':
11355         {
11356           if (LocaleCompare(attribute,"frames") == 0)
11357             {
11358               number_frames=SvIV(ST(i));
11359               break;
11360             }
11361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11362             attribute);
11363           break;
11364         }
11365         default:
11366         {
11367           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11368             attribute);
11369           break;
11370         }
11371       }
11372     }
11373     image=MorphImages(image,number_frames,exception);
11374     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11375       goto PerlException;
11376     for ( ; image; image=image->next)
11377     {
11378       AddImageToRegistry(sv,image);
11379       rv=newRV(sv);
11380       av_push(av,sv_bless(rv,hv));
11381       SvREFCNT_dec(sv);
11382     }
11383     exception=DestroyExceptionInfo(exception);
11384     ST(0)=av_reference;
11385     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11386     XSRETURN(1);
11387
11388   PerlException:
11389     InheritPerlException(exception,perl_exception);
11390     exception=DestroyExceptionInfo(exception);
11391     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11392     SvPOK_on(perl_exception);
11393     ST(0)=sv_2mortal(perl_exception);
11394     XSRETURN(1);
11395   }
11396 \f
11397 #
11398 ###############################################################################
11399 #                                                                             #
11400 #                                                                             #
11401 #                                                                             #
11402 #   M o s a i c                                                               #
11403 #                                                                             #
11404 #                                                                             #
11405 #                                                                             #
11406 ###############################################################################
11407 #
11408 #
11409 void
11410 Mosaic(ref)
11411   Image::Magick ref=NO_INIT
11412   ALIAS:
11413     MosaicImage   = 1
11414     mosaic        = 2
11415     mosaicimage   = 3
11416   PPCODE:
11417   {
11418     AV
11419       *av;
11420
11421     ExceptionInfo
11422       *exception;
11423
11424     HV
11425       *hv;
11426
11427     Image
11428       *image;
11429
11430     struct PackageInfo
11431       *info;
11432
11433     SV
11434       *perl_exception,
11435       *reference,
11436       *rv,
11437       *sv;
11438
11439     PERL_UNUSED_VAR(ref);
11440     PERL_UNUSED_VAR(ix);
11441     exception=AcquireExceptionInfo();
11442     perl_exception=newSVpv("",0);
11443     sv=NULL;
11444     if (sv_isobject(ST(0)) == 0)
11445       {
11446         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11447           PackageName);
11448         goto PerlException;
11449       }
11450     reference=SvRV(ST(0));
11451     hv=SvSTASH(reference);
11452     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11453     if (image == (Image *) NULL)
11454       {
11455         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11456           PackageName);
11457         goto PerlException;
11458       }
11459     image=MergeImageLayers(image,MosaicLayer,exception);
11460     /*
11461       Create blessed Perl array for the returned image.
11462     */
11463     av=newAV();
11464     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11465     SvREFCNT_dec(av);
11466     AddImageToRegistry(sv,image);
11467     rv=newRV(sv);
11468     av_push(av,sv_bless(rv,hv));
11469     SvREFCNT_dec(sv);
11470     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11471     (void) CopyMagickString(info->image_info->filename,image->filename,
11472       MaxTextExtent);
11473     SetImageInfo(info->image_info,0,exception);
11474     exception=DestroyExceptionInfo(exception);
11475     SvREFCNT_dec(perl_exception);
11476     XSRETURN(1);
11477
11478   PerlException:
11479     InheritPerlException(exception,perl_exception);
11480     exception=DestroyExceptionInfo(exception);
11481     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11482     SvPOK_on(perl_exception);  /* return messages in string context */
11483     ST(0)=sv_2mortal(perl_exception);
11484     XSRETURN(1);
11485   }
11486 \f
11487 #
11488 ###############################################################################
11489 #                                                                             #
11490 #                                                                             #
11491 #                                                                             #
11492 #   P i n g                                                                   #
11493 #                                                                             #
11494 #                                                                             #
11495 #                                                                             #
11496 ###############################################################################
11497 #
11498 #
11499 void
11500 Ping(ref,...)
11501   Image::Magick ref=NO_INIT
11502   ALIAS:
11503     PingImage  = 1
11504     ping       = 2
11505     pingimage  = 3
11506   PPCODE:
11507   {
11508     AV
11509       *av;
11510
11511     char
11512       **keep,
11513       **list;
11514
11515     ExceptionInfo
11516       *exception;
11517
11518     Image
11519       *image,
11520       *next;
11521
11522     int
11523       n;
11524
11525     MagickBooleanType
11526       status;
11527
11528     register char
11529       **p;
11530
11531     register ssize_t
11532       i;
11533
11534     ssize_t
11535       ac;
11536
11537     STRLEN
11538       *length;
11539
11540     struct PackageInfo
11541       *info,
11542       *package_info;
11543
11544     SV
11545       *perl_exception,
11546       *reference;
11547
11548     size_t
11549       count;
11550
11551     PERL_UNUSED_VAR(ref);
11552     PERL_UNUSED_VAR(ix);
11553     exception=AcquireExceptionInfo();
11554     perl_exception=newSVpv("",0);
11555     package_info=(struct PackageInfo *) NULL;
11556     ac=(items < 2) ? 1 : items-1;
11557     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11558     keep=list;
11559     length=(STRLEN *) NULL;
11560     if (list == (char **) NULL)
11561       {
11562         ThrowPerlException(exception,ResourceLimitError,
11563           "MemoryAllocationFailed",PackageName);
11564         goto PerlException;
11565       }
11566     keep=list;
11567     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11568     if (length == (STRLEN *) NULL)
11569       {
11570         ThrowPerlException(exception,ResourceLimitError,
11571           "MemoryAllocationFailed",PackageName);
11572         goto PerlException;
11573       }
11574     if (sv_isobject(ST(0)) == 0)
11575       {
11576         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11577           PackageName);
11578         goto PerlException;
11579       }
11580     reference=SvRV(ST(0));
11581     if (SvTYPE(reference) != SVt_PVAV)
11582       {
11583         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11584           PackageName);
11585         goto PerlException;
11586       }
11587     av=(AV *) reference;
11588     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11589       exception);
11590     package_info=ClonePackageInfo(info,exception);
11591     n=1;
11592     if (items <= 1)
11593       *list=(char *) (*package_info->image_info->filename ?
11594         package_info->image_info->filename : "XC:black");
11595     else
11596       for (n=0, i=0; i < ac; i++)
11597       {
11598         list[n]=(char *) SvPV(ST(i+1),length[n]);
11599         if ((items >= 3) && strEQcase(list[n],"blob"))
11600           {
11601             void
11602               *blob;
11603
11604             i++;
11605             blob=(void *) (SvPV(ST(i+1),length[n]));
11606             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11607           }
11608         if ((items >= 3) && strEQcase(list[n],"filename"))
11609           continue;
11610         if ((items >= 3) && strEQcase(list[n],"file"))
11611           {
11612             FILE
11613               *file;
11614
11615             PerlIO
11616               *io_info;
11617
11618             i++;
11619             io_info=IoIFP(sv_2io(ST(i+1)));
11620             if (io_info == (PerlIO *) NULL)
11621               {
11622                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11623                   PackageName);
11624                 continue;
11625               }
11626             file=PerlIO_findFILE(io_info);
11627             if (file == (FILE *) NULL)
11628               {
11629                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11630                   PackageName);
11631                 continue;
11632               }
11633             SetImageInfoFile(package_info->image_info,file);
11634           }
11635         if ((items >= 3) && strEQcase(list[n],"magick"))
11636           continue;
11637         n++;
11638       }
11639     list[n]=(char *) NULL;
11640     keep=list;
11641     status=ExpandFilenames(&n,&list);
11642     if (status == MagickFalse)
11643       {
11644         ThrowPerlException(exception,ResourceLimitError,
11645           "MemoryAllocationFailed",PackageName);
11646         goto PerlException;
11647       }
11648     count=0;
11649     for (i=0; i < n; i++)
11650     {
11651       (void) CopyMagickString(package_info->image_info->filename,list[i],
11652         MaxTextExtent);
11653       image=PingImage(package_info->image_info,exception);
11654       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11655         break;
11656       if ((package_info->image_info->file != (FILE *) NULL) ||
11657           (package_info->image_info->blob != (void *) NULL))
11658         DisassociateImageStream(image);
11659       count+=GetImageListLength(image);
11660       EXTEND(sp,4*count);
11661       for (next=image; next; next=next->next)
11662       {
11663         PUSHs(sv_2mortal(newSViv(next->columns)));
11664         PUSHs(sv_2mortal(newSViv(next->rows)));
11665         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11666         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11667       }
11668       image=DestroyImageList(image);
11669     }
11670     /*
11671       Free resources.
11672     */
11673     for (i=0; i < n; i++)
11674       if (list[i] != (char *) NULL)
11675         for (p=keep; list[i] != *p++; )
11676           if (*p == NULL)
11677             {
11678               list[i]=(char *) RelinquishMagickMemory(list[i]);
11679               break;
11680             }
11681
11682   PerlException:
11683     if (package_info != (struct PackageInfo *) NULL)
11684       DestroyPackageInfo(package_info);
11685     if (list && (list != keep))
11686       list=(char **) RelinquishMagickMemory(list);
11687     if (keep)
11688       keep=(char **) RelinquishMagickMemory(keep);
11689     if (length)
11690       length=(STRLEN *) RelinquishMagickMemory(length);
11691     InheritPerlException(exception,perl_exception);
11692     exception=DestroyExceptionInfo(exception);
11693     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11694   }
11695 \f
11696 #
11697 ###############################################################################
11698 #                                                                             #
11699 #                                                                             #
11700 #                                                                             #
11701 #   P r e v i e w                                                             #
11702 #                                                                             #
11703 #                                                                             #
11704 #                                                                             #
11705 ###############################################################################
11706 #
11707 #
11708 void
11709 Preview(ref,...)
11710   Image::Magick ref=NO_INIT
11711   ALIAS:
11712     PreviewImage = 1
11713     preview      = 2
11714     previewimage = 3
11715   PPCODE:
11716   {
11717     AV
11718       *av;
11719
11720     ExceptionInfo
11721       *exception;
11722
11723     HV
11724       *hv;
11725
11726     Image
11727       *image,
11728       *preview_image;
11729
11730     PreviewType
11731       preview_type;
11732
11733     struct PackageInfo
11734       *info;
11735
11736     SV
11737       *av_reference,
11738       *perl_exception,
11739       *reference,
11740       *rv,
11741       *sv;
11742
11743     PERL_UNUSED_VAR(ref);
11744     PERL_UNUSED_VAR(ix);
11745     exception=AcquireExceptionInfo();
11746     perl_exception=newSVpv("",0);
11747     sv=NULL;
11748     av=NULL;
11749     if (sv_isobject(ST(0)) == 0)
11750       {
11751         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11752           PackageName);
11753         goto PerlException;
11754       }
11755     reference=SvRV(ST(0));
11756     hv=SvSTASH(reference);
11757     av=newAV();
11758     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11759     SvREFCNT_dec(av);
11760     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11761     if (image == (Image *) NULL)
11762       {
11763         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11764           PackageName);
11765         goto PerlException;
11766       }
11767     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11768     preview_type=GammaPreview;
11769     if (items > 1)
11770       preview_type=(PreviewType)
11771         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11772     for ( ; image; image=image->next)
11773     {
11774       preview_image=PreviewImage(image,preview_type,exception);
11775       if (preview_image == (Image *) NULL)
11776         goto PerlException;
11777       AddImageToRegistry(sv,preview_image);
11778       rv=newRV(sv);
11779       av_push(av,sv_bless(rv,hv));
11780       SvREFCNT_dec(sv);
11781     }
11782     exception=DestroyExceptionInfo(exception);
11783     ST(0)=av_reference;
11784     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11785     XSRETURN(1);
11786
11787   PerlException:
11788     InheritPerlException(exception,perl_exception);
11789     exception=DestroyExceptionInfo(exception);
11790     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11791     SvPOK_on(perl_exception);
11792     ST(0)=sv_2mortal(perl_exception);
11793     XSRETURN(1);
11794   }
11795 \f
11796 #
11797 ###############################################################################
11798 #                                                                             #
11799 #                                                                             #
11800 #                                                                             #
11801 #   Q u e r y C o l o r                                                       #
11802 #                                                                             #
11803 #                                                                             #
11804 #                                                                             #
11805 ###############################################################################
11806 #
11807 #
11808 void
11809 QueryColor(ref,...)
11810   Image::Magick ref=NO_INIT
11811   ALIAS:
11812     querycolor = 1
11813   PPCODE:
11814   {
11815     char
11816       *name;
11817
11818     ExceptionInfo
11819       *exception;
11820
11821     PixelInfo
11822       color;
11823
11824     register ssize_t
11825       i;
11826
11827     SV
11828       *perl_exception;
11829
11830     PERL_UNUSED_VAR(ref);
11831     PERL_UNUSED_VAR(ix);
11832     exception=AcquireExceptionInfo();
11833     perl_exception=newSVpv("",0);
11834     if (items == 1)
11835       {
11836         const ColorInfo
11837           **colorlist;
11838
11839         size_t
11840           colors;
11841
11842         colorlist=GetColorInfoList("*",&colors,exception);
11843         EXTEND(sp,colors);
11844         for (i=0; i < (ssize_t) colors; i++)
11845         {
11846           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11847         }
11848         colorlist=(const ColorInfo **)
11849           RelinquishMagickMemory((ColorInfo **) colorlist);
11850         goto PerlException;
11851       }
11852     EXTEND(sp,5*items);
11853     for (i=1; i < items; i++)
11854     {
11855       name=(char *) SvPV(ST(i),na);
11856       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
11857         {
11858           PUSHs(&sv_undef);
11859           continue;
11860         }
11861       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11862       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11863       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11864       if (color.colorspace == CMYKColorspace)
11865         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11866       if (color.matte != MagickFalse)
11867         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11868     }
11869
11870   PerlException:
11871     InheritPerlException(exception,perl_exception);
11872     exception=DestroyExceptionInfo(exception);
11873     SvREFCNT_dec(perl_exception);
11874   }
11875 \f
11876 #
11877 ###############################################################################
11878 #                                                                             #
11879 #                                                                             #
11880 #                                                                             #
11881 #   Q u e r y C o l o r N a m e                                               #
11882 #                                                                             #
11883 #                                                                             #
11884 #                                                                             #
11885 ###############################################################################
11886 #
11887 #
11888 void
11889 QueryColorname(ref,...)
11890   Image::Magick ref=NO_INIT
11891   ALIAS:
11892     querycolorname = 1
11893   PPCODE:
11894   {
11895     AV
11896       *av;
11897
11898     char
11899       message[MaxTextExtent];
11900
11901     ExceptionInfo
11902       *exception;
11903
11904     Image
11905       *image;
11906
11907     PixelInfo
11908       target_color;
11909
11910     register ssize_t
11911       i;
11912
11913     struct PackageInfo
11914       *info;
11915
11916     SV
11917       *perl_exception,
11918       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11919
11920     PERL_UNUSED_VAR(ref);
11921     PERL_UNUSED_VAR(ix);
11922     exception=AcquireExceptionInfo();
11923     perl_exception=newSVpv("",0);
11924     reference=SvRV(ST(0));
11925     av=(AV *) reference;
11926     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11927       exception);
11928     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11929     if (image == (Image *) NULL)
11930       {
11931         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11932           PackageName);
11933         goto PerlException;
11934       }
11935     EXTEND(sp,items);
11936     for (i=1; i < items; i++)
11937     {
11938       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
11939         exception);
11940       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11941         exception);
11942       PUSHs(sv_2mortal(newSVpv(message,0)));
11943     }
11944
11945   PerlException:
11946     InheritPerlException(exception,perl_exception);
11947     exception=DestroyExceptionInfo(exception);
11948     SvREFCNT_dec(perl_exception);
11949   }
11950 \f
11951 #
11952 ###############################################################################
11953 #                                                                             #
11954 #                                                                             #
11955 #                                                                             #
11956 #   Q u e r y F o n t                                                         #
11957 #                                                                             #
11958 #                                                                             #
11959 #                                                                             #
11960 ###############################################################################
11961 #
11962 #
11963 void
11964 QueryFont(ref,...)
11965   Image::Magick ref=NO_INIT
11966   ALIAS:
11967     queryfont = 1
11968   PPCODE:
11969   {
11970     char
11971       *name,
11972       message[MaxTextExtent];
11973
11974     ExceptionInfo
11975       *exception;
11976
11977     register ssize_t
11978       i;
11979
11980     SV
11981       *perl_exception;
11982
11983     volatile const TypeInfo
11984       *type_info;
11985
11986     PERL_UNUSED_VAR(ref);
11987     PERL_UNUSED_VAR(ix);
11988     exception=AcquireExceptionInfo();
11989     perl_exception=newSVpv("",0);
11990     if (items == 1)
11991       {
11992         const TypeInfo
11993           **typelist;
11994
11995         size_t
11996           types;
11997
11998         typelist=GetTypeInfoList("*",&types,exception);
11999         EXTEND(sp,types);
12000         for (i=0; i < (ssize_t) types; i++)
12001         {
12002           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12003         }
12004         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12005           typelist);
12006         goto PerlException;
12007       }
12008     EXTEND(sp,10*items);
12009     for (i=1; i < items; i++)
12010     {
12011       name=(char *) SvPV(ST(i),na);
12012       type_info=GetTypeInfo(name,exception);
12013       if (type_info == (TypeInfo *) NULL)
12014         {
12015           PUSHs(&sv_undef);
12016           continue;
12017         }
12018       if (type_info->name == (char *) NULL)
12019         PUSHs(&sv_undef);
12020       else
12021         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12022       if (type_info->description == (char *) NULL)
12023         PUSHs(&sv_undef);
12024       else
12025         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12026       if (type_info->family == (char *) NULL)
12027         PUSHs(&sv_undef);
12028       else
12029         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12030       if (type_info->style == UndefinedStyle)
12031         PUSHs(&sv_undef);
12032       else
12033         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12034           type_info->style),0)));
12035       if (type_info->stretch == UndefinedStretch)
12036         PUSHs(&sv_undef);
12037       else
12038         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12039           type_info->stretch),0)));
12040       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12041         type_info->weight);
12042       PUSHs(sv_2mortal(newSVpv(message,0)));
12043       if (type_info->encoding == (char *) NULL)
12044         PUSHs(&sv_undef);
12045       else
12046         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12047       if (type_info->foundry == (char *) NULL)
12048         PUSHs(&sv_undef);
12049       else
12050         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12051       if (type_info->format == (char *) NULL)
12052         PUSHs(&sv_undef);
12053       else
12054         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12055       if (type_info->metrics == (char *) NULL)
12056         PUSHs(&sv_undef);
12057       else
12058         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12059       if (type_info->glyphs == (char *) NULL)
12060         PUSHs(&sv_undef);
12061       else
12062         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12063     }
12064
12065   PerlException:
12066     InheritPerlException(exception,perl_exception);
12067     exception=DestroyExceptionInfo(exception);
12068     SvREFCNT_dec(perl_exception);
12069   }
12070 \f
12071 #
12072 ###############################################################################
12073 #                                                                             #
12074 #                                                                             #
12075 #                                                                             #
12076 #   Q u e r y F o n t M e t r i c s                                           #
12077 #                                                                             #
12078 #                                                                             #
12079 #                                                                             #
12080 ###############################################################################
12081 #
12082 #
12083 void
12084 QueryFontMetrics(ref,...)
12085   Image::Magick ref=NO_INIT
12086   ALIAS:
12087     queryfontmetrics = 1
12088   PPCODE:
12089   {
12090     AffineMatrix
12091       affine,
12092       current;
12093
12094     AV
12095       *av;
12096
12097     char
12098       *attribute;
12099
12100     double
12101       x,
12102       y;
12103
12104     DrawInfo
12105       *draw_info;
12106
12107     ExceptionInfo
12108       *exception;
12109
12110     GeometryInfo
12111       geometry_info;
12112
12113     Image
12114       *image;
12115
12116     MagickBooleanType
12117       status;
12118
12119     MagickStatusType
12120       flags;
12121
12122     register ssize_t
12123       i;
12124
12125     ssize_t
12126       type;
12127
12128     struct PackageInfo
12129       *info,
12130       *package_info;
12131
12132     SV
12133       *perl_exception,
12134       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12135
12136     TypeMetric
12137       metrics;
12138
12139     PERL_UNUSED_VAR(ref);
12140     PERL_UNUSED_VAR(ix);
12141     exception=AcquireExceptionInfo();
12142     package_info=(struct PackageInfo *) NULL;
12143     perl_exception=newSVpv("",0);
12144     reference=SvRV(ST(0));
12145     av=(AV *) reference;
12146     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12147       exception);
12148     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12149     if (image == (Image *) NULL)
12150       {
12151         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12152           PackageName);
12153         goto PerlException;
12154       }
12155     package_info=ClonePackageInfo(info,exception);
12156     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12157     CloneString(&draw_info->text,"");
12158     current=draw_info->affine;
12159     GetAffineMatrix(&affine);
12160     x=0.0;
12161     y=0.0;
12162     EXTEND(sp,7*items);
12163     for (i=2; i < items; i+=2)
12164     {
12165       attribute=(char *) SvPV(ST(i-1),na);
12166       switch (*attribute)
12167       {
12168         case 'A':
12169         case 'a':
12170         {
12171           if (LocaleCompare(attribute,"antialias") == 0)
12172             {
12173               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12174                 SvPV(ST(i),na));
12175               if (type < 0)
12176                 {
12177                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12178                     SvPV(ST(i),na));
12179                   break;
12180                 }
12181               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12182               break;
12183             }
12184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12185             attribute);
12186           break;
12187         }
12188         case 'd':
12189         case 'D':
12190         {
12191           if (LocaleCompare(attribute,"density") == 0)
12192             {
12193               CloneString(&draw_info->density,SvPV(ST(i),na));
12194               break;
12195             }
12196           if (LocaleCompare(attribute,"direction") == 0)
12197             {
12198               draw_info->direction=(DirectionType) ParseCommandOption(
12199                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12200               break;
12201             }
12202           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12203             attribute);
12204           break;
12205         }
12206         case 'e':
12207         case 'E':
12208         {
12209           if (LocaleCompare(attribute,"encoding") == 0)
12210             {
12211               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12212               break;
12213             }
12214           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12215             attribute);
12216           break;
12217         }
12218         case 'f':
12219         case 'F':
12220         {
12221           if (LocaleCompare(attribute,"family") == 0)
12222             {
12223               CloneString(&draw_info->family,SvPV(ST(i),na));
12224               break;
12225             }
12226           if (LocaleCompare(attribute,"fill") == 0)
12227             {
12228               if (info)
12229                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12230                   &draw_info->fill,exception);
12231               break;
12232             }
12233           if (LocaleCompare(attribute,"font") == 0)
12234             {
12235               CloneString(&draw_info->font,SvPV(ST(i),na));
12236               break;
12237             }
12238           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12239             attribute);
12240           break;
12241         }
12242         case 'g':
12243         case 'G':
12244         {
12245           if (LocaleCompare(attribute,"geometry") == 0)
12246             {
12247               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12248               break;
12249             }
12250           if (LocaleCompare(attribute,"gravity") == 0)
12251             {
12252               draw_info->gravity=(GravityType) ParseCommandOption(
12253                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12254               break;
12255             }
12256           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12257             attribute);
12258           break;
12259         }
12260         case 'i':
12261         case 'I':
12262         {
12263           if (LocaleCompare(attribute,"interline-spacing") == 0)
12264             {
12265               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12266               draw_info->interline_spacing=geometry_info.rho;
12267               break;
12268             }
12269           if (LocaleCompare(attribute,"interword-spacing") == 0)
12270             {
12271               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12272               draw_info->interword_spacing=geometry_info.rho;
12273               break;
12274             }
12275           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12276             attribute);
12277           break;
12278         }
12279         case 'k':
12280         case 'K':
12281         {
12282           if (LocaleCompare(attribute,"kerning") == 0)
12283             {
12284               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12285               draw_info->kerning=geometry_info.rho;
12286               break;
12287             }
12288           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12289             attribute);
12290           break;
12291         }
12292         case 'p':
12293         case 'P':
12294         {
12295           if (LocaleCompare(attribute,"pointsize") == 0)
12296             {
12297               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12298               draw_info->pointsize=geometry_info.rho;
12299               break;
12300             }
12301           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12302             attribute);
12303           break;
12304         }
12305         case 'r':
12306         case 'R':
12307         {
12308           if (LocaleCompare(attribute,"rotate") == 0)
12309             {
12310               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12311               affine.rx=geometry_info.rho;
12312               affine.ry=geometry_info.sigma;
12313               if ((flags & SigmaValue) == 0)
12314                 affine.ry=affine.rx;
12315               break;
12316             }
12317           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12318             attribute);
12319           break;
12320         }
12321         case 's':
12322         case 'S':
12323         {
12324           if (LocaleCompare(attribute,"scale") == 0)
12325             {
12326               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12327               affine.sx=geometry_info.rho;
12328               affine.sy=geometry_info.sigma;
12329               if ((flags & SigmaValue) == 0)
12330                 affine.sy=affine.sx;
12331               break;
12332             }
12333           if (LocaleCompare(attribute,"skew") == 0)
12334             {
12335               double
12336                 x_angle,
12337                 y_angle;
12338
12339               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12340               x_angle=geometry_info.rho;
12341               y_angle=geometry_info.sigma;
12342               if ((flags & SigmaValue) == 0)
12343                 y_angle=x_angle;
12344               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12345               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12346               break;
12347             }
12348           if (LocaleCompare(attribute,"stroke") == 0)
12349             {
12350               if (info)
12351                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12352                   &draw_info->stroke,exception);
12353               break;
12354             }
12355           if (LocaleCompare(attribute,"style") == 0)
12356             {
12357               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12358                 SvPV(ST(i),na));
12359               if (type < 0)
12360                 {
12361                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12362                     SvPV(ST(i),na));
12363                   break;
12364                 }
12365               draw_info->style=(StyleType) type;
12366               break;
12367             }
12368           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12369             attribute);
12370           break;
12371         }
12372         case 't':
12373         case 'T':
12374         {
12375           if (LocaleCompare(attribute,"text") == 0)
12376             {
12377               CloneString(&draw_info->text,SvPV(ST(i),na));
12378               break;
12379             }
12380           if (LocaleCompare(attribute,"translate") == 0)
12381             {
12382               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12383               affine.tx=geometry_info.rho;
12384               affine.ty=geometry_info.sigma;
12385               if ((flags & SigmaValue) == 0)
12386                 affine.ty=affine.tx;
12387               break;
12388             }
12389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12390             attribute);
12391           break;
12392         }
12393         case 'w':
12394         case 'W':
12395         {
12396           if (LocaleCompare(attribute,"weight") == 0)
12397             {
12398               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12399               draw_info->weight=(size_t) geometry_info.rho;
12400               break;
12401             }
12402           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12403             attribute);
12404           break;
12405         }
12406         case 'x':
12407         case 'X':
12408         {
12409           if (LocaleCompare(attribute,"x") == 0)
12410             {
12411               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12412               x=geometry_info.rho;
12413               break;
12414             }
12415           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12416             attribute);
12417           break;
12418         }
12419         case 'y':
12420         case 'Y':
12421         {
12422           if (LocaleCompare(attribute,"y") == 0)
12423             {
12424               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12425               y=geometry_info.rho;
12426               break;
12427             }
12428           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12429             attribute);
12430           break;
12431         }
12432         default:
12433         {
12434           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12435             attribute);
12436           break;
12437         }
12438       }
12439     }
12440     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12441     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12442     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12443     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12444     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12445     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12446     if (draw_info->geometry == (char *) NULL)
12447       {
12448         draw_info->geometry=AcquireString((char *) NULL);
12449         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12450           "%.15g,%.15g",x,y);
12451       }
12452     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12453     (void) CatchImageException(image);
12454     if (status == MagickFalse)
12455       PUSHs(&sv_undef);
12456     else
12457       {
12458         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12459         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12460         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12461         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12462         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12463         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12464         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12465         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12466         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12467         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12468         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12469         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12470         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12471       }
12472     draw_info=DestroyDrawInfo(draw_info);
12473
12474   PerlException:
12475     if (package_info != (struct PackageInfo *) NULL)
12476       DestroyPackageInfo(package_info);
12477     InheritPerlException(exception,perl_exception);
12478     exception=DestroyExceptionInfo(exception);
12479     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12480   }
12481 \f
12482 #
12483 ###############################################################################
12484 #                                                                             #
12485 #                                                                             #
12486 #                                                                             #
12487 #   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                         #
12488 #                                                                             #
12489 #                                                                             #
12490 #                                                                             #
12491 ###############################################################################
12492 #
12493 #
12494 void
12495 QueryMultilineFontMetrics(ref,...)
12496   Image::Magick ref=NO_INIT
12497   ALIAS:
12498     querymultilinefontmetrics = 1
12499   PPCODE:
12500   {
12501     AffineMatrix
12502       affine,
12503       current;
12504
12505     AV
12506       *av;
12507
12508     char
12509       *attribute;
12510
12511     double
12512       x,
12513       y;
12514
12515     DrawInfo
12516       *draw_info;
12517
12518     ExceptionInfo
12519       *exception;
12520
12521     GeometryInfo
12522       geometry_info;
12523
12524     Image
12525       *image;
12526
12527     MagickBooleanType
12528       status;
12529
12530     MagickStatusType
12531       flags;
12532
12533     register ssize_t
12534       i;
12535
12536     ssize_t
12537       type;
12538
12539     struct PackageInfo
12540       *info,
12541       *package_info;
12542
12543     SV
12544       *perl_exception,
12545       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12546
12547     TypeMetric
12548       metrics;
12549
12550     PERL_UNUSED_VAR(ref);
12551     PERL_UNUSED_VAR(ix);
12552     exception=AcquireExceptionInfo();
12553     package_info=(struct PackageInfo *) NULL;
12554     perl_exception=newSVpv("",0);
12555     reference=SvRV(ST(0));
12556     av=(AV *) reference;
12557     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12558       exception);
12559     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12560     if (image == (Image *) NULL)
12561       {
12562         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12563           PackageName);
12564         goto PerlException;
12565       }
12566     package_info=ClonePackageInfo(info,exception);
12567     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12568     CloneString(&draw_info->text,"");
12569     current=draw_info->affine;
12570     GetAffineMatrix(&affine);
12571     x=0.0;
12572     y=0.0;
12573     EXTEND(sp,7*items);
12574     for (i=2; i < items; i+=2)
12575     {
12576       attribute=(char *) SvPV(ST(i-1),na);
12577       switch (*attribute)
12578       {
12579         case 'A':
12580         case 'a':
12581         {
12582           if (LocaleCompare(attribute,"antialias") == 0)
12583             {
12584               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12585                 SvPV(ST(i),na));
12586               if (type < 0)
12587                 {
12588                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12589                     SvPV(ST(i),na));
12590                   break;
12591                 }
12592               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12593               break;
12594             }
12595           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12596             attribute);
12597           break;
12598         }
12599         case 'd':
12600         case 'D':
12601         {
12602           if (LocaleCompare(attribute,"density") == 0)
12603             {
12604               CloneString(&draw_info->density,SvPV(ST(i),na));
12605               break;
12606             }
12607           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12608             attribute);
12609           break;
12610         }
12611         case 'e':
12612         case 'E':
12613         {
12614           if (LocaleCompare(attribute,"encoding") == 0)
12615             {
12616               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12617               break;
12618             }
12619           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12620             attribute);
12621           break;
12622         }
12623         case 'f':
12624         case 'F':
12625         {
12626           if (LocaleCompare(attribute,"family") == 0)
12627             {
12628               CloneString(&draw_info->family,SvPV(ST(i),na));
12629               break;
12630             }
12631           if (LocaleCompare(attribute,"fill") == 0)
12632             {
12633               if (info)
12634                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12635                   &draw_info->fill,exception);
12636               break;
12637             }
12638           if (LocaleCompare(attribute,"font") == 0)
12639             {
12640               CloneString(&draw_info->font,SvPV(ST(i),na));
12641               break;
12642             }
12643           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12644             attribute);
12645           break;
12646         }
12647         case 'g':
12648         case 'G':
12649         {
12650           if (LocaleCompare(attribute,"geometry") == 0)
12651             {
12652               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12653               break;
12654             }
12655           if (LocaleCompare(attribute,"gravity") == 0)
12656             {
12657               draw_info->gravity=(GravityType) ParseCommandOption(
12658                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12659               break;
12660             }
12661           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12662             attribute);
12663           break;
12664         }
12665         case 'p':
12666         case 'P':
12667         {
12668           if (LocaleCompare(attribute,"pointsize") == 0)
12669             {
12670               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12671               draw_info->pointsize=geometry_info.rho;
12672               break;
12673             }
12674           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12675             attribute);
12676           break;
12677         }
12678         case 'r':
12679         case 'R':
12680         {
12681           if (LocaleCompare(attribute,"rotate") == 0)
12682             {
12683               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12684               affine.rx=geometry_info.rho;
12685               affine.ry=geometry_info.sigma;
12686               if ((flags & SigmaValue) == 0)
12687                 affine.ry=affine.rx;
12688               break;
12689             }
12690           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12691             attribute);
12692           break;
12693         }
12694         case 's':
12695         case 'S':
12696         {
12697           if (LocaleCompare(attribute,"scale") == 0)
12698             {
12699               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12700               affine.sx=geometry_info.rho;
12701               affine.sy=geometry_info.sigma;
12702               if ((flags & SigmaValue) == 0)
12703                 affine.sy=affine.sx;
12704               break;
12705             }
12706           if (LocaleCompare(attribute,"skew") == 0)
12707             {
12708               double
12709                 x_angle,
12710                 y_angle;
12711
12712               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12713               x_angle=geometry_info.rho;
12714               y_angle=geometry_info.sigma;
12715               if ((flags & SigmaValue) == 0)
12716                 y_angle=x_angle;
12717               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12718               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12719               break;
12720             }
12721           if (LocaleCompare(attribute,"stroke") == 0)
12722             {
12723               if (info)
12724                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12725                   &draw_info->stroke,exception);
12726               break;
12727             }
12728           if (LocaleCompare(attribute,"style") == 0)
12729             {
12730               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12731                 SvPV(ST(i),na));
12732               if (type < 0)
12733                 {
12734                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12735                     SvPV(ST(i),na));
12736                   break;
12737                 }
12738               draw_info->style=(StyleType) type;
12739               break;
12740             }
12741           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12742             attribute);
12743           break;
12744         }
12745         case 't':
12746         case 'T':
12747         {
12748           if (LocaleCompare(attribute,"text") == 0)
12749             {
12750               CloneString(&draw_info->text,SvPV(ST(i),na));
12751               break;
12752             }
12753           if (LocaleCompare(attribute,"translate") == 0)
12754             {
12755               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12756               affine.tx=geometry_info.rho;
12757               affine.ty=geometry_info.sigma;
12758               if ((flags & SigmaValue) == 0)
12759                 affine.ty=affine.tx;
12760               break;
12761             }
12762           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12763             attribute);
12764           break;
12765         }
12766         case 'w':
12767         case 'W':
12768         {
12769           if (LocaleCompare(attribute,"weight") == 0)
12770             {
12771               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12772               draw_info->weight=(size_t) geometry_info.rho;
12773               break;
12774             }
12775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12776             attribute);
12777           break;
12778         }
12779         case 'x':
12780         case 'X':
12781         {
12782           if (LocaleCompare(attribute,"x") == 0)
12783             {
12784               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12785               x=geometry_info.rho;
12786               break;
12787             }
12788           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12789             attribute);
12790           break;
12791         }
12792         case 'y':
12793         case 'Y':
12794         {
12795           if (LocaleCompare(attribute,"y") == 0)
12796             {
12797               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12798               y=geometry_info.rho;
12799               break;
12800             }
12801           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12802             attribute);
12803           break;
12804         }
12805         default:
12806         {
12807           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12808             attribute);
12809           break;
12810         }
12811       }
12812     }
12813     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12814     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12815     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12816     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12817     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12818     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12819     if (draw_info->geometry == (char *) NULL)
12820       {
12821         draw_info->geometry=AcquireString((char *) NULL);
12822         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12823           "%.15g,%.15g",x,y);
12824       }
12825     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12826     (void) CatchException(exception);
12827     if (status == MagickFalse)
12828       PUSHs(&sv_undef);
12829     else
12830       {
12831         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12832         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12833         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12834         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12835         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12836         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12837         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12838         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12839         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12840         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12841         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12842         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12843         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12844       }
12845     draw_info=DestroyDrawInfo(draw_info);
12846
12847   PerlException:
12848     if (package_info != (struct PackageInfo *) NULL)
12849       DestroyPackageInfo(package_info);
12850     InheritPerlException(exception,perl_exception);
12851     exception=DestroyExceptionInfo(exception);
12852     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12853   }
12854 \f
12855 #
12856 ###############################################################################
12857 #                                                                             #
12858 #                                                                             #
12859 #                                                                             #
12860 #   Q u e r y F o r m a t                                                     #
12861 #                                                                             #
12862 #                                                                             #
12863 #                                                                             #
12864 ###############################################################################
12865 #
12866 #
12867 void
12868 QueryFormat(ref,...)
12869   Image::Magick ref=NO_INIT
12870   ALIAS:
12871     queryformat = 1
12872   PPCODE:
12873   {
12874     char
12875       *name;
12876
12877     ExceptionInfo
12878       *exception;
12879
12880     register ssize_t
12881       i;
12882
12883     SV
12884       *perl_exception;
12885
12886     volatile const MagickInfo
12887       *magick_info;
12888
12889     PERL_UNUSED_VAR(ref);
12890     PERL_UNUSED_VAR(ix);
12891     exception=AcquireExceptionInfo();
12892     perl_exception=newSVpv("",0);
12893     if (items == 1)
12894       {
12895         char
12896           format[MaxTextExtent];
12897
12898         const MagickInfo
12899           **format_list;
12900
12901         size_t
12902           types;
12903
12904         format_list=GetMagickInfoList("*",&types,exception);
12905         EXTEND(sp,types);
12906         for (i=0; i < (ssize_t) types; i++)
12907         {
12908           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12909           LocaleLower(format);
12910           PUSHs(sv_2mortal(newSVpv(format,0)));
12911         }
12912         format_list=(const MagickInfo **)
12913           RelinquishMagickMemory((MagickInfo *) format_list);
12914         goto PerlException;
12915       }
12916     EXTEND(sp,8*items);
12917     for (i=1; i < items; i++)
12918     {
12919       name=(char *) SvPV(ST(i),na);
12920       magick_info=GetMagickInfo(name,exception);
12921       if (magick_info == (const MagickInfo *) NULL)
12922         {
12923           PUSHs(&sv_undef);
12924           continue;
12925         }
12926       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12927       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12928       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12929       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12930       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12931       if (magick_info->description == (char *) NULL)
12932         PUSHs(&sv_undef);
12933       else
12934         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12935       if (magick_info->module == (char *) NULL)
12936         PUSHs(&sv_undef);
12937       else
12938         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12939     }
12940
12941   PerlException:
12942     InheritPerlException(exception,perl_exception);
12943     exception=DestroyExceptionInfo(exception);
12944     SvREFCNT_dec(perl_exception);
12945   }
12946 \f
12947 #
12948 ###############################################################################
12949 #                                                                             #
12950 #                                                                             #
12951 #                                                                             #
12952 #   Q u e r y O p t i o n                                                     #
12953 #                                                                             #
12954 #                                                                             #
12955 #                                                                             #
12956 ###############################################################################
12957 #
12958 #
12959 void
12960 QueryOption(ref,...)
12961   Image::Magick ref=NO_INIT
12962   ALIAS:
12963     queryoption = 1
12964   PPCODE:
12965   {
12966     char
12967       **options;
12968
12969     ExceptionInfo
12970       *exception;
12971
12972     register ssize_t
12973       i;
12974
12975     ssize_t
12976       j,
12977       option;
12978
12979     SV
12980       *perl_exception;
12981
12982     PERL_UNUSED_VAR(ref);
12983     PERL_UNUSED_VAR(ix);
12984     exception=AcquireExceptionInfo();
12985     perl_exception=newSVpv("",0);
12986     EXTEND(sp,8*items);
12987     for (i=1; i < items; i++)
12988     {
12989       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12990         SvPV(ST(i),na));
12991       options=GetCommandOptions((CommandOption) option);
12992       if (options == (char **) NULL)
12993         PUSHs(&sv_undef);
12994       else
12995         {
12996           for (j=0; options[j] != (char *) NULL; j++)
12997             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12998           options=DestroyStringList(options);
12999         }
13000     }
13001
13002     InheritPerlException(exception,perl_exception);
13003     exception=DestroyExceptionInfo(exception);
13004     SvREFCNT_dec(perl_exception);
13005   }
13006 \f
13007 #
13008 ###############################################################################
13009 #                                                                             #
13010 #                                                                             #
13011 #                                                                             #
13012 #   R e a d                                                                   #
13013 #                                                                             #
13014 #                                                                             #
13015 #                                                                             #
13016 ###############################################################################
13017 #
13018 #
13019 void
13020 Read(ref,...)
13021   Image::Magick ref=NO_INIT
13022   ALIAS:
13023     ReadImage  = 1
13024     read       = 2
13025     readimage  = 3
13026   PPCODE:
13027   {
13028     AV
13029       *av;
13030
13031     char
13032       **keep,
13033       **list;
13034
13035     ExceptionInfo
13036       *exception;
13037
13038     HV
13039       *hv;
13040
13041     Image
13042       *image;
13043
13044     int
13045       n;
13046
13047     MagickBooleanType
13048       status;
13049
13050     register char
13051       **p;
13052
13053     register ssize_t
13054       i;
13055
13056     ssize_t
13057       ac,
13058       number_images;
13059
13060     STRLEN
13061       *length;
13062
13063     struct PackageInfo
13064       *info,
13065       *package_info;
13066
13067     SV
13068       *perl_exception,  /* Perl variable for storing messages */
13069       *reference,
13070       *rv,
13071       *sv;
13072
13073     PERL_UNUSED_VAR(ref);
13074     PERL_UNUSED_VAR(ix);
13075     exception=AcquireExceptionInfo();
13076     perl_exception=newSVpv("",0);
13077     sv=NULL;
13078     package_info=(struct PackageInfo *) NULL;
13079     number_images=0;
13080     ac=(items < 2) ? 1 : items-1;
13081     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13082     keep=list;
13083     length=(STRLEN *) NULL;
13084     if (list == (char **) NULL)
13085       {
13086         ThrowPerlException(exception,ResourceLimitError,
13087           "MemoryAllocationFailed",PackageName);
13088         goto PerlException;
13089       }
13090     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13091     if (length == (STRLEN *) NULL)
13092       {
13093         ThrowPerlException(exception,ResourceLimitError,
13094           "MemoryAllocationFailed",PackageName);
13095         goto PerlException;
13096       }
13097     if (sv_isobject(ST(0)) == 0)
13098       {
13099         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13100           PackageName);
13101         goto PerlException;
13102       }
13103     reference=SvRV(ST(0));
13104     hv=SvSTASH(reference);
13105     if (SvTYPE(reference) != SVt_PVAV)
13106       {
13107         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13108           PackageName);
13109         goto PerlException;
13110       }
13111     av=(AV *) reference;
13112     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13113       exception);
13114     package_info=ClonePackageInfo(info,exception);
13115     n=1;
13116     if (items <= 1)
13117       *list=(char *) (*package_info->image_info->filename ?
13118         package_info->image_info->filename : "XC:black");
13119     else
13120       for (n=0, i=0; i < ac; i++)
13121       {
13122         list[n]=(char *) SvPV(ST(i+1),length[n]);
13123         if ((items >= 3) && strEQcase(list[n],"blob"))
13124           {
13125             void
13126               *blob;
13127
13128             i++;
13129             blob=(void *) (SvPV(ST(i+1),length[n]));
13130             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13131           }
13132         if ((items >= 3) && strEQcase(list[n],"filename"))
13133           continue;
13134         if ((items >= 3) && strEQcase(list[n],"file"))
13135           {
13136             FILE
13137               *file;
13138
13139             PerlIO
13140               *io_info;
13141
13142             i++;
13143             io_info=IoIFP(sv_2io(ST(i+1)));
13144             if (io_info == (PerlIO *) NULL)
13145               {
13146                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13147                   PackageName);
13148                 continue;
13149               }
13150             file=PerlIO_findFILE(io_info);
13151             if (file == (FILE *) NULL)
13152               {
13153                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13154                   PackageName);
13155                 continue;
13156               }
13157             SetImageInfoFile(package_info->image_info,file);
13158           }
13159         if ((items >= 3) && strEQcase(list[n],"magick"))
13160           continue;
13161         n++;
13162       }
13163     list[n]=(char *) NULL;
13164     keep=list;
13165     status=ExpandFilenames(&n,&list);
13166     if (status == MagickFalse)
13167       {
13168         ThrowPerlException(exception,ResourceLimitError,
13169           "MemoryAllocationFailed",PackageName);
13170         goto PerlException;
13171       }
13172     number_images=0;
13173     for (i=0; i < n; i++)
13174     {
13175       if ((package_info->image_info->file != (FILE *) NULL) ||
13176           (package_info->image_info->blob != (void *) NULL))
13177         {
13178           image=ReadImages(package_info->image_info,exception);
13179           if (image != (Image *) NULL)
13180             DisassociateImageStream(image);
13181         }
13182       else
13183         {
13184           (void) CopyMagickString(package_info->image_info->filename,list[i],
13185             MaxTextExtent);
13186           image=ReadImages(package_info->image_info,exception);
13187         }
13188       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13189         break;
13190       for ( ; image; image=image->next)
13191       {
13192         AddImageToRegistry(sv,image);
13193         rv=newRV(sv);
13194         av_push(av,sv_bless(rv,hv));
13195         SvREFCNT_dec(sv);
13196         number_images++;
13197       }
13198     }
13199     /*
13200       Free resources.
13201     */
13202     for (i=0; i < n; i++)
13203       if (list[i] != (char *) NULL)
13204         for (p=keep; list[i] != *p++; )
13205           if (*p == (char *) NULL)
13206             {
13207               list[i]=(char *) RelinquishMagickMemory(list[i]);
13208               break;
13209             }
13210
13211   PerlException:
13212     if (package_info != (struct PackageInfo *) NULL)
13213       DestroyPackageInfo(package_info);
13214     if (list && (list != keep))
13215       list=(char **) RelinquishMagickMemory(list);
13216     if (keep)
13217       keep=(char **) RelinquishMagickMemory(keep);
13218     if (length)
13219       length=(STRLEN *) RelinquishMagickMemory(length);
13220     InheritPerlException(exception,perl_exception);
13221     exception=DestroyExceptionInfo(exception);
13222     sv_setiv(perl_exception,(IV) number_images);
13223     SvPOK_on(perl_exception);
13224     ST(0)=sv_2mortal(perl_exception);
13225     XSRETURN(1);
13226   }
13227 \f
13228 #
13229 ###############################################################################
13230 #                                                                             #
13231 #                                                                             #
13232 #                                                                             #
13233 #   R e m o t e                                                               #
13234 #                                                                             #
13235 #                                                                             #
13236 #                                                                             #
13237 ###############################################################################
13238 #
13239 #
13240 void
13241 Remote(ref,...)
13242   Image::Magick ref=NO_INIT
13243   ALIAS:
13244     RemoteCommand  = 1
13245     remote         = 2
13246     remoteCommand  = 3
13247   PPCODE:
13248   {
13249     AV
13250       *av;
13251
13252     ExceptionInfo
13253       *exception;
13254
13255     register ssize_t
13256       i;
13257
13258     SV
13259       *perl_exception,
13260       *reference;
13261
13262     struct PackageInfo
13263       *info;
13264
13265     PERL_UNUSED_VAR(ref);
13266     PERL_UNUSED_VAR(ix);
13267     exception=AcquireExceptionInfo();
13268     perl_exception=newSVpv("",0);
13269     reference=SvRV(ST(0));
13270     av=(AV *) reference;
13271     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13272       exception);
13273     for (i=1; i < items; i++)
13274       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13275         SvPV(ST(i),na),exception);
13276     InheritPerlException(exception,perl_exception);
13277     exception=DestroyExceptionInfo(exception);
13278     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13279   }
13280 \f
13281 #
13282 ###############################################################################
13283 #                                                                             #
13284 #                                                                             #
13285 #                                                                             #
13286 #   S e t                                                                     #
13287 #                                                                             #
13288 #                                                                             #
13289 #                                                                             #
13290 ###############################################################################
13291 #
13292 #
13293 void
13294 Set(ref,...)
13295   Image::Magick ref=NO_INIT
13296   ALIAS:
13297     SetAttributes  = 1
13298     SetAttribute   = 2
13299     set            = 3
13300     setattributes  = 4
13301     setattribute   = 5
13302   PPCODE:
13303   {
13304     ExceptionInfo
13305       *exception;
13306
13307     Image
13308       *image;
13309
13310     register ssize_t
13311       i;
13312
13313     struct PackageInfo
13314       *info;
13315
13316     SV
13317       *perl_exception,
13318       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13319
13320     PERL_UNUSED_VAR(ref);
13321     PERL_UNUSED_VAR(ix);
13322     exception=AcquireExceptionInfo();
13323     perl_exception=newSVpv("",0);
13324     if (sv_isobject(ST(0)) == 0)
13325       {
13326         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13327           PackageName);
13328         goto PerlException;
13329       }
13330     reference=SvRV(ST(0));
13331     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13332     if (items == 2)
13333       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13334     else
13335       for (i=2; i < items; i+=2)
13336         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13337
13338   PerlException:
13339     InheritPerlException(exception,perl_exception);
13340     exception=DestroyExceptionInfo(exception);
13341     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13342     SvPOK_on(perl_exception);
13343     ST(0)=sv_2mortal(perl_exception);
13344     XSRETURN(1);
13345   }
13346 \f
13347 #
13348 ###############################################################################
13349 #                                                                             #
13350 #                                                                             #
13351 #                                                                             #
13352 #   S e t P i x e l                                                           #
13353 #                                                                             #
13354 #                                                                             #
13355 #                                                                             #
13356 ###############################################################################
13357 #
13358 #
13359 void
13360 SetPixel(ref,...)
13361   Image::Magick ref=NO_INIT
13362   ALIAS:
13363     setpixel = 1
13364     setPixel = 2
13365   PPCODE:
13366   {
13367     AV
13368       *av;
13369
13370     char
13371       *attribute;
13372
13373     ChannelType
13374       channel,
13375       channel_mask;
13376
13377     ExceptionInfo
13378       *exception;
13379
13380     Image
13381       *image;
13382
13383     MagickBooleanType
13384       normalize;
13385
13386     RectangleInfo
13387       region;
13388
13389     register ssize_t
13390       i;
13391
13392     register Quantum
13393       *q;
13394
13395     ssize_t
13396       option;
13397
13398     struct PackageInfo
13399       *info;
13400
13401     SV
13402       *perl_exception,
13403       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13404
13405     PERL_UNUSED_VAR(ref);
13406     PERL_UNUSED_VAR(ix);
13407     exception=AcquireExceptionInfo();
13408     perl_exception=newSVpv("",0);
13409     reference=SvRV(ST(0));
13410     av=(AV *) reference;
13411     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13412       exception);
13413     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13414     if (image == (Image *) NULL)
13415       {
13416         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13417           PackageName);
13418         goto PerlException;
13419       }
13420     av=(AV *) NULL;
13421     normalize=MagickTrue;
13422     region.x=0;
13423     region.y=0;
13424     region.width=image->columns;
13425     region.height=1;
13426     if (items == 1)
13427       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13428     channel=DefaultChannels;
13429     for (i=2; i < items; i+=2)
13430     {
13431       attribute=(char *) SvPV(ST(i-1),na);
13432       switch (*attribute)
13433       {
13434         case 'C':
13435         case 'c':
13436         {
13437           if (LocaleCompare(attribute,"channel") == 0)
13438             {
13439               ssize_t
13440                 option;
13441
13442               option=ParseChannelOption(SvPV(ST(i),na));
13443               if (option < 0)
13444                 {
13445                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13446                     SvPV(ST(i),na));
13447                   return;
13448                 }
13449               channel=(ChannelType) option;
13450               break;
13451             }
13452           if (LocaleCompare(attribute,"color") == 0)
13453             {
13454               if (SvTYPE(ST(i)) != SVt_RV)
13455                 {
13456                   char
13457                     message[MaxTextExtent];
13458
13459                   (void) FormatLocaleString(message,MaxTextExtent,
13460                     "invalid %.60s value",attribute);
13461                   ThrowPerlException(exception,OptionError,message,
13462                     SvPV(ST(i),na));
13463                 }
13464               av=(AV *) SvRV(ST(i));
13465               break;
13466             }
13467           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13468             attribute);
13469           break;
13470         }
13471         case 'g':
13472         case 'G':
13473         {
13474           if (LocaleCompare(attribute,"geometry") == 0)
13475             {
13476               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13477               break;
13478             }
13479           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13480             attribute);
13481           break;
13482         }
13483         case 'N':
13484         case 'n':
13485         {
13486           if (LocaleCompare(attribute,"normalize") == 0)
13487             {
13488               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13489                 SvPV(ST(i),na));
13490               if (option < 0)
13491                 {
13492                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13493                     SvPV(ST(i),na));
13494                   break;
13495                 }
13496              normalize=option != 0 ? MagickTrue : MagickFalse;
13497              break;
13498             }
13499           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13500             attribute);
13501           break;
13502         }
13503         case 'x':
13504         case 'X':
13505         {
13506           if (LocaleCompare(attribute,"x") == 0)
13507             {
13508               region.x=SvIV(ST(i));
13509               break;
13510             }
13511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13512             attribute);
13513           break;
13514         }
13515         case 'y':
13516         case 'Y':
13517         {
13518           if (LocaleCompare(attribute,"y") == 0)
13519             {
13520               region.y=SvIV(ST(i));
13521               break;
13522             }
13523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13524             attribute);
13525           break;
13526         }
13527         default:
13528         {
13529           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13530             attribute);
13531           break;
13532         }
13533       }
13534     }
13535     (void) SetImageStorageClass(image,DirectClass,exception);
13536     channel_mask=SetPixelChannelMask(image,channel);
13537     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13538     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13539         (SvTYPE(av) != SVt_PVAV))
13540       PUSHs(&sv_undef);
13541     else
13542       {
13543         double
13544           scale;
13545
13546         register ssize_t
13547           i;
13548
13549         i=0;
13550         scale=1.0;
13551         if (normalize != MagickFalse)
13552           scale=QuantumRange;
13553         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13554             (i <= av_len(av)))
13555           {
13556             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13557               av_fetch(av,i,0)))),q);
13558             i++;
13559           }
13560         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13561             (i <= av_len(av)))
13562           {
13563             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13564               av_fetch(av,i,0)))),q);
13565             i++;
13566           }
13567         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13568             (i <= av_len(av)))
13569           {
13570             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13571               av_fetch(av,i,0)))),q);
13572             i++;
13573           }
13574         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13575             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13576           {
13577             SetPixelBlack(image,ClampToQuantum(scale*
13578               SvNV(*(av_fetch(av,i,0)))),q);
13579             i++;
13580           }
13581         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13582             (i <= av_len(av)))
13583           {
13584             SetPixelAlpha(image,ClampToQuantum(scale*
13585               SvNV(*(av_fetch(av,i,0)))),q);
13586             i++;
13587           }
13588         (void) SyncAuthenticPixels(image,exception);
13589       }
13590     (void) SetPixelChannelMask(image,channel_mask);
13591
13592   PerlException:
13593     InheritPerlException(exception,perl_exception);
13594     exception=DestroyExceptionInfo(exception);
13595     SvREFCNT_dec(perl_exception);
13596   }
13597 \f
13598 #
13599 ###############################################################################
13600 #                                                                             #
13601 #                                                                             #
13602 #                                                                             #
13603 #   S m u s h                                                                 #
13604 #                                                                             #
13605 #                                                                             #
13606 #                                                                             #
13607 ###############################################################################
13608 #
13609 #
13610 void
13611 Smush(ref,...)
13612   Image::Magick ref=NO_INIT
13613   ALIAS:
13614     SmushImage  = 1
13615     smush       = 2
13616     smushimage  = 3
13617   PPCODE:
13618   {
13619     AV
13620       *av;
13621
13622     char
13623       *attribute;
13624
13625     ExceptionInfo
13626       *exception;
13627
13628     HV
13629       *hv;
13630
13631     Image
13632       *image;
13633
13634     register ssize_t
13635       i;
13636
13637     ssize_t
13638       offset,
13639       stack;
13640
13641     struct PackageInfo
13642       *info;
13643
13644     SV
13645       *av_reference,
13646       *perl_exception,
13647       *reference,
13648       *rv,
13649       *sv;
13650
13651     PERL_UNUSED_VAR(ref);
13652     PERL_UNUSED_VAR(ix);
13653     exception=AcquireExceptionInfo();
13654     perl_exception=newSVpv("",0);
13655     sv=NULL;
13656     attribute=NULL;
13657     av=NULL;
13658     if (sv_isobject(ST(0)) == 0)
13659       {
13660         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13661           PackageName);
13662         goto PerlException;
13663       }
13664     reference=SvRV(ST(0));
13665     hv=SvSTASH(reference);
13666     av=newAV();
13667     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13668     SvREFCNT_dec(av);
13669     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13670     if (image == (Image *) NULL)
13671       {
13672         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13673           PackageName);
13674         goto PerlException;
13675       }
13676     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13677     /*
13678       Get options.
13679     */
13680     offset=0;
13681     stack=MagickTrue;
13682     for (i=2; i < items; i+=2)
13683     {
13684       attribute=(char *) SvPV(ST(i-1),na);
13685       switch (*attribute)
13686       {
13687         case 'O':
13688         case 'o':
13689         {
13690           if (LocaleCompare(attribute,"offset") == 0)
13691             {
13692               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13693               break;
13694             }
13695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13696             attribute);
13697           break;
13698         }
13699         case 'S':
13700         case 's':
13701         {
13702           if (LocaleCompare(attribute,"stack") == 0)
13703             {
13704               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13705                 SvPV(ST(i),na));
13706               if (stack < 0)
13707                 {
13708                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13709                     SvPV(ST(i),na));
13710                   return;
13711                 }
13712               break;
13713             }
13714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13715             attribute);
13716           break;
13717         }
13718         default:
13719         {
13720           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13721             attribute);
13722           break;
13723         }
13724       }
13725     }
13726     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13727       exception);
13728     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13729       goto PerlException;
13730     for ( ; image; image=image->next)
13731     {
13732       AddImageToRegistry(sv,image);
13733       rv=newRV(sv);
13734       av_push(av,sv_bless(rv,hv));
13735       SvREFCNT_dec(sv);
13736     }
13737     exception=DestroyExceptionInfo(exception);
13738     ST(0)=av_reference;
13739     SvREFCNT_dec(perl_exception);
13740     XSRETURN(1);
13741
13742   PerlException:
13743     InheritPerlException(exception,perl_exception);
13744     exception=DestroyExceptionInfo(exception);
13745     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13746     SvPOK_on(perl_exception);
13747     ST(0)=sv_2mortal(perl_exception);
13748     XSRETURN(1);
13749   }
13750 \f
13751 #
13752 ###############################################################################
13753 #                                                                             #
13754 #                                                                             #
13755 #                                                                             #
13756 #   S t a t i s t i c s                                                       #
13757 #                                                                             #
13758 #                                                                             #
13759 #                                                                             #
13760 ###############################################################################
13761 #
13762 #
13763 void
13764 Statistics(ref,...)
13765   Image::Magick ref=NO_INIT
13766   ALIAS:
13767     StatisticsImage = 1
13768     statistics      = 2
13769     statisticsimage = 3
13770   PPCODE:
13771   {
13772 #define ChannelStatistics(channel) \
13773 { \
13774   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13775     (double) channel_statistics[channel].depth); \
13776   PUSHs(sv_2mortal(newSVpv(message,0))); \
13777   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13778     channel_statistics[channel].minima/scale); \
13779   PUSHs(sv_2mortal(newSVpv(message,0))); \
13780   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13781     channel_statistics[channel].maxima/scale); \
13782   PUSHs(sv_2mortal(newSVpv(message,0))); \
13783   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13784     channel_statistics[channel].mean/scale); \
13785   PUSHs(sv_2mortal(newSVpv(message,0))); \
13786   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13787     channel_statistics[channel].standard_deviation/scale); \
13788   PUSHs(sv_2mortal(newSVpv(message,0))); \
13789   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13790     channel_statistics[channel].kurtosis); \
13791   PUSHs(sv_2mortal(newSVpv(message,0))); \
13792   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13793     channel_statistics[channel].skewness); \
13794   PUSHs(sv_2mortal(newSVpv(message,0))); \
13795 }
13796
13797     AV
13798       *av;
13799
13800     char
13801       message[MaxTextExtent];
13802
13803     ChannelStatistics
13804       *channel_statistics;
13805
13806     double
13807       scale;
13808
13809     ExceptionInfo
13810       *exception;
13811
13812     Image
13813       *image;
13814
13815     ssize_t
13816       count;
13817
13818     struct PackageInfo
13819       *info;
13820
13821     SV
13822       *perl_exception,
13823       *reference;
13824
13825     PERL_UNUSED_VAR(ref);
13826     PERL_UNUSED_VAR(ix);
13827     exception=AcquireExceptionInfo();
13828     perl_exception=newSVpv("",0);
13829     av=NULL;
13830     if (sv_isobject(ST(0)) == 0)
13831       {
13832         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13833           PackageName);
13834         goto PerlException;
13835       }
13836     reference=SvRV(ST(0));
13837     av=newAV();
13838     SvREFCNT_dec(av);
13839     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13840     if (image == (Image *) NULL)
13841       {
13842         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13843           PackageName);
13844         goto PerlException;
13845       }
13846     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13847     count=0;
13848     for ( ; image; image=image->next)
13849     {
13850       channel_statistics=GetImageStatistics(image,exception);
13851       if (channel_statistics == (ChannelStatistics *) NULL)
13852         continue;
13853       count++;
13854       EXTEND(sp,35*count);
13855       scale=(double) QuantumRange;
13856       ChannelStatistics(RedChannel);
13857       ChannelStatistics(GreenChannel);
13858       ChannelStatistics(BlueChannel);
13859       if (image->colorspace == CMYKColorspace)
13860         ChannelStatistics(BlackChannel);
13861       if (image->matte != MagickFalse)
13862         ChannelStatistics(AlphaChannel);
13863       channel_statistics=(ChannelStatistics *)
13864         RelinquishMagickMemory(channel_statistics);
13865     }
13866
13867   PerlException:
13868     InheritPerlException(exception,perl_exception);
13869     exception=DestroyExceptionInfo(exception);
13870     SvREFCNT_dec(perl_exception);
13871   }
13872 \f
13873 #
13874 ###############################################################################
13875 #                                                                             #
13876 #                                                                             #
13877 #                                                                             #
13878 #   S y n c A u t h e n t i c P i x e l s                                     #
13879 #                                                                             #
13880 #                                                                             #
13881 #                                                                             #
13882 ###############################################################################
13883 #
13884 #
13885 void
13886 SyncAuthenticPixels(ref,...)
13887   Image::Magick ref = NO_INIT
13888   ALIAS:
13889     Syncauthenticpixels = 1
13890     SyncImagePixels = 2
13891     syncimagepixels = 3
13892   CODE:
13893   {
13894     ExceptionInfo
13895       *exception;
13896
13897     Image
13898       *image;
13899
13900     MagickBooleanType
13901       status;
13902
13903     struct PackageInfo
13904       *info;
13905
13906     SV
13907       *perl_exception,
13908       *reference;
13909
13910     PERL_UNUSED_VAR(ref);
13911     PERL_UNUSED_VAR(ix);
13912     exception=AcquireExceptionInfo();
13913     perl_exception=newSVpv("",0);
13914     if (sv_isobject(ST(0)) == 0)
13915       {
13916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13917           PackageName);
13918         goto PerlException;
13919       }
13920
13921     reference=SvRV(ST(0));
13922     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13923     if (image == (Image *) NULL)
13924       {
13925         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13926           PackageName);
13927         goto PerlException;
13928       }
13929
13930     status=SyncAuthenticPixels(image,exception);
13931     if (status != MagickFalse)
13932       return;
13933
13934   PerlException:
13935     InheritPerlException(exception,perl_exception);
13936     exception=DestroyExceptionInfo(exception);
13937     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13938   }
13939 \f
13940 #
13941 ###############################################################################
13942 #                                                                             #
13943 #                                                                             #
13944 #                                                                             #
13945 #   T r a n s f o r m                                                         #
13946 #                                                                             #
13947 #                                                                             #
13948 #                                                                             #
13949 ###############################################################################
13950 #
13951 #
13952 void
13953 Transform(ref,...)
13954   Image::Magick ref=NO_INIT
13955   ALIAS:
13956     TransformImage = 1
13957     transform      = 2
13958     transformimage = 3
13959   PPCODE:
13960   {
13961     AV
13962       *av;
13963
13964     char
13965       *attribute,
13966       *crop_geometry,
13967       *geometry;
13968
13969     ExceptionInfo
13970       *exception;
13971
13972     HV
13973       *hv;
13974
13975     Image
13976       *clone,
13977       *image;
13978
13979     register ssize_t
13980       i;
13981
13982     struct PackageInfo
13983       *info;
13984
13985     SV
13986       *av_reference,
13987       *perl_exception,
13988       *reference,
13989       *rv,
13990       *sv;
13991
13992     PERL_UNUSED_VAR(ref);
13993     PERL_UNUSED_VAR(ix);
13994     exception=AcquireExceptionInfo();
13995     perl_exception=newSVpv("",0);
13996     sv=NULL;
13997     av=NULL;
13998     attribute=NULL;
13999     if (sv_isobject(ST(0)) == 0)
14000       {
14001         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14002           PackageName);
14003         goto PerlException;
14004       }
14005     reference=SvRV(ST(0));
14006     hv=SvSTASH(reference);
14007     av=newAV();
14008     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14009     SvREFCNT_dec(av);
14010     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14011     if (image == (Image *) NULL)
14012       {
14013         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14014           PackageName);
14015         goto PerlException;
14016       }
14017     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14018     /*
14019       Get attribute.
14020     */
14021     crop_geometry=(char *) NULL;
14022     geometry=(char *) NULL;
14023     for (i=2; i < items; i+=2)
14024     {
14025       attribute=(char *) SvPV(ST(i-1),na);
14026       switch (*attribute)
14027       {
14028         case 'c':
14029         case 'C':
14030         {
14031           if (LocaleCompare(attribute,"crop") == 0)
14032             {
14033               crop_geometry=SvPV(ST(i),na);
14034               break;
14035             }
14036           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14037             attribute);
14038           break;
14039         }
14040         case 'g':
14041         case 'G':
14042         {
14043           if (LocaleCompare(attribute,"geometry") == 0)
14044             {
14045               geometry=SvPV(ST(i),na);
14046               break;
14047             }
14048          if (LocaleCompare(attribute,"gravity") == 0)
14049            {
14050              Image
14051                *next;
14052
14053              ssize_t
14054                in;
14055
14056              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
14057                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
14058              if (in < 0)
14059                {
14060                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14061                    SvPV(ST(i),na));
14062                  return;
14063                }
14064              for (next=image; next; next=next->next)
14065                next->gravity=(GravityType) in;
14066              break;
14067            }
14068           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14069             attribute);
14070           break;
14071         }
14072         default:
14073         {
14074           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14075             attribute);
14076           break;
14077         }
14078       }
14079     }
14080     for ( ; image; image=image->next)
14081     {
14082       clone=CloneImage(image,0,0,MagickTrue,exception);
14083       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
14084         goto PerlException;
14085       TransformImage(&clone,crop_geometry,geometry,exception);
14086       for ( ; clone; clone=clone->next)
14087       {
14088         AddImageToRegistry(sv,clone);
14089         rv=newRV(sv);
14090         av_push(av,sv_bless(rv,hv));
14091         SvREFCNT_dec(sv);
14092       }
14093     }
14094     exception=DestroyExceptionInfo(exception);
14095     ST(0)=av_reference;
14096     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14097     XSRETURN(1);
14098
14099   PerlException:
14100     InheritPerlException(exception,perl_exception);
14101     exception=DestroyExceptionInfo(exception);
14102     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14103     SvPOK_on(perl_exception);
14104     ST(0)=sv_2mortal(perl_exception);
14105     XSRETURN(1);
14106   }
14107 \f
14108 #
14109 ###############################################################################
14110 #                                                                             #
14111 #                                                                             #
14112 #                                                                             #
14113 #   W r i t e                                                                 #
14114 #                                                                             #
14115 #                                                                             #
14116 #                                                                             #
14117 ###############################################################################
14118 #
14119 #
14120 void
14121 Write(ref,...)
14122   Image::Magick ref=NO_INIT
14123   ALIAS:
14124     WriteImage    = 1
14125     write         = 2
14126     writeimage    = 3
14127   PPCODE:
14128   {
14129     char
14130       filename[MaxTextExtent];
14131
14132     ExceptionInfo
14133       *exception;
14134
14135     Image
14136       *image,
14137       *next;
14138
14139     register ssize_t
14140       i;
14141
14142     ssize_t
14143       number_images,
14144       scene;
14145
14146     struct PackageInfo
14147       *info,
14148       *package_info;
14149
14150     SV
14151       *perl_exception,
14152       *reference;
14153
14154     PERL_UNUSED_VAR(ref);
14155     PERL_UNUSED_VAR(ix);
14156     exception=AcquireExceptionInfo();
14157     perl_exception=newSVpv("",0);
14158     number_images=0;
14159     package_info=(struct PackageInfo *) NULL;
14160     if (sv_isobject(ST(0)) == 0)
14161       {
14162         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14163           PackageName);
14164         goto PerlException;
14165       }
14166     reference=SvRV(ST(0));
14167     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14168     if (image == (Image *) NULL)
14169       {
14170         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14171           PackageName);
14172         goto PerlException;
14173       }
14174     package_info=ClonePackageInfo(info,exception);
14175     if (items == 2)
14176       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14177     else
14178       if (items > 2)
14179         for (i=2; i < items; i+=2)
14180           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14181             exception);
14182     (void) CopyMagickString(filename,package_info->image_info->filename,
14183       MaxTextExtent);
14184     scene=0;
14185     for (next=image; next; next=next->next)
14186     {
14187       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14188       next->scene=scene++;
14189     }
14190     SetImageInfo(package_info->image_info,(unsigned int)
14191       GetImageListLength(image),exception);
14192     for (next=image; next; next=next->next)
14193     {
14194       (void) WriteImage(package_info->image_info,next,exception);
14195       number_images++;
14196       if (package_info->image_info->adjoin)
14197         break;
14198     }
14199
14200   PerlException:
14201     if (package_info != (struct PackageInfo *) NULL)
14202       DestroyPackageInfo(package_info);
14203     InheritPerlException(exception,perl_exception);
14204     exception=DestroyExceptionInfo(exception);
14205     sv_setiv(perl_exception,(IV) number_images);
14206     SvPOK_on(perl_exception);
14207     ST(0)=sv_2mortal(perl_exception);
14208     XSRETURN(1);
14209   }