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%                                 Cristy                                      %
23%                             February 1997                                   %
24%                                                                             %
25%                                                                             %
26%  Copyright 1999-2021 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%    https://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
48/*
49  Include declarations.
50*/
51#if defined(__cplusplus) || defined(c_plusplus)
52extern "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 <magick/MagickCore.h>
61#undef tainted
62
63#if defined(__cplusplus) || defined(c_plusplus)
64}
65#endif
66
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 MagickPI  3.14159265358979323846264338327950288419716939937510
78#define MaxArguments  34
79#ifndef na
80#define na  PL_na
81#endif
82#define NumberOf(array)  (sizeof(array)/sizeof(*array))
83#define PackageName   "Image::Magick::@MAGICK_ABI_SUFFIX@"
84#if PERL_VERSION <= 6
85#define PerlIO  FILE
86#define PerlIO_importFILE(f, fl)  (f)
87#define PerlIO_findFILE(f)  NULL
88#endif
89#ifndef sv_undef
90#define sv_undef  PL_sv_undef
91#endif
92
93#define AddImageToRegistry(sv,image) \
94{ \
95  if (magick_registry != (SplayTreeInfo *) NULL) \
96    { \
97      (void) AddValueToSplayTree(magick_registry,image,image); \
98      (sv)=newSViv(PTR2IV(image)); \
99    } \
100}
101
102#define DeleteImageFromRegistry(reference,image) \
103{ \
104  if (magick_registry != (SplayTreeInfo *) NULL) \
105    { \
106      if (GetImageReferenceCount(image) == 1) \
107       (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108      image=DestroyImage(image); \
109      sv_setiv(reference,0); \
110    } \
111}
112
113#define InheritPerlException(exception,perl_exception) \
114{ \
115  char \
116    message[MaxTextExtent]; \
117 \
118  if ((exception)->severity != UndefinedException) \
119    { \
120      (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
121        (exception)->severity, (exception)->reason ? \
122        GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123        "Unknown", (exception)->description ? " (" : "", \
124        (exception)->description ? GetLocaleExceptionMessage( \
125        (exception)->severity,(exception)->description) : "", \
126        (exception)->description ? ")" : ""); \
127      if ((perl_exception) != (SV *) NULL) \
128        { \
129          if (SvCUR(perl_exception)) \
130            sv_catpv(perl_exception,"\n"); \
131          sv_catpv(perl_exception,message); \
132        } \
133    } \
134}
135
136#define ThrowPerlException(exception,severity,tag,reason) \
137  (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138    tag,"`%s'",reason); \
139
140/*
141  Typedef and structure declarations.
142*/
143typedef enum
144{
145  NullReference = 0,
146  ArrayReference = (~0),
147  RealReference = (~0)-1,
148  FileReference = (~0)-2,
149  ImageReference = (~0)-3,
150  IntegerReference = (~0)-4,
151  StringReference = (~0)-5
152} MagickReference;
153
154typedef struct _Arguments
155{
156  const char
157    *method;
158
159  ssize_t
160    type;
161} Arguments;
162
163struct ArgumentList
164{
165  ssize_t
166    integer_reference;
167
168  MagickRealType
169    real_reference;
170
171  const char
172    *string_reference;
173
174  Image
175    *image_reference;
176
177  SV
178    *array_reference;
179
180  FILE
181    *file_reference;
182
183  size_t
184    length;
185};
186
187struct PackageInfo
188{
189  ImageInfo
190    *image_info;
191};
192
193typedef void
194  *Image__Magick__@MAGICK_ABI_SUFFIX@;  /* data type for the Image::Magick::@MAGICK_ABI_SUFFIX@ package */
195
196/*
197  Static declarations.
198*/
199static struct
200  Methods
201  {
202    const char
203      *name;
204
205    Arguments
206      arguments[MaxArguments];
207  } Methods[] =
208  {
209    { "Comment", { {"comment", StringReference} } },
210    { "Label", { {"label", StringReference} } },
211    { "AddNoise", { {"noise", MagickNoiseOptions},
212      {"channel", MagickChannelOptions} } },
213    { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
214    { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
215      {"height", IntegerReference}, {"fill", StringReference},
216      {"bordercolor", StringReference}, {"color", StringReference},
217      {"compose", MagickComposeOptions} } },
218    { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
219      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
220    { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
221      {"height", IntegerReference}, {"x", IntegerReference},
222      {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
223    { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
224      {"height", IntegerReference}, {"x", IntegerReference},
225      {"y", IntegerReference}, {"fuzz", StringReference},
226      {"gravity", MagickGravityOptions} } },
227    { "Despeckle", { { (const char *) NULL, NullReference } } },
228    { "Edge", { {"radius", RealReference} } },
229    { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
230      {"sigma", RealReference} } },
231    { "Enhance", { { (const char *) NULL, NullReference } } },
232    { "Flip", { { (const char *) NULL, NullReference } } },
233    { "Flop", { { (const char *) NULL, NullReference } } },
234    { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
235      {"height", IntegerReference}, {"inner", IntegerReference},
236      {"outer", IntegerReference}, {"fill", StringReference},
237      {"color", StringReference}, {"compose", MagickComposeOptions} } },
238    { "Implode", { {"amount", RealReference},
239      {"interpolate", MagickInterpolateOptions} } },
240    { "Magnify", { { (const char *) NULL, NullReference } } },
241    { "MedianFilter", { {"geometry", StringReference},
242      {"width", IntegerReference},{"height", IntegerReference},
243      {"channel", MagickChannelOptions} } },
244    { "Minify", { { (const char *) NULL, NullReference } } },
245    { "OilPaint", { {"radius", RealReference} } },
246    { "ReduceNoise", { {"geometry", StringReference},
247      {"width", IntegerReference},{"height", IntegerReference},
248      {"channel", MagickChannelOptions} } },
249    { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
250      {"y", IntegerReference} } },
251    { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
252      {"color", StringReference}, {"background", StringReference} } },
253    { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
254      {"height", IntegerReference} } },
255    { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
256      {"height", IntegerReference} } },
257    { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
258      {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
259    { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
260      {"sigma", RealReference}, {"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      {"decorate", MagickDecorateOptions} } },
293    { "ColorFloodfill", { {"geometry", StringReference},
294      {"x", IntegerReference}, {"y", IntegerReference},
295      {"fill", StringReference}, {"bordercolor", StringReference},
296      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297    { "Composite", { {"image", ImageReference},
298      {"compose", MagickComposeOptions}, {"geometry", StringReference},
299      {"x", IntegerReference}, {"y", IntegerReference},
300      {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301      {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302      {"color", StringReference}, {"mask", ImageReference},
303      {"channel", MagickChannelOptions},
304      {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
305      {"blend", StringReference} } },
306    { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307    { "CycleColormap", { {"display", IntegerReference} } },
308    { "Draw", { {"primitive", MagickPrimitiveOptions},
309      {"points", StringReference}, {"method", MagickMethodOptions},
310      {"stroke", StringReference}, {"fill", StringReference},
311      {"strokewidth", RealReference}, {"font", StringReference},
312      {"bordercolor", StringReference}, {"x", RealReference},
313      {"y", RealReference}, {"translate", StringReference},
314      {"scale", StringReference}, {"rotate", RealReference},
315      {"skewX", RealReference}, {"skewY", RealReference},
316      {"tile", ImageReference}, {"pointsize", RealReference},
317      {"antialias", MagickBooleanOptions}, {"density", StringReference},
318      {"linewidth", RealReference}, {"affine", ArrayReference},
319      {"stroke-dashoffset", RealReference},
320      {"stroke-dasharray", ArrayReference},
321      {"interpolate", MagickInterpolateOptions},
322      {"origin", StringReference}, {"text", StringReference},
323      {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324      {"vector-graphics", StringReference}, {"kerning", RealReference},
325      {"interline-spacing", RealReference},
326      {"interword-spacing", RealReference},
327      {"direction", MagickDirectionOptions} } },
328    { "Equalize", { {"channel", MagickChannelOptions} } },
329    { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330      {"red", RealReference}, {"green", RealReference},
331      {"blue", RealReference} } },
332    { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
333      {"dither-method", MagickDitherOptions} } },
334    { "MatteFloodfill", { {"geometry", StringReference},
335      {"x", IntegerReference}, {"y", IntegerReference},
336      {"opacity", StringReference}, {"bordercolor", StringReference},
337      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338    { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339      {"saturation", RealReference}, {"whiteness", RealReference},
340      {"brightness", RealReference}, {"lightness", RealReference},
341      {"blackness", RealReference} } },
342    { "Negate", { {"gray", MagickBooleanOptions},
343      {"channel", MagickChannelOptions} } },
344    { "Normalize", { {"channel", MagickChannelOptions} } },
345    { "NumberColors", { { (const char *) NULL, NullReference } } },
346    { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348      {"invert", MagickBooleanOptions} } },
349    { "Quantize", { {"colors", IntegerReference},
350      {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351      {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
352      {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353      {"dither-method", MagickDitherOptions} } },
354    { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355      {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356    { "Segment", { {"geometry", StringReference},
357      {"cluster-threshold", RealReference},
358      {"smoothing-threshold", RealReference},
359      {"colorspace", MagickColorspaceOptions},
360      {"verbose", MagickBooleanOptions} } },
361    { "Signature", { { (const char *) NULL, NullReference } } },
362    { "Solarize", { {"geometry", StringReference},
363      {"threshold", StringReference}, {"channel", MagickChannelOptions} } },
364    { "Sync", { { (const char *) NULL, NullReference } } },
365    { "Texture", { {"texture", ImageReference} } },
366    { "Evaluate", { {"value", RealReference},
367      {"operator", MagickEvaluateOptions},
368      {"channel", MagickChannelOptions} } },
369    { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371    { "Threshold", { {"threshold", StringReference},
372      {"channel", MagickChannelOptions} } },
373    { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374      {"sigma", RealReference} } },
375    { "Trim", { {"fuzz", StringReference} } },
376    { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377      {"wavelength", RealReference},
378      {"interpolate", MagickInterpolateOptions} } },
379    { "Separate", { {"channel", MagickChannelOptions} } },
380    { "Condense", { { (const char *) NULL, NullReference } } },
381    { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382      {"y", IntegerReference} } },
383    { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
384    { "Deconstruct", { { (const char *) NULL, NullReference } } },
385    { "GaussianBlur", { {"geometry", StringReference},
386      {"radius", RealReference}, {"sigma", RealReference},
387      {"channel", MagickChannelOptions} } },
388    { "Convolve", { {"coefficients", ArrayReference},
389      {"channel", MagickChannelOptions}, {"bias", 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}, {"channel", MagickChannelOptions} } },
400    { "OrderedDither", { {"threshold", StringReference},
401      {"channel", MagickChannelOptions} } },
402    { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
403      {"height", IntegerReference} } },
404    { "Level", { {"levels", StringReference}, {"black-point", RealReference},
405      {"white-point", RealReference}, {"gamma", RealReference},
406      {"channel", MagickChannelOptions}, {"level", StringReference} } },
407    { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
408    { "AffineTransform", { {"affine", ArrayReference},
409      {"translate", StringReference}, {"scale", StringReference},
410      {"rotate", RealReference}, {"skewX", RealReference},
411      {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
412      {"background", StringReference} } },
413    { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
414    { "AdaptiveThreshold", { {"geometry", StringReference},
415      {"width", IntegerReference}, {"height", IntegerReference},
416      {"offset", IntegerReference} } },
417    { "Resample", { {"density", StringReference}, {"x", RealReference},
418      {"y", RealReference}, {"filter", MagickFilterOptions},
419      {"support", RealReference }, {"blur", RealReference } } },
420    { "Describe", { {"file", FileReference} } },
421    { "BlackThreshold", { {"threshold", StringReference},
422      {"channel", MagickChannelOptions} } },
423    { "WhiteThreshold", { {"threshold", StringReference},
424      {"channel", MagickChannelOptions} } },
425    { "RotationalBlur", { {"geometry", StringReference},
426      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
427    { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
428      {"height", IntegerReference} } },
429    { "Strip", { { (const char *) NULL, NullReference } } },
430    { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
431    { "Channel", { {"channel", MagickChannelOptions} } },
432    { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
433      {"height", IntegerReference}, {"x", IntegerReference},
434      {"y", IntegerReference}, {"fuzz", StringReference},
435      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
436    { "Posterize", { {"levels", IntegerReference},
437      {"dither", MagickBooleanOptions} } },
438    { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
439      {"sigma", RealReference}, {"x", IntegerReference},
440      {"y", IntegerReference} } },
441    { "Identify", { {"file", FileReference}, {"features", StringReference},
442      {"moments", MagickBooleanOptions}, {"unique", MagickBooleanOptions} } },
443    { "SepiaTone", { {"threshold", RealReference} } },
444    { "SigmoidalContrast", { {"geometry", StringReference},
445      {"contrast", RealReference}, {"mid-point", RealReference},
446      {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
447    { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
448      {"height", IntegerReference}, {"x", IntegerReference},
449      {"y", IntegerReference}, {"fuzz", StringReference},
450      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
451    { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
452      {"sigma", RealReference}, {"x", IntegerReference},
453      {"y", IntegerReference}, {"background", StringReference} } },
454    { "ContrastStretch", { {"levels", StringReference},
455      {"black-point", RealReference},{"white-point", RealReference},
456      {"channel", MagickChannelOptions} } },
457    { "Sans0", { { (const char *) NULL, NullReference } } },
458    { "Sans1", { { (const char *) NULL, NullReference } } },
459    { "AdaptiveSharpen", { {"geometry", StringReference},
460      {"radius", RealReference}, {"sigma", RealReference},
461      {"channel", MagickChannelOptions} } },
462    { "Transpose", { { (const char *) NULL, NullReference } } },
463    { "Transverse", { { (const char *) NULL, NullReference } } },
464    { "AutoOrient", { { (const char *) NULL, NullReference } } },
465    { "AdaptiveBlur", { {"geometry", StringReference},
466      {"radius", RealReference}, {"sigma", RealReference},
467      {"channel", MagickChannelOptions} } },
468    { "Sketch", { {"geometry", StringReference},
469      {"radius", RealReference}, {"sigma", RealReference},
470      {"angle", RealReference} } },
471    { "UniqueColors", { { (const char *) NULL, NullReference } } },
472    { "AdaptiveResize", { {"geometry", StringReference},
473      {"width", IntegerReference}, {"height", IntegerReference},
474      {"filter", MagickFilterOptions}, {"support", StringReference },
475      {"blur", RealReference } } },
476    { "ClipMask", { {"mask", ImageReference} } },
477    { "LinearStretch", { {"levels", StringReference},
478      {"black-point", RealReference},{"white-point", RealReference} } },
479    { "Recolor", { {"matrix", ArrayReference} } },
480    { "Mask", { {"mask", ImageReference} } },
481    { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
482      {"font", StringReference}, {"stroke", StringReference},
483      {"fill", StringReference}, {"strokewidth", RealReference},
484      {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
485      {"background", StringReference} } },
486    { "FloodfillPaint", { {"geometry", StringReference},
487      {"x", IntegerReference}, {"y", IntegerReference},
488      {"fill", StringReference}, {"bordercolor", StringReference},
489      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
490      {"invert", MagickBooleanOptions} } },
491    { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
492      {"virtual-pixel", MagickVirtualPixelOptions},
493      {"best-fit", MagickBooleanOptions} } },
494    { "Clut", { {"image", ImageReference},
495      {"channel", MagickChannelOptions} } },
496    { "LiquidRescale", { {"geometry", StringReference},
497      {"width", IntegerReference}, {"height", IntegerReference},
498      {"delta-x", RealReference}, {"rigidity", RealReference } } },
499    { "Encipher", { {"passphrase", StringReference} } },
500    { "Decipher", { {"passphrase", StringReference} } },
501    { "Deskew", { {"geometry", StringReference},
502      {"threshold", StringReference} } },
503    { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
504      {"dither-method", MagickDitherOptions} } },
505    { "SparseColor", { {"points", ArrayReference},
506      {"method", MagickSparseColorOptions},
507      {"virtual-pixel", MagickVirtualPixelOptions},
508      {"channel", MagickChannelOptions} } },
509    { "Function", { {"parameters", ArrayReference},
510      {"function", MagickFunctionOptions},
511      {"virtual-pixel", MagickVirtualPixelOptions} } },
512    { "SelectiveBlur", { {"geometry", StringReference},
513      {"radius", RealReference}, {"sigma", RealReference},
514      {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515    { "HaldClut", { {"image", ImageReference},
516      {"channel", MagickChannelOptions} } },
517    { "BlueShift", { {"factor", StringReference} } },
518    { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519    { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520    { "ColorDecisionList", {
521      {"color-correction-collection", StringReference} } },
522    { "AutoGamma", { {"channel", MagickChannelOptions} } },
523    { "AutoLevel", { {"channel", MagickChannelOptions} } },
524    { "LevelColors", { {"invert", MagickBooleanOptions},
525      {"black-point", StringReference}, {"white-point", StringReference},
526      {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527    { "Clamp", { {"channel", MagickChannelOptions} } },
528    { "Filter", { {"kernel", StringReference},
529      {"channel", MagickChannelOptions}, {"bias", StringReference} } },
530    { "BrightnessContrast", { {"levels", StringReference},
531      {"brightness", RealReference},{"contrast", RealReference},
532      {"channel", MagickChannelOptions} } },
533    { "Morphology", { {"kernel", StringReference},
534      {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
535      {"iterations", IntegerReference} } },
536    { "ColorMatrix", { {"matrix", ArrayReference} } },
537    { "Color", { {"color", StringReference} } },
538    { "Mode", { {"geometry", StringReference},
539      {"width", IntegerReference},{"height", IntegerReference},
540      {"channel", MagickChannelOptions} } },
541    { "Statistic", { {"geometry", StringReference},
542      {"width", IntegerReference},{"height", IntegerReference},
543      {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
544    { "Perceptible", { {"epsilon", RealReference},
545      {"channel", MagickChannelOptions} } },
546    { "Poly", { {"terms", ArrayReference},
547      {"channel", MagickChannelOptions} } },
548    { "Grayscale", { {"method", MagickPixelIntensityOptions} } },
549    { "CannyEdge", { {"geometry", StringReference},
550      {"radius", RealReference}, {"sigma", RealReference},
551      {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
552    { "HoughLine", { {"geometry", StringReference},
553      {"width", IntegerReference}, {"height", IntegerReference},
554      {"threshold", IntegerReference} } },
555    { "MeanShift", { {"geometry", StringReference},
556      {"width", IntegerReference}, {"height", IntegerReference},
557      {"distance", RealReference} } },
558    { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
559      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
560    { "ConnectedComponents", { {"connectivity", IntegerReference} } },
561    { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
562      {"width", IntegerReference}, {"height", IntegerReference},
563      {"x", IntegerReference}, {"y", IntegerReference},
564      {"gravity", MagickGravityOptions}, {"offset", StringReference},
565      {"dx", IntegerReference}, {"dy", IntegerReference} } },
566    { "WaveletDenoise", {  {"geometry", StringReference},
567      {"threshold", RealReference}, {"softness", RealReference} } },
568    { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
569    { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } }
570  };
571
572static SplayTreeInfo
573  *magick_registry = (SplayTreeInfo *) NULL;
574
575/*
576  Forward declarations.
577*/
578static Image
579  *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
580
581static ssize_t
582  strEQcase(const char *,const char *);
583
584/*
585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586%                                                                             %
587%                                                                             %
588%                                                                             %
589%   C l o n e P a c k a g e I n f o                                           %
590%                                                                             %
591%                                                                             %
592%                                                                             %
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594%
595%  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
596%  a new one.
597%
598%  The format of the ClonePackageInfo routine is:
599%
600%      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
601%        exception)
602%
603%  A description of each parameter follows:
604%
605%    o info: a structure of type info.
606%
607%    o exception: Return any errors or warnings in this structure.
608%
609*/
610static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
611  ExceptionInfo *exception)
612{
613  struct PackageInfo
614    *clone_info;
615
616  clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
617  if (clone_info == (struct PackageInfo *) NULL)
618    {
619      ThrowPerlException(exception,ResourceLimitError,
620        "UnableToClonePackageInfo",PackageName);
621      return((struct PackageInfo *) NULL);
622    }
623  if (info == (struct PackageInfo *) NULL)
624    {
625      clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
626      return(clone_info);
627    }
628  *clone_info=(*info);
629  clone_info->image_info=CloneImageInfo(info->image_info);
630  return(clone_info);
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635%                                                                             %
636%                                                                             %
637%                                                                             %
638%   c o n s t a n t                                                           %
639%                                                                             %
640%                                                                             %
641%                                                                             %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
644%  constant() returns a double value for the specified name.
645%
646%  The format of the constant routine is:
647%
648%      double constant(char *name,ssize_t sans)
649%
650%  A description of each parameter follows:
651%
652%    o value: Method constant returns a double value for the specified name.
653%
654%    o name: The name of the constant.
655%
656%    o sans: This integer value is not used.
657%
658*/
659static double constant(char *name,ssize_t sans)
660{
661  (void) sans;
662  errno=0;
663  switch (*name)
664  {
665    case 'B':
666    {
667      if (strEQ(name,"BlobError"))
668        return(BlobError);
669      if (strEQ(name,"BlobWarning"))
670        return(BlobWarning);
671      break;
672    }
673    case 'C':
674    {
675      if (strEQ(name,"CacheError"))
676        return(CacheError);
677      if (strEQ(name,"CacheWarning"))
678        return(CacheWarning);
679      if (strEQ(name,"CoderError"))
680        return(CoderError);
681      if (strEQ(name,"CoderWarning"))
682        return(CoderWarning);
683      if (strEQ(name,"ConfigureError"))
684        return(ConfigureError);
685      if (strEQ(name,"ConfigureWarning"))
686        return(ConfigureWarning);
687      if (strEQ(name,"CorruptImageError"))
688        return(CorruptImageError);
689      if (strEQ(name,"CorruptImageWarning"))
690        return(CorruptImageWarning);
691      break;
692    }
693    case 'D':
694    {
695      if (strEQ(name,"DelegateError"))
696        return(DelegateError);
697      if (strEQ(name,"DelegateWarning"))
698        return(DelegateWarning);
699      if (strEQ(name,"DrawError"))
700        return(DrawError);
701      if (strEQ(name,"DrawWarning"))
702        return(DrawWarning);
703      break;
704    }
705    case 'E':
706    {
707      if (strEQ(name,"ErrorException"))
708        return(ErrorException);
709      if (strEQ(name,"ExceptionError"))
710        return(CoderError);
711      if (strEQ(name,"ExceptionWarning"))
712        return(CoderWarning);
713      break;
714    }
715    case 'F':
716    {
717      if (strEQ(name,"FatalErrorException"))
718        return(FatalErrorException);
719      if (strEQ(name,"FileOpenError"))
720        return(FileOpenError);
721      if (strEQ(name,"FileOpenWarning"))
722        return(FileOpenWarning);
723      break;
724    }
725    case 'I':
726    {
727      if (strEQ(name,"ImageError"))
728        return(ImageError);
729      if (strEQ(name,"ImageWarning"))
730        return(ImageWarning);
731      break;
732    }
733    case 'M':
734    {
735      if (strEQ(name,"MaxRGB"))
736        return(QuantumRange);
737      if (strEQ(name,"MissingDelegateError"))
738        return(MissingDelegateError);
739      if (strEQ(name,"MissingDelegateWarning"))
740        return(MissingDelegateWarning);
741      if (strEQ(name,"ModuleError"))
742        return(ModuleError);
743      if (strEQ(name,"ModuleWarning"))
744        return(ModuleWarning);
745      break;
746    }
747    case 'O':
748    {
749      if (strEQ(name,"Opaque"))
750        return(OpaqueOpacity);
751      if (strEQ(name,"OptionError"))
752        return(OptionError);
753      if (strEQ(name,"OptionWarning"))
754        return(OptionWarning);
755      break;
756    }
757    case 'Q':
758    {
759      if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
760        return(MAGICKCORE_QUANTUM_DEPTH);
761      if (strEQ(name,"QuantumDepth"))
762        return(MAGICKCORE_QUANTUM_DEPTH);
763      if (strEQ(name,"QuantumRange"))
764        return(QuantumRange);
765      break;
766    }
767    case 'R':
768    {
769      if (strEQ(name,"ResourceLimitError"))
770        return(ResourceLimitError);
771      if (strEQ(name,"ResourceLimitWarning"))
772        return(ResourceLimitWarning);
773      if (strEQ(name,"RegistryError"))
774        return(RegistryError);
775      if (strEQ(name,"RegistryWarning"))
776        return(RegistryWarning);
777      break;
778    }
779    case 'S':
780    {
781      if (strEQ(name,"StreamError"))
782        return(StreamError);
783      if (strEQ(name,"StreamWarning"))
784        return(StreamWarning);
785      if (strEQ(name,"Success"))
786        return(0);
787      break;
788    }
789    case 'T':
790    {
791      if (strEQ(name,"Transparent"))
792        return(TransparentOpacity);
793      if (strEQ(name,"TypeError"))
794        return(TypeError);
795      if (strEQ(name,"TypeWarning"))
796        return(TypeWarning);
797      break;
798    }
799    case 'W':
800    {
801      if (strEQ(name,"WarningException"))
802        return(WarningException);
803      break;
804    }
805    case 'X':
806    {
807      if (strEQ(name,"XServerError"))
808        return(XServerError);
809      if (strEQ(name,"XServerWarning"))
810        return(XServerWarning);
811      break;
812    }
813  }
814  errno=EINVAL;
815  return(0);
816}
817
818/*
819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820%                                                                             %
821%                                                                             %
822%                                                                             %
823%   D e s t r o y P a c k a g e I n f o                                       %
824%                                                                             %
825%                                                                             %
826%                                                                             %
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828%
829%  Method DestroyPackageInfo frees a previously created info structure.
830%
831%  The format of the DestroyPackageInfo routine is:
832%
833%      DestroyPackageInfo(struct PackageInfo *info)
834%
835%  A description of each parameter follows:
836%
837%    o info: a structure of type info.
838%
839*/
840static void DestroyPackageInfo(struct PackageInfo *info)
841{
842  info->image_info=DestroyImageInfo(info->image_info);
843  info=(struct PackageInfo *) RelinquishMagickMemory(info);
844}
845
846/*
847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848%                                                                             %
849%                                                                             %
850%                                                                             %
851%   G e t L i s t                                                             %
852%                                                                             %
853%                                                                             %
854%                                                                             %
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%
857%  Method GetList is recursively called by SetupList to traverse the
858%  Image__Magick reference.  If building an reference_vector (see SetupList),
859%  *current is the current position in *reference_vector and *last is the final
860%  entry in *reference_vector.
861%
862%  The format of the GetList routine is:
863%
864%      GetList(info)
865%
866%  A description of each parameter follows:
867%
868%    o info: a structure of type info.
869%
870*/
871static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
872  ssize_t *current,ssize_t *last,ExceptionInfo *exception)
873{
874  Image
875    *image;
876
877  if (reference == (SV *) NULL)
878    return(NULL);
879  switch (SvTYPE(reference))
880  {
881    case SVt_PVAV:
882    {
883      AV
884        *av;
885
886      Image
887        *head,
888        *previous;
889
890      ssize_t
891        i;
892
893      ssize_t
894        n;
895
896      /*
897        Array of images.
898      */
899      previous=(Image *) NULL;
900      head=(Image *) NULL;
901      av=(AV *) reference;
902      n=av_len(av);
903      for (i=0; i <= n; i++)
904      {
905        SV
906          **rv;
907
908        rv=av_fetch(av,i,0);
909        if (rv && *rv && sv_isobject(*rv))
910          {
911            image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
912              exception);
913            if (image == (Image *) NULL)
914              continue;
915            if (image == previous)
916              {
917                image=CloneImage(image,0,0,MagickTrue,exception);
918                if (image == (Image *) NULL)
919                  return(NULL);
920              }
921            image->previous=previous;
922            *(previous ? &previous->next : &head)=image;
923            for (previous=image; previous->next; previous=previous->next) ;
924          }
925      }
926      return(head);
927    }
928    case SVt_PVMG:
929    {
930      /*
931        Blessed scalar, one image.
932      */
933      image=INT2PTR(Image *,SvIV(reference));
934      if (image == (Image *) NULL)
935        return(NULL);
936      image->previous=(Image *) NULL;
937      image->next=(Image *) NULL;
938      if (reference_vector)
939        {
940          if (*current == *last)
941            {
942              *last+=256;
943              if (*reference_vector == (SV **) NULL)
944                *reference_vector=(SV **) AcquireQuantumMemory(*last,
945                  sizeof(*reference_vector));
946              else
947                *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
948                  *last,sizeof(*reference_vector));
949            }
950          if (*reference_vector == (SV **) NULL)
951            {
952              ThrowPerlException(exception,ResourceLimitError,
953                "MemoryAllocationFailed",PackageName);
954              return((Image *) NULL);
955            }
956          (*reference_vector)[*current]=reference;
957          (*reference_vector)[++(*current)]=NULL;
958        }
959      return(image);
960    }
961    default:
962      break;
963  }
964  (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
965    (double) SvTYPE(reference));
966  return((Image *) NULL);
967}
968
969/*
970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971%                                                                             %
972%                                                                             %
973%                                                                             %
974%   G e t P a c k a g e I n f o                                               %
975%                                                                             %
976%                                                                             %
977%                                                                             %
978%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979%
980%  Method GetPackageInfo looks up or creates an info structure for the given
981%  Image__Magick reference.  If it does create a new one, the information in
982%  package_info is used to initialize it.
983%
984%  The format of the GetPackageInfo routine is:
985%
986%      struct PackageInfo *GetPackageInfo(void *reference,
987%        struct PackageInfo *package_info,ExceptionInfo *exception)
988%
989%  A description of each parameter follows:
990%
991%    o info: a structure of type info.
992%
993%    o exception: Return any errors or warnings in this structure.
994%
995*/
996static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
997  struct PackageInfo *package_info,ExceptionInfo *exception)
998{
999  char
1000    message[MaxTextExtent];
1001
1002  struct PackageInfo
1003    *clone_info;
1004
1005  SV
1006    *sv;
1007
1008  (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
1009    PackageName,XS_VERSION,reference);
1010  sv=perl_get_sv(message,(TRUE | 0x02));
1011  if (sv == (SV *) NULL)
1012    {
1013      ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1014        message);
1015      return(package_info);
1016    }
1017  if (SvREFCNT(sv) == 0)
1018    (void) SvREFCNT_inc(sv);
1019  if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1020    return(clone_info);
1021  clone_info=ClonePackageInfo(package_info,exception);
1022  sv_setiv(sv,PTR2IV(clone_info));
1023  return(clone_info);
1024}
1025
1026/*
1027%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1028%                                                                             %
1029%                                                                             %
1030%                                                                             %
1031%   S e t A t t r i b u t e                                                   %
1032%                                                                             %
1033%                                                                             %
1034%                                                                             %
1035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1036%
1037%  SetAttribute() sets the attribute to the value in sval.  This can change
1038%  either or both of image or info.
1039%
1040%  The format of the SetAttribute routine is:
1041%
1042%      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1043%        SV *sval,ExceptionInfo *exception)
1044%
1045%  A description of each parameter follows:
1046%
1047%    o list: a list of strings.
1048%
1049%    o string: a character string.
1050%
1051*/
1052
1053static double SiPrefixToDoubleInterval(const char *string,const double interval)
1054{
1055  char
1056    *q;
1057
1058  double
1059    value;
1060
1061  value=InterpretSiPrefixValue(string,&q);
1062  if (*q == '%')
1063    value*=interval/100.0;
1064  return(value);
1065}
1066
1067static inline double StringToDouble(const char *string,char **sentinal)
1068{
1069  return(InterpretLocaleValue(string,sentinal));
1070}
1071
1072static double StringToDoubleInterval(const char *string,const double interval)
1073{
1074  char
1075    *q;
1076
1077  double
1078    value;
1079
1080  value=InterpretLocaleValue(string,&q);
1081  if (*q == '%')
1082    value*=interval/100.0;
1083  return(value);
1084}
1085
1086static inline ssize_t StringToLong(const char *value)
1087{
1088  return(strtol(value,(char **) NULL,10));
1089}
1090
1091static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1092  const char *attribute,SV *sval,ExceptionInfo *exception)
1093{
1094  GeometryInfo
1095    geometry_info;
1096
1097  long
1098    x,
1099    y;
1100
1101  MagickPixelPacket
1102    pixel;
1103
1104  MagickStatusType
1105    flags;
1106
1107  PixelPacket
1108    *color,
1109    target_color;
1110
1111  ssize_t
1112    sp;
1113
1114  switch (*attribute)
1115  {
1116    case 'A':
1117    case 'a':
1118    {
1119      if (LocaleCompare(attribute,"adjoin") == 0)
1120        {
1121          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1122            SvPV(sval,na)) : SvIV(sval);
1123          if (sp < 0)
1124            {
1125              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1126                SvPV(sval,na));
1127              break;
1128            }
1129          if (info)
1130            info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1131          break;
1132        }
1133      if (LocaleCompare(attribute,"alpha") == 0)
1134        {
1135          sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1136            SvPV(sval,na)) : SvIV(sval);
1137          if (sp < 0)
1138            {
1139              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1140                SvPV(sval,na));
1141              break;
1142            }
1143          for ( ; image; image=image->next)
1144            (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1145          break;
1146        }
1147      if (LocaleCompare(attribute,"antialias") == 0)
1148        {
1149          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1150            SvPV(sval,na)) : SvIV(sval);
1151          if (sp < 0)
1152            {
1153              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1154                SvPV(sval,na));
1155              break;
1156            }
1157          if (info)
1158            info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1159          break;
1160        }
1161      if (LocaleCompare(attribute,"area-limit") == 0)
1162        {
1163          MagickSizeType
1164            limit;
1165
1166          limit=MagickResourceInfinity;
1167          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1168            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1169              100.0);
1170          (void) SetMagickResourceLimit(AreaResource,limit);
1171          break;
1172        }
1173      if (LocaleCompare(attribute,"attenuate") == 0)
1174        {
1175          if (info)
1176            (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1177          break;
1178        }
1179      if (LocaleCompare(attribute,"authenticate") == 0)
1180        {
1181          if (info)
1182            (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1183          break;
1184        }
1185      if (info)
1186        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1187      for ( ; image; image=image->next)
1188      {
1189        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1190        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1191      }
1192      break;
1193    }
1194    case 'B':
1195    case 'b':
1196    {
1197      if (LocaleCompare(attribute,"background") == 0)
1198        {
1199          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1200          if (info)
1201            info->image_info->background_color=target_color;
1202          for ( ; image; image=image->next)
1203            image->background_color=target_color;
1204          break;
1205        }
1206      if (LocaleCompare(attribute,"bias") == 0)
1207        {
1208          for ( ; image; image=image->next)
1209            image->bias=StringToDoubleInterval(SvPV(sval,na),(double)
1210              QuantumRange+1.0);
1211          break;
1212        }
1213      if (LocaleCompare(attribute,"blue-primary") == 0)
1214        {
1215          for ( ; image; image=image->next)
1216          {
1217            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1218            image->chromaticity.blue_primary.x=geometry_info.rho;
1219            image->chromaticity.blue_primary.y=geometry_info.sigma;
1220            if ((flags & SigmaValue) == 0)
1221              image->chromaticity.blue_primary.y=
1222                image->chromaticity.blue_primary.x;
1223          }
1224          break;
1225        }
1226      if (LocaleCompare(attribute,"bordercolor") == 0)
1227        {
1228          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1229          if (info)
1230            info->image_info->border_color=target_color;
1231          for ( ; image; image=image->next)
1232            image->border_color=target_color;
1233          break;
1234        }
1235      if (info)
1236        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1237      for ( ; image; image=image->next)
1238      {
1239        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1240        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1241      }
1242      break;
1243    }
1244    case 'C':
1245    case 'c':
1246    {
1247      if (LocaleCompare(attribute,"cache-threshold") == 0)
1248        {
1249          (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1250            SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1251          (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1252            (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1253          break;
1254        }
1255      if (LocaleCompare(attribute,"clip-mask") == 0)
1256        {
1257          Image
1258            *clip_mask;
1259
1260          clip_mask=(Image *) NULL;
1261          if (SvPOK(sval))
1262            clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1263          for ( ; image; image=image->next)
1264            SetImageClipMask(image,clip_mask);
1265          break;
1266        }
1267      if (LocaleNCompare(attribute,"colormap",8) == 0)
1268        {
1269          for ( ; image; image=image->next)
1270          {
1271            int
1272              items;
1273
1274            long
1275              i;
1276
1277            if (image->storage_class == DirectClass)
1278              continue;
1279            i=0;
1280            items=sscanf(attribute,"%*[^[][%ld",&i);
1281            (void) items;
1282            if (i > (ssize_t) image->colors)
1283              i%=image->colors;
1284            if ((strchr(SvPV(sval,na),',') == 0) ||
1285                (strchr(SvPV(sval,na),')') != 0))
1286              QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1287            else
1288              {
1289                color=image->colormap+i;
1290                pixel.red=color->red;
1291                pixel.green=color->green;
1292                pixel.blue=color->blue;
1293                flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1294                pixel.red=geometry_info.rho;
1295                pixel.green=geometry_info.sigma;
1296                pixel.blue=geometry_info.xi;
1297                color->red=ClampToQuantum(pixel.red);
1298                color->green=ClampToQuantum(pixel.green);
1299                color->blue=ClampToQuantum(pixel.blue);
1300              }
1301          }
1302          break;
1303        }
1304      if (LocaleCompare(attribute,"colorspace") == 0)
1305        {
1306          sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1307            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1308          if (sp < 0)
1309            {
1310              ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1311                SvPV(sval,na));
1312              break;
1313            }
1314          for ( ; image; image=image->next)
1315            (void) SetImageColorspace(image,(ColorspaceType) sp);
1316          break;
1317        }
1318      if (LocaleCompare(attribute,"comment") == 0)
1319        {
1320          for ( ; image; image=image->next)
1321            (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1322              info ? info->image_info : (ImageInfo *) NULL,image,
1323              SvPV(sval,na)));
1324          break;
1325        }
1326      if (LocaleCompare(attribute,"compression") == 0)
1327        {
1328          sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1329            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1330          if (sp < 0)
1331            {
1332              ThrowPerlException(exception,OptionError,
1333                "UnrecognizedImageCompression",SvPV(sval,na));
1334              break;
1335            }
1336          if (info)
1337            info->image_info->compression=(CompressionType) sp;
1338          for ( ; image; image=image->next)
1339            image->compression=(CompressionType) sp;
1340          break;
1341        }
1342      if (info)
1343        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1344      for ( ; image; image=image->next)
1345      {
1346        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1347        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1348      }
1349      break;
1350    }
1351    case 'D':
1352    case 'd':
1353    {
1354      if (LocaleCompare(attribute,"debug") == 0)
1355        {
1356          SetLogEventMask(SvPV(sval,na));
1357          break;
1358        }
1359      if (LocaleCompare(attribute,"delay") == 0)
1360        {
1361          flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1362          for ( ; image; image=image->next)
1363          {
1364            image->delay=(size_t) floor(geometry_info.rho+0.5);
1365            if ((flags & SigmaValue) != 0)
1366              image->ticks_per_second=(ssize_t)
1367                floor(geometry_info.sigma+0.5);
1368          }
1369          break;
1370        }
1371      if (LocaleCompare(attribute,"disk-limit") == 0)
1372        {
1373          MagickSizeType
1374            limit;
1375
1376          limit=MagickResourceInfinity;
1377          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1378            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1379              100.0);
1380          (void) SetMagickResourceLimit(DiskResource,limit);
1381          break;
1382        }
1383      if (LocaleCompare(attribute,"density") == 0)
1384        {
1385          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1386            {
1387              ThrowPerlException(exception,OptionError,"MissingGeometry",
1388                SvPV(sval,na));
1389              break;
1390            }
1391          if (info)
1392            (void) CloneString(&info->image_info->density,SvPV(sval,na));
1393          for ( ; image; image=image->next)
1394          {
1395            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1396            image->x_resolution=geometry_info.rho;
1397            image->y_resolution=geometry_info.sigma;
1398            if ((flags & SigmaValue) == 0)
1399              image->y_resolution=image->x_resolution;
1400          }
1401          break;
1402        }
1403      if (LocaleCompare(attribute,"depth") == 0)
1404        {
1405          if (info)
1406            info->image_info->depth=SvIV(sval);
1407          for ( ; image; image=image->next)
1408            (void) SetImageDepth(image,SvIV(sval));
1409          break;
1410        }
1411      if (LocaleCompare(attribute,"dispose") == 0)
1412        {
1413          sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1414            SvPV(sval,na)) : SvIV(sval);
1415          if (sp < 0)
1416            {
1417              ThrowPerlException(exception,OptionError,
1418                "UnrecognizedDisposeMethod",SvPV(sval,na));
1419              break;
1420            }
1421          for ( ; image; image=image->next)
1422            image->dispose=(DisposeType) sp;
1423          break;
1424        }
1425      if (LocaleCompare(attribute,"dither") == 0)
1426        {
1427          if (info)
1428            {
1429              sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1430                MagickFalse,SvPV(sval,na)) : SvIV(sval);
1431              if (sp < 0)
1432                {
1433                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
1434                    SvPV(sval,na));
1435                  break;
1436                }
1437              info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1438            }
1439          break;
1440        }
1441      if (LocaleCompare(attribute,"display") == 0)
1442        {
1443          display:
1444          if (info)
1445            (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1446          break;
1447        }
1448      if (info)
1449        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1450      for ( ; image; image=image->next)
1451      {
1452        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1453        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1454      }
1455      break;
1456    }
1457    case 'E':
1458    case 'e':
1459    {
1460      if (LocaleCompare(attribute,"endian") == 0)
1461        {
1462          sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1463            SvPV(sval,na)) : SvIV(sval);
1464          if (sp < 0)
1465            {
1466              ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1467                SvPV(sval,na));
1468              break;
1469            }
1470          if (info)
1471            info->image_info->endian=(EndianType) sp;
1472          for ( ; image; image=image->next)
1473            image->endian=(EndianType) sp;
1474          break;
1475        }
1476      if (LocaleCompare(attribute,"extract") == 0)
1477        {
1478          /*
1479            Set image extract geometry.
1480          */
1481          (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1482          break;
1483        }
1484      if (info)
1485        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1486      for ( ; image; image=image->next)
1487      {
1488        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1489        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1490      }
1491      break;
1492    }
1493    case 'F':
1494    case 'f':
1495    {
1496      if (LocaleCompare(attribute,"filename") == 0)
1497        {
1498          if (info)
1499            (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1500              MaxTextExtent);
1501          for ( ; image; image=image->next)
1502            (void) CopyMagickString(image->filename,SvPV(sval,na),
1503              MaxTextExtent);
1504          break;
1505        }
1506      if (LocaleCompare(attribute,"file") == 0)
1507        {
1508          FILE
1509            *file;
1510
1511          PerlIO
1512            *io_info;
1513
1514          if (info == (struct PackageInfo *) NULL)
1515            break;
1516          io_info=IoIFP(sv_2io(sval));
1517          if (io_info == (PerlIO *) NULL)
1518            {
1519              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1520                PackageName);
1521              break;
1522            }
1523          file=PerlIO_findFILE(io_info);
1524          if (file == (FILE *) NULL)
1525            {
1526              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1527                PackageName);
1528              break;
1529            }
1530          SetImageInfoFile(info->image_info,file);
1531          break;
1532        }
1533      if (LocaleCompare(attribute,"fill") == 0)
1534        {
1535          if (info)
1536            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1537          break;
1538        }
1539      if (LocaleCompare(attribute,"font") == 0)
1540        {
1541          if (info)
1542            (void) CloneString(&info->image_info->font,SvPV(sval,na));
1543          break;
1544        }
1545      if (LocaleCompare(attribute,"foreground") == 0)
1546        break;
1547      if (LocaleCompare(attribute,"fuzz") == 0)
1548        {
1549          if (info)
1550            info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1551              QuantumRange+1.0);
1552          for ( ; image; image=image->next)
1553            image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1554              QuantumRange+1.0);
1555          break;
1556        }
1557      if (info)
1558        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1559      for ( ; image; image=image->next)
1560      {
1561        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1562        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1563      }
1564      break;
1565    }
1566    case 'G':
1567    case 'g':
1568    {
1569      if (LocaleCompare(attribute,"gamma") == 0)
1570        {
1571          for ( ; image; image=image->next)
1572            image->gamma=SvNV(sval);
1573          break;
1574        }
1575      if (LocaleCompare(attribute,"gravity") == 0)
1576        {
1577          sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1578            SvPV(sval,na)) : SvIV(sval);
1579          if (sp < 0)
1580            {
1581              ThrowPerlException(exception,OptionError,
1582                "UnrecognizedGravityType",SvPV(sval,na));
1583              break;
1584            }
1585          if (info)
1586            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1587          for ( ; image; image=image->next)
1588            image->gravity=(GravityType) sp;
1589          break;
1590        }
1591      if (LocaleCompare(attribute,"green-primary") == 0)
1592        {
1593          for ( ; image; image=image->next)
1594          {
1595            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1596            image->chromaticity.green_primary.x=geometry_info.rho;
1597            image->chromaticity.green_primary.y=geometry_info.sigma;
1598            if ((flags & SigmaValue) == 0)
1599              image->chromaticity.green_primary.y=
1600                image->chromaticity.green_primary.x;
1601          }
1602          break;
1603        }
1604      if (info)
1605        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1606      for ( ; image; image=image->next)
1607      {
1608        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1609        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1610      }
1611      break;
1612    }
1613    case 'I':
1614    case 'i':
1615    {
1616      if (LocaleNCompare(attribute,"index",5) == 0)
1617        {
1618          IndexPacket
1619            *indexes;
1620
1621          int
1622            items;
1623
1624          long
1625            index;
1626
1627          PixelPacket
1628            *p;
1629
1630          CacheView
1631            *image_view;
1632
1633          for ( ; image; image=image->next)
1634          {
1635            if (image->storage_class != PseudoClass)
1636              continue;
1637            x=0;
1638            y=0;
1639            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1640            (void) items;
1641            image_view=AcquireAuthenticCacheView(image,exception);
1642            p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1643            if (p != (PixelPacket *) NULL)
1644              {
1645                indexes=GetCacheViewAuthenticIndexQueue(image_view);
1646                items=sscanf(SvPV(sval,na),"%ld",&index);
1647                if ((index >= 0) && (index < (ssize_t) image->colors))
1648                  SetPixelIndex(indexes,index);
1649                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1650              }
1651            image_view=DestroyCacheView(image_view);
1652          }
1653          break;
1654        }
1655      if (LocaleCompare(attribute,"iterations") == 0)
1656        {
1657  iterations:
1658          for ( ; image; image=image->next)
1659            image->iterations=SvIV(sval);
1660          break;
1661        }
1662      if (LocaleCompare(attribute,"interlace") == 0)
1663        {
1664          sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1665            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1666          if (sp < 0)
1667            {
1668              ThrowPerlException(exception,OptionError,
1669                "UnrecognizedInterlaceType",SvPV(sval,na));
1670              break;
1671            }
1672          if (info)
1673            info->image_info->interlace=(InterlaceType) sp;
1674          for ( ; image; image=image->next)
1675            image->interlace=(InterlaceType) sp;
1676          break;
1677        }
1678      if (info)
1679        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1680      for ( ; image; image=image->next)
1681      {
1682        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1683        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1684      }
1685      break;
1686    }
1687    case 'L':
1688    case 'l':
1689    {
1690      if (LocaleCompare(attribute,"label") == 0)
1691        {
1692          for ( ; image; image=image->next)
1693            (void) SetImageProperty(image,"label",InterpretImageProperties(
1694              info ? info->image_info : (ImageInfo *) NULL,image,
1695              SvPV(sval,na)));
1696          break;
1697        }
1698      if (LocaleCompare(attribute,"loop") == 0)
1699        goto iterations;
1700      if (info)
1701        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1702      for ( ; image; image=image->next)
1703      {
1704        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1705        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1706      }
1707      break;
1708    }
1709    case 'M':
1710    case 'm':
1711    {
1712      if (LocaleCompare(attribute,"magick") == 0)
1713        {
1714          if (info)
1715            (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1716              "%s:",SvPV(sval,na));
1717          for ( ; image; image=image->next)
1718            (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1719          break;
1720        }
1721      if (LocaleCompare(attribute,"map-limit") == 0)
1722        {
1723          MagickSizeType
1724            limit;
1725
1726          limit=MagickResourceInfinity;
1727          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1728            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1729              100.0);
1730          (void) SetMagickResourceLimit(MapResource,limit);
1731          break;
1732        }
1733      if (LocaleCompare(attribute,"mask") == 0)
1734        {
1735          Image
1736            *mask;
1737
1738          mask=(Image *) NULL;
1739          if (SvPOK(sval))
1740            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1741          for ( ; image; image=image->next)
1742            SetImageMask(image,mask);
1743          break;
1744        }
1745      if (LocaleCompare(attribute,"mattecolor") == 0)
1746        {
1747          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1748          if (info)
1749            info->image_info->matte_color=target_color;
1750          for ( ; image; image=image->next)
1751            image->matte_color=target_color;
1752          break;
1753        }
1754      if (LocaleCompare(attribute,"matte") == 0)
1755        {
1756          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1757            SvPV(sval,na)) : SvIV(sval);
1758          if (sp < 0)
1759            {
1760              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1761                SvPV(sval,na));
1762              break;
1763            }
1764          for ( ; image; image=image->next)
1765            image->matte=sp != 0 ? MagickTrue : MagickFalse;
1766          break;
1767        }
1768      if (LocaleCompare(attribute,"memory-limit") == 0)
1769        {
1770          MagickSizeType
1771            limit;
1772
1773          limit=MagickResourceInfinity;
1774          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1775            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1776              100.0);
1777          (void) SetMagickResourceLimit(MemoryResource,limit);
1778          break;
1779        }
1780      if (LocaleCompare(attribute,"monochrome") == 0)
1781        {
1782          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1783            SvPV(sval,na)) : SvIV(sval);
1784          if (sp < 0)
1785            {
1786              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1787                SvPV(sval,na));
1788              break;
1789            }
1790          if (info)
1791            info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1792          for ( ; image; image=image->next)
1793            (void) SetImageType(image,BilevelType);
1794          break;
1795        }
1796      if (info)
1797        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1798      for ( ; image; image=image->next)
1799      {
1800        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1801        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1802      }
1803      break;
1804    }
1805    case 'O':
1806    case 'o':
1807    {
1808      if (LocaleCompare(attribute,"option") == 0)
1809        {
1810          if (info)
1811            DefineImageOption(info->image_info,SvPV(sval,na));
1812          break;
1813        }
1814      if (LocaleCompare(attribute,"orientation") == 0)
1815        {
1816          sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1817            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1818          if (sp < 0)
1819            {
1820              ThrowPerlException(exception,OptionError,
1821                "UnrecognizedOrientationType",SvPV(sval,na));
1822              break;
1823            }
1824          if (info)
1825            info->image_info->orientation=(OrientationType) sp;
1826          for ( ; image; image=image->next)
1827            image->orientation=(OrientationType) sp;
1828          break;
1829        }
1830      if (info)
1831        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1832      for ( ; image; image=image->next)
1833      {
1834        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1835        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1836      }
1837      break;
1838    }
1839    case 'P':
1840    case 'p':
1841    {
1842      if (LocaleCompare(attribute,"page") == 0)
1843        {
1844          char
1845            *geometry;
1846
1847          geometry=GetPageGeometry(SvPV(sval,na));
1848          if (info)
1849            (void) CloneString(&info->image_info->page,geometry);
1850          for ( ; image; image=image->next)
1851            (void) ParsePageGeometry(image,geometry,&image->page,exception);
1852          geometry=(char *) RelinquishMagickMemory(geometry);
1853          break;
1854        }
1855      if (LocaleCompare(attribute,"pen") == 0)
1856        {
1857          if (info)
1858            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1859          break;
1860        }
1861      if (LocaleNCompare(attribute,"pixel",5) == 0)
1862        {
1863          int
1864            items;
1865
1866          MagickPixelPacket
1867            pixel;
1868
1869          IndexPacket
1870            *indexes;
1871
1872          PixelPacket
1873            *q;
1874
1875          CacheView
1876            *image_view;
1877
1878          for ( ; image; image=image->next)
1879          {
1880            if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1881              break;
1882            x=0;
1883            y=0;
1884            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1885            (void) items;
1886            image_view=AcquireAuthenticCacheView(image,exception);
1887            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1888            indexes=GetCacheViewAuthenticIndexQueue(image_view);
1889            if (q != (PixelPacket *) NULL)
1890              {
1891                if ((strchr(SvPV(sval,na),',') == 0) ||
1892                    (strchr(SvPV(sval,na),')') != 0))
1893                  QueryMagickColor(SvPV(sval,na),&pixel,exception);
1894                else
1895                  {
1896                    GetMagickPixelPacket(image,&pixel);
1897                    flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1898                    pixel.red=geometry_info.rho;
1899                    if ((flags & SigmaValue) != 0)
1900                      pixel.green=geometry_info.sigma;
1901                    if ((flags & XiValue) != 0)
1902                      pixel.blue=geometry_info.xi;
1903                    if ((flags & PsiValue) != 0)
1904                      pixel.opacity=geometry_info.psi;
1905                    if ((flags & ChiValue) != 0)
1906                      pixel.index=geometry_info.chi;
1907                  }
1908                SetPixelRed(q,ClampToQuantum(pixel.red));
1909                SetPixelGreen(q,ClampToQuantum(pixel.green));
1910                SetPixelBlue(q,ClampToQuantum(pixel.blue));
1911                SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1912                if (((image->colorspace == CMYKColorspace) ||
1913                     (image->storage_class == PseudoClass)) &&
1914                    (indexes != (IndexPacket *) NULL))
1915                  SetPixelIndex(indexes,ClampToQuantum(pixel.index));
1916                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1917              }
1918            image_view=DestroyCacheView(image_view);
1919          }
1920          break;
1921        }
1922      if (LocaleCompare(attribute,"pointsize") == 0)
1923        {
1924          if (info)
1925            {
1926              (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1927              info->image_info->pointsize=geometry_info.rho;
1928            }
1929          break;
1930        }
1931      if (LocaleCompare(attribute,"precision") == 0)
1932        {
1933          (void) SetMagickPrecision(SvIV(sval));
1934          break;
1935        }
1936      if (LocaleCompare(attribute,"preview") == 0)
1937        {
1938          sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1939            SvPV(sval,na)) : SvIV(sval);
1940          if (sp < 0)
1941            {
1942              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1943                SvPV(sval,na));
1944              break;
1945            }
1946          if (info)
1947            info->image_info->preview_type=(PreviewType) sp;
1948          break;
1949        }
1950      if (info)
1951        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1952      for ( ; image; image=image->next)
1953      {
1954        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1955        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1956      }
1957      break;
1958    }
1959    case 'Q':
1960    case 'q':
1961    {
1962      if (LocaleCompare(attribute,"quality") == 0)
1963        {
1964          if (info)
1965            info->image_info->quality=SvIV(sval);
1966          for ( ; image; image=image->next)
1967            image->quality=SvIV(sval);
1968          break;
1969        }
1970      if (info)
1971        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1972      for ( ; image; image=image->next)
1973      {
1974        (void) SetImageProperty(image,attribute,SvPV(sval,na));
1975        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1976      }
1977      break;
1978    }
1979    case 'R':
1980    case 'r':
1981    {
1982      if (LocaleCompare(attribute,"red-primary") == 0)
1983        {
1984          for ( ; image; image=image->next)
1985          {
1986            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1987            image->chromaticity.red_primary.x=geometry_info.rho;
1988            image->chromaticity.red_primary.y=geometry_info.sigma;
1989            if ((flags & SigmaValue) == 0)
1990              image->chromaticity.red_primary.y=
1991                image->chromaticity.red_primary.x;
1992          }
1993          break;
1994        }
1995      if (LocaleCompare(attribute,"render") == 0)
1996        {
1997          sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1998            SvPV(sval,na)) : SvIV(sval);
1999          if (sp < 0)
2000            {
2001              ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
2002                SvPV(sval,na));
2003              break;
2004            }
2005         for ( ; image; image=image->next)
2006           image->rendering_intent=(RenderingIntent) sp;
2007         break;
2008       }
2009      if (LocaleCompare(attribute,"repage") == 0)
2010        {
2011          RectangleInfo
2012            geometry;
2013
2014          for ( ; image; image=image->next)
2015          {
2016            flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2017            if ((flags & WidthValue) != 0)
2018              {
2019                if ((flags & HeightValue) == 0)
2020                  geometry.height=geometry.width;
2021                image->page.width=geometry.width;
2022                image->page.height=geometry.height;
2023              }
2024            if ((flags & AspectValue) != 0)
2025              {
2026                if ((flags & XValue) != 0)
2027                  image->page.x+=geometry.x;
2028                if ((flags & YValue) != 0)
2029                  image->page.y+=geometry.y;
2030              }
2031            else
2032              {
2033                if ((flags & XValue) != 0)
2034                  {
2035                    image->page.x=geometry.x;
2036                    if (((flags & WidthValue) != 0) && (geometry.x > 0))
2037                      image->page.width=image->columns+geometry.x;
2038                  }
2039                if ((flags & YValue) != 0)
2040                  {
2041                    image->page.y=geometry.y;
2042                    if (((flags & HeightValue) != 0) && (geometry.y > 0))
2043                      image->page.height=image->rows+geometry.y;
2044                  }
2045              }
2046          }
2047          break;
2048        }
2049      if (info)
2050        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2051      for ( ; image; image=image->next)
2052      {
2053        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2054        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2055      }
2056      break;
2057    }
2058    case 'S':
2059    case 's':
2060    {
2061      if (LocaleCompare(attribute,"sampling-factor") == 0)
2062        {
2063          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2064            {
2065              ThrowPerlException(exception,OptionError,"MissingGeometry",
2066                SvPV(sval,na));
2067              break;
2068            }
2069          if (info)
2070            (void) CloneString(&info->image_info->sampling_factor,
2071              SvPV(sval,na));
2072          break;
2073        }
2074      if (LocaleCompare(attribute,"scene") == 0)
2075        {
2076          for ( ; image; image=image->next)
2077            image->scene=SvIV(sval);
2078          break;
2079        }
2080      if (LocaleCompare(attribute,"subimage") == 0)
2081        {
2082          if (info)
2083            info->image_info->subimage=SvIV(sval);
2084          break;
2085        }
2086      if (LocaleCompare(attribute,"subrange") == 0)
2087        {
2088          if (info)
2089            info->image_info->subrange=SvIV(sval);
2090          break;
2091        }
2092      if (LocaleCompare(attribute,"server") == 0)
2093        goto display;
2094      if (LocaleCompare(attribute,"size") == 0)
2095        {
2096          if (info)
2097            {
2098              if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2099                {
2100                  ThrowPerlException(exception,OptionError,"MissingGeometry",
2101                    SvPV(sval,na));
2102                  break;
2103                }
2104              (void) CloneString(&info->image_info->size,SvPV(sval,na));
2105            }
2106          break;
2107        }
2108      if (LocaleCompare(attribute,"stroke") == 0)
2109        {
2110          if (info)
2111            (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2112          break;
2113        }
2114      if (info)
2115        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2116      for ( ; image; image=image->next)
2117      {
2118        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2119        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2120      }
2121      break;
2122    }
2123    case 'T':
2124    case 't':
2125    {
2126      if (LocaleCompare(attribute,"texture") == 0)
2127        {
2128          if (info)
2129            (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2130          break;
2131        }
2132      if (LocaleCompare(attribute,"thread-limit") == 0)
2133        {
2134          MagickSizeType
2135            limit;
2136
2137          limit=MagickResourceInfinity;
2138          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2139            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2140              100.0);
2141          (void) SetMagickResourceLimit(ThreadResource,limit);
2142          break;
2143        }
2144      if (LocaleCompare(attribute,"tile") == 0)
2145        {
2146          if (info)
2147            (void) CloneString(&info->image_info->tile,SvPV(sval,na));
2148          break;
2149        }
2150      if (LocaleCompare(attribute,"tile-offset") == 0)
2151        {
2152          char
2153            *geometry;
2154
2155          geometry=GetPageGeometry(SvPV(sval,na));
2156          if (info)
2157            (void) CloneString(&info->image_info->page,geometry);
2158          for ( ; image; image=image->next)
2159            (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2160              exception);
2161          geometry=(char *) RelinquishMagickMemory(geometry);
2162          break;
2163        }
2164      if (LocaleCompare(attribute,"time-limit") == 0)
2165        {
2166          MagickSizeType
2167            limit;
2168
2169          limit=MagickResourceInfinity;
2170          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2171            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2172              100.0);
2173          (void) SetMagickResourceLimit(TimeResource,limit);
2174          break;
2175        }
2176      if (LocaleCompare(attribute,"transparent-color") == 0)
2177        {
2178          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2179          if (info)
2180            info->image_info->transparent_color=target_color;
2181          for ( ; image; image=image->next)
2182            image->transparent_color=target_color;
2183          break;
2184        }
2185      if (LocaleCompare(attribute,"type") == 0)
2186        {
2187          sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2188            SvPV(sval,na)) : SvIV(sval);
2189          if (sp < 0)
2190            {
2191              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2192                SvPV(sval,na));
2193              break;
2194            }
2195          if (info)
2196            info->image_info->type=(ImageType) sp;
2197          for ( ; image; image=image->next)
2198            SetImageType(image,(ImageType) sp);
2199          break;
2200        }
2201      if (info)
2202        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2203      for ( ; image; image=image->next)
2204      {
2205        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2206        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2207      }
2208      break;
2209    }
2210    case 'U':
2211    case 'u':
2212    {
2213      if (LocaleCompare(attribute,"units") == 0)
2214        {
2215          sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2216            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2217          if (sp < 0)
2218            {
2219              ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2220                SvPV(sval,na));
2221              break;
2222            }
2223          if (info)
2224            info->image_info->units=(ResolutionType) sp;
2225          for ( ; image; image=image->next)
2226          {
2227            ResolutionType
2228              units;
2229
2230            units=(ResolutionType) sp;
2231            if (image->units != units)
2232              switch (image->units)
2233              {
2234                case UndefinedResolution:
2235                case PixelsPerInchResolution:
2236                {
2237                  if (units == PixelsPerCentimeterResolution)
2238                    {
2239                      image->x_resolution*=2.54;
2240                      image->y_resolution*=2.54;
2241                    }
2242                  break;
2243                }
2244                case PixelsPerCentimeterResolution:
2245                {
2246                  if (units == PixelsPerInchResolution)
2247                    {
2248                      image->x_resolution/=2.54;
2249                      image->y_resolution/=2.54;
2250                    }
2251                  break;
2252                }
2253              }
2254            image->units=units;
2255          }
2256          break;
2257        }
2258      if (info)
2259        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2260      for ( ; image; image=image->next)
2261      {
2262        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2263        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2264      }
2265      break;
2266    }
2267    case 'V':
2268    case 'v':
2269    {
2270      if (LocaleCompare(attribute,"verbose") == 0)
2271        {
2272          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2273            SvPV(sval,na)) : SvIV(sval);
2274          if (sp < 0)
2275            {
2276              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2277                SvPV(sval,na));
2278              break;
2279            }
2280          if (info)
2281            info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2282          break;
2283        }
2284      if (LocaleCompare(attribute,"view") == 0)
2285        {
2286          if (info)
2287            (void) CloneString(&info->image_info->view,SvPV(sval,na));
2288          break;
2289        }
2290      if (LocaleCompare(attribute,"virtual-pixel") == 0)
2291        {
2292          sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2293            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2294          if (sp < 0)
2295            {
2296              ThrowPerlException(exception,OptionError,
2297                "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2298              break;
2299            }
2300          if (info)
2301            info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2302          for ( ; image; image=image->next)
2303            SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2304          break;
2305        }
2306      if (info)
2307        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2308      for ( ; image; image=image->next)
2309      {
2310        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2311        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2312      }
2313      break;
2314    }
2315    case 'W':
2316    case 'w':
2317    {
2318      if (LocaleCompare(attribute,"white-point") == 0)
2319        {
2320          for ( ; image; image=image->next)
2321          {
2322            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2323            image->chromaticity.white_point.x=geometry_info.rho;
2324            image->chromaticity.white_point.y=geometry_info.sigma;
2325            if ((flags & SigmaValue) == 0)
2326              image->chromaticity.white_point.y=
2327                image->chromaticity.white_point.x;
2328          }
2329          break;
2330        }
2331      if (info)
2332        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2333      for ( ; image; image=image->next)
2334      {
2335        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2336        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2337      }
2338      break;
2339    }
2340    default:
2341    {
2342      if (info)
2343        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2344      for ( ; image; image=image->next)
2345      {
2346        (void) SetImageProperty(image,attribute,SvPV(sval,na));
2347        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2348      }
2349      break;
2350    }
2351  }
2352}
2353
2354/*
2355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2356%                                                                             %
2357%                                                                             %
2358%                                                                             %
2359%   S e t u p L i s t                                                         %
2360%                                                                             %
2361%                                                                             %
2362%                                                                             %
2363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2364%
2365%  Method SetupList returns the list of all the images linked by their
2366%  image->next and image->previous link lists for use with ImageMagick.  If
2367%  info is non-NULL, an info structure is returned in *info.  If
2368%  reference_vector is non-NULL,an array of SV* are returned in
2369%  *reference_vector.  Reference_vector is used when the images are going to be
2370%  replaced with new Image*'s.
2371%
2372%  The format of the SetupList routine is:
2373%
2374%      Image *SetupList(SV *reference,struct PackageInfo **info,
2375%        SV ***reference_vector,ExceptionInfo *exception)
2376%
2377%  A description of each parameter follows:
2378%
2379%    o list: a list of strings.
2380%
2381%    o string: a character string.
2382%
2383%    o exception: Return any errors or warnings in this structure.
2384%
2385*/
2386static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2387  SV ***reference_vector,ExceptionInfo *exception)
2388{
2389  Image
2390    *image;
2391
2392  ssize_t
2393    current,
2394    last;
2395
2396  if (reference_vector)
2397    *reference_vector=NULL;
2398  if (info)
2399    *info=NULL;
2400  current=0;
2401  last=0;
2402  image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2403  if (info && (SvTYPE(reference) == SVt_PVAV))
2404    *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2405      exception);
2406  return(image);
2407}
2408
2409/*
2410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2411%                                                                             %
2412%                                                                             %
2413%                                                                             %
2414%   s t r E Q c a s e                                                         %
2415%                                                                             %
2416%                                                                             %
2417%                                                                             %
2418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2419%
2420%  strEQcase() compares two strings and returns 0 if they are the
2421%  same or if the second string runs out first.  The comparison is case
2422%  insensitive.
2423%
2424%  The format of the strEQcase routine is:
2425%
2426%      ssize_t strEQcase(const char *p,const char *q)
2427%
2428%  A description of each parameter follows:
2429%
2430%    o p: a character string.
2431%
2432%    o q: a character string.
2433%
2434%
2435*/
2436static ssize_t strEQcase(const char *p,const char *q)
2437{
2438  char
2439    c;
2440
2441  ssize_t
2442    i;
2443
2444  for (i=0 ; (c=(*q)) != 0; i++)
2445  {
2446    if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2447        (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2448      return(0);
2449    p++;
2450    q++;
2451  }
2452  return(((*q == 0) && (*p == 0)) ? i : 0);
2453}
2454
2455/*
2456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2457%                                                                             %
2458%                                                                             %
2459%                                                                             %
2460%   I m a g e : : M a g i c k                                                 %
2461%                                                                             %
2462%                                                                             %
2463%                                                                             %
2464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2465%
2466%
2467*/
2468MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2469
2470PROTOTYPES: ENABLE
2471
2472BOOT:
2473  MagickCoreGenesis("PerlMagick",MagickFalse);
2474  SetWarningHandler(NULL);
2475  SetErrorHandler(NULL);
2476  magick_registry=NewSplayTree((int (*)(const void *,const void *))
2477    NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2478
2479void
2480UNLOAD()
2481  PPCODE:
2482  {
2483    if (magick_registry != (SplayTreeInfo *) NULL)
2484      magick_registry=DestroySplayTree(magick_registry);
2485    MagickCoreTerminus();
2486  }
2487
2488double
2489constant(name,argument)
2490  char *name
2491  ssize_t argument
2492
2493#
2494###############################################################################
2495#                                                                             #
2496#                                                                             #
2497#                                                                             #
2498#   A n i m a t e                                                             #
2499#                                                                             #
2500#                                                                             #
2501#                                                                             #
2502###############################################################################
2503#
2504#
2505void
2506Animate(ref,...)
2507  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2508  ALIAS:
2509    AnimateImage  = 1
2510    animate       = 2
2511    animateimage  = 3
2512  PPCODE:
2513  {
2514    ExceptionInfo
2515      *exception;
2516
2517    Image
2518      *image;
2519
2520    ssize_t
2521      i;
2522
2523    struct PackageInfo
2524      *info,
2525      *package_info;
2526
2527    SV
2528      *perl_exception,
2529      *reference;
2530
2531    PERL_UNUSED_VAR(ref);
2532    PERL_UNUSED_VAR(ix);
2533    exception=AcquireExceptionInfo();
2534    perl_exception=newSVpv("",0);
2535    package_info=(struct PackageInfo *) NULL;
2536    if (sv_isobject(ST(0)) == 0)
2537      {
2538        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2539          PackageName);
2540        goto PerlException;
2541      }
2542    reference=SvRV(ST(0));
2543    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2544    if (image == (Image *) NULL)
2545      {
2546        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2547          PackageName);
2548        goto PerlException;
2549      }
2550    package_info=ClonePackageInfo(info,exception);
2551    if (items == 2)
2552      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2553    else
2554      if (items > 2)
2555        for (i=2; i < items; i+=2)
2556          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2557            exception);
2558    (void) AnimateImages(package_info->image_info,image);
2559    (void) CatchImageException(image);
2560    InheritException(exception,&image->exception);
2561
2562  PerlException:
2563    if (package_info != (struct PackageInfo *) NULL)
2564      DestroyPackageInfo(package_info);
2565    InheritPerlException(exception,perl_exception);
2566    exception=DestroyExceptionInfo(exception);
2567    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2568    SvPOK_on(perl_exception);
2569    ST(0)=sv_2mortal(perl_exception);
2570    XSRETURN(1);
2571  }
2572
2573#
2574###############################################################################
2575#                                                                             #
2576#                                                                             #
2577#                                                                             #
2578#   A p p e n d                                                               #
2579#                                                                             #
2580#                                                                             #
2581#                                                                             #
2582###############################################################################
2583#
2584#
2585void
2586Append(ref,...)
2587  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2588  ALIAS:
2589    AppendImage  = 1
2590    append       = 2
2591    appendimage  = 3
2592  PPCODE:
2593  {
2594    AV
2595      *av;
2596
2597    char
2598      *attribute;
2599
2600    ExceptionInfo
2601      *exception;
2602
2603    HV
2604      *hv;
2605
2606    Image
2607      *image;
2608
2609    ssize_t
2610      i;
2611
2612    ssize_t
2613      stack;
2614
2615    struct PackageInfo
2616      *info;
2617
2618    SV
2619      *av_reference,
2620      *perl_exception,
2621      *reference,
2622      *rv,
2623      *sv;
2624
2625    PERL_UNUSED_VAR(ref);
2626    PERL_UNUSED_VAR(ix);
2627    exception=AcquireExceptionInfo();
2628    perl_exception=newSVpv("",0);
2629    sv=NULL;
2630    attribute=NULL;
2631    av=NULL;
2632    if (sv_isobject(ST(0)) == 0)
2633      {
2634        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2635          PackageName);
2636        goto PerlException;
2637      }
2638    reference=SvRV(ST(0));
2639    hv=SvSTASH(reference);
2640    av=newAV();
2641    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2642    SvREFCNT_dec(av);
2643    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2644    if (image == (Image *) NULL)
2645      {
2646        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2647          PackageName);
2648        goto PerlException;
2649      }
2650    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2651    /*
2652      Get options.
2653    */
2654    stack=MagickTrue;
2655    for (i=2; i < items; i+=2)
2656    {
2657      attribute=(char *) SvPV(ST(i-1),na);
2658      switch (*attribute)
2659      {
2660        case 'S':
2661        case 's':
2662        {
2663          if (LocaleCompare(attribute,"stack") == 0)
2664            {
2665              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2666                SvPV(ST(i),na));
2667              if (stack < 0)
2668                {
2669                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
2670                    SvPV(ST(i),na));
2671                  return;
2672                }
2673              break;
2674            }
2675          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2676            attribute);
2677          break;
2678        }
2679        default:
2680        {
2681          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2682            attribute);
2683          break;
2684        }
2685      }
2686    }
2687    image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2688    if (image == (Image *) NULL)
2689      goto PerlException;
2690    for ( ; image; image=image->next)
2691    {
2692      AddImageToRegistry(sv,image);
2693      rv=newRV(sv);
2694      av_push(av,sv_bless(rv,hv));
2695      SvREFCNT_dec(sv);
2696    }
2697    exception=DestroyExceptionInfo(exception);
2698    ST(0)=av_reference;
2699    SvREFCNT_dec(perl_exception);
2700    XSRETURN(1);
2701
2702  PerlException:
2703    InheritPerlException(exception,perl_exception);
2704    exception=DestroyExceptionInfo(exception);
2705    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2706    SvPOK_on(perl_exception);
2707    ST(0)=sv_2mortal(perl_exception);
2708    XSRETURN(1);
2709  }
2710
2711#
2712###############################################################################
2713#                                                                             #
2714#                                                                             #
2715#                                                                             #
2716#   A v e r a g e                                                             #
2717#                                                                             #
2718#                                                                             #
2719#                                                                             #
2720###############################################################################
2721#
2722#
2723void
2724Average(ref)
2725  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2726  ALIAS:
2727    AverageImage   = 1
2728    average        = 2
2729    averageimage   = 3
2730  PPCODE:
2731  {
2732    AV
2733      *av;
2734
2735    char
2736      *p;
2737
2738    ExceptionInfo
2739      *exception;
2740
2741    HV
2742      *hv;
2743
2744    Image
2745      *image;
2746
2747    struct PackageInfo
2748      *info;
2749
2750    SV
2751      *perl_exception,
2752      *reference,
2753      *rv,
2754      *sv;
2755
2756    PERL_UNUSED_VAR(ref);
2757    PERL_UNUSED_VAR(ix);
2758    exception=AcquireExceptionInfo();
2759    perl_exception=newSVpv("",0);
2760    sv=NULL;
2761    if (sv_isobject(ST(0)) == 0)
2762      {
2763        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2764          PackageName);
2765        goto PerlException;
2766      }
2767    reference=SvRV(ST(0));
2768    hv=SvSTASH(reference);
2769    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2770    if (image == (Image *) NULL)
2771      {
2772        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2773          PackageName);
2774        goto PerlException;
2775      }
2776    image=EvaluateImages(image,MeanEvaluateOperator,exception);
2777    if (image == (Image *) NULL)
2778      goto PerlException;
2779    /*
2780      Create blessed Perl array for the returned image.
2781    */
2782    av=newAV();
2783    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2784    SvREFCNT_dec(av);
2785    AddImageToRegistry(sv,image);
2786    rv=newRV(sv);
2787    av_push(av,sv_bless(rv,hv));
2788    SvREFCNT_dec(sv);
2789    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2790    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2791      "average-%.*s",(int) (MaxTextExtent-9),
2792      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2793    (void) CopyMagickString(image->filename,info->image_info->filename,
2794      MaxTextExtent);
2795    SetImageInfo(info->image_info,0,exception);
2796    exception=DestroyExceptionInfo(exception);
2797    SvREFCNT_dec(perl_exception);
2798    XSRETURN(1);
2799
2800  PerlException:
2801    InheritPerlException(exception,perl_exception);
2802    exception=DestroyExceptionInfo(exception);
2803    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2804    SvPOK_on(perl_exception);
2805    ST(0)=sv_2mortal(perl_exception);
2806    XSRETURN(1);
2807  }
2808
2809#
2810###############################################################################
2811#                                                                             #
2812#                                                                             #
2813#                                                                             #
2814#   B l o b T o I m a g e                                                     #
2815#                                                                             #
2816#                                                                             #
2817#                                                                             #
2818###############################################################################
2819#
2820#
2821void
2822BlobToImage(ref,...)
2823  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2824  ALIAS:
2825    BlobToImage  = 1
2826    blobtoimage  = 2
2827    blobto       = 3
2828  PPCODE:
2829  {
2830    AV
2831      *av;
2832
2833    char
2834      **keep,
2835      **list;
2836
2837    ExceptionInfo
2838      *exception;
2839
2840    HV
2841      *hv;
2842
2843    Image
2844      *image;
2845
2846    char
2847      **p;
2848
2849    ssize_t
2850      i;
2851
2852    ssize_t
2853      ac,
2854      n,
2855      number_images;
2856
2857    STRLEN
2858      *length;
2859
2860    struct PackageInfo
2861      *info;
2862
2863    SV
2864      *perl_exception,
2865      *reference,
2866      *rv,
2867      *sv;
2868
2869    PERL_UNUSED_VAR(ref);
2870    PERL_UNUSED_VAR(ix);
2871    exception=AcquireExceptionInfo();
2872    perl_exception=newSVpv("",0);
2873    sv=NULL;
2874    number_images=0;
2875    ac=(items < 2) ? 1 : items-1;
2876    length=(STRLEN *) NULL;
2877    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2878    if (list == (char **) NULL)
2879      {
2880        ThrowPerlException(exception,ResourceLimitError,
2881          "MemoryAllocationFailed",PackageName);
2882        goto PerlException;
2883      }
2884    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2885    if (length == (STRLEN *) NULL)
2886      {
2887        ThrowPerlException(exception,ResourceLimitError,
2888          "MemoryAllocationFailed",PackageName);
2889        goto PerlException;
2890      }
2891    if (sv_isobject(ST(0)) == 0)
2892      {
2893        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2894          PackageName);
2895        goto PerlException;
2896      }
2897    reference=SvRV(ST(0));
2898    hv=SvSTASH(reference);
2899    if (SvTYPE(reference) != SVt_PVAV)
2900      {
2901        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2902          PackageName);
2903        goto PerlException;
2904      }
2905    av=(AV *) reference;
2906    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2907      exception);
2908    n=1;
2909    if (items <= 1)
2910      {
2911        ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2912        goto PerlException;
2913      }
2914    for (n=0, i=0; i < ac; i++)
2915    {
2916      list[n]=(char *) (SvPV(ST(i+1),length[n]));
2917      if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2918        {
2919          list[n]=(char *) (SvPV(ST(i+2),length[n]));
2920          continue;
2921        }
2922      n++;
2923    }
2924    list[n]=(char *) NULL;
2925    keep=list;
2926    for (i=number_images=0; i < n; i++)
2927    {
2928      image=BlobToImage(info->image_info,list[i],length[i],exception);
2929      if (image == (Image *) NULL)
2930        break;
2931      for ( ; image; image=image->next)
2932      {
2933        AddImageToRegistry(sv,image);
2934        rv=newRV(sv);
2935        av_push(av,sv_bless(rv,hv));
2936        SvREFCNT_dec(sv);
2937        number_images++;
2938      }
2939    }
2940    /*
2941      Free resources.
2942    */
2943    for (i=0; i < n; i++)
2944      if (list[i] != (char *) NULL)
2945        for (p=keep; list[i] != *p++; )
2946          if (*p == (char *) NULL)
2947            {
2948              list[i]=(char *) RelinquishMagickMemory(list[i]);
2949              break;
2950            }
2951
2952  PerlException:
2953    if (list)
2954      list=(char **) RelinquishMagickMemory(list);
2955    if (length)
2956      length=(STRLEN *) RelinquishMagickMemory(length);
2957    InheritPerlException(exception,perl_exception);
2958    exception=DestroyExceptionInfo(exception);
2959    sv_setiv(perl_exception,(IV) number_images);
2960    SvPOK_on(perl_exception);
2961    ST(0)=sv_2mortal(perl_exception);
2962    XSRETURN(1);
2963  }
2964
2965#
2966###############################################################################
2967#                                                                             #
2968#                                                                             #
2969#                                                                             #
2970#   C l o n e                                                                 #
2971#                                                                             #
2972#                                                                             #
2973#                                                                             #
2974###############################################################################
2975#
2976#
2977void
2978Clone(ref)
2979  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2980  ALIAS:
2981    CopyImage   = 1
2982    copy        = 2
2983    copyimage   = 3
2984    CloneImage  = 4
2985    clone       = 5
2986    cloneimage  = 6
2987    Clone       = 7
2988  PPCODE:
2989  {
2990    AV
2991      *av;
2992
2993    ExceptionInfo
2994      *exception;
2995
2996    HV
2997      *hv;
2998
2999    Image
3000      *clone,
3001      *image;
3002
3003    struct PackageInfo
3004      *info;
3005
3006    SV
3007      *perl_exception,
3008      *reference,
3009      *rv,
3010      *sv;
3011
3012    PERL_UNUSED_VAR(ref);
3013    PERL_UNUSED_VAR(ix);
3014    exception=AcquireExceptionInfo();
3015    perl_exception=newSVpv("",0);
3016    sv=NULL;
3017    if (sv_isobject(ST(0)) == 0)
3018      {
3019        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3020          PackageName);
3021        goto PerlException;
3022      }
3023    reference=SvRV(ST(0));
3024    hv=SvSTASH(reference);
3025    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3026    if (image == (Image *) NULL)
3027      {
3028        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3029          PackageName);
3030        goto PerlException;
3031      }
3032    /*
3033      Create blessed Perl array for the returned image.
3034    */
3035    av=newAV();
3036    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3037    SvREFCNT_dec(av);
3038    for ( ; image; image=image->next)
3039    {
3040      clone=CloneImage(image,0,0,MagickTrue,exception);
3041      if (clone == (Image *) NULL)
3042        break;
3043      AddImageToRegistry(sv,clone);
3044      rv=newRV(sv);
3045      av_push(av,sv_bless(rv,hv));
3046      SvREFCNT_dec(sv);
3047    }
3048    exception=DestroyExceptionInfo(exception);
3049    SvREFCNT_dec(perl_exception);
3050    XSRETURN(1);
3051
3052  PerlException:
3053    InheritPerlException(exception,perl_exception);
3054    exception=DestroyExceptionInfo(exception);
3055    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3056    SvPOK_on(perl_exception);
3057    ST(0)=sv_2mortal(perl_exception);
3058    XSRETURN(1);
3059  }
3060
3061#
3062###############################################################################
3063#                                                                             #
3064#                                                                             #
3065#                                                                             #
3066#   C L O N E                                                                 #
3067#                                                                             #
3068#                                                                             #
3069#                                                                             #
3070###############################################################################
3071#
3072#
3073void
3074CLONE(ref,...)
3075  SV *ref;
3076  CODE:
3077  {
3078    PERL_UNUSED_VAR(ref);
3079    if (magick_registry != (SplayTreeInfo *) NULL)
3080      {
3081        Image
3082          *p;
3083
3084        ResetSplayTreeIterator(magick_registry);
3085        p=(Image *) GetNextKeyInSplayTree(magick_registry);
3086        while (p != (Image *) NULL)
3087        {
3088          ReferenceImage(p);
3089          p=(Image *) GetNextKeyInSplayTree(magick_registry);
3090        }
3091      }
3092  }
3093
3094#
3095###############################################################################
3096#                                                                             #
3097#                                                                             #
3098#                                                                             #
3099#   C o a l e s c e                                                           #
3100#                                                                             #
3101#                                                                             #
3102#                                                                             #
3103###############################################################################
3104#
3105#
3106void
3107Coalesce(ref)
3108  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3109  ALIAS:
3110    CoalesceImage   = 1
3111    coalesce        = 2
3112    coalesceimage   = 3
3113  PPCODE:
3114  {
3115    AV
3116      *av;
3117
3118    ExceptionInfo
3119      *exception;
3120
3121    HV
3122      *hv;
3123
3124    Image
3125      *image;
3126
3127    struct PackageInfo
3128      *info;
3129
3130    SV
3131      *av_reference,
3132      *perl_exception,
3133      *reference,
3134      *rv,
3135      *sv;
3136
3137    PERL_UNUSED_VAR(ref);
3138    PERL_UNUSED_VAR(ix);
3139    exception=AcquireExceptionInfo();
3140    perl_exception=newSVpv("",0);
3141    sv=NULL;
3142    if (sv_isobject(ST(0)) == 0)
3143      {
3144        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3145          PackageName);
3146        goto PerlException;
3147      }
3148    reference=SvRV(ST(0));
3149    hv=SvSTASH(reference);
3150    av=newAV();
3151    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3152    SvREFCNT_dec(av);
3153    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3154    if (image == (Image *) NULL)
3155      {
3156        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3157          PackageName);
3158        goto PerlException;
3159      }
3160    image=CoalesceImages(image,exception);
3161    if (image == (Image *) NULL)
3162      goto PerlException;
3163    for ( ; image; image=image->next)
3164    {
3165      AddImageToRegistry(sv,image);
3166      rv=newRV(sv);
3167      av_push(av,sv_bless(rv,hv));
3168      SvREFCNT_dec(sv);
3169    }
3170    exception=DestroyExceptionInfo(exception);
3171    ST(0)=av_reference;
3172    SvREFCNT_dec(perl_exception);
3173    XSRETURN(1);
3174
3175  PerlException:
3176    InheritPerlException(exception,perl_exception);
3177    exception=DestroyExceptionInfo(exception);
3178    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3179    SvPOK_on(perl_exception);
3180    ST(0)=sv_2mortal(perl_exception);
3181    XSRETURN(1);
3182  }
3183
3184#
3185###############################################################################
3186#                                                                             #
3187#                                                                             #
3188#                                                                             #
3189#   C o m p a r e                                                             #
3190#                                                                             #
3191#                                                                             #
3192#                                                                             #
3193###############################################################################
3194#
3195#
3196void
3197Compare(ref,...)
3198  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3199  ALIAS:
3200    CompareImage = 1
3201    compare      = 2
3202    compareimage = 3
3203  PPCODE:
3204  {
3205    AV
3206      *av;
3207
3208    char
3209      *attribute;
3210
3211    ChannelType
3212      channel;
3213
3214    double
3215      distortion;
3216
3217    ExceptionInfo
3218      *exception;
3219
3220    HV
3221      *hv;
3222
3223    Image
3224      *difference_image,
3225      *image,
3226      *reconstruct_image;
3227
3228    MetricType
3229      metric;
3230
3231    ssize_t
3232      i;
3233
3234    ssize_t
3235      option;
3236
3237    struct PackageInfo
3238      *info;
3239
3240    SV
3241      *av_reference,
3242      *perl_exception,
3243      *reference,
3244      *rv,
3245      *sv;
3246
3247    PERL_UNUSED_VAR(ref);
3248    PERL_UNUSED_VAR(ix);
3249    exception=AcquireExceptionInfo();
3250    perl_exception=newSVpv("",0);
3251    sv=NULL;
3252    av=NULL;
3253    attribute=NULL;
3254    if (sv_isobject(ST(0)) == 0)
3255      {
3256        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3257          PackageName);
3258        goto PerlException;
3259      }
3260    reference=SvRV(ST(0));
3261    hv=SvSTASH(reference);
3262    av=newAV();
3263    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3264    SvREFCNT_dec(av);
3265    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3266    if (image == (Image *) NULL)
3267      {
3268        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3269          PackageName);
3270        goto PerlException;
3271      }
3272    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3273    /*
3274      Get attribute.
3275    */
3276    channel=DefaultChannels;
3277    reconstruct_image=image;
3278    metric=RootMeanSquaredErrorMetric;
3279    for (i=2; i < items; i+=2)
3280    {
3281      attribute=(char *) SvPV(ST(i-1),na);
3282      switch (*attribute)
3283      {
3284        case 'C':
3285        case 'c':
3286        {
3287          if (LocaleCompare(attribute,"channel") == 0)
3288            {
3289              ssize_t
3290                option;
3291
3292              option=ParseChannelOption(SvPV(ST(i),na));
3293              if (option < 0)
3294                {
3295                  ThrowPerlException(exception,OptionError,
3296                    "UnrecognizedType",SvPV(ST(i),na));
3297                  return;
3298                }
3299              channel=(ChannelType) option;
3300              break;
3301            }
3302          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3303            attribute);
3304          break;
3305        }
3306        case 'F':
3307        case 'f':
3308        {
3309          if (LocaleCompare(attribute,"fuzz") == 0)
3310            {
3311              image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3312              break;
3313            }
3314          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3315            attribute);
3316          break;
3317        }
3318        case 'I':
3319        case 'i':
3320        {
3321          if (LocaleCompare(attribute,"image") == 0)
3322            {
3323              reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3324                (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3325              break;
3326            }
3327          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3328            attribute);
3329          break;
3330        }
3331        case 'M':
3332        case 'm':
3333        {
3334          if (LocaleCompare(attribute,"metric") == 0)
3335            {
3336              option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3337                SvPV(ST(i),na));
3338              if (option < 0)
3339                {
3340                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3341                    SvPV(ST(i),na));
3342                  break;
3343                }
3344              metric=(MetricType) option;
3345              break;
3346            }
3347          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3348            attribute);
3349          break;
3350        }
3351        default:
3352        {
3353          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3354            attribute);
3355          break;
3356        }
3357      }
3358    }
3359    difference_image=CompareImageChannels(image,reconstruct_image,channel,
3360      metric,&distortion,exception);
3361    if (difference_image != (Image *) NULL)
3362      {
3363        difference_image->error.mean_error_per_pixel=distortion;
3364        AddImageToRegistry(sv,difference_image);
3365        rv=newRV(sv);
3366        av_push(av,sv_bless(rv,hv));
3367        SvREFCNT_dec(sv);
3368      }
3369    exception=DestroyExceptionInfo(exception);
3370    ST(0)=av_reference;
3371    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3372    XSRETURN(1);
3373
3374  PerlException:
3375    InheritPerlException(exception,perl_exception);
3376    exception=DestroyExceptionInfo(exception);
3377    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3378    SvPOK_on(perl_exception);
3379    ST(0)=sv_2mortal(perl_exception);
3380    XSRETURN(1);
3381  }
3382
3383#
3384###############################################################################
3385#                                                                             #
3386#                                                                             #
3387#                                                                             #
3388#   C o m p a r e L a y e r s                                                 #
3389#                                                                             #
3390#                                                                             #
3391#                                                                             #
3392###############################################################################
3393#
3394#
3395void
3396CompareLayers(ref,...)
3397  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3398  ALIAS:
3399    CompareImageLayers   = 1
3400    comparelayers        = 2
3401    compareimagelayers   = 3
3402  PPCODE:
3403  {
3404    AV
3405      *av;
3406
3407    char
3408      *attribute;
3409
3410    ExceptionInfo
3411      *exception;
3412
3413    HV
3414      *hv;
3415
3416    Image
3417      *image;
3418
3419    ImageLayerMethod
3420      method;
3421
3422    ssize_t
3423      i;
3424
3425    ssize_t
3426      option;
3427
3428    struct PackageInfo
3429      *info;
3430
3431    SV
3432      *av_reference,
3433      *perl_exception,
3434      *reference,
3435      *rv,
3436      *sv;
3437
3438    PERL_UNUSED_VAR(ref);
3439    PERL_UNUSED_VAR(ix);
3440    exception=AcquireExceptionInfo();
3441    perl_exception=newSVpv("",0);
3442    sv=NULL;
3443    if (sv_isobject(ST(0)) == 0)
3444      {
3445        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3446          PackageName);
3447        goto PerlException;
3448      }
3449    reference=SvRV(ST(0));
3450    hv=SvSTASH(reference);
3451    av=newAV();
3452    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3453    SvREFCNT_dec(av);
3454    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3455    if (image == (Image *) NULL)
3456      {
3457        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3458          PackageName);
3459        goto PerlException;
3460      }
3461    method=CompareAnyLayer;
3462    for (i=2; i < items; i+=2)
3463    {
3464      attribute=(char *) SvPV(ST(i-1),na);
3465      switch (*attribute)
3466      {
3467        case 'M':
3468        case 'm':
3469        {
3470          if (LocaleCompare(attribute,"method") == 0)
3471            {
3472              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3473                SvPV(ST(i),na));
3474              if (option < 0)
3475                {
3476                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3477                    SvPV(ST(i),na));
3478                  break;
3479                }
3480               method=(ImageLayerMethod) option;
3481              break;
3482            }
3483          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3484            attribute);
3485          break;
3486        }
3487        default:
3488        {
3489          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3490            attribute);
3491          break;
3492        }
3493      }
3494    }
3495    image=CompareImageLayers(image,method,exception);
3496    if (image == (Image *) NULL)
3497      goto PerlException;
3498    for ( ; image; image=image->next)
3499    {
3500      AddImageToRegistry(sv,image);
3501      rv=newRV(sv);
3502      av_push(av,sv_bless(rv,hv));
3503      SvREFCNT_dec(sv);
3504    }
3505    exception=DestroyExceptionInfo(exception);
3506    ST(0)=av_reference;
3507    SvREFCNT_dec(perl_exception);
3508    XSRETURN(1);
3509
3510  PerlException:
3511    InheritPerlException(exception,perl_exception);
3512    exception=DestroyExceptionInfo(exception);
3513    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3514    SvPOK_on(perl_exception);
3515    ST(0)=sv_2mortal(perl_exception);
3516    XSRETURN(1);
3517  }
3518
3519#
3520###############################################################################
3521#                                                                             #
3522#                                                                             #
3523#                                                                             #
3524#   C o m p l e x I m a g e s                                                 #
3525#                                                                             #
3526#                                                                             #
3527#                                                                             #
3528###############################################################################
3529#
3530#
3531void
3532ComplexImages(ref,...)
3533  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3534  ALIAS:
3535    ComplexImages   = 1
3536    compleximages   = 2
3537  PPCODE:
3538  {
3539    AV
3540      *av;
3541
3542    char
3543      *attribute,
3544      *p;
3545
3546    ExceptionInfo
3547      *exception;
3548
3549    HV
3550      *hv;
3551
3552    Image
3553      *image;
3554
3555    ComplexOperator
3556      op;
3557
3558    ssize_t
3559      i;
3560
3561    struct PackageInfo
3562      *info;
3563
3564    SV
3565      *perl_exception,
3566      *reference,
3567      *rv,
3568      *sv;
3569
3570    PERL_UNUSED_VAR(ref);
3571    PERL_UNUSED_VAR(ix);
3572    exception=AcquireExceptionInfo();
3573    perl_exception=newSVpv("",0);
3574    sv=NULL;
3575    if (sv_isobject(ST(0)) == 0)
3576      {
3577        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3578          PackageName);
3579        goto PerlException;
3580      }
3581    reference=SvRV(ST(0));
3582    hv=SvSTASH(reference);
3583    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3584    if (image == (Image *) NULL)
3585      {
3586        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3587          PackageName);
3588        goto PerlException;
3589      }
3590    op=UndefinedComplexOperator;
3591    if (items == 2)
3592      {
3593        ssize_t
3594          in;
3595
3596        in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3597          SvPV(ST(1),na));
3598        if (in < 0)
3599          {
3600            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3601              SvPV(ST(1),na));
3602            return;
3603          }
3604        op=(ComplexOperator) in;
3605      }
3606    else
3607      for (i=2; i < items; i+=2)
3608      {
3609        attribute=(char *) SvPV(ST(i-1),na);
3610        switch (*attribute)
3611        {
3612          case 'O':
3613          case 'o':
3614          {
3615            if (LocaleCompare(attribute,"operator") == 0)
3616              {
3617                ssize_t
3618                  in;
3619
3620                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3621                  MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3622                if (in < 0)
3623                  {
3624                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
3625                      SvPV(ST(i),na));
3626                    return;
3627                  }
3628                op=(ComplexOperator) in;
3629                break;
3630              }
3631            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3632              attribute);
3633            break;
3634          }
3635          default:
3636          {
3637            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3638              attribute);
3639            break;
3640          }
3641        }
3642      }
3643    image=ComplexImages(image,op,exception);
3644    if (image == (Image *) NULL)
3645      goto PerlException;
3646    /*
3647      Create blessed Perl array for the returned image.
3648    */
3649    av=newAV();
3650    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3651    SvREFCNT_dec(av);
3652    AddImageToRegistry(sv,image);
3653    rv=newRV(sv);
3654    av_push(av,sv_bless(rv,hv));
3655    SvREFCNT_dec(sv);
3656    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3657    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3658      "complex-%.*s",(int) (MaxTextExtent-9),
3659      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3660    (void) CopyMagickString(image->filename,info->image_info->filename,
3661      MaxTextExtent);
3662    SetImageInfo(info->image_info,0,exception);
3663    exception=DestroyExceptionInfo(exception);
3664    SvREFCNT_dec(perl_exception);
3665    XSRETURN(1);
3666
3667  PerlException:
3668    InheritPerlException(exception,perl_exception);
3669    exception=DestroyExceptionInfo(exception);
3670    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3671    SvPOK_on(perl_exception);
3672    ST(0)=sv_2mortal(perl_exception);
3673    XSRETURN(1);
3674  }
3675
3676#
3677###############################################################################
3678#                                                                             #
3679#                                                                             #
3680#                                                                             #
3681#   D e s t r o y                                                             #
3682#                                                                             #
3683#                                                                             #
3684#                                                                             #
3685###############################################################################
3686#
3687#
3688void
3689DESTROY(ref)
3690  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3691  PPCODE:
3692  {
3693    SV
3694      *reference;
3695
3696    PERL_UNUSED_VAR(ref);
3697    if (sv_isobject(ST(0)) == 0)
3698      croak("ReferenceIsNotMyType");
3699    reference=SvRV(ST(0));
3700    switch (SvTYPE(reference))
3701    {
3702      case SVt_PVAV:
3703      {
3704        char
3705          message[MaxTextExtent];
3706
3707        const SV
3708          *key;
3709
3710        HV
3711          *hv;
3712
3713        GV
3714          **gvp;
3715
3716        struct PackageInfo
3717          *info;
3718
3719        SV
3720          *sv;
3721
3722        /*
3723          Array (AV *) reference
3724        */
3725        (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3726          XS_VERSION,reference);
3727        hv=gv_stashpv(PackageName, FALSE);
3728        if (!hv)
3729          break;
3730        gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3731        if (!gvp)
3732          break;
3733        sv=GvSV(*gvp);
3734        if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3735          {
3736            info=INT2PTR(struct PackageInfo *,SvIV(sv));
3737            DestroyPackageInfo(info);
3738          }
3739        key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3740        (void) key;
3741        break;
3742      }
3743      case SVt_PVMG:
3744      {
3745        Image
3746          *image;
3747
3748        /*
3749          Blessed scalar = (Image *) SvIV(reference)
3750        */
3751        image=INT2PTR(Image *,SvIV(reference));
3752        if (image != (Image *) NULL)
3753          DeleteImageFromRegistry(reference,image);
3754        break;
3755      }
3756      default:
3757        break;
3758    }
3759  }
3760
3761#
3762###############################################################################
3763#                                                                             #
3764#                                                                             #
3765#                                                                             #
3766#   D i s p l a y                                                             #
3767#                                                                             #
3768#                                                                             #
3769#                                                                             #
3770###############################################################################
3771#
3772#
3773void
3774Display(ref,...)
3775  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3776  ALIAS:
3777    DisplayImage  = 1
3778    display       = 2
3779    displayimage  = 3
3780  PPCODE:
3781  {
3782    ExceptionInfo
3783      *exception;
3784
3785    Image
3786      *image;
3787
3788    ssize_t
3789      i;
3790
3791    struct PackageInfo
3792      *info,
3793      *package_info;
3794
3795    SV
3796      *perl_exception,
3797      *reference;
3798
3799    PERL_UNUSED_VAR(ref);
3800    PERL_UNUSED_VAR(ix);
3801    exception=AcquireExceptionInfo();
3802    perl_exception=newSVpv("",0);
3803    package_info=(struct PackageInfo *) NULL;
3804    if (sv_isobject(ST(0)) == 0)
3805      {
3806        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3807          PackageName);
3808        goto PerlException;
3809      }
3810    reference=SvRV(ST(0));
3811    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3812    if (image == (Image *) NULL)
3813      {
3814        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3815          PackageName);
3816        goto PerlException;
3817      }
3818    package_info=ClonePackageInfo(info,exception);
3819    if (items == 2)
3820      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3821    else
3822      if (items > 2)
3823        for (i=2; i < items; i+=2)
3824          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3825            exception);
3826    (void) DisplayImages(package_info->image_info,image);
3827    (void) CatchImageException(image);
3828    InheritException(exception,&image->exception);
3829
3830  PerlException:
3831    if (package_info != (struct PackageInfo *) NULL)
3832      DestroyPackageInfo(package_info);
3833    InheritPerlException(exception,perl_exception);
3834    exception=DestroyExceptionInfo(exception);
3835    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3836    SvPOK_on(perl_exception);
3837    ST(0)=sv_2mortal(perl_exception);
3838    XSRETURN(1);
3839  }
3840
3841#
3842###############################################################################
3843#                                                                             #
3844#                                                                             #
3845#                                                                             #
3846#   E v a l u a t e I m a g e s                                               #
3847#                                                                             #
3848#                                                                             #
3849#                                                                             #
3850###############################################################################
3851#
3852#
3853void
3854EvaluateImages(ref,...)
3855  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3856  ALIAS:
3857    EvaluateImages   = 1
3858    evaluateimages   = 2
3859  PPCODE:
3860  {
3861    AV
3862      *av;
3863
3864    char
3865      *attribute,
3866      *p;
3867
3868    ExceptionInfo
3869      *exception;
3870
3871    HV
3872      *hv;
3873
3874    Image
3875      *image;
3876
3877    MagickEvaluateOperator
3878      op;
3879
3880    ssize_t
3881      i;
3882
3883    struct PackageInfo
3884      *info;
3885
3886    SV
3887      *perl_exception,
3888      *reference,
3889      *rv,
3890      *sv;
3891
3892    PERL_UNUSED_VAR(ref);
3893    PERL_UNUSED_VAR(ix);
3894    exception=AcquireExceptionInfo();
3895    perl_exception=newSVpv("",0);
3896    sv=NULL;
3897    if (sv_isobject(ST(0)) == 0)
3898      {
3899        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3900          PackageName);
3901        goto PerlException;
3902      }
3903    reference=SvRV(ST(0));
3904    hv=SvSTASH(reference);
3905    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3906    if (image == (Image *) NULL)
3907      {
3908        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3909          PackageName);
3910        goto PerlException;
3911      }
3912    op=MeanEvaluateOperator;
3913    if (items == 2)
3914      {
3915        ssize_t
3916          in;
3917
3918        in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3919          SvPV(ST(1),na));
3920        if (in < 0)
3921          {
3922            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3923              SvPV(ST(1),na));
3924            return;
3925          }
3926        op=(MagickEvaluateOperator) in;
3927      }
3928    else
3929      for (i=2; i < items; i+=2)
3930      {
3931        attribute=(char *) SvPV(ST(i-1),na);
3932        switch (*attribute)
3933        {
3934          case 'O':
3935          case 'o':
3936          {
3937            if (LocaleCompare(attribute,"operator") == 0)
3938              {
3939                ssize_t
3940                  in;
3941
3942                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3943                  MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3944                if (in < 0)
3945                  {
3946                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
3947                      SvPV(ST(i),na));
3948                    return;
3949                  }
3950                op=(MagickEvaluateOperator) in;
3951                break;
3952              }
3953            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3954              attribute);
3955            break;
3956          }
3957          default:
3958          {
3959            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3960              attribute);
3961            break;
3962          }
3963        }
3964      }
3965    image=EvaluateImages(image,op,exception);
3966    if (image == (Image *) NULL)
3967      goto PerlException;
3968    /*
3969      Create blessed Perl array for the returned image.
3970    */
3971    av=newAV();
3972    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3973    SvREFCNT_dec(av);
3974    AddImageToRegistry(sv,image);
3975    rv=newRV(sv);
3976    av_push(av,sv_bless(rv,hv));
3977    SvREFCNT_dec(sv);
3978    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3979    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3980      "evaluate-%.*s",(int) (MaxTextExtent-9),
3981      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3982    (void) CopyMagickString(image->filename,info->image_info->filename,
3983      MaxTextExtent);
3984    SetImageInfo(info->image_info,0,exception);
3985    exception=DestroyExceptionInfo(exception);
3986    SvREFCNT_dec(perl_exception);
3987    XSRETURN(1);
3988
3989  PerlException:
3990    InheritPerlException(exception,perl_exception);
3991    exception=DestroyExceptionInfo(exception);
3992    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3993    SvPOK_on(perl_exception);
3994    ST(0)=sv_2mortal(perl_exception);
3995    XSRETURN(1);
3996  }
3997
3998#
3999###############################################################################
4000#                                                                             #
4001#                                                                             #
4002#                                                                             #
4003#   F e a t u r e s                                                           #
4004#                                                                             #
4005#                                                                             #
4006#                                                                             #
4007###############################################################################
4008#
4009#
4010void
4011Features(ref,...)
4012  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4013  ALIAS:
4014    FeaturesImage = 1
4015    features      = 2
4016    featuresimage = 3
4017  PPCODE:
4018  {
4019#define ChannelFeatures(channel,direction) \
4020{ \
4021  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4022    channel_features[channel].angular_second_moment[direction]); \
4023  PUSHs(sv_2mortal(newSVpv(message,0))); \
4024  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4025    channel_features[channel].contrast[direction]); \
4026  PUSHs(sv_2mortal(newSVpv(message,0))); \
4027  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4028    channel_features[channel].contrast[direction]); \
4029  PUSHs(sv_2mortal(newSVpv(message,0))); \
4030  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4031    channel_features[channel].variance_sum_of_squares[direction]); \
4032  PUSHs(sv_2mortal(newSVpv(message,0))); \
4033  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4034    channel_features[channel].inverse_difference_moment[direction]); \
4035  PUSHs(sv_2mortal(newSVpv(message,0))); \
4036  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4037    channel_features[channel].sum_average[direction]); \
4038  PUSHs(sv_2mortal(newSVpv(message,0))); \
4039  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4040    channel_features[channel].sum_variance[direction]); \
4041  PUSHs(sv_2mortal(newSVpv(message,0))); \
4042  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4043    channel_features[channel].sum_entropy[direction]); \
4044  PUSHs(sv_2mortal(newSVpv(message,0))); \
4045  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4046    channel_features[channel].entropy[direction]); \
4047  PUSHs(sv_2mortal(newSVpv(message,0))); \
4048  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4049    channel_features[channel].difference_variance[direction]); \
4050  PUSHs(sv_2mortal(newSVpv(message,0))); \
4051  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4052    channel_features[channel].difference_entropy[direction]); \
4053  PUSHs(sv_2mortal(newSVpv(message,0))); \
4054  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4055    channel_features[channel].measure_of_correlation_1[direction]); \
4056  PUSHs(sv_2mortal(newSVpv(message,0))); \
4057  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4058    channel_features[channel].measure_of_correlation_2[direction]); \
4059  PUSHs(sv_2mortal(newSVpv(message,0))); \
4060  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
4061    channel_features[channel].maximum_correlation_coefficient[direction]); \
4062  PUSHs(sv_2mortal(newSVpv(message,0))); \
4063}
4064
4065    AV
4066      *av;
4067
4068    char
4069      *attribute,
4070      message[MaxTextExtent];
4071
4072    ChannelFeatures
4073      *channel_features;
4074
4075    double
4076      distance;
4077
4078    ExceptionInfo
4079      *exception;
4080
4081    Image
4082      *image;
4083
4084    ssize_t
4085      i;
4086
4087    ssize_t
4088      count;
4089
4090    struct PackageInfo
4091      *info;
4092
4093    SV
4094      *perl_exception,
4095      *reference;
4096
4097    PERL_UNUSED_VAR(ref);
4098    PERL_UNUSED_VAR(ix);
4099    exception=AcquireExceptionInfo();
4100    perl_exception=newSVpv("",0);
4101    av=NULL;
4102    if (sv_isobject(ST(0)) == 0)
4103      {
4104        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4105          PackageName);
4106        goto PerlException;
4107      }
4108    reference=SvRV(ST(0));
4109    av=newAV();
4110    SvREFCNT_dec(av);
4111    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4112    if (image == (Image *) NULL)
4113      {
4114        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4115          PackageName);
4116        goto PerlException;
4117      }
4118    distance=1.0;
4119    for (i=2; i < items; i+=2)
4120    {
4121      attribute=(char *) SvPV(ST(i-1),na);
4122      switch (*attribute)
4123      {
4124        case 'D':
4125        case 'd':
4126        {
4127          if (LocaleCompare(attribute,"distance") == 0)
4128            {
4129              distance=StringToLong((char *) SvPV(ST(1),na));
4130              break;
4131            }
4132          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4133            attribute);
4134          break;
4135        }
4136        default:
4137        {
4138          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4139            attribute);
4140          break;
4141        }
4142      }
4143    }
4144    count=0;
4145    for ( ; image; image=image->next)
4146    {
4147      channel_features=GetImageChannelFeatures(image,distance,
4148        &image->exception);
4149      if (channel_features == (ChannelFeatures *) NULL)
4150        continue;
4151      count++;
4152      EXTEND(sp,280*count);
4153      for (i=0; i < 4; i++)
4154      {
4155        ChannelFeatures(RedChannel,i);
4156        ChannelFeatures(GreenChannel,i);
4157        ChannelFeatures(BlueChannel,i);
4158        if (image->colorspace == CMYKColorspace)
4159          ChannelFeatures(IndexChannel,i);
4160        if (image->matte != MagickFalse)
4161          ChannelFeatures(OpacityChannel,i);
4162      }
4163      channel_features=(ChannelFeatures *)
4164        RelinquishMagickMemory(channel_features);
4165    }
4166
4167  PerlException:
4168    InheritPerlException(exception,perl_exception);
4169    exception=DestroyExceptionInfo(exception);
4170    SvREFCNT_dec(perl_exception);
4171  }
4172
4173#
4174###############################################################################
4175#                                                                             #
4176#                                                                             #
4177#                                                                             #
4178#   F l a t t e n                                                             #
4179#                                                                             #
4180#                                                                             #
4181#                                                                             #
4182###############################################################################
4183#
4184#
4185void
4186Flatten(ref,...)
4187  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4188  ALIAS:
4189    FlattenImage   = 1
4190    flatten        = 2
4191    flattenimage   = 3
4192  PPCODE:
4193  {
4194    AV
4195      *av;
4196
4197    char
4198      *attribute,
4199      *p;
4200
4201    ExceptionInfo
4202      *exception;
4203
4204    HV
4205      *hv;
4206
4207    Image
4208      *image;
4209
4210    PixelPacket
4211      background_color;
4212
4213    ssize_t
4214      i;
4215
4216    struct PackageInfo
4217      *info;
4218
4219    SV
4220      *perl_exception,
4221      *reference,
4222      *rv,
4223      *sv;
4224
4225    PERL_UNUSED_VAR(ref);
4226    PERL_UNUSED_VAR(ix);
4227    exception=AcquireExceptionInfo();
4228    perl_exception=newSVpv("",0);
4229    sv=NULL;
4230    if (sv_isobject(ST(0)) == 0)
4231      {
4232        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4233          PackageName);
4234        goto PerlException;
4235      }
4236    reference=SvRV(ST(0));
4237    hv=SvSTASH(reference);
4238    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4239    if (image == (Image *) NULL)
4240      {
4241        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4242          PackageName);
4243        goto PerlException;
4244      }
4245    background_color=image->background_color;
4246    if (items == 2)
4247      (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
4248        exception);
4249    else
4250      for (i=2; i < items; i+=2)
4251      {
4252        attribute=(char *) SvPV(ST(i-1),na);
4253        switch (*attribute)
4254        {
4255          case 'B':
4256          case 'b':
4257          {
4258            if (LocaleCompare(attribute,"background") == 0)
4259              {
4260                (void) QueryColorDatabase((char *) SvPV(ST(1),na),
4261                  &background_color,exception);
4262                break;
4263              }
4264            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4265              attribute);
4266            break;
4267          }
4268          default:
4269          {
4270            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4271              attribute);
4272            break;
4273          }
4274        }
4275      }
4276    image->background_color=background_color;
4277    image=MergeImageLayers(image,FlattenLayer,exception);
4278    if (image == (Image *) NULL)
4279      goto PerlException;
4280    /*
4281      Create blessed Perl array for the returned image.
4282    */
4283    av=newAV();
4284    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4285    SvREFCNT_dec(av);
4286    AddImageToRegistry(sv,image);
4287    rv=newRV(sv);
4288    av_push(av,sv_bless(rv,hv));
4289    SvREFCNT_dec(sv);
4290    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4291    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4292      "flatten-%.*s",(int) (MaxTextExtent-9),
4293      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4294    (void) CopyMagickString(image->filename,info->image_info->filename,
4295      MaxTextExtent);
4296    SetImageInfo(info->image_info,0,exception);
4297    exception=DestroyExceptionInfo(exception);
4298    SvREFCNT_dec(perl_exception);
4299    XSRETURN(1);
4300
4301  PerlException:
4302    InheritPerlException(exception,perl_exception);
4303    exception=DestroyExceptionInfo(exception);
4304    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4305    SvPOK_on(perl_exception);  /* return messages in string context */
4306    ST(0)=sv_2mortal(perl_exception);
4307    XSRETURN(1);
4308  }
4309
4310#
4311###############################################################################
4312#                                                                             #
4313#                                                                             #
4314#                                                                             #
4315#   F x                                                                       #
4316#                                                                             #
4317#                                                                             #
4318#                                                                             #
4319###############################################################################
4320#
4321#
4322void
4323Fx(ref,...)
4324  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4325  ALIAS:
4326    FxImage  = 1
4327    fx       = 2
4328    fximage  = 3
4329  PPCODE:
4330  {
4331    AV
4332      *av;
4333
4334    char
4335      *attribute,
4336      expression[MaxTextExtent];
4337
4338    ChannelType
4339      channel;
4340
4341    ExceptionInfo
4342      *exception;
4343
4344    HV
4345      *hv;
4346
4347    Image
4348      *image;
4349
4350    ssize_t
4351      i;
4352
4353    struct PackageInfo
4354      *info;
4355
4356    SV
4357      *av_reference,
4358      *perl_exception,
4359      *reference,
4360      *rv,
4361      *sv;
4362
4363    PERL_UNUSED_VAR(ref);
4364    PERL_UNUSED_VAR(ix);
4365    exception=AcquireExceptionInfo();
4366    perl_exception=newSVpv("",0);
4367    sv=NULL;
4368    attribute=NULL;
4369    av=NULL;
4370    if (sv_isobject(ST(0)) == 0)
4371      {
4372        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4373          PackageName);
4374        goto PerlException;
4375      }
4376    reference=SvRV(ST(0));
4377    hv=SvSTASH(reference);
4378    av=newAV();
4379    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4380    SvREFCNT_dec(av);
4381    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4382    if (image == (Image *) NULL)
4383      {
4384        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4385          PackageName);
4386        goto PerlException;
4387      }
4388    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4389    /*
4390      Get options.
4391    */
4392    channel=DefaultChannels;
4393    (void) CopyMagickString(expression,"u",MaxTextExtent);
4394    if (items == 2)
4395      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4396    else
4397      for (i=2; i < items; i+=2)
4398      {
4399        attribute=(char *) SvPV(ST(i-1),na);
4400        switch (*attribute)
4401        {
4402          case 'C':
4403          case 'c':
4404          {
4405            if (LocaleCompare(attribute,"channel") == 0)
4406              {
4407                ssize_t
4408                  option;
4409
4410                option=ParseChannelOption(SvPV(ST(i),na));
4411                if (option < 0)
4412                  {
4413                    ThrowPerlException(exception,OptionError,
4414                      "UnrecognizedType",SvPV(ST(i),na));
4415                    return;
4416                  }
4417                channel=(ChannelType) option;
4418                break;
4419              }
4420            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4421              attribute);
4422            break;
4423          }
4424          case 'E':
4425          case 'e':
4426          {
4427            if (LocaleCompare(attribute,"expression") == 0)
4428              {
4429                (void) CopyMagickString(expression,SvPV(ST(i),na),
4430                  MaxTextExtent);
4431                break;
4432              }
4433            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4434              attribute);
4435            break;
4436          }
4437          default:
4438          {
4439            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4440              attribute);
4441            break;
4442          }
4443        }
4444      }
4445    image=FxImageChannel(image,channel,expression,exception);
4446    if (image == (Image *) NULL)
4447      goto PerlException;
4448    for ( ; image; image=image->next)
4449    {
4450      AddImageToRegistry(sv,image);
4451      rv=newRV(sv);
4452      av_push(av,sv_bless(rv,hv));
4453      SvREFCNT_dec(sv);
4454    }
4455    exception=DestroyExceptionInfo(exception);
4456    ST(0)=av_reference;
4457    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4458    XSRETURN(1);
4459
4460  PerlException:
4461    InheritPerlException(exception,perl_exception);
4462    exception=DestroyExceptionInfo(exception);
4463    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4464    SvPOK_on(perl_exception);
4465    ST(0)=sv_2mortal(perl_exception);
4466    XSRETURN(1);
4467  }
4468
4469#
4470###############################################################################
4471#                                                                             #
4472#                                                                             #
4473#                                                                             #
4474#   G e t                                                                     #
4475#                                                                             #
4476#                                                                             #
4477#                                                                             #
4478###############################################################################
4479#
4480#
4481void
4482Get(ref,...)
4483  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4484  ALIAS:
4485    GetAttributes = 1
4486    GetAttribute  = 2
4487    get           = 3
4488    getattributes = 4
4489    getattribute  = 5
4490  PPCODE:
4491  {
4492    char
4493      *attribute,
4494      color[MaxTextExtent];
4495
4496    const char
4497      *value;
4498
4499    ExceptionInfo
4500      *exception;
4501
4502    Image
4503      *image;
4504
4505    long
4506      j;
4507
4508    ssize_t
4509      i;
4510
4511    struct PackageInfo
4512      *info;
4513
4514    SV
4515      *perl_exception,
4516      *reference,
4517      *s;
4518
4519    PERL_UNUSED_VAR(ref);
4520    PERL_UNUSED_VAR(ix);
4521    exception=AcquireExceptionInfo();
4522    perl_exception=newSVpv("",0);
4523    if (sv_isobject(ST(0)) == 0)
4524      {
4525        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4526          PackageName);
4527        XSRETURN_EMPTY;
4528      }
4529    reference=SvRV(ST(0));
4530    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4531    if (image == (Image *) NULL && !info)
4532      XSRETURN_EMPTY;
4533    EXTEND(sp,items);
4534    for (i=1; i < items; i++)
4535    {
4536      attribute=(char *) SvPV(ST(i),na);
4537      s=NULL;
4538      switch (*attribute)
4539      {
4540        case 'A':
4541        case 'a':
4542        {
4543          if (LocaleCompare(attribute,"adjoin") == 0)
4544            {
4545              if (info)
4546                s=newSViv((ssize_t) info->image_info->adjoin);
4547              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4548              continue;
4549            }
4550          if (LocaleCompare(attribute,"antialias") == 0)
4551            {
4552              if (info)
4553                s=newSViv((ssize_t) info->image_info->antialias);
4554              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4555              continue;
4556            }
4557          if (LocaleCompare(attribute,"area") == 0)
4558            {
4559              s=newSViv(GetMagickResource(AreaResource));
4560              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4561              continue;
4562            }
4563          if (LocaleCompare(attribute,"attenuate") == 0)
4564            {
4565              const char
4566                *value;
4567
4568              value=GetImageProperty(image,attribute);
4569              if (value != (const char *) NULL)
4570                s=newSVpv(value,0);
4571              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4572              continue;
4573            }
4574          if (LocaleCompare(attribute,"authenticate") == 0)
4575            {
4576              if (info)
4577                s=newSVpv(info->image_info->authenticate,0);
4578              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4579              continue;
4580            }
4581          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4582            attribute);
4583          break;
4584        }
4585        case 'B':
4586        case 'b':
4587        {
4588          if (LocaleCompare(attribute,"background") == 0)
4589            {
4590              if (image == (Image *) NULL)
4591                break;
4592              (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4593                QuantumFormat "," QuantumFormat "," QuantumFormat,
4594                image->background_color.red,image->background_color.green,
4595                image->background_color.blue,image->background_color.opacity);
4596              s=newSVpv(color,0);
4597              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4598              continue;
4599            }
4600          if (LocaleCompare(attribute,"base-columns") == 0)
4601            {
4602              if (image != (Image *) NULL)
4603                s=newSViv((ssize_t) image->magick_columns);
4604              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4605              continue;
4606            }
4607          if (LocaleCompare(attribute,"base-filename") == 0)
4608            {
4609              if (image != (Image *) NULL)
4610                s=newSVpv(image->magick_filename,0);
4611              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4612              continue;
4613            }
4614          if (LocaleCompare(attribute,"base-height") == 0)
4615            {
4616              if (image != (Image *) NULL)
4617                s=newSViv((ssize_t) image->magick_rows);
4618              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619              continue;
4620            }
4621          if (LocaleCompare(attribute,"base-rows") == 0)
4622            {
4623              if (image != (Image *) NULL)
4624                s=newSViv((ssize_t) image->magick_rows);
4625              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626              continue;
4627            }
4628          if (LocaleCompare(attribute,"base-width") == 0)
4629            {
4630              if (image != (Image *) NULL)
4631                s=newSViv((ssize_t) image->magick_columns);
4632              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4633              continue;
4634            }
4635          if (LocaleCompare(attribute,"bias") == 0)
4636            {
4637              if (image != (Image *) NULL)
4638                s=newSVnv(image->bias);
4639              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4640              continue;
4641            }
4642          if (LocaleCompare(attribute,"blue-primary") == 0)
4643            {
4644              if (image == (Image *) NULL)
4645                break;
4646              (void) FormatLocaleString(color,MaxTextExtent,"%.20g,%.15g",
4647                image->chromaticity.blue_primary.x,
4648                image->chromaticity.blue_primary.y);
4649              s=newSVpv(color,0);
4650              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4651              continue;
4652            }
4653          if (LocaleCompare(attribute,"bordercolor") == 0)
4654            {
4655              if (image == (Image *) NULL)
4656                break;
4657              (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4658                QuantumFormat "," QuantumFormat "," QuantumFormat,
4659                image->border_color.red,image->border_color.green,
4660                image->border_color.blue,image->border_color.opacity);
4661              s=newSVpv(color,0);
4662              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4663              continue;
4664            }
4665          if (LocaleCompare(attribute,"bounding-box") == 0)
4666            {
4667              char
4668                geometry[MaxTextExtent];
4669
4670              RectangleInfo
4671                page;
4672
4673              if (image == (Image *) NULL)
4674                break;
4675              page=GetImageBoundingBox(image,&image->exception);
4676              (void) FormatLocaleString(geometry,MaxTextExtent,
4677                "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4678                page.height,(double) page.x,(double) page.y);
4679              s=newSVpv(geometry,0);
4680              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4681              continue;
4682            }
4683          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4684            attribute);
4685          break;
4686        }
4687        case 'C':
4688        case 'c':
4689        {
4690          if (LocaleCompare(attribute,"class") == 0)
4691            {
4692              if (image == (Image *) NULL)
4693                break;
4694              s=newSViv(image->storage_class);
4695              (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4696                image->storage_class));
4697              SvIOK_on(s);
4698              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699              continue;
4700            }
4701          if (LocaleCompare(attribute,"clip-mask") == 0)
4702            {
4703              if (image != (Image *) NULL)
4704                {
4705                  SV
4706                    *sv;
4707
4708                  sv=NULL;
4709                  if (image->mask == (Image *) NULL)
4710                    ClipImage(image);
4711                  if (image->mask != (Image *) NULL)
4712                    {
4713                      AddImageToRegistry(sv,image->mask);
4714                      s=sv_bless(newRV(sv),SvSTASH(reference));
4715                    }
4716                }
4717              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4718              continue;
4719            }
4720          if (LocaleCompare(attribute,"clip-path") == 0)
4721            {
4722              if (image != (Image *) NULL)
4723                {
4724                  SV
4725                    *sv;
4726
4727                  sv=NULL;
4728                  if (image->clip_mask == (Image *) NULL)
4729                    ClipImage(image);
4730                  if (image->clip_mask != (Image *) NULL)
4731                    {
4732                      AddImageToRegistry(sv,image->clip_mask);
4733                      s=sv_bless(newRV(sv),SvSTASH(reference));
4734                    }
4735                }
4736              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737              continue;
4738            }
4739          if (LocaleCompare(attribute,"compression") == 0)
4740            {
4741              j=info ? info->image_info->compression : image ?
4742                image->compression : UndefinedCompression;
4743              if (info)
4744                if (info->image_info->compression == UndefinedCompression)
4745                  j=image->compression;
4746              s=newSViv(j);
4747              (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4748                j));
4749              SvIOK_on(s);
4750              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4751              continue;
4752            }
4753          if (LocaleCompare(attribute,"colorspace") == 0)
4754            {
4755              j=image ? image->colorspace : RGBColorspace;
4756              s=newSViv(j);
4757              (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4758                j));
4759              SvIOK_on(s);
4760              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761              continue;
4762            }
4763          if (LocaleCompare(attribute,"colors") == 0)
4764            {
4765              if (image != (Image *) NULL)
4766                s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4767                  &image->exception));
4768              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4769              continue;
4770            }
4771          if (LocaleNCompare(attribute,"colormap",8) == 0)
4772            {
4773              int
4774                items;
4775
4776              if (image == (Image *) NULL || !image->colormap)
4777                break;
4778              j=0;
4779              items=sscanf(attribute,"%*[^[][%ld",&j);
4780              (void) items;
4781              if (j > (ssize_t) image->colors)
4782                j%=image->colors;
4783              (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4784                QuantumFormat "," QuantumFormat "," QuantumFormat,
4785                image->colormap[j].red,image->colormap[j].green,
4786                image->colormap[j].blue,image->colormap[j].opacity);
4787              s=newSVpv(color,0);
4788              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4789              continue;
4790            }
4791          if (LocaleCompare(attribute,"columns") == 0)
4792            {
4793              if (image != (Image *) NULL)
4794                s=newSViv((ssize_t) image->columns);
4795              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796              continue;
4797            }
4798          if (LocaleCompare(attribute,"comment") == 0)
4799            {
4800              const char
4801                *value;
4802
4803              value=GetImageProperty(image,attribute);
4804              if (value != (const char *) NULL)
4805                s=newSVpv(value,0);
4806              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4807              continue;
4808            }
4809          if (LocaleCompare(attribute,"copyright") == 0)
4810            {
4811              s=newSVpv(GetMagickCopyright(),0);
4812              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4813              continue;
4814            }
4815          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4816            attribute);
4817          break;
4818        }
4819        case 'D':
4820        case 'd':
4821        {
4822          if (LocaleCompare(attribute,"density") == 0)
4823            {
4824              char
4825                geometry[MaxTextExtent];
4826
4827              if (image == (Image *) NULL)
4828                break;
4829              (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.15g",
4830                image->x_resolution,image->y_resolution);
4831              s=newSVpv(geometry,0);
4832              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4833              continue;
4834            }
4835          if (LocaleCompare(attribute,"delay") == 0)
4836            {
4837              if (image != (Image *) NULL)
4838                s=newSViv((ssize_t) image->delay);
4839              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4840              continue;
4841            }
4842          if (LocaleCompare(attribute,"depth") == 0)
4843            {
4844              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4845              if (image != (Image *) NULL)
4846                s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4847              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4848              continue;
4849            }
4850          if (LocaleCompare(attribute,"directory") == 0)
4851            {
4852              if (image && image->directory)
4853                s=newSVpv(image->directory,0);
4854              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4855              continue;
4856            }
4857          if (LocaleCompare(attribute,"dispose") == 0)
4858            {
4859              if (image == (Image *) NULL)
4860                break;
4861
4862              s=newSViv(image->dispose);
4863              (void) sv_setpv(s,
4864                CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4865              SvIOK_on(s);
4866              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867              continue;
4868            }
4869          if (LocaleCompare(attribute,"disk") == 0)
4870            {
4871              s=newSViv(GetMagickResource(DiskResource));
4872              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4873              continue;
4874            }
4875          if (LocaleCompare(attribute,"dither") == 0)
4876            {
4877              if (info)
4878                s=newSViv((ssize_t) info->image_info->dither);
4879              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4880              continue;
4881            }
4882          if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4883            {
4884              if (info && info->image_info->server_name)
4885                s=newSVpv(info->image_info->server_name,0);
4886              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4887              continue;
4888            }
4889          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4890            attribute);
4891          break;
4892        }
4893        case 'E':
4894        case 'e':
4895        {
4896          if (LocaleCompare(attribute,"elapsed-time") == 0)
4897            {
4898              if (image != (Image *) NULL)
4899                s=newSVnv(GetElapsedTime(&image->timer));
4900              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4901              continue;
4902            }
4903          if (LocaleCompare(attribute,"endian") == 0)
4904            {
4905              j=info ? info->image_info->endian : image ? image->endian :
4906                UndefinedEndian;
4907              if (info)
4908                if (info->image_info->endian == UndefinedEndian)
4909                  j=image->endian;
4910              s=newSViv(j);
4911              (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4912              SvIOK_on(s);
4913              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4914              continue;
4915            }
4916          if (LocaleCompare(attribute,"error") == 0)
4917            {
4918              if (image != (Image *) NULL)
4919                s=newSVnv(image->error.mean_error_per_pixel);
4920              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4921              continue;
4922            }
4923          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4924            attribute);
4925          break;
4926        }
4927        case 'F':
4928        case 'f':
4929        {
4930          if (LocaleCompare(attribute,"filesize") == 0)
4931            {
4932              if (image != (Image *) NULL)
4933                s=newSViv((ssize_t) GetBlobSize(image));
4934              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4935              continue;
4936            }
4937          if (LocaleCompare(attribute,"filename") == 0)
4938            {
4939              if (image != (Image *) NULL)
4940                s=newSVpv(image->filename,0);
4941              else
4942                if (info && *info->image_info->filename)
4943                  s=newSVpv(info->image_info->filename,0);
4944              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945              continue;
4946            }
4947          if (LocaleCompare(attribute,"filter") == 0)
4948            {
4949              s=image ? newSViv(image->filter) : newSViv(0);
4950              (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4951                image->filter));
4952              SvIOK_on(s);
4953              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4954              continue;
4955            }
4956          if (LocaleCompare(attribute,"font") == 0)
4957            {
4958              if (info && info->image_info->font)
4959                s=newSVpv(info->image_info->font,0);
4960              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961              continue;
4962            }
4963          if (LocaleCompare(attribute,"foreground") == 0)
4964            continue;
4965          if (LocaleCompare(attribute,"format") == 0)
4966            {
4967              const MagickInfo
4968                *magick_info;
4969
4970              magick_info=(const MagickInfo *) NULL;
4971              if (info && (*info->image_info->magick != '\0'))
4972                magick_info=GetMagickInfo(info->image_info->magick,exception);
4973              if (image != (Image *) NULL)
4974                magick_info=GetMagickInfo(image->magick,&image->exception);
4975              if ((magick_info != (const MagickInfo *) NULL) &&
4976                  (*magick_info->description != '\0'))
4977                s=newSVpv((char *) magick_info->description,0);
4978              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979              continue;
4980            }
4981          if (LocaleCompare(attribute,"fuzz") == 0)
4982            {
4983              if (info)
4984                s=newSVnv(info->image_info->fuzz);
4985              if (image != (Image *) NULL)
4986                s=newSVnv(image->fuzz);
4987              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4988              continue;
4989            }
4990          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4991            attribute);
4992          break;
4993        }
4994        case 'G':
4995        case 'g':
4996        {
4997          if (LocaleCompare(attribute,"gamma") == 0)
4998            {
4999              if (image != (Image *) NULL)
5000                s=newSVnv(image->gamma);
5001              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002              continue;
5003            }
5004          if (LocaleCompare(attribute,"geometry") == 0)
5005            {
5006              if (image && image->geometry)
5007                s=newSVpv(image->geometry,0);
5008              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5009              continue;
5010            }
5011          if (LocaleCompare(attribute,"gravity") == 0)
5012            {
5013              s=image ? newSViv(image->gravity) : newSViv(0);
5014              (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5015                image->gravity));
5016              SvIOK_on(s);
5017              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018              continue;
5019            }
5020          if (LocaleCompare(attribute,"green-primary") == 0)
5021            {
5022              if (image == (Image *) NULL)
5023                break;
5024              (void) FormatLocaleString(color,MaxTextExtent,"%.20g,%.15g",
5025                image->chromaticity.green_primary.x,
5026                image->chromaticity.green_primary.y);
5027              s=newSVpv(color,0);
5028              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5029              continue;
5030            }
5031          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5032            attribute);
5033          break;
5034        }
5035        case 'H':
5036        case 'h':
5037        {
5038          if (LocaleCompare(attribute,"height") == 0)
5039            {
5040              if (image != (Image *) NULL)
5041                s=newSViv((ssize_t) image->rows);
5042              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5043              continue;
5044            }
5045          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5046            attribute);
5047          break;
5048        }
5049        case 'I':
5050        case 'i':
5051        {
5052          if (LocaleCompare(attribute,"icc") == 0)
5053            {
5054              if (image != (Image *) NULL)
5055                {
5056                  const StringInfo
5057                    *profile;
5058
5059                  profile=GetImageProfile(image,"icc");
5060                  if (profile != (StringInfo *) NULL)
5061                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5062                      GetStringInfoLength(profile));
5063                }
5064              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065              continue;
5066            }
5067          if (LocaleCompare(attribute,"icm") == 0)
5068            {
5069              if (image != (Image *) NULL)
5070                {
5071                  const StringInfo
5072                    *profile;
5073
5074                  profile=GetImageProfile(image,"icm");
5075                  if (profile != (const StringInfo *) NULL)
5076                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5077                      GetStringInfoLength(profile));
5078                }
5079              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5080              continue;
5081            }
5082          if (LocaleCompare(attribute,"id") == 0)
5083            {
5084              if (image != (Image *) NULL)
5085                {
5086                  char
5087                    key[MaxTextExtent];
5088
5089                  MagickBooleanType
5090                    status;
5091
5092                  static ssize_t
5093                    id = 0;
5094
5095                  (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
5096                    id);
5097                  status=SetImageRegistry(ImageRegistryType,key,image,
5098                    &image->exception);
5099                  (void) status;
5100                  s=newSViv(id++);
5101                }
5102              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5103              continue;
5104            }
5105          if (LocaleNCompare(attribute,"index",5) == 0)
5106            {
5107              char
5108                name[MaxTextExtent];
5109
5110              int
5111                items;
5112
5113              long
5114                x,
5115                y;
5116
5117              const IndexPacket
5118                *indexes;
5119
5120              const PixelPacket
5121                *p;
5122
5123              CacheView
5124                *image_view;
5125
5126              if (image == (Image *) NULL)
5127                break;
5128              if (image->storage_class != PseudoClass)
5129                break;
5130              x=0;
5131              y=0;
5132              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5133              (void) items;
5134              image_view=AcquireVirtualCacheView(image,exception);
5135              p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
5136              if (p != (const PixelPacket *) NULL)
5137                {
5138                  indexes=GetCacheViewVirtualIndexQueue(image_view);
5139                  (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5140                    GetPixelIndex(indexes));
5141                  s=newSVpv(name,0);
5142                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5143                }
5144              image_view=DestroyCacheView(image_view);
5145              continue;
5146            }
5147          if (LocaleCompare(attribute,"iptc") == 0)
5148            {
5149              if (image != (Image *) NULL)
5150                {
5151                  const StringInfo
5152                    *profile;
5153
5154                  profile=GetImageProfile(image,"iptc");
5155                  if (profile != (const StringInfo *) NULL)
5156                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5157                      GetStringInfoLength(profile));
5158                }
5159              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160              continue;
5161            }
5162          if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5163            {
5164              if (image != (Image *) NULL)
5165                s=newSViv((ssize_t) image->iterations);
5166              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5167              continue;
5168            }
5169          if (LocaleCompare(attribute,"interlace") == 0)
5170            {
5171              j=info ? info->image_info->interlace : image ? image->interlace :
5172                UndefinedInterlace;
5173              if (info)
5174                if (info->image_info->interlace == UndefinedInterlace)
5175                  j=image->interlace;
5176              s=newSViv(j);
5177              (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5178                j));
5179              SvIOK_on(s);
5180              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5181              continue;
5182            }
5183          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5184            attribute);
5185          break;
5186        }
5187        case 'L':
5188        case 'l':
5189        {
5190          if (LocaleCompare(attribute,"label") == 0)
5191            {
5192              const char
5193                *value;
5194
5195              if (image == (Image *) NULL)
5196                break;
5197              value=GetImageProperty(image,"Label");
5198              if (value != (const char *) NULL)
5199                s=newSVpv(value,0);
5200              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5201              continue;
5202            }
5203          if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5204            {
5205              if (image != (Image *) NULL)
5206                s=newSViv((ssize_t) image->iterations);
5207              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5208              continue;
5209            }
5210          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5211            attribute);
5212          break;
5213        }
5214        case 'M':
5215        case 'm':
5216        {
5217          if (LocaleCompare(attribute,"magick") == 0)
5218            {
5219              if (info && *info->image_info->magick)
5220                s=newSVpv(info->image_info->magick,0);
5221              if (image != (Image *) NULL)
5222                s=newSVpv(image->magick,0);
5223              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5224              continue;
5225            }
5226          if (LocaleCompare(attribute,"map") == 0)
5227            {
5228              s=newSViv(GetMagickResource(MapResource));
5229              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5230              continue;
5231            }
5232          if (LocaleCompare(attribute,"maximum-error") == 0)
5233            {
5234              if (image != (Image *) NULL)
5235                s=newSVnv(image->error.normalized_maximum_error);
5236              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237              continue;
5238            }
5239          if (LocaleCompare(attribute,"memory") == 0)
5240            {
5241              s=newSViv(GetMagickResource(MemoryResource));
5242              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5243              continue;
5244            }
5245          if (LocaleCompare(attribute,"mean-error") == 0)
5246            {
5247              if (image != (Image *) NULL)
5248                s=newSVnv(image->error.normalized_mean_error);
5249              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5250              continue;
5251            }
5252          if (LocaleCompare(attribute,"mime") == 0)
5253            {
5254              if (info && *info->image_info->magick)
5255                s=newSVpv(MagickToMime(info->image_info->magick),0);
5256              if (image != (Image *) NULL)
5257                s=newSVpv(MagickToMime(image->magick),0);
5258              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5259              continue;
5260            }
5261          if (LocaleCompare(attribute,"mattecolor") == 0)
5262            {
5263              if (image == (Image *) NULL)
5264                break;
5265              (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5266                QuantumFormat "," QuantumFormat "," QuantumFormat,
5267                image->matte_color.red,image->matte_color.green,
5268                image->matte_color.blue,image->matte_color.opacity);
5269              s=newSVpv(color,0);
5270              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5271              continue;
5272            }
5273          if (LocaleCompare(attribute,"matte") == 0)
5274            {
5275              if (image != (Image *) NULL)
5276                s=newSViv((ssize_t) image->matte);
5277              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5278              continue;
5279            }
5280          if (LocaleCompare(attribute,"mime") == 0)
5281            {
5282              const char
5283                *magick;
5284
5285              magick=NULL;
5286              if (info && *info->image_info->magick)
5287                magick=info->image_info->magick;
5288              if (image != (Image *) NULL)
5289                magick=image->magick;
5290              if (magick)
5291                {
5292                  char
5293                    *mime;
5294
5295                  mime=MagickToMime(magick);
5296                  s=newSVpv(mime,0);
5297                  mime=(char *) RelinquishMagickMemory(mime);
5298                }
5299              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5300              continue;
5301            }
5302          if (LocaleCompare(attribute,"monochrome") == 0)
5303            {
5304              if (image == (Image *) NULL)
5305                continue;
5306              j=info ? info->image_info->monochrome :
5307                IsMonochromeImage(image,&image->exception);
5308              s=newSViv(j);
5309              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5310              continue;
5311            }
5312          if (LocaleCompare(attribute,"montage") == 0)
5313            {
5314              if (image && image->montage)
5315                s=newSVpv(image->montage,0);
5316              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317              continue;
5318            }
5319          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5320            attribute);
5321          break;
5322        }
5323        case 'O':
5324        case 'o':
5325        {
5326          if (LocaleCompare(attribute,"orientation") == 0)
5327            {
5328              j=info ? info->image_info->orientation : image ?
5329                image->orientation : UndefinedOrientation;
5330              if (info)
5331                if (info->image_info->orientation == UndefinedOrientation)
5332                  j=image->orientation;
5333              s=newSViv(j);
5334              (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5335                j));
5336              SvIOK_on(s);
5337              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338              continue;
5339            }
5340          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5341            attribute);
5342          break;
5343        }
5344        case 'P':
5345        case 'p':
5346        {
5347          if (LocaleCompare(attribute,"page") == 0)
5348            {
5349              if (info && info->image_info->page)
5350                s=newSVpv(info->image_info->page,0);
5351              if (image != (Image *) NULL)
5352                {
5353                  char
5354                    geometry[MaxTextExtent];
5355
5356                  (void) FormatLocaleString(geometry,MaxTextExtent,
5357                    "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5358                    (double) image->page.height,(double) image->page.x,(double)
5359                    image->page.y);
5360                  s=newSVpv(geometry,0);
5361                }
5362              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5363              continue;
5364            }
5365          if (LocaleCompare(attribute,"page.x") == 0)
5366            {
5367              if (image != (Image *) NULL)
5368                s=newSViv((ssize_t) image->page.x);
5369              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5370              continue;
5371            }
5372          if (LocaleCompare(attribute,"page.y") == 0)
5373            {
5374              if (image != (Image *) NULL)
5375                s=newSViv((ssize_t) image->page.y);
5376              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5377              continue;
5378            }
5379          if (LocaleNCompare(attribute,"pixel",5) == 0)
5380            {
5381              char
5382                tuple[MaxTextExtent];
5383
5384              int
5385                items;
5386
5387              long
5388                x,
5389                y;
5390
5391              const PixelPacket
5392                *p;
5393
5394              const IndexPacket
5395                *indexes;
5396
5397              if (image == (Image *) NULL)
5398                break;
5399              x=0;
5400              y=0;
5401              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5402              (void) items;
5403              p=GetVirtualPixels(image,x,y,1,1,exception);
5404              indexes=GetVirtualIndexQueue(image);
5405              if (image->colorspace != CMYKColorspace)
5406                (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5407                  QuantumFormat "," QuantumFormat "," QuantumFormat,
5408                  GetPixelRed(p),GetPixelGreen(p),
5409                  GetPixelBlue(p),GetPixelOpacity(p));
5410              else
5411                (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5412                  QuantumFormat "," QuantumFormat "," QuantumFormat ","
5413                  QuantumFormat,GetPixelRed(p),
5414                  GetPixelGreen(p),GetPixelBlue(p),
5415                  GetPixelIndex(indexes),GetPixelOpacity(p));
5416              s=newSVpv(tuple,0);
5417              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5418              continue;
5419            }
5420          if (LocaleCompare(attribute,"pointsize") == 0)
5421            {
5422              if (info)
5423                s=newSViv((ssize_t) info->image_info->pointsize);
5424              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5425              continue;
5426            }
5427          if (LocaleCompare(attribute,"precision") == 0)
5428            {
5429              s=newSViv((ssize_t) GetMagickPrecision());
5430              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5431              continue;
5432            }
5433          if (LocaleCompare(attribute,"preview") == 0)
5434            {
5435              s=newSViv(info->image_info->preview_type);
5436              (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5437                info->image_info->preview_type));
5438              SvIOK_on(s);
5439              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5440              continue;
5441            }
5442          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5443            attribute);
5444          break;
5445        }
5446        case 'Q':
5447        case 'q':
5448        {
5449          if (LocaleCompare(attribute,"quality") == 0)
5450            {
5451              if (info)
5452                s=newSViv((ssize_t) info->image_info->quality);
5453              if (image != (Image *) NULL)
5454                s=newSViv((ssize_t) image->quality);
5455              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5456              continue;
5457            }
5458          if (LocaleCompare(attribute,"quantum") == 0)
5459            {
5460              if (info)
5461                s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5462              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463              continue;
5464            }
5465          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5466            attribute);
5467          break;
5468        }
5469        case 'R':
5470        case 'r':
5471        {
5472          if (LocaleCompare(attribute,"rendering-intent") == 0)
5473            {
5474              s=newSViv(image->rendering_intent);
5475              (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5476                image->rendering_intent));
5477              SvIOK_on(s);
5478              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5479              continue;
5480            }
5481          if (LocaleCompare(attribute,"red-primary") == 0)
5482            {
5483              if (image == (Image *) NULL)
5484                break;
5485              (void) FormatLocaleString(color,MaxTextExtent,"%.20g,%.15g",
5486                image->chromaticity.red_primary.x,
5487                image->chromaticity.red_primary.y);
5488              s=newSVpv(color,0);
5489              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5490              continue;
5491            }
5492          if (LocaleCompare(attribute,"rows") == 0)
5493            {
5494              if (image != (Image *) NULL)
5495                s=newSViv((ssize_t) image->rows);
5496              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497              continue;
5498            }
5499          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5500            attribute);
5501          break;
5502        }
5503        case 'S':
5504        case 's':
5505        {
5506          if (LocaleCompare(attribute,"sampling-factor") == 0)
5507            {
5508              if (info && info->image_info->sampling_factor)
5509                s=newSVpv(info->image_info->sampling_factor,0);
5510              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5511              continue;
5512            }
5513          if (LocaleCompare(attribute,"subimage") == 0)
5514            {
5515              if (info)
5516                s=newSViv((ssize_t) info->image_info->subimage);
5517              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5518              continue;
5519            }
5520          if (LocaleCompare(attribute,"subrange") == 0)
5521            {
5522              if (info)
5523                s=newSViv((ssize_t) info->image_info->subrange);
5524              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5525              continue;
5526            }
5527          if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5528            {
5529              if (info && info->image_info->server_name)
5530                s=newSVpv(info->image_info->server_name,0);
5531              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5532              continue;
5533            }
5534          if (LocaleCompare(attribute,"size") == 0)
5535            {
5536              if (info && info->image_info->size)
5537                s=newSVpv(info->image_info->size,0);
5538              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5539              continue;
5540            }
5541          if (LocaleCompare(attribute,"scene") == 0)
5542            {
5543              if (image != (Image *) NULL)
5544                s=newSViv((ssize_t) image->scene);
5545              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5546              continue;
5547            }
5548          if (LocaleCompare(attribute,"scenes") == 0)
5549            {
5550              if (image != (Image *) NULL)
5551                s=newSViv((ssize_t) info->image_info->number_scenes);
5552              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5553              continue;
5554            }
5555          if (LocaleCompare(attribute,"signature") == 0)
5556            {
5557              const char
5558                *value;
5559
5560              if (image == (Image *) NULL)
5561                break;
5562              (void) SignatureImage(image);
5563              value=GetImageProperty(image,"Signature");
5564              if (value != (const char *) NULL)
5565                s=newSVpv(value,0);
5566              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5567              continue;
5568            }
5569          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5570            attribute);
5571          break;
5572        }
5573        case 'T':
5574        case 't':
5575        {
5576          if (LocaleCompare(attribute,"taint") == 0)
5577            {
5578              if (image != (Image *) NULL)
5579                s=newSViv((ssize_t) IsTaintImage(image));
5580              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5581              continue;
5582            }
5583          if (LocaleCompare(attribute,"tile") == 0)
5584            {
5585              if (info && info->image_info->tile)
5586                s=newSVpv(info->image_info->tile,0);
5587              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5588              continue;
5589            }
5590          if (LocaleCompare(attribute,"texture") == 0)
5591            {
5592              if (info && info->image_info->texture)
5593                s=newSVpv(info->image_info->texture,0);
5594              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5595              continue;
5596            }
5597          if (LocaleCompare(attribute,"total-ink-density") == 0)
5598            {
5599              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5600              if (image != (Image *) NULL)
5601                s=newSVnv(GetImageTotalInkDensity(image));
5602              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5603              continue;
5604            }
5605          if (LocaleCompare(attribute,"transparent-color") == 0)
5606            {
5607              if (image == (Image *) NULL)
5608                break;
5609              (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5610                QuantumFormat "," QuantumFormat "," QuantumFormat,
5611                image->transparent_color.red,image->transparent_color.green,
5612                image->transparent_color.blue,image->transparent_color.opacity);
5613              s=newSVpv(color,0);
5614              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5615              continue;
5616            }
5617          if (LocaleCompare(attribute,"type") == 0)
5618            {
5619              if (image == (Image *) NULL)
5620                break;
5621              j=(ssize_t) GetImageType(image,&image->exception);
5622              s=newSViv(j);
5623              (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5624              SvIOK_on(s);
5625              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626              continue;
5627            }
5628          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5629            attribute);
5630          break;
5631        }
5632        case 'U':
5633        case 'u':
5634        {
5635          if (LocaleCompare(attribute,"units") == 0)
5636            {
5637              j=info ? info->image_info->units : image ? image->units :
5638                UndefinedResolution;
5639              if (info)
5640                if (info->image_info->units == UndefinedResolution)
5641                  j=image->units;
5642              if (j == UndefinedResolution)
5643                s=newSVpv("undefined units",0);
5644              else
5645                if (j == PixelsPerInchResolution)
5646                  s=newSVpv("pixels / inch",0);
5647                else
5648                  s=newSVpv("pixels / centimeter",0);
5649              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5650              continue;
5651            }
5652          if (LocaleCompare(attribute,"user-time") == 0)
5653            {
5654              if (image != (Image *) NULL)
5655                s=newSVnv(GetUserTime(&image->timer));
5656              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5657              continue;
5658            }
5659          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5660            attribute);
5661          break;
5662        }
5663        case 'V':
5664        case 'v':
5665        {
5666          if (LocaleCompare(attribute,"verbose") == 0)
5667            {
5668              if (info)
5669                s=newSViv((ssize_t) info->image_info->verbose);
5670              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5671              continue;
5672            }
5673          if (LocaleCompare(attribute,"version") == 0)
5674            {
5675              s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5676              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5677              continue;
5678            }
5679          if (LocaleCompare(attribute,"view") == 0)
5680            {
5681              if (info && info->image_info->view)
5682                s=newSVpv(info->image_info->view,0);
5683              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5684              continue;
5685            }
5686          if (LocaleCompare(attribute,"virtual-pixel") == 0)
5687            {
5688              if (image == (Image *) NULL)
5689                break;
5690              j=(ssize_t) GetImageVirtualPixelMethod(image);
5691              s=newSViv(j);
5692              (void) sv_setpv(s,CommandOptionToMnemonic(
5693                MagickVirtualPixelOptions,j));
5694              SvIOK_on(s);
5695              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5696              continue;
5697            }
5698          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5699            attribute);
5700          break;
5701        }
5702        case 'W':
5703        case 'w':
5704        {
5705          if (LocaleCompare(attribute,"white-point") == 0)
5706            {
5707              if (image == (Image *) NULL)
5708                break;
5709              (void) FormatLocaleString(color,MaxTextExtent,"%.20g,%.15g",
5710                image->chromaticity.white_point.x,
5711                image->chromaticity.white_point.y);
5712              s=newSVpv(color,0);
5713              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5714              continue;
5715            }
5716          if (LocaleCompare(attribute,"width") == 0)
5717            {
5718              if (image != (Image *) NULL)
5719                s=newSViv((ssize_t) image->columns);
5720              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5721              continue;
5722            }
5723          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5724             attribute);
5725          break;
5726        }
5727        case 'X':
5728        case 'x':
5729        {
5730          if (LocaleCompare(attribute,"xmp") == 0)
5731            {
5732              if (image != (Image *) NULL)
5733                {
5734                  const StringInfo
5735                    *profile;
5736
5737                  profile=GetImageProfile(image,"xmp");
5738                  if (profile != (StringInfo *) NULL)
5739                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5740                      GetStringInfoLength(profile));
5741                }
5742              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5743              continue;
5744            }
5745          if (LocaleCompare(attribute,"x-resolution") == 0)
5746            {
5747              if (image != (Image *) NULL)
5748                s=newSVnv(image->x_resolution);
5749              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5750              continue;
5751            }
5752          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5753            attribute);
5754          break;
5755        }
5756        case 'Y':
5757        case 'y':
5758        {
5759          if (LocaleCompare(attribute,"y-resolution") == 0)
5760            {
5761              if (image != (Image *) NULL)
5762                s=newSVnv(image->y_resolution);
5763              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5764              continue;
5765            }
5766          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5767            attribute);
5768          break;
5769        }
5770        default:
5771          break;
5772      }
5773      if (image == (Image *) NULL)
5774        ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5775          attribute)
5776      else
5777        {
5778          value=GetImageProperty(image,attribute);
5779          if (value != (const char *) NULL)
5780            {
5781              s=newSVpv(value,0);
5782              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5783            }
5784          else
5785            if (*attribute != '%')
5786              ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5787                attribute)
5788            else
5789              {
5790                 char
5791                   *meta;
5792
5793                 meta=InterpretImageProperties(info ? info->image_info :
5794                   (ImageInfo *) NULL,image,attribute);
5795                 s=newSVpv(meta,0);
5796                 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5797                 meta=(char *) RelinquishMagickMemory(meta);
5798              }
5799        }
5800    }
5801    exception=DestroyExceptionInfo(exception);
5802    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5803  }
5804
5805#
5806###############################################################################
5807#                                                                             #
5808#                                                                             #
5809#                                                                             #
5810#   G e t A u t h e n t i c P i x e l s                                       #
5811#                                                                             #
5812#                                                                             #
5813#                                                                             #
5814###############################################################################
5815#
5816#
5817void *
5818GetAuthenticPixels(ref,...)
5819  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5820  ALIAS:
5821    getauthenticpixels = 1
5822    GetImagePixels = 2
5823    getimagepixels = 3
5824  CODE:
5825  {
5826    char
5827      *attribute;
5828
5829    ExceptionInfo
5830      *exception;
5831
5832    Image
5833      *image;
5834
5835    RectangleInfo
5836      region;
5837
5838    ssize_t
5839      i;
5840
5841    struct PackageInfo
5842      *info;
5843
5844    SV
5845      *perl_exception,
5846      *reference;
5847
5848    void
5849      *blob = NULL;
5850
5851    PERL_UNUSED_VAR(ref);
5852    PERL_UNUSED_VAR(ix);
5853    exception=AcquireExceptionInfo();
5854    perl_exception=newSVpv("",0);
5855    if (sv_isobject(ST(0)) == 0)
5856      {
5857        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5858          PackageName);
5859        goto PerlException;
5860      }
5861    reference=SvRV(ST(0));
5862
5863    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5864    if (image == (Image *) NULL)
5865      {
5866        ThrowPerlException(exception,OptionError,"NoImagesDefined",
5867          PackageName);
5868        goto PerlException;
5869      }
5870
5871    region.x=0;
5872    region.y=0;
5873    region.width=image->columns;
5874    region.height=1;
5875    if (items == 1)
5876      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5877    for (i=2; i < items; i+=2)
5878    {
5879      attribute=(char *) SvPV(ST(i-1),na);
5880      switch (*attribute)
5881      {
5882        case 'g':
5883        case 'G':
5884        {
5885          if (LocaleCompare(attribute,"geometry") == 0)
5886            {
5887              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5888              break;
5889            }
5890          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5891            attribute);
5892          break;
5893        }
5894        case 'H':
5895        case 'h':
5896        {
5897          if (LocaleCompare(attribute,"height") == 0)
5898            {
5899              region.height=SvIV(ST(i));
5900              continue;
5901            }
5902          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5903            attribute);
5904          break;
5905        }
5906        case 'X':
5907        case 'x':
5908        {
5909          if (LocaleCompare(attribute,"x") == 0)
5910            {
5911              region.x=SvIV(ST(i));
5912              continue;
5913            }
5914          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5915            attribute);
5916          break;
5917        }
5918        case 'Y':
5919        case 'y':
5920        {
5921          if (LocaleCompare(attribute,"y") == 0)
5922            {
5923              region.y=SvIV(ST(i));
5924              continue;
5925            }
5926          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5927            attribute);
5928          break;
5929        }
5930        case 'W':
5931        case 'w':
5932        {
5933          if (LocaleCompare(attribute,"width") == 0)
5934            {
5935              region.width=SvIV(ST(i));
5936              continue;
5937            }
5938          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5939            attribute);
5940          break;
5941        }
5942      }
5943    }
5944    blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5945      region.height,exception);
5946    if (blob != (void *) NULL)
5947      goto PerlEnd;
5948
5949  PerlException:
5950    InheritPerlException(exception,perl_exception);
5951    exception=DestroyExceptionInfo(exception);
5952    SvREFCNT_dec(perl_exception);  /* throw away all errors */
5953
5954  PerlEnd:
5955    RETVAL = blob;
5956  }
5957  OUTPUT:
5958    RETVAL
5959
5960#
5961###############################################################################
5962#                                                                             #
5963#                                                                             #
5964#                                                                             #
5965#   G e t V i r t u a l P i x e l s                                           #
5966#                                                                             #
5967#                                                                             #
5968#                                                                             #
5969###############################################################################
5970#
5971#
5972void *
5973GetVirtualPixels(ref,...)
5974  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5975  ALIAS:
5976    getvirtualpixels = 1
5977    AcquireImagePixels = 2
5978    acquireimagepixels = 3
5979  CODE:
5980  {
5981    char
5982      *attribute;
5983
5984    const void
5985      *blob = NULL;
5986
5987    ExceptionInfo
5988      *exception;
5989
5990    Image
5991      *image;
5992
5993    RectangleInfo
5994      region;
5995
5996    ssize_t
5997      i;
5998
5999    struct PackageInfo
6000      *info;
6001
6002    SV
6003      *perl_exception,
6004      *reference;
6005
6006    PERL_UNUSED_VAR(ref);
6007    PERL_UNUSED_VAR(ix);
6008    exception=AcquireExceptionInfo();
6009    perl_exception=newSVpv("",0);
6010    if (sv_isobject(ST(0)) == 0)
6011      {
6012        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6013          PackageName);
6014        goto PerlException;
6015      }
6016    reference=SvRV(ST(0));
6017
6018    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6019    if (image == (Image *) NULL)
6020      {
6021        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6022          PackageName);
6023        goto PerlException;
6024      }
6025
6026    region.x=0;
6027    region.y=0;
6028    region.width=image->columns;
6029    region.height=1;
6030    if (items == 1)
6031      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6032    for (i=2; i < items; i+=2)
6033    {
6034      attribute=(char *) SvPV(ST(i-1),na);
6035      switch (*attribute)
6036      {
6037        case 'g':
6038        case 'G':
6039        {
6040          if (LocaleCompare(attribute,"geometry") == 0)
6041            {
6042              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6043              break;
6044            }
6045          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6046            attribute);
6047          break;
6048        }
6049        case 'H':
6050        case 'h':
6051        {
6052          if (LocaleCompare(attribute,"height") == 0)
6053            {
6054              region.height=SvIV(ST(i));
6055              continue;
6056            }
6057          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6058            attribute);
6059          break;
6060        }
6061        case 'X':
6062        case 'x':
6063        {
6064          if (LocaleCompare(attribute,"x") == 0)
6065            {
6066              region.x=SvIV(ST(i));
6067              continue;
6068            }
6069          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6070            attribute);
6071          break;
6072        }
6073        case 'Y':
6074        case 'y':
6075        {
6076          if (LocaleCompare(attribute,"y") == 0)
6077            {
6078              region.y=SvIV(ST(i));
6079              continue;
6080            }
6081          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6082            attribute);
6083          break;
6084        }
6085        case 'W':
6086        case 'w':
6087        {
6088          if (LocaleCompare(attribute,"width") == 0)
6089            {
6090              region.width=SvIV(ST(i));
6091              continue;
6092            }
6093          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6094            attribute);
6095          break;
6096        }
6097      }
6098    }
6099    blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6100      region.height,exception);
6101    if (blob != (void *) NULL)
6102      goto PerlEnd;
6103
6104  PerlException:
6105    InheritPerlException(exception,perl_exception);
6106    exception=DestroyExceptionInfo(exception);
6107    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6108
6109  PerlEnd:
6110    RETVAL = (void *) blob;
6111  }
6112  OUTPUT:
6113    RETVAL
6114
6115#
6116###############################################################################
6117#                                                                             #
6118#                                                                             #
6119#                                                                             #
6120#   G e t A u t h e n t i c I n d e x Q u e u e                               #
6121#                                                                             #
6122#                                                                             #
6123#                                                                             #
6124###############################################################################
6125#
6126#
6127void *
6128GetAuthenticIndexQueue(ref,...)
6129  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6130  ALIAS:
6131    getauthenticindexqueue = 1
6132    GetIndexes = 2
6133    getindexes = 3
6134  CODE:
6135  {
6136    ExceptionInfo
6137      *exception;
6138
6139    Image
6140      *image;
6141
6142    struct PackageInfo
6143      *info;
6144
6145    SV
6146      *perl_exception,
6147      *reference;
6148
6149    void
6150      *blob = NULL;
6151
6152    PERL_UNUSED_VAR(ref);
6153    PERL_UNUSED_VAR(ix);
6154    exception=AcquireExceptionInfo();
6155    perl_exception=newSVpv("",0);
6156    if (sv_isobject(ST(0)) == 0)
6157      {
6158        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6159          PackageName);
6160        goto PerlException;
6161      }
6162    reference=SvRV(ST(0));
6163
6164    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6165    if (image == (Image *) NULL)
6166      {
6167        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6168          PackageName);
6169        goto PerlException;
6170      }
6171
6172    blob=(void *) GetAuthenticIndexQueue(image);
6173    if (blob != (void *) NULL)
6174      goto PerlEnd;
6175
6176  PerlException:
6177    InheritPerlException(exception,perl_exception);
6178    exception=DestroyExceptionInfo(exception);
6179    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6180
6181  PerlEnd:
6182    RETVAL = blob;
6183  }
6184  OUTPUT:
6185    RETVAL
6186
6187#
6188###############################################################################
6189#                                                                             #
6190#                                                                             #
6191#                                                                             #
6192#   G e t V i r t u a l I n d e x Q u e u e                                   #
6193#                                                                             #
6194#                                                                             #
6195#                                                                             #
6196###############################################################################
6197#
6198#
6199void *
6200GetVirtualIndexQueue(ref,...)
6201  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6202  ALIAS:
6203    getvirtualindexqueue = 1
6204  CODE:
6205  {
6206    ExceptionInfo
6207      *exception;
6208
6209    Image
6210      *image;
6211
6212    struct PackageInfo
6213      *info;
6214
6215    SV
6216      *perl_exception,
6217      *reference;
6218
6219    void
6220      *blob = NULL;
6221
6222    PERL_UNUSED_VAR(ref);
6223    PERL_UNUSED_VAR(ix);
6224    exception=AcquireExceptionInfo();
6225    perl_exception=newSVpv("",0);
6226    if (sv_isobject(ST(0)) == 0)
6227      {
6228        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6229          PackageName);
6230        goto PerlException;
6231      }
6232    reference=SvRV(ST(0));
6233
6234    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6235    if (image == (Image *) NULL)
6236      {
6237        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6238          PackageName);
6239        goto PerlException;
6240      }
6241
6242    blob=(void *) GetVirtualIndexQueue(image);
6243    if (blob != (void *) NULL)
6244      goto PerlEnd;
6245
6246  PerlException:
6247    InheritPerlException(exception,perl_exception);
6248    exception=DestroyExceptionInfo(exception);
6249    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6250
6251  PerlEnd:
6252    RETVAL = blob;
6253  }
6254  OUTPUT:
6255    RETVAL
6256
6257#
6258###############################################################################
6259#                                                                             #
6260#                                                                             #
6261#                                                                             #
6262#   H i s t o g r a m                                                         #
6263#                                                                             #
6264#                                                                             #
6265#                                                                             #
6266###############################################################################
6267#
6268#
6269void
6270Histogram(ref,...)
6271  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6272  ALIAS:
6273    HistogramImage = 1
6274    histogram      = 2
6275    histogramimage = 3
6276  PPCODE:
6277  {
6278    AV
6279      *av;
6280
6281    char
6282      message[MaxTextExtent];
6283
6284    ColorPacket
6285      *histogram;
6286
6287    ExceptionInfo
6288      *exception;
6289
6290    Image
6291      *image;
6292
6293    ssize_t
6294      i;
6295
6296    ssize_t
6297      count;
6298
6299    struct PackageInfo
6300      *info;
6301
6302    SV
6303      *perl_exception,
6304      *reference;
6305
6306    size_t
6307      number_colors;
6308
6309    PERL_UNUSED_VAR(ref);
6310    PERL_UNUSED_VAR(ix);
6311    exception=AcquireExceptionInfo();
6312    perl_exception=newSVpv("",0);
6313    av=NULL;
6314    if (sv_isobject(ST(0)) == 0)
6315      {
6316        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6317          PackageName);
6318        goto PerlException;
6319      }
6320    reference=SvRV(ST(0));
6321    av=newAV();
6322    SvREFCNT_dec(av);
6323    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6324    if (image == (Image *) NULL)
6325      {
6326        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6327          PackageName);
6328        goto PerlException;
6329      }
6330    count=0;
6331    for ( ; image; image=image->next)
6332    {
6333      histogram=GetImageHistogram(image,&number_colors,&image->exception);
6334      if (histogram == (ColorPacket *) NULL)
6335        continue;
6336      count+=(ssize_t) number_colors;
6337      EXTEND(sp,6*count);
6338      for (i=0; i < (ssize_t) number_colors; i++)
6339      {
6340        (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6341          histogram[i].pixel.red);
6342        PUSHs(sv_2mortal(newSVpv(message,0)));
6343        (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6344          histogram[i].pixel.green);
6345        PUSHs(sv_2mortal(newSVpv(message,0)));
6346        (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6347          histogram[i].pixel.blue);
6348        PUSHs(sv_2mortal(newSVpv(message,0)));
6349        if (image->colorspace == CMYKColorspace)
6350          {
6351            (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6352              histogram[i].index);
6353            PUSHs(sv_2mortal(newSVpv(message,0)));
6354          }
6355        (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6356          histogram[i].pixel.opacity);
6357        PUSHs(sv_2mortal(newSVpv(message,0)));
6358        (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6359          histogram[i].count);
6360        PUSHs(sv_2mortal(newSVpv(message,0)));
6361      }
6362      histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
6363    }
6364
6365  PerlException:
6366    InheritPerlException(exception,perl_exception);
6367    exception=DestroyExceptionInfo(exception);
6368    SvREFCNT_dec(perl_exception);
6369  }
6370
6371#
6372###############################################################################
6373#                                                                             #
6374#                                                                             #
6375#                                                                             #
6376#   G e t P i x e l                                                           #
6377#                                                                             #
6378#                                                                             #
6379#                                                                             #
6380###############################################################################
6381#
6382#
6383void
6384GetPixel(ref,...)
6385  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6386  ALIAS:
6387    getpixel = 1
6388    getPixel = 2
6389  PPCODE:
6390  {
6391    AV
6392      *av;
6393
6394    char
6395      *attribute;
6396
6397    ChannelType
6398      channel;
6399
6400    ExceptionInfo
6401      *exception;
6402
6403    Image
6404      *image;
6405
6406    MagickBooleanType
6407      normalize;
6408
6409    RectangleInfo
6410      region;
6411
6412    const IndexPacket
6413      *indexes;
6414
6415    const PixelPacket
6416      *p;
6417
6418    ssize_t
6419      i;
6420
6421    ssize_t
6422      option;
6423
6424    struct PackageInfo
6425      *info;
6426
6427    SV
6428      *perl_exception,
6429      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6430
6431    PERL_UNUSED_VAR(ref);
6432    PERL_UNUSED_VAR(ix);
6433    exception=AcquireExceptionInfo();
6434    perl_exception=newSVpv("",0);
6435    reference=SvRV(ST(0));
6436    av=(AV *) reference;
6437    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6438      exception);
6439    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6440    if (image == (Image *) NULL)
6441      {
6442        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6443          PackageName);
6444        goto PerlException;
6445      }
6446    channel=DefaultChannels;
6447    normalize=MagickTrue;
6448    region.x=0;
6449    region.y=0;
6450    region.width=image->columns;
6451    region.height=1;
6452    if (items == 1)
6453      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6454    for (i=2; i < items; i+=2)
6455    {
6456      attribute=(char *) SvPV(ST(i-1),na);
6457      switch (*attribute)
6458      {
6459        case 'C':
6460        case 'c':
6461        {
6462          if (LocaleCompare(attribute,"channel") == 0)
6463            {
6464              ssize_t
6465                option;
6466
6467              option=ParseChannelOption(SvPV(ST(i),na));
6468              if (option < 0)
6469                {
6470                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6471                    SvPV(ST(i),na));
6472                  return;
6473                }
6474               channel=(ChannelType) option;
6475              break;
6476            }
6477          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6478            attribute);
6479          break;
6480        }
6481        case 'g':
6482        case 'G':
6483        {
6484          if (LocaleCompare(attribute,"geometry") == 0)
6485            {
6486              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6487              break;
6488            }
6489          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6490            attribute);
6491          break;
6492        }
6493        case 'N':
6494        case 'n':
6495        {
6496          if (LocaleCompare(attribute,"normalize") == 0)
6497            {
6498              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6499                SvPV(ST(i),na));
6500              if (option < 0)
6501                {
6502                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6503                    SvPV(ST(i),na));
6504                  break;
6505                }
6506             normalize=option != 0 ? MagickTrue : MagickFalse;
6507             break;
6508            }
6509          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6510            attribute);
6511          break;
6512        }
6513        case 'x':
6514        case 'X':
6515        {
6516          if (LocaleCompare(attribute,"x") == 0)
6517            {
6518              region.x=SvIV(ST(i));
6519              break;
6520            }
6521          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6522            attribute);
6523          break;
6524        }
6525        case 'y':
6526        case 'Y':
6527        {
6528          if (LocaleCompare(attribute,"y") == 0)
6529            {
6530              region.y=SvIV(ST(i));
6531              break;
6532            }
6533          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6534            attribute);
6535          break;
6536        }
6537        default:
6538        {
6539          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6540            attribute);
6541          break;
6542        }
6543      }
6544    }
6545    p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6546    if (p == (const PixelPacket *) NULL)
6547      PUSHs(&sv_undef);
6548    else
6549      {
6550        double
6551          scale;
6552
6553        indexes=GetVirtualIndexQueue(image);
6554        scale=1.0;
6555        if (normalize != MagickFalse)
6556          scale=1.0/QuantumRange;
6557        if ((channel & RedChannel) != 0)
6558          PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(p))));
6559        if ((channel & GreenChannel) != 0)
6560          PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(p))));
6561        if ((channel & BlueChannel) != 0)
6562          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(p))));
6563        if (((channel & IndexChannel) != 0) &&
6564            (image->colorspace == CMYKColorspace))
6565          PUSHs(sv_2mortal(newSVnv(scale*GetPixelIndex(indexes))));
6566        if ((channel & OpacityChannel) != 0)
6567          PUSHs(sv_2mortal(newSVnv(scale*GetPixelOpacity(p))));
6568      }
6569
6570  PerlException:
6571    InheritPerlException(exception,perl_exception);
6572    exception=DestroyExceptionInfo(exception);
6573    SvREFCNT_dec(perl_exception);
6574  }
6575
6576#
6577###############################################################################
6578#                                                                             #
6579#                                                                             #
6580#                                                                             #
6581#   G e t P i x e l s                                                         #
6582#                                                                             #
6583#                                                                             #
6584#                                                                             #
6585###############################################################################
6586#
6587#
6588void
6589GetPixels(ref,...)
6590  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6591  ALIAS:
6592    getpixels = 1
6593    getPixels = 2
6594  PPCODE:
6595  {
6596    AV
6597      *av;
6598
6599    char
6600      *attribute;
6601
6602    const char
6603      *map;
6604
6605    ExceptionInfo
6606      *exception;
6607
6608    Image
6609      *image;
6610
6611    MagickBooleanType
6612      normalize,
6613      status;
6614
6615    RectangleInfo
6616      region;
6617
6618    ssize_t
6619      i;
6620
6621    ssize_t
6622      option;
6623
6624    struct PackageInfo
6625      *info;
6626
6627    SV
6628      *perl_exception,
6629      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6630
6631    PERL_UNUSED_VAR(ref);
6632    PERL_UNUSED_VAR(ix);
6633    exception=AcquireExceptionInfo();
6634    perl_exception=newSVpv("",0);
6635    reference=SvRV(ST(0));
6636    av=(AV *) reference;
6637    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6638      exception);
6639    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6640    if (image == (Image *) NULL)
6641      {
6642        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6643          PackageName);
6644        goto PerlException;
6645      }
6646    map="RGB";
6647    if (image->matte != MagickFalse)
6648      map="RGBA";
6649    if (image->colorspace == CMYKColorspace)
6650      {
6651        map="CMYK";
6652        if (image->matte != MagickFalse)
6653          map="CMYKA";
6654      }
6655    normalize=MagickFalse;
6656    region.x=0;
6657    region.y=0;
6658    region.width=image->columns;
6659    region.height=1;
6660    if (items == 1)
6661      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6662    for (i=2; i < items; i+=2)
6663    {
6664      attribute=(char *) SvPV(ST(i-1),na);
6665      switch (*attribute)
6666      {
6667        case 'g':
6668        case 'G':
6669        {
6670          if (LocaleCompare(attribute,"geometry") == 0)
6671            {
6672              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6673              break;
6674            }
6675          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6676            attribute);
6677          break;
6678        }
6679        case 'H':
6680        case 'h':
6681        {
6682          if (LocaleCompare(attribute,"height") == 0)
6683            {
6684              region.height=SvIV(ST(i));
6685              break;
6686            }
6687          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6688            attribute);
6689          break;
6690        }
6691        case 'M':
6692        case 'm':
6693        {
6694          if (LocaleCompare(attribute,"map") == 0)
6695            {
6696              map=SvPV(ST(i),na);
6697              break;
6698            }
6699          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6700            attribute);
6701          break;
6702        }
6703        case 'N':
6704        case 'n':
6705        {
6706          if (LocaleCompare(attribute,"normalize") == 0)
6707            {
6708              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6709                SvPV(ST(i),na));
6710              if (option < 0)
6711                {
6712                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6713                    SvPV(ST(i),na));
6714                  break;
6715                }
6716             normalize=option != 0 ? MagickTrue : MagickFalse;
6717             break;
6718            }
6719          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6720            attribute);
6721          break;
6722        }
6723        case 'W':
6724        case 'w':
6725        {
6726          if (LocaleCompare(attribute,"width") == 0)
6727            {
6728              region.width=SvIV(ST(i));
6729              break;
6730            }
6731          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6732            attribute);
6733          break;
6734        }
6735        case 'x':
6736        case 'X':
6737        {
6738          if (LocaleCompare(attribute,"x") == 0)
6739            {
6740              region.x=SvIV(ST(i));
6741              break;
6742            }
6743          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6744            attribute);
6745          break;
6746        }
6747        case 'y':
6748        case 'Y':
6749        {
6750          if (LocaleCompare(attribute,"y") == 0)
6751            {
6752              region.y=SvIV(ST(i));
6753              break;
6754            }
6755          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6756            attribute);
6757          break;
6758        }
6759        default:
6760        {
6761          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6762            attribute);
6763          break;
6764        }
6765      }
6766    }
6767    if (normalize != MagickFalse)
6768      {
6769        float
6770          *pixels;
6771
6772        MemoryInfo
6773          *pixels_info;
6774
6775        pixels_info=AcquireVirtualMemory(strlen(map)*region.width,
6776          region.height*sizeof(*pixels));
6777        if (pixels_info == (MemoryInfo *) NULL)
6778          {
6779            ThrowPerlException(exception,ResourceLimitError,
6780              "MemoryAllocationFailed",PackageName);
6781            goto PerlException;
6782          }
6783        pixels=(float *) GetVirtualMemoryBlob(pixels_info);
6784        status=ExportImagePixels(image,region.x,region.y,region.width,
6785          region.height,map,FloatPixel,pixels,exception);
6786        if (status == MagickFalse)
6787          PUSHs(&sv_undef);
6788        else
6789          {
6790            EXTEND(sp,strlen(map)*region.width*region.height);
6791            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6792              PUSHs(sv_2mortal(newSVnv(pixels[i])));
6793          }
6794        pixels_info=RelinquishVirtualMemory(pixels_info);
6795      }
6796    else
6797      {
6798        MemoryInfo
6799          *pixels_info;
6800
6801        Quantum
6802          *pixels;
6803
6804        pixels_info=AcquireVirtualMemory(strlen(map)*region.width,
6805          region.height*sizeof(*pixels));
6806        if (pixels_info == (MemoryInfo *) NULL)
6807          {
6808            ThrowPerlException(exception,ResourceLimitError,
6809              "MemoryAllocationFailed",PackageName);
6810            goto PerlException;
6811          }
6812        pixels=(Quantum *) GetVirtualMemoryBlob(pixels_info);
6813        status=ExportImagePixels(image,region.x,region.y,region.width,
6814          region.height,map,QuantumPixel,pixels,exception);
6815        if (status == MagickFalse)
6816          PUSHs(&sv_undef);
6817        else
6818          {
6819            EXTEND(sp,strlen(map)*region.width*region.height);
6820            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6821              PUSHs(sv_2mortal(newSViv(pixels[i])));
6822          }
6823        pixels_info=RelinquishVirtualMemory(pixels_info);
6824      }
6825
6826  PerlException:
6827    InheritPerlException(exception,perl_exception);
6828    exception=DestroyExceptionInfo(exception);
6829    SvREFCNT_dec(perl_exception);
6830  }
6831
6832#
6833###############################################################################
6834#                                                                             #
6835#                                                                             #
6836#                                                                             #
6837#   I m a g e T o B l o b                                                     #
6838#                                                                             #
6839#                                                                             #
6840#                                                                             #
6841###############################################################################
6842#
6843#
6844void
6845ImageToBlob(ref,...)
6846  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6847  ALIAS:
6848    ImageToBlob  = 1
6849    imagetoblob  = 2
6850    toblob       = 3
6851    blob         = 4
6852  PPCODE:
6853  {
6854    char
6855      filename[MaxTextExtent];
6856
6857    ExceptionInfo
6858      *exception;
6859
6860    Image
6861      *image,
6862      *next;
6863
6864    ssize_t
6865      i;
6866
6867    struct PackageInfo
6868      *info,
6869      *package_info;
6870
6871    size_t
6872      length;
6873
6874    ssize_t
6875      scene;
6876
6877    SV
6878      *perl_exception,
6879      *reference;
6880
6881    void
6882      *blob;
6883
6884    PERL_UNUSED_VAR(ref);
6885    PERL_UNUSED_VAR(ix);
6886    exception=AcquireExceptionInfo();
6887    perl_exception=newSVpv("",0);
6888    package_info=(struct PackageInfo *) NULL;
6889    if (sv_isobject(ST(0)) == 0)
6890      {
6891        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6892          PackageName);
6893        goto PerlException;
6894      }
6895    reference=SvRV(ST(0));
6896    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6897    if (image == (Image *) NULL)
6898      {
6899        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6900          PackageName);
6901        goto PerlException;
6902      }
6903    package_info=ClonePackageInfo(info,exception);
6904    for (i=2; i < items; i+=2)
6905      SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6906    (void) CopyMagickString(filename,package_info->image_info->filename,
6907      MaxTextExtent);
6908    scene=0;
6909    for (next=image; next; next=next->next)
6910    {
6911      (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6912      next->scene=scene++;
6913    }
6914    SetImageInfo(package_info->image_info,(unsigned int)
6915      GetImageListLength(image),&image->exception);
6916    EXTEND(sp,(ssize_t) GetImageListLength(image));
6917    for ( ; image; image=image->next)
6918    {
6919      length=0;
6920      blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6921      if (blob != (char *) NULL)
6922        {
6923          PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6924          blob=(unsigned char *) RelinquishMagickMemory(blob);
6925        }
6926      if (package_info->image_info->adjoin)
6927        break;
6928    }
6929
6930  PerlException:
6931    if (package_info != (struct PackageInfo *) NULL)
6932      DestroyPackageInfo(package_info);
6933    InheritPerlException(exception,perl_exception);
6934    exception=DestroyExceptionInfo(exception);
6935    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6936  }
6937
6938#
6939###############################################################################
6940#                                                                             #
6941#                                                                             #
6942#                                                                             #
6943#   L a y e r s                                                               #
6944#                                                                             #
6945#                                                                             #
6946#                                                                             #
6947###############################################################################
6948#
6949#
6950void
6951Layers(ref,...)
6952  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6953  ALIAS:
6954    Layers                = 1
6955    layers           = 2
6956    OptimizeImageLayers   = 3
6957    optimizelayers        = 4
6958    optimizeimagelayers   = 5
6959  PPCODE:
6960  {
6961    AV
6962      *av;
6963
6964    char
6965      *attribute;
6966
6967    CompositeOperator
6968      compose;
6969
6970    ExceptionInfo
6971      *exception;
6972
6973    HV
6974      *hv;
6975
6976    Image
6977      *image,
6978      *layers;
6979
6980    ImageLayerMethod
6981      method;
6982
6983    ssize_t
6984      i;
6985
6986    ssize_t
6987      option,
6988      sp;
6989
6990    struct PackageInfo
6991      *info;
6992
6993    SV
6994      *av_reference,
6995      *perl_exception,
6996      *reference,
6997      *rv,
6998      *sv;
6999
7000    PERL_UNUSED_VAR(ref);
7001    PERL_UNUSED_VAR(ix);
7002    exception=AcquireExceptionInfo();
7003    perl_exception=newSVpv("",0);
7004    sv=NULL;
7005    if (sv_isobject(ST(0)) == 0)
7006      {
7007        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7008          PackageName);
7009        goto PerlException;
7010      }
7011    reference=SvRV(ST(0));
7012    hv=SvSTASH(reference);
7013    av=newAV();
7014    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7015    SvREFCNT_dec(av);
7016    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7017    if (image == (Image *) NULL)
7018      {
7019        ThrowPerlException(exception,OptionError,"NoImagesDefined",
7020          PackageName);
7021        goto PerlException;
7022      }
7023    compose=image->compose;
7024    method=OptimizeLayer;
7025    for (i=2; i < items; i+=2)
7026    {
7027      attribute=(char *) SvPV(ST(i-1),na);
7028      switch (*attribute)
7029      {
7030        case 'C':
7031        case 'c':
7032        {
7033          if (LocaleCompare(attribute,"compose") == 0)
7034            {
7035              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7036                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7037              if (sp < 0)
7038                {
7039                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7040                    SvPV(ST(i),na));
7041                  break;
7042                }
7043              compose=(CompositeOperator) sp;
7044              break;
7045            }
7046          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7047            attribute);
7048          break;
7049        }
7050        case 'M':
7051        case 'm':
7052        {
7053          if (LocaleCompare(attribute,"method") == 0)
7054            {
7055              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7056                SvPV(ST(i),na));
7057              if (option < 0)
7058                {
7059                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7060                    SvPV(ST(i),na));
7061                  break;
7062                }
7063              method=(ImageLayerMethod) option;
7064              break;
7065            }
7066          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7067            attribute);
7068          break;
7069        }
7070        default:
7071        {
7072          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7073            attribute);
7074          break;
7075        }
7076      }
7077    }
7078    layers=(Image *) NULL;
7079    switch (method)
7080    {
7081      case CompareAnyLayer:
7082      case CompareClearLayer:
7083      case CompareOverlayLayer:
7084      default:
7085      {
7086        layers=CompareImageLayers(image,method,exception);
7087        break;
7088      }
7089      case MergeLayer:
7090      case FlattenLayer:
7091      case MosaicLayer:
7092      {
7093        layers=MergeImageLayers(image,method,exception);
7094        break;
7095      }
7096      case DisposeLayer:
7097      {
7098        layers=DisposeImages(image,exception);
7099        break;
7100      }
7101      case OptimizeImageLayer:
7102      {
7103        layers=OptimizeImageLayers(image,exception);
7104        break;
7105      }
7106      case OptimizePlusLayer:
7107      {
7108        layers=OptimizePlusImageLayers(image,exception);
7109        break;
7110      }
7111      case OptimizeTransLayer:
7112      {
7113        OptimizeImageTransparency(image,exception);
7114        InheritException(&(image->exception),exception);
7115        break;
7116      }
7117      case RemoveDupsLayer:
7118      {
7119        RemoveDuplicateLayers(&image,exception);
7120        InheritException(&(image->exception),exception);
7121        break;
7122      }
7123      case RemoveZeroLayer:
7124      {
7125        RemoveZeroDelayLayers(&image,exception);
7126        InheritException(&(image->exception),exception);
7127        break;
7128      }
7129      case OptimizeLayer:
7130      {
7131        QuantizeInfo
7132          *quantize_info;
7133
7134        /*
7135          General Purpose, GIF Animation Optimizer.
7136        */
7137        layers=CoalesceImages(image,exception);
7138        if (layers == (Image *) NULL)
7139          break;
7140        InheritException(&(layers->exception),exception);
7141        image=layers;
7142        layers=OptimizeImageLayers(image,exception);
7143        if (layers == (Image *) NULL)
7144          break;
7145        InheritException(&(layers->exception),exception);
7146        image=DestroyImageList(image);
7147        image=layers;
7148        layers=(Image *) NULL;
7149        OptimizeImageTransparency(image,exception);
7150        InheritException(&(image->exception),exception);
7151        quantize_info=AcquireQuantizeInfo(info->image_info);
7152        (void) RemapImages(quantize_info,image,(Image *) NULL);
7153        quantize_info=DestroyQuantizeInfo(quantize_info);
7154        break;
7155      }
7156      case CompositeLayer:
7157      {
7158        Image
7159          *source;
7160
7161        RectangleInfo
7162          geometry;
7163
7164        /*
7165          Split image sequence at the first 'NULL:' image.
7166        */
7167        source=image;
7168        while (source != (Image *) NULL)
7169        {
7170          source=GetNextImageInList(source);
7171          if ((source != (Image *) NULL) &&
7172              (LocaleCompare(source->magick,"NULL") == 0))
7173            break;
7174        }
7175        if (source != (Image *) NULL)
7176          {
7177            if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7178                (GetNextImageInList(source) == (Image *) NULL))
7179              source=(Image *) NULL;
7180            else
7181              {
7182                /*
7183                  Separate the two lists, junk the null: image.
7184                */
7185                source=SplitImageList(source->previous);
7186                DeleteImageFromList(&source);
7187              }
7188          }
7189        if (source == (Image *) NULL)
7190          {
7191            (void) ThrowMagickException(exception,GetMagickModule(),
7192              OptionError,"MissingNullSeparator","layers Composite");
7193            break;
7194          }
7195        /*
7196          Adjust offset with gravity and virtual canvas.
7197        */
7198        SetGeometry(image,&geometry);
7199        (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7200        geometry.width=source->page.width != 0 ? source->page.width :
7201          source->columns;
7202        geometry.height=source->page.height != 0 ? source->page.height :
7203          source->rows;
7204        GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7205          image->columns,image->page.height != 0 ? image->page.height :
7206          image->rows,image->gravity,&geometry);
7207        CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7208        source=DestroyImageList(source);
7209        InheritException(&(image->exception),exception);
7210        break;
7211      }
7212    }
7213    if (layers == (Image *) NULL)
7214      image=CloneImage(image,0,0,MagickTrue,exception);
7215    else
7216      {
7217        InheritException(&(layers->exception),exception);
7218        image=layers;
7219      }
7220    if (image == (Image *) NULL)
7221      goto PerlException;
7222    for ( ; image; image=image->next)
7223    {
7224      AddImageToRegistry(sv,image);
7225      rv=newRV(sv);
7226      av_push(av,sv_bless(rv,hv));
7227      SvREFCNT_dec(sv);
7228    }
7229    exception=DestroyExceptionInfo(exception);
7230    ST(0)=av_reference;
7231    SvREFCNT_dec(perl_exception);
7232    XSRETURN(1);
7233
7234  PerlException:
7235    InheritPerlException(exception,perl_exception);
7236    exception=DestroyExceptionInfo(exception);
7237    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7238    SvPOK_on(perl_exception);
7239    ST(0)=sv_2mortal(perl_exception);
7240    XSRETURN(1);
7241  }
7242
7243#
7244###############################################################################
7245#                                                                             #
7246#                                                                             #
7247#                                                                             #
7248#   M a g i c k T o M i m e                                                   #
7249#                                                                             #
7250#                                                                             #
7251#                                                                             #
7252###############################################################################
7253#
7254#
7255SV *
7256MagickToMime(ref,name)
7257  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7258  char *name
7259  ALIAS:
7260    magicktomime = 1
7261  CODE:
7262  {
7263    char
7264      *mime;
7265
7266    PERL_UNUSED_VAR(ref);
7267    PERL_UNUSED_VAR(ix);
7268    mime=MagickToMime(name);
7269    RETVAL=newSVpv(mime,0);
7270    mime=(char *) RelinquishMagickMemory(mime);
7271  }
7272  OUTPUT:
7273    RETVAL
7274
7275#
7276###############################################################################
7277#                                                                             #
7278#                                                                             #
7279#                                                                             #
7280#   M o g r i f y                                                             #
7281#                                                                             #
7282#                                                                             #
7283#                                                                             #
7284###############################################################################
7285#
7286#
7287void
7288Mogrify(ref,...)
7289  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7290  ALIAS:
7291    Comment            =   1
7292    CommentImage       =   2
7293    Label              =   3
7294    LabelImage         =   4
7295    AddNoise           =   5
7296    AddNoiseImage      =   6
7297    Colorize           =   7
7298    ColorizeImage      =   8
7299    Border             =   9
7300    BorderImage        =  10
7301    Blur               =  11
7302    BlurImage          =  12
7303    Chop               =  13
7304    ChopImage          =  14
7305    Crop               =  15
7306    CropImage          =  16
7307    Despeckle          =  17
7308    DespeckleImage     =  18
7309    Edge               =  19
7310    EdgeImage          =  20
7311    Emboss             =  21
7312    EmbossImage        =  22
7313    Enhance            =  23
7314    EnhanceImage       =  24
7315    Flip               =  25
7316    FlipImage          =  26
7317    Flop               =  27
7318    FlopImage          =  28
7319    Frame              =  29
7320    FrameImage         =  30
7321    Implode            =  31
7322    ImplodeImage       =  32
7323    Magnify            =  33
7324    MagnifyImage       =  34
7325    MedianFilter       =  35
7326    MedianFilterImage  =  36
7327    Minify             =  37
7328    MinifyImage        =  38
7329    OilPaint           =  39
7330    OilPaintImage      =  40
7331    ReduceNoise        =  41
7332    ReduceNoiseImage   =  42
7333    Roll               =  43
7334    RollImage          =  44
7335    Rotate             =  45
7336    RotateImage        =  46
7337    Sample             =  47
7338    SampleImage        =  48
7339    Scale              =  49
7340    ScaleImage         =  50
7341    Shade              =  51
7342    ShadeImage         =  52
7343    Sharpen            =  53
7344    SharpenImage       =  54
7345    Shear              =  55
7346    ShearImage         =  56
7347    Spread             =  57
7348    SpreadImage        =  58
7349    Swirl              =  59
7350    SwirlImage         =  60
7351    Resize             =  61
7352    ResizeImage        =  62
7353    Zoom               =  63
7354    ZoomImage          =  64
7355    Annotate           =  65
7356    AnnotateImage      =  66
7357    ColorFloodfill     =  67
7358    ColorFloodfillImage=  68
7359    Composite          =  69
7360    CompositeImage     =  70
7361    Contrast           =  71
7362    ContrastImage      =  72
7363    CycleColormap      =  73
7364    CycleColormapImage =  74
7365    Draw               =  75
7366    DrawImage          =  76
7367    Equalize           =  77
7368    EqualizeImage      =  78
7369    Gamma              =  79
7370    GammaImage         =  80
7371    Map                =  81
7372    MapImage           =  82
7373    MatteFloodfill     =  83
7374    MatteFloodfillImage=  84
7375    Modulate           =  85
7376    ModulateImage      =  86
7377    Negate             =  87
7378    NegateImage        =  88
7379    Normalize          =  89
7380    NormalizeImage     =  90
7381    NumberColors       =  91
7382    NumberColorsImage  =  92
7383    Opaque             =  93
7384    OpaqueImage        =  94
7385    Quantize           =  95
7386    QuantizeImage      =  96
7387    Raise              =  97
7388    RaiseImage         =  98
7389    Segment            =  99
7390    SegmentImage       = 100
7391    Signature          = 101
7392    SignatureImage     = 102
7393    Solarize           = 103
7394    SolarizeImage      = 104
7395    Sync               = 105
7396    SyncImage          = 106
7397    Texture            = 107
7398    TextureImage       = 108
7399    Evaluate           = 109
7400    EvaluateImage      = 110
7401    Transparent        = 111
7402    TransparentImage   = 112
7403    Threshold          = 113
7404    ThresholdImage     = 114
7405    Charcoal           = 115
7406    CharcoalImage      = 116
7407    Trim               = 117
7408    TrimImage          = 118
7409    Wave               = 119
7410    WaveImage          = 120
7411    Separate           = 121
7412    SeparateImage      = 122
7413    Stereo             = 125
7414    StereoImage        = 126
7415    Stegano            = 127
7416    SteganoImage       = 128
7417    Deconstruct        = 129
7418    DeconstructImage   = 130
7419    GaussianBlur       = 131
7420    GaussianBlurImage  = 132
7421    Convolve           = 133
7422    ConvolveImage      = 134
7423    Profile            = 135
7424    ProfileImage       = 136
7425    UnsharpMask        = 137
7426    UnsharpMaskImage   = 138
7427    MotionBlur         = 139
7428    MotionBlurImage    = 140
7429    OrderedDither      = 141
7430    OrderedDitherImage = 142
7431    Shave              = 143
7432    ShaveImage         = 144
7433    Level              = 145
7434    LevelImage         = 146
7435    Clip               = 147
7436    ClipImage          = 148
7437    AffineTransform    = 149
7438    AffineTransformImage = 150
7439    Difference         = 151
7440    DifferenceImage    = 152
7441    AdaptiveThreshold  = 153
7442    AdaptiveThresholdImage = 154
7443    Resample           = 155
7444    ResampleImage      = 156
7445    Describe           = 157
7446    DescribeImage      = 158
7447    BlackThreshold     = 159
7448    BlackThresholdImage= 160
7449    WhiteThreshold     = 161
7450    WhiteThresholdImage= 162
7451    RotationalBlur     = 163
7452    RotationalBlurImage= 164
7453    Thumbnail          = 165
7454    ThumbnailImage     = 166
7455    Strip              = 167
7456    StripImage         = 168
7457    Tint               = 169
7458    TintImage          = 170
7459    Channel            = 171
7460    ChannelImage       = 172
7461    Splice             = 173
7462    SpliceImage        = 174
7463    Posterize          = 175
7464    PosterizeImage     = 176
7465    Shadow             = 177
7466    ShadowImage        = 178
7467    Identify           = 179
7468    IdentifyImage      = 180
7469    SepiaTone          = 181
7470    SepiaToneImage     = 182
7471    SigmoidalContrast  = 183
7472    SigmoidalContrastImage = 184
7473    Extent             = 185
7474    ExtentImage        = 186
7475    Vignette           = 187
7476    VignetteImage      = 188
7477    ContrastStretch    = 189
7478    ContrastStretchImage = 190
7479    Sans0              = 191
7480    Sans0Image         = 192
7481    Sans1              = 193
7482    Sans1Image         = 194
7483    AdaptiveSharpen    = 195
7484    AdaptiveSharpenImage = 196
7485    Transpose          = 197
7486    TransposeImage     = 198
7487    Transverse         = 199
7488    TransverseImage    = 200
7489    AutoOrient         = 201
7490    AutoOrientImage    = 202
7491    AdaptiveBlur       = 203
7492    AdaptiveBlurImage  = 204
7493    Sketch             = 205
7494    SketchImage        = 206
7495    UniqueColors       = 207
7496    UniqueColorsImage  = 208
7497    AdaptiveResize     = 209
7498    AdaptiveResizeImage= 210
7499    ClipMask           = 211
7500    ClipMaskImage      = 212
7501    LinearStretch      = 213
7502    LinearStretchImage = 214
7503    RecolorImage       = 215
7504    Recolor            = 216
7505    Mask               = 217
7506    MaskImage          = 218
7507    Polaroid           = 219
7508    PolaroidImage      = 220
7509    FloodfillPaint     = 221
7510    FloodfillPaintImage= 222
7511    Distort            = 223
7512    DistortImage       = 224
7513    Clut               = 225
7514    ClutImage          = 226
7515    LiquidRescale      = 227
7516    LiquidRescaleImage = 228
7517    Encipher           = 229
7518    EncipherImage      = 230
7519    Decipher           = 231
7520    DecipherImage      = 232
7521    Deskew             = 233
7522    DeskewImage        = 234
7523    Remap              = 235
7524    RemapImage         = 236
7525    SparseColor        = 237
7526    SparseColorImage   = 238
7527    Function           = 239
7528    FunctionImage      = 240
7529    SelectiveBlur      = 241
7530    SelectiveBlurImage = 242
7531    HaldClut           = 243
7532    HaldClutImage      = 244
7533    BlueShift          = 245
7534    BlueShiftImage     = 246
7535    ForwardFourierTransform  = 247
7536    ForwardFourierTransformImage = 248
7537    InverseFourierTransform = 249
7538    InverseFourierTransformImage = 250
7539    ColorDecisionList  = 251
7540    ColorDecisionListImage = 252
7541    AutoGamma          = 253
7542    AutoGammaImage     = 254
7543    AutoLevel          = 255
7544    AutoLevelImage     = 256
7545    LevelColors        = 257
7546    LevelColorsImage   = 258
7547    Clamp              = 259
7548    ClampImage         = 260
7549    Filter             = 261
7550    FilterImage        = 262
7551    BrightnessContrast = 263
7552    BrightnessContrastImage = 264
7553    Morphology         = 265
7554    MorphologyImage    = 266
7555    ColorMatrix        = 267
7556    ColorMatrixImage   = 268
7557    Color              = 269
7558    ColorImage         = 270
7559    Mode               = 271
7560    ModeImage          = 272
7561    Statistic          = 273
7562    StatisticImage     = 274
7563    Perceptible        = 275
7564    PerceptibleImage   = 276
7565    Poly               = 277
7566    PolyImage          = 278
7567    Grayscale          = 279
7568    GrayscaleImage     = 280
7569    CannyEdge          = 281
7570    CannyEdgeImage     = 282
7571    HoughLine          = 283
7572    HoughLineImage     = 284
7573    MeanShift          = 285
7574    MeanShiftImage     = 286
7575    Kuwahara           = 287
7576    KuwaharaImage      = 288
7577    ConnectedComponents= 289
7578    ConnectedComponentsImage = 290
7579    CopyPixels         = 291
7580    CopyImagePixels    = 292
7581    WaveletDenoise     = 293
7582    WaveletDenoiseImage= 294
7583    Colorspace         = 295
7584    ColorspaceImage    = 296
7585    AutoThreshold      = 297
7586    AutoThresholdImage = 298
7587    MogrifyRegion      = 666
7588  PPCODE:
7589  {
7590    AffineMatrix
7591      affine,
7592      current;
7593
7594    char
7595      attribute_flag[MaxArguments],
7596      message[MaxTextExtent];
7597
7598    ChannelType
7599      channel;
7600
7601    CompositeOperator
7602      compose;
7603
7604    const char
7605      *attribute,
7606      *value;
7607
7608    double
7609      angle;
7610
7611    ExceptionInfo
7612      *exception;
7613
7614    GeometryInfo
7615      geometry_info;
7616
7617    Image
7618      *image,
7619      *next,
7620      *region_image;
7621
7622    MagickBooleanType
7623      status;
7624
7625    MagickStatusType
7626      flags;
7627
7628    PixelPacket
7629      fill_color;
7630
7631    RectangleInfo
7632      geometry,
7633      region_info;
7634
7635    ssize_t
7636      i;
7637
7638    ssize_t
7639      base,
7640      j,
7641      number_images;
7642
7643    struct Methods
7644      *rp;
7645
7646    struct PackageInfo
7647      *info;
7648
7649    SV
7650      *perl_exception,
7651      **pv,
7652      *reference,
7653      **reference_vector;
7654
7655    struct ArgumentList
7656      argument_list[MaxArguments];
7657
7658    PERL_UNUSED_VAR(ref);
7659    PERL_UNUSED_VAR(ix);
7660    exception=AcquireExceptionInfo();
7661    perl_exception=newSVpv("",0);
7662    reference_vector=NULL;
7663    region_image=NULL;
7664    number_images=0;
7665    base=2;
7666    if (sv_isobject(ST(0)) == 0)
7667      {
7668        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7669          PackageName);
7670        goto PerlException;
7671      }
7672    reference=SvRV(ST(0));
7673    region_info.width=0;
7674    region_info.height=0;
7675    region_info.x=0;
7676    region_info.y=0;
7677    region_image=(Image *) NULL;
7678    image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7679    if (ix && (ix != 666))
7680      {
7681        /*
7682          Called as Method(...)
7683        */
7684        ix=(ix+1)/2;
7685        rp=(&Methods[ix-1]);
7686        attribute=rp->name;
7687      }
7688    else
7689      {
7690        /*
7691          Called as Mogrify("Method",...)
7692        */
7693        attribute=(char *) SvPV(ST(1),na);
7694        if (ix)
7695          {
7696            flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7697            attribute=(char *) SvPV(ST(2),na);
7698            base++;
7699          }
7700        for (rp=Methods; ; rp++)
7701        {
7702          if (rp >= EndOf(Methods))
7703            {
7704              ThrowPerlException(exception,OptionError,
7705                "UnrecognizedPerlMagickMethod",attribute);
7706              goto PerlException;
7707            }
7708          if (strEQcase(attribute,rp->name))
7709            break;
7710        }
7711        ix=rp-Methods+1;
7712        base++;
7713      }
7714    if (image == (Image *) NULL)
7715      {
7716        ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7717        goto PerlException;
7718      }
7719    Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7720    Zero(&attribute_flag,NumberOf(attribute_flag),char);
7721    for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7722    {
7723      Arguments
7724        *pp,
7725        *qq;
7726
7727      ssize_t
7728        ssize_test;
7729
7730      struct ArgumentList
7731        *al;
7732
7733      SV
7734        *sv;
7735
7736      sv=NULL;
7737      ssize_test=0;
7738      pp=(Arguments *) NULL;
7739      qq=rp->arguments;
7740      if (i == items)
7741        {
7742          pp=rp->arguments,
7743          sv=ST(i-1);
7744        }
7745      else
7746        for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7747        {
7748          if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7749            break;
7750          if (strEQcase(attribute,qq->method) > ssize_test)
7751            {
7752              pp=qq;
7753              ssize_test=strEQcase(attribute,qq->method);
7754            }
7755        }
7756      if (pp == (Arguments *) NULL)
7757        {
7758          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7759            attribute);
7760          goto continue_outer_loop;
7761        }
7762      al=(&argument_list[pp-rp->arguments]);
7763      switch (pp->type)
7764      {
7765        case ArrayReference:
7766        {
7767          if (SvTYPE(sv) != SVt_RV)
7768            {
7769              (void) FormatLocaleString(message,MaxTextExtent,
7770                "invalid %.60s value",pp->method);
7771              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7772              goto continue_outer_loop;
7773            }
7774          al->array_reference=SvRV(sv);
7775          break;
7776        }
7777        case RealReference:
7778        {
7779          al->real_reference=SvNV(sv);
7780          break;
7781        }
7782        case FileReference:
7783        {
7784          al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7785          break;
7786        }
7787        case ImageReference:
7788        {
7789          if (!sv_isobject(sv) ||
7790              !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7791                (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7792            {
7793              ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7794                PackageName);
7795              goto PerlException;
7796            }
7797          break;
7798        }
7799        case IntegerReference:
7800        {
7801          al->integer_reference=SvIV(sv);
7802          break;
7803        }
7804        case StringReference:
7805        {
7806          al->string_reference=(char *) SvPV(sv,al->length);
7807          if (sv_isobject(sv))
7808            al->image_reference=SetupList(aTHX_ SvRV(sv),
7809              (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7810          break;
7811        }
7812        default:
7813        {
7814          /*
7815            Is a string; look up name.
7816          */
7817          if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7818            {
7819              al->string_reference=(char *) SvPV(sv,al->length);
7820              al->integer_reference=(-1);
7821              break;
7822            }
7823          al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7824            MagickFalse,SvPV(sv,na));
7825          if (pp->type == MagickChannelOptions)
7826            al->integer_reference=ParseChannelOption(SvPV(sv,na));
7827          if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7828            {
7829              (void) FormatLocaleString(message,MaxTextExtent,
7830                "invalid %.60s value",pp->method);
7831              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7832              goto continue_outer_loop;
7833            }
7834          break;
7835        }
7836      }
7837      attribute_flag[pp-rp->arguments]++;
7838      continue_outer_loop: ;
7839    }
7840    (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7841    pv=reference_vector;
7842    SetGeometryInfo(&geometry_info);
7843    channel=DefaultChannels;
7844    for (next=image; next; next=next->next)
7845    {
7846      image=next;
7847      SetGeometry(image,&geometry);
7848      if ((region_info.width*region_info.height) != 0)
7849        {
7850          region_image=image;
7851          image=CropImage(image,&region_info,exception);
7852        }
7853      switch (ix)
7854      {
7855        default:
7856        {
7857          (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7858          ThrowPerlException(exception,OptionError,
7859            "UnrecognizedPerlMagickMethod",message);
7860          goto PerlException;
7861        }
7862        case 1:  /* Comment */
7863        {
7864          if (attribute_flag[0] == 0)
7865            argument_list[0].string_reference=(char *) NULL;
7866          (void) SetImageProperty(image,"comment",InterpretImageProperties(
7867            info ? info->image_info : (ImageInfo *) NULL,image,
7868            argument_list[0].string_reference));
7869          break;
7870        }
7871        case 2:  /* Label */
7872        {
7873          if (attribute_flag[0] == 0)
7874            argument_list[0].string_reference=(char *) NULL;
7875          (void) SetImageProperty(image,"label",InterpretImageProperties(
7876            info ? info->image_info : (ImageInfo *) NULL,image,
7877            argument_list[0].string_reference));
7878          break;
7879        }
7880        case 3:  /* AddNoise */
7881        {
7882          if (attribute_flag[0] == 0)
7883            argument_list[0].integer_reference=UniformNoise;
7884          if (attribute_flag[1] != 0)
7885            channel=(ChannelType) argument_list[1].integer_reference;
7886          image=AddNoiseImageChannel(image,channel,(NoiseType)
7887            argument_list[0].integer_reference,exception);
7888          break;
7889        }
7890        case 4:  /* Colorize */
7891        {
7892          PixelPacket
7893            target;
7894
7895          (void) GetOneVirtualPixel(image,0,0,&target,exception);
7896          if (attribute_flag[0] != 0)
7897            (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7898              exception);
7899          if (attribute_flag[1] == 0)
7900            argument_list[1].string_reference="100%";
7901          image=ColorizeImage(image,argument_list[1].string_reference,target,
7902            exception);
7903          break;
7904        }
7905        case 5:  /* Border */
7906        {
7907          geometry.width=0;
7908          geometry.height=0;
7909          if (attribute_flag[0] != 0)
7910            flags=ParsePageGeometry(image,argument_list[0].string_reference,
7911              &geometry,exception);
7912          if (attribute_flag[1] != 0)
7913            geometry.width=argument_list[1].integer_reference;
7914          if (attribute_flag[2] != 0)
7915            geometry.height=argument_list[2].integer_reference;
7916          if (attribute_flag[3] != 0)
7917            QueryColorDatabase(argument_list[3].string_reference,
7918              &image->border_color,exception);
7919          if (attribute_flag[4] != 0)
7920            QueryColorDatabase(argument_list[4].string_reference,
7921              &image->border_color,exception);
7922          if (attribute_flag[5] != 0)
7923            QueryColorDatabase(argument_list[5].string_reference,
7924              &image->border_color,exception);
7925          if (attribute_flag[6] != 0)
7926            image->compose=(CompositeOperator)
7927              argument_list[6].integer_reference;
7928          image=BorderImage(image,&geometry,exception);
7929          break;
7930        }
7931        case 6:  /* Blur */
7932        {
7933          if (attribute_flag[0] != 0)
7934            {
7935              flags=ParseGeometry(argument_list[0].string_reference,
7936                &geometry_info);
7937              if ((flags & SigmaValue) == 0)
7938                geometry_info.sigma=1.0;
7939            }
7940          if (attribute_flag[1] != 0)
7941            geometry_info.rho=argument_list[1].real_reference;
7942          if (attribute_flag[2] != 0)
7943            geometry_info.sigma=argument_list[2].real_reference;
7944          if (attribute_flag[3] != 0)
7945            channel=(ChannelType) argument_list[3].integer_reference;
7946          image=BlurImageChannel(image,channel,geometry_info.rho,
7947            geometry_info.sigma,exception);
7948          break;
7949        }
7950        case 7:  /* Chop */
7951        {
7952          if (attribute_flag[5] != 0)
7953            image->gravity=(GravityType) argument_list[5].integer_reference;
7954          if (attribute_flag[0] != 0)
7955            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7956              &geometry,exception);
7957          if (attribute_flag[1] != 0)
7958            geometry.width=argument_list[1].integer_reference;
7959          if (attribute_flag[2] != 0)
7960            geometry.height=argument_list[2].integer_reference;
7961          if (attribute_flag[3] != 0)
7962            geometry.x=argument_list[3].integer_reference;
7963          if (attribute_flag[4] != 0)
7964            geometry.y=argument_list[4].integer_reference;
7965          image=ChopImage(image,&geometry,exception);
7966          break;
7967        }
7968        case 8:  /* Crop */
7969        {
7970          if (attribute_flag[6] != 0)
7971            image->gravity=(GravityType) argument_list[6].integer_reference;
7972          if (attribute_flag[0] != 0)
7973            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7974              &geometry,exception);
7975          if (attribute_flag[1] != 0)
7976            geometry.width=argument_list[1].integer_reference;
7977          if (attribute_flag[2] != 0)
7978            geometry.height=argument_list[2].integer_reference;
7979          if (attribute_flag[3] != 0)
7980            geometry.x=argument_list[3].integer_reference;
7981          if (attribute_flag[4] != 0)
7982            geometry.y=argument_list[4].integer_reference;
7983          if (attribute_flag[5] != 0)
7984            image->fuzz=StringToDoubleInterval(
7985              argument_list[5].string_reference,(double) QuantumRange+1.0);
7986          image=CropImage(image,&geometry,exception);
7987          break;
7988        }
7989        case 9:  /* Despeckle */
7990        {
7991          image=DespeckleImage(image,exception);
7992          break;
7993        }
7994        case 10:  /* Edge */
7995        {
7996          if (attribute_flag[0] != 0)
7997            geometry_info.rho=argument_list[0].real_reference;
7998          image=EdgeImage(image,geometry_info.rho,exception);
7999          break;
8000        }
8001        case 11:  /* Emboss */
8002        {
8003          if (attribute_flag[0] != 0)
8004            {
8005              flags=ParseGeometry(argument_list[0].string_reference,
8006                &geometry_info);
8007              if ((flags & SigmaValue) == 0)
8008                geometry_info.sigma=1.0;
8009            }
8010          if (attribute_flag[1] != 0)
8011            geometry_info.rho=argument_list[1].real_reference;
8012          if (attribute_flag[2] != 0)
8013            geometry_info.sigma=argument_list[2].real_reference;
8014          image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8015            exception);
8016          break;
8017        }
8018        case 12:  /* Enhance */
8019        {
8020          image=EnhanceImage(image,exception);
8021          break;
8022        }
8023        case 13:  /* Flip */
8024        {
8025          image=FlipImage(image,exception);
8026          break;
8027        }
8028        case 14:  /* Flop */
8029        {
8030          image=FlopImage(image,exception);
8031          break;
8032        }
8033        case 15:  /* Frame */
8034        {
8035          FrameInfo
8036            frame_info;
8037
8038          if (attribute_flag[0] != 0)
8039            {
8040              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8041                &geometry,exception);
8042              frame_info.width=geometry.width;
8043              frame_info.height=geometry.height;
8044              frame_info.outer_bevel=geometry.x;
8045              frame_info.inner_bevel=geometry.y;
8046            }
8047          if (attribute_flag[1] != 0)
8048            frame_info.width=argument_list[1].integer_reference;
8049          if (attribute_flag[2] != 0)
8050            frame_info.height=argument_list[2].integer_reference;
8051          if (attribute_flag[3] != 0)
8052            frame_info.inner_bevel=argument_list[3].integer_reference;
8053          if (attribute_flag[4] != 0)
8054            frame_info.outer_bevel=argument_list[4].integer_reference;
8055          if (attribute_flag[5] != 0)
8056            QueryColorDatabase(argument_list[5].string_reference,&fill_color,
8057              exception);
8058          if (attribute_flag[6] != 0)
8059            QueryColorDatabase(argument_list[6].string_reference,&fill_color,
8060              exception);
8061          frame_info.x=(ssize_t) frame_info.width;
8062          frame_info.y=(ssize_t) frame_info.height;
8063          frame_info.width=image->columns+2*frame_info.x;
8064          frame_info.height=image->rows+2*frame_info.y;
8065          if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8066            image->matte_color=fill_color;
8067          if (attribute_flag[7] != 0)
8068            image->compose=(CompositeOperator) argument_list[7].integer_reference;
8069          image=FrameImage(image,&frame_info,exception);
8070          break;
8071        }
8072        case 16:  /* Implode */
8073        {
8074          if (attribute_flag[0] == 0)
8075            argument_list[0].real_reference=0.5;
8076          if (attribute_flag[1] != 0)
8077            image->interpolate=(InterpolatePixelMethod)
8078              argument_list[1].integer_reference;
8079          image=ImplodeImage(image,argument_list[0].real_reference,
8080            exception);
8081          break;
8082        }
8083        case 17:  /* Magnify */
8084        {
8085          image=MagnifyImage(image,exception);
8086          break;
8087        }
8088        case 18:  /* MedianFilter */
8089        {
8090          if (attribute_flag[0] != 0)
8091            {
8092              flags=ParseGeometry(argument_list[0].string_reference,
8093                &geometry_info);
8094              if ((flags & SigmaValue) == 0)
8095                geometry_info.sigma=1.0;
8096            }
8097          if (attribute_flag[1] != 0)
8098            geometry_info.rho=argument_list[1].real_reference;
8099          if (attribute_flag[2] != 0)
8100            geometry_info.sigma=argument_list[2].real_reference;
8101          if (attribute_flag[3] != 0)
8102            channel=(ChannelType) argument_list[3].integer_reference;
8103          image=StatisticImageChannel(image,channel,MedianStatistic,
8104            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
8105          break;
8106        }
8107        case 19:  /* Minify */
8108        {
8109          image=MinifyImage(image,exception);
8110          break;
8111        }
8112        case 20:  /* OilPaint */
8113        {
8114          if (attribute_flag[0] == 0)
8115            argument_list[0].real_reference=0.0;
8116          image=OilPaintImage(image,argument_list[0].real_reference,
8117            exception);
8118          break;
8119        }
8120        case 21:  /* ReduceNoise */
8121        {
8122          if (attribute_flag[0] != 0)
8123            {
8124              flags=ParseGeometry(argument_list[0].string_reference,
8125                &geometry_info);
8126              if ((flags & SigmaValue) == 0)
8127                geometry_info.sigma=1.0;
8128            }
8129          if (attribute_flag[1] != 0)
8130            geometry_info.rho=argument_list[1].real_reference;
8131          if (attribute_flag[2] != 0)
8132            geometry_info.sigma=argument_list[2].real_reference;
8133          if (attribute_flag[3] != 0)
8134            channel=(ChannelType) argument_list[3].integer_reference;
8135          image=StatisticImageChannel(image,channel,NonpeakStatistic,
8136            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
8137          break;
8138        }
8139        case 22:  /* Roll */
8140        {
8141          if (attribute_flag[0] != 0)
8142            {
8143              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8144                &geometry,exception);
8145              if ((flags & PercentValue) != 0)
8146                {
8147                  geometry.x*=(double) image->columns/100.0;
8148                  geometry.y*=(double) image->rows/100.0;
8149                }
8150            }
8151          if (attribute_flag[1] != 0)
8152            geometry.x=argument_list[1].integer_reference;
8153          if (attribute_flag[2] != 0)
8154            geometry.y=argument_list[2].integer_reference;
8155          image=RollImage(image,geometry.x,geometry.y,exception);
8156          break;
8157        }
8158        case 23:  /* Rotate */
8159        {
8160          if (attribute_flag[0] == 0)
8161            argument_list[0].real_reference=90.0;
8162          if (attribute_flag[1] != 0)
8163            QueryColorDatabase(argument_list[1].string_reference,
8164              &image->background_color,exception);
8165          if (attribute_flag[2] != 0)
8166            QueryColorDatabase(argument_list[2].string_reference,
8167              &image->background_color,exception);
8168          if (attribute_flag[3] != 0)
8169            QueryColorDatabase(argument_list[3].string_reference,
8170              &image->background_color,exception);
8171          image=RotateImage(image,argument_list[0].real_reference,exception);
8172          break;
8173        }
8174        case 24:  /* Sample */
8175        {
8176          if (attribute_flag[0] != 0)
8177            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8178              &geometry,exception);
8179          if (attribute_flag[1] != 0)
8180            geometry.width=argument_list[1].integer_reference;
8181          if (attribute_flag[2] != 0)
8182            geometry.height=argument_list[2].integer_reference;
8183          image=SampleImage(image,geometry.width,geometry.height,exception);
8184          break;
8185        }
8186        case 25:  /* Scale */
8187        {
8188          if (attribute_flag[0] != 0)
8189            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8190              &geometry,exception);
8191          if (attribute_flag[1] != 0)
8192            geometry.width=argument_list[1].integer_reference;
8193          if (attribute_flag[2] != 0)
8194            geometry.height=argument_list[2].integer_reference;
8195          image=ScaleImage(image,geometry.width,geometry.height,exception);
8196          break;
8197        }
8198        case 26:  /* Shade */
8199        {
8200          if (attribute_flag[0] != 0)
8201            {
8202              flags=ParseGeometry(argument_list[0].string_reference,
8203                &geometry_info);
8204              if ((flags & SigmaValue) == 0)
8205                geometry_info.sigma=0.0;
8206            }
8207          if (attribute_flag[1] != 0)
8208            geometry_info.rho=argument_list[1].real_reference;
8209          if (attribute_flag[2] != 0)
8210            geometry_info.sigma=argument_list[2].real_reference;
8211          image=ShadeImage(image,
8212            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8213            geometry_info.rho,geometry_info.sigma,exception);
8214          break;
8215        }
8216        case 27:  /* Sharpen */
8217        {
8218          if (attribute_flag[0] != 0)
8219            {
8220              flags=ParseGeometry(argument_list[0].string_reference,
8221                &geometry_info);
8222              if ((flags & SigmaValue) == 0)
8223                geometry_info.sigma=1.0;
8224            }
8225          if (attribute_flag[1] != 0)
8226            geometry_info.rho=argument_list[1].real_reference;
8227          if (attribute_flag[2] != 0)
8228            geometry_info.sigma=argument_list[2].real_reference;
8229          if (attribute_flag[3] != 0)
8230            channel=(ChannelType) argument_list[3].integer_reference;
8231          image=SharpenImageChannel(image,channel,geometry_info.rho,
8232            geometry_info.sigma,exception);
8233          break;
8234        }
8235        case 28:  /* Shear */
8236        {
8237          if (attribute_flag[0] != 0)
8238            {
8239              flags=ParseGeometry(argument_list[0].string_reference,
8240                &geometry_info);
8241              if ((flags & SigmaValue) == 0)
8242                geometry_info.sigma=geometry_info.rho;
8243            }
8244          if (attribute_flag[1] != 0)
8245            geometry_info.rho=argument_list[1].real_reference;
8246          if (attribute_flag[2] != 0)
8247            geometry_info.sigma=argument_list[2].real_reference;
8248          if (attribute_flag[3] != 0)
8249            QueryColorDatabase(argument_list[3].string_reference,
8250              &image->background_color,exception);
8251          if (attribute_flag[4] != 0)
8252            QueryColorDatabase(argument_list[4].string_reference,
8253              &image->background_color,exception);
8254          image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8255            exception);
8256          break;
8257        }
8258        case 29:  /* Spread */
8259        {
8260          if (attribute_flag[0] == 0)
8261            argument_list[0].real_reference=1.0;
8262          image=SpreadImage(image,argument_list[0].real_reference,exception);
8263          break;
8264        }
8265        case 30:  /* Swirl */
8266        {
8267          if (attribute_flag[0] == 0)
8268            argument_list[0].real_reference=50.0;
8269          if (attribute_flag[1] != 0)
8270            image->interpolate=(InterpolatePixelMethod)
8271              argument_list[1].integer_reference;
8272          image=SwirlImage(image,argument_list[0].real_reference,exception);
8273          break;
8274        }
8275        case 31:  /* Resize */
8276        case 32:  /* Zoom */
8277        {
8278          if (attribute_flag[0] != 0)
8279            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8280              &geometry,exception);
8281          if (attribute_flag[1] != 0)
8282            geometry.width=argument_list[1].integer_reference;
8283          if (attribute_flag[2] != 0)
8284            geometry.height=argument_list[2].integer_reference;
8285          if (attribute_flag[3] == 0)
8286            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8287          if (attribute_flag[4] != 0)
8288            SetImageArtifact(image,"filter:support",
8289              argument_list[4].string_reference);
8290          if (attribute_flag[5] == 0)
8291            argument_list[5].real_reference=1.0;
8292          image=ResizeImage(image,geometry.width,geometry.height,
8293            (FilterTypes) argument_list[3].integer_reference,
8294            argument_list[5].real_reference,exception);
8295          break;
8296        }
8297        case 33:  /* Annotate */
8298        {
8299          DrawInfo
8300            *draw_info;
8301
8302          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8303            (DrawInfo *) NULL);
8304          if (attribute_flag[0] != 0)
8305            {
8306              char
8307                *text;
8308
8309              text=InterpretImageProperties(info ? info->image_info :
8310                (ImageInfo *) NULL,image,argument_list[0].string_reference);
8311              (void) CloneString(&draw_info->text,text);
8312              text=DestroyString(text);
8313            }
8314          if (attribute_flag[1] != 0)
8315            (void) CloneString(&draw_info->font,
8316              argument_list[1].string_reference);
8317          if (attribute_flag[2] != 0)
8318            draw_info->pointsize=argument_list[2].real_reference;
8319          if (attribute_flag[3] != 0)
8320            (void) CloneString(&draw_info->density,
8321              argument_list[3].string_reference);
8322          if (attribute_flag[4] != 0)
8323            (void) QueryColorDatabase(argument_list[4].string_reference,
8324              &draw_info->undercolor,exception);
8325          if (attribute_flag[5] != 0)
8326            {
8327              (void) QueryColorDatabase(argument_list[5].string_reference,
8328                &draw_info->stroke,exception);
8329              if (argument_list[5].image_reference != (Image *) NULL)
8330                draw_info->stroke_pattern=CloneImage(
8331                  argument_list[5].image_reference,0,0,MagickTrue,exception);
8332            }
8333          if (attribute_flag[6] != 0)
8334            {
8335              (void) QueryColorDatabase(argument_list[6].string_reference,
8336                &draw_info->fill,exception);
8337              if (argument_list[6].image_reference != (Image *) NULL)
8338                draw_info->fill_pattern=CloneImage(
8339                  argument_list[6].image_reference,0,0,MagickTrue,exception);
8340            }
8341          if (attribute_flag[7] != 0)
8342            {
8343              (void) CloneString(&draw_info->geometry,
8344                argument_list[7].string_reference);
8345              flags=ParsePageGeometry(image,argument_list[7].string_reference,
8346                &geometry,exception);
8347              if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8348                geometry_info.sigma=geometry_info.xi;
8349            }
8350          if (attribute_flag[8] != 0)
8351            (void) QueryColorDatabase(argument_list[8].string_reference,
8352              &draw_info->fill,exception);
8353          if (attribute_flag[11] != 0)
8354            draw_info->gravity=(GravityType) argument_list[11].integer_reference;
8355          if (attribute_flag[25] != 0)
8356            {
8357              AV
8358                *av;
8359
8360              av=(AV *) argument_list[25].array_reference;
8361              if ((av_len(av) != 3) && (av_len(av) != 5))
8362                {
8363                  ThrowPerlException(exception,OptionError,
8364                    "affine matrix must have 4 or 6 elements",PackageName);
8365                  goto PerlException;
8366                }
8367              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8368              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8369              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8370              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8371              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8372                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8373                {
8374                  ThrowPerlException(exception,OptionError,
8375                    "affine matrix is singular",PackageName);
8376                   goto PerlException;
8377                }
8378              if (av_len(av) == 5)
8379                {
8380                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8381                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8382                }
8383            }
8384          for (j=12; j < 17; j++)
8385          {
8386            if (attribute_flag[j] == 0)
8387              continue;
8388            value=argument_list[j].string_reference;
8389            angle=argument_list[j].real_reference;
8390            current=draw_info->affine;
8391            GetAffineMatrix(&affine);
8392            switch (j)
8393            {
8394              case 12:
8395              {
8396                /*
8397                  Translate.
8398                */
8399                flags=ParseGeometry(value,&geometry_info);
8400                affine.tx=geometry_info.xi;
8401                affine.ty=geometry_info.psi;
8402                if ((flags & PsiValue) == 0)
8403                  affine.ty=affine.tx;
8404                break;
8405              }
8406              case 13:
8407              {
8408                /*
8409                  Scale.
8410                */
8411                flags=ParseGeometry(value,&geometry_info);
8412                affine.sx=geometry_info.rho;
8413                affine.sy=geometry_info.sigma;
8414                if ((flags & SigmaValue) == 0)
8415                  affine.sy=affine.sx;
8416                break;
8417              }
8418              case 14:
8419              {
8420                /*
8421                  Rotate.
8422                */
8423                if (angle == 0.0)
8424                  break;
8425                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8426                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8427                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8428                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8429                break;
8430              }
8431              case 15:
8432              {
8433                /*
8434                  SkewX.
8435                */
8436                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8437                break;
8438              }
8439              case 16:
8440              {
8441                /*
8442                  SkewY.
8443                */
8444                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8445                break;
8446              }
8447            }
8448            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8449            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8450            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8451            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8452            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8453              current.tx;
8454            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8455              current.ty;
8456          }
8457          if (attribute_flag[9] == 0)
8458            argument_list[9].real_reference=0.0;
8459          if (attribute_flag[10] == 0)
8460            argument_list[10].real_reference=0.0;
8461          if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8462            {
8463              char
8464                geometry[MaxTextExtent];
8465
8466              (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8467                (double) argument_list[9].real_reference+draw_info->affine.tx,
8468                (double) argument_list[10].real_reference+draw_info->affine.ty);
8469              (void) CloneString(&draw_info->geometry,geometry);
8470            }
8471          if (attribute_flag[17] != 0)
8472            draw_info->stroke_width=argument_list[17].real_reference;
8473          if (attribute_flag[18] != 0)
8474            {
8475              draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8476                MagickTrue : MagickFalse;
8477              draw_info->stroke_antialias=draw_info->text_antialias;
8478            }
8479          if (attribute_flag[19] != 0)
8480            (void) CloneString(&draw_info->family,
8481              argument_list[19].string_reference);
8482          if (attribute_flag[20] != 0)
8483            draw_info->style=(StyleType) argument_list[20].integer_reference;
8484          if (attribute_flag[21] != 0)
8485            draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8486          if (attribute_flag[22] != 0)
8487            draw_info->weight=argument_list[22].integer_reference;
8488          if (attribute_flag[23] != 0)
8489            draw_info->align=(AlignType) argument_list[23].integer_reference;
8490          if (attribute_flag[24] != 0)
8491            (void) CloneString(&draw_info->encoding,
8492              argument_list[24].string_reference);
8493          if (attribute_flag[25] != 0)
8494            draw_info->fill_pattern=CloneImage(
8495              argument_list[25].image_reference,0,0,MagickTrue,exception);
8496          if (attribute_flag[26] != 0)
8497            draw_info->fill_pattern=CloneImage(
8498              argument_list[26].image_reference,0,0,MagickTrue,exception);
8499          if (attribute_flag[27] != 0)
8500            draw_info->stroke_pattern=CloneImage(
8501              argument_list[27].image_reference,0,0,MagickTrue,exception);
8502          if (attribute_flag[29] != 0)
8503            draw_info->kerning=argument_list[29].real_reference;
8504          if (attribute_flag[30] != 0)
8505            draw_info->interline_spacing=argument_list[30].real_reference;
8506          if (attribute_flag[31] != 0)
8507            draw_info->interword_spacing=argument_list[31].real_reference;
8508          if (attribute_flag[32] != 0)
8509            draw_info->direction=(DirectionType)
8510              argument_list[32].integer_reference;
8511          if (attribute_flag[33] != 0)
8512            draw_info->decorate=(DecorationType)
8513              argument_list[33].integer_reference;
8514          (void) AnnotateImage(image,draw_info);
8515          draw_info=DestroyDrawInfo(draw_info);
8516          break;
8517        }
8518        case 34:  /* ColorFloodfill */
8519        {
8520          DrawInfo
8521            *draw_info;
8522
8523          MagickBooleanType
8524            invert;
8525
8526          MagickPixelPacket
8527            target;
8528
8529          draw_info=CloneDrawInfo(info ? info->image_info :
8530            (ImageInfo *) NULL,(DrawInfo *) NULL);
8531          if (attribute_flag[0] != 0)
8532            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8533              &geometry,exception);
8534          if (attribute_flag[1] != 0)
8535            geometry.x=argument_list[1].integer_reference;
8536          if (attribute_flag[2] != 0)
8537            geometry.y=argument_list[2].integer_reference;
8538          if (attribute_flag[3] != 0)
8539            (void) QueryColorDatabase(argument_list[3].string_reference,
8540              &draw_info->fill,exception);
8541          (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8542            exception);
8543          invert=MagickFalse;
8544          if (attribute_flag[4] != 0)
8545            {
8546              QueryMagickColor(argument_list[4].string_reference,&target,
8547                exception);
8548              invert=MagickTrue;
8549            }
8550          if (attribute_flag[5] != 0)
8551            image->fuzz=StringToDoubleInterval(
8552              argument_list[5].string_reference,(double) QuantumRange+1.0);
8553          if (attribute_flag[6] != 0)
8554            invert=(MagickBooleanType) argument_list[6].integer_reference;
8555          (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8556            geometry.x,geometry.y,invert);
8557          draw_info=DestroyDrawInfo(draw_info);
8558          break;
8559        }
8560        case 35:  /* Composite */
8561        {
8562          char
8563            composite_geometry[MaxTextExtent];
8564
8565          Image
8566            *composite_image,
8567            *rotate_image;
8568
8569          compose=OverCompositeOp;
8570          if (attribute_flag[0] != 0)
8571            composite_image=argument_list[0].image_reference;
8572          else
8573            {
8574              ThrowPerlException(exception,OptionError,
8575                "CompositeImageRequired",PackageName);
8576              goto PerlException;
8577            }
8578          /*
8579            Parameter Handling used for BOTH normal and tiled composition.
8580          */
8581          if (attribute_flag[1] != 0) /* compose */
8582            compose=(CompositeOperator) argument_list[1].integer_reference;
8583          if (attribute_flag[6] != 0) /* opacity  */
8584            {
8585              if (compose != DissolveCompositeOp)
8586                (void) SetImageOpacity(composite_image,(Quantum) (QuantumRange-
8587                  StringToDoubleInterval(argument_list[6].string_reference,
8588                  (double) QuantumRange+1.0)));
8589              else
8590                {
8591                  CacheView
8592                    *composite_view;
8593
8594                  double
8595                    opacity;
8596
8597                  MagickBooleanType
8598                    sync;
8599
8600                  ssize_t
8601                    x;
8602
8603                  PixelPacket
8604                    *q;
8605
8606                  ssize_t
8607                    y;
8608
8609                  /*
8610                    Handle dissolve composite operator.
8611                  */
8612                  (void) CloneString(&image->geometry,
8613                    argument_list[6].string_reference);
8614                  opacity=(Quantum) (QuantumRange-StringToDoubleInterval(
8615                    argument_list[6].string_reference,(double) QuantumRange+
8616                    1.0));
8617                  if (composite_image->matte != MagickTrue)
8618                    (void) SetImageOpacity(composite_image,OpaqueOpacity);
8619                  composite_view=AcquireAuthenticCacheView(composite_image,
8620                    exception);
8621                  for (y=0; y < (ssize_t) composite_image->rows ; y++)
8622                  {
8623                    q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8624                      composite_image->columns,1,exception);
8625                    for (x=0; x < (ssize_t) composite_image->columns; x++)
8626                    {
8627                      if (q->opacity == OpaqueOpacity)
8628                        q->opacity=ClampToQuantum(opacity);
8629                      q++;
8630                    }
8631                    sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8632                    if (sync == MagickFalse)
8633                      break;
8634                  }
8635                  composite_view=DestroyCacheView(composite_view);
8636                }
8637            }
8638          if (attribute_flag[9] != 0)    /* "color=>" */
8639            QueryColorDatabase(argument_list[9].string_reference,
8640              &composite_image->background_color,exception);
8641          if (attribute_flag[12] != 0) /* "interpolate=>" */
8642            image->interpolate=(InterpolatePixelMethod)
8643              argument_list[12].integer_reference;
8644          if (attribute_flag[13] != 0)   /* "args=>" */
8645            (void) SetImageArtifact(composite_image,"compose:args",
8646              argument_list[13].string_reference);
8647          if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8648            (void) SetImageArtifact(composite_image,"compose:args",
8649              argument_list[14].string_reference);
8650          /*
8651            Tiling Composition (with orthogonal rotate).
8652          */
8653          rotate_image=(Image *) NULL;
8654          if (attribute_flag[8] != 0)   /* "rotate=>" */
8655            {
8656               /*
8657                 Rotate image.
8658               */
8659               rotate_image=RotateImage(composite_image,
8660                 argument_list[8].real_reference,exception);
8661               if (rotate_image == (Image *) NULL)
8662                 break;
8663            }
8664          if ((attribute_flag[7] != 0) &&
8665              (argument_list[7].integer_reference != 0)) /* tile */
8666            {
8667              ssize_t
8668                x,
8669                y;
8670
8671              /*
8672                Tile the composite image.
8673              */
8674             if (attribute_flag[8] != 0)   /* "tile=>" */
8675               (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8676                 "false");
8677             else
8678               (void) SetImageArtifact(composite_image,
8679                 "compose:outside-overlay","false");
8680             for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8681                for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8682                {
8683                  if (attribute_flag[8] != 0) /* rotate */
8684                    (void) CompositeImage(image,compose,rotate_image,x,y);
8685                  else
8686                    (void) CompositeImage(image,compose,composite_image,x,y);
8687                }
8688              if (attribute_flag[8] != 0) /* rotate */
8689                rotate_image=DestroyImage(rotate_image);
8690              break;
8691            }
8692          /*
8693            Parameter Handling used used ONLY for normal composition.
8694          */
8695          if (attribute_flag[5] != 0) /* gravity */
8696            image->gravity=(GravityType) argument_list[5].integer_reference;
8697          if (attribute_flag[2] != 0) /* geometry offset */
8698            {
8699              SetGeometry(image,&geometry);
8700              (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8701                &geometry);
8702              GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8703                &geometry);
8704            }
8705          if (attribute_flag[3] != 0) /* x offset */
8706            geometry.x=argument_list[3].integer_reference;
8707          if (attribute_flag[4] != 0) /* y offset */
8708            geometry.y=argument_list[4].integer_reference;
8709          if (attribute_flag[10] != 0) /* mask */
8710            {
8711              if ((image->compose == DisplaceCompositeOp) ||
8712                  (image->compose == DistortCompositeOp))
8713                {
8714                  /*
8715                    Merge Y displacement into X displacement image.
8716                  */
8717                  composite_image=CloneImage(composite_image,0,0,MagickTrue,
8718                    &image->exception);
8719                  (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8720                    argument_list[10].image_reference,0,0);
8721                }
8722              else
8723                {
8724                  /*
8725                    Set a blending mask for the composition.
8726                  */
8727                  image->mask=CloneImage(argument_list[10].image_reference,0,0,
8728                    MagickTrue,&image->exception);
8729                  (void) NegateImage(image->mask,MagickFalse);
8730                }
8731            }
8732          if (attribute_flag[11] != 0) /* channel */
8733            channel=(ChannelType) argument_list[11].integer_reference;
8734          /*
8735            Composite two images (normal composition).
8736          */
8737          (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8738            "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8739            (double) composite_image->rows,(double) geometry.x,(double)
8740            geometry.y);
8741          flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8742            exception);
8743          if (attribute_flag[8] == 0) /* no rotate */
8744            CompositeImageChannel(image,channel,compose,composite_image,
8745              geometry.x,geometry.y);
8746          else
8747            {
8748              /*
8749                Position adjust rotated image then composite.
8750              */
8751              geometry.x-=(ssize_t) (rotate_image->columns-
8752                composite_image->columns)/2;
8753              geometry.y-=(ssize_t) (rotate_image->rows-
8754                composite_image->rows)/2;
8755              CompositeImageChannel(image,channel,compose,rotate_image,
8756                geometry.x,geometry.y);
8757              rotate_image=DestroyImage(rotate_image);
8758            }
8759          if (attribute_flag[10] != 0) /* mask */
8760            {
8761              if ((image->compose == DisplaceCompositeOp) ||
8762                  (image->compose == DistortCompositeOp))
8763                composite_image=DestroyImage(composite_image);
8764              else
8765                image->mask=DestroyImage(image->mask);
8766            }
8767          break;
8768        }
8769        case 36:  /* Contrast */
8770        {
8771          if (attribute_flag[0] == 0)
8772            argument_list[0].integer_reference=0;
8773          (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8774            MagickTrue : MagickFalse);
8775          break;
8776        }
8777        case 37:  /* CycleColormap */
8778        {
8779          if (attribute_flag[0] == 0)
8780            argument_list[0].integer_reference=6;
8781          (void) CycleColormapImage(image,argument_list[0].integer_reference);
8782          break;
8783        }
8784        case 38:  /* Draw */
8785        {
8786          DrawInfo
8787            *draw_info;
8788
8789          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8790            (DrawInfo *) NULL);
8791          (void) CloneString(&draw_info->primitive,"point");
8792          if (attribute_flag[0] != 0)
8793            {
8794              if (argument_list[0].integer_reference < 0)
8795                (void) CloneString(&draw_info->primitive,
8796                  argument_list[0].string_reference);
8797              else
8798                (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8799                  MagickPrimitiveOptions,argument_list[0].integer_reference));
8800            }
8801          if (attribute_flag[1] != 0)
8802            {
8803              if (LocaleCompare(draw_info->primitive,"path") == 0)
8804                {
8805                  (void) ConcatenateString(&draw_info->primitive," '");
8806                  ConcatenateString(&draw_info->primitive,
8807                    argument_list[1].string_reference);
8808                  (void) ConcatenateString(&draw_info->primitive,"'");
8809                }
8810              else
8811                {
8812                  (void) ConcatenateString(&draw_info->primitive," ");
8813                  ConcatenateString(&draw_info->primitive,
8814                    argument_list[1].string_reference);
8815                }
8816            }
8817          if (attribute_flag[2] != 0)
8818            {
8819              (void) ConcatenateString(&draw_info->primitive," ");
8820              (void) ConcatenateString(&draw_info->primitive,
8821                CommandOptionToMnemonic(MagickMethodOptions,
8822                argument_list[2].integer_reference));
8823            }
8824          if (attribute_flag[3] != 0)
8825            {
8826              (void) QueryColorDatabase(argument_list[3].string_reference,
8827                &draw_info->stroke,exception);
8828              if (argument_list[3].image_reference != (Image *) NULL)
8829                draw_info->stroke_pattern=CloneImage(
8830                  argument_list[3].image_reference,0,0,MagickTrue,exception);
8831            }
8832          if (attribute_flag[4] != 0)
8833            {
8834              (void) QueryColorDatabase(argument_list[4].string_reference,
8835                &draw_info->fill,exception);
8836              if (argument_list[4].image_reference != (Image *) NULL)
8837                draw_info->fill_pattern=CloneImage(
8838                  argument_list[4].image_reference,0,0,MagickTrue,exception);
8839            }
8840          if (attribute_flag[5] != 0)
8841            draw_info->stroke_width=argument_list[5].real_reference;
8842          if (attribute_flag[6] != 0)
8843            (void) CloneString(&draw_info->font,
8844              argument_list[6].string_reference);
8845          if (attribute_flag[7] != 0)
8846            (void) QueryColorDatabase(argument_list[7].string_reference,
8847              &draw_info->border_color,exception);
8848          if (attribute_flag[8] != 0)
8849            draw_info->affine.tx=argument_list[8].real_reference;
8850          if (attribute_flag[9] != 0)
8851            draw_info->affine.ty=argument_list[9].real_reference;
8852          if (attribute_flag[20] != 0)
8853            {
8854              AV
8855                *av;
8856
8857              av=(AV *) argument_list[20].array_reference;
8858              if ((av_len(av) != 3) && (av_len(av) != 5))
8859                {
8860                  ThrowPerlException(exception,OptionError,
8861                    "affine matrix must have 4 or 6 elements",PackageName);
8862                  goto PerlException;
8863                }
8864              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8865              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8866              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8867              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8868              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8869                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8870                {
8871                  ThrowPerlException(exception,OptionError,
8872                    "affine matrix is singular",PackageName);
8873                   goto PerlException;
8874                }
8875              if (av_len(av) == 5)
8876                {
8877                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8878                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8879                }
8880            }
8881          for (j=10; j < 15; j++)
8882          {
8883            if (attribute_flag[j] == 0)
8884              continue;
8885            value=argument_list[j].string_reference;
8886            angle=argument_list[j].real_reference;
8887            current=draw_info->affine;
8888            GetAffineMatrix(&affine);
8889            switch (j)
8890            {
8891              case 10:
8892              {
8893                /*
8894                  Translate.
8895                */
8896                flags=ParseGeometry(value,&geometry_info);
8897                affine.tx=geometry_info.xi;
8898                affine.ty=geometry_info.psi;
8899                if ((flags & PsiValue) == 0)
8900                  affine.ty=affine.tx;
8901                break;
8902              }
8903              case 11:
8904              {
8905                /*
8906                  Scale.
8907                */
8908                flags=ParseGeometry(value,&geometry_info);
8909                affine.sx=geometry_info.rho;
8910                affine.sy=geometry_info.sigma;
8911                if ((flags & SigmaValue) == 0)
8912                  affine.sy=affine.sx;
8913                break;
8914              }
8915              case 12:
8916              {
8917                /*
8918                  Rotate.
8919                */
8920                if (angle == 0.0)
8921                  break;
8922                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8923                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8924                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8925                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8926                break;
8927              }
8928              case 13:
8929              {
8930                /*
8931                  SkewX.
8932                */
8933                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8934                break;
8935              }
8936              case 14:
8937              {
8938                /*
8939                  SkewY.
8940                */
8941                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8942                break;
8943              }
8944            }
8945            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8946            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8947            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8948            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8949            draw_info->affine.tx=
8950              current.sx*affine.tx+current.ry*affine.ty+current.tx;
8951            draw_info->affine.ty=
8952              current.rx*affine.tx+current.sy*affine.ty+current.ty;
8953          }
8954          if (attribute_flag[15] != 0)
8955            draw_info->fill_pattern=CloneImage(
8956              argument_list[15].image_reference,0,0,MagickTrue,exception);
8957          if (attribute_flag[16] != 0)
8958            draw_info->pointsize=argument_list[16].real_reference;
8959          if (attribute_flag[17] != 0)
8960            {
8961              draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8962                ? MagickTrue : MagickFalse;
8963              draw_info->text_antialias=draw_info->stroke_antialias;
8964            }
8965          if (attribute_flag[18] != 0)
8966            (void) CloneString(&draw_info->density,
8967              argument_list[18].string_reference);
8968          if (attribute_flag[19] != 0)
8969            draw_info->stroke_width=argument_list[19].real_reference;
8970          if (attribute_flag[21] != 0)
8971            draw_info->dash_offset=argument_list[21].real_reference;
8972          if (attribute_flag[22] != 0)
8973            {
8974              AV
8975                *av;
8976
8977              av=(AV *) argument_list[22].array_reference;
8978              draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8979                av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8980              if (draw_info->dash_pattern != (double *) NULL)
8981                {
8982                  for (i=0; i <= av_len(av); i++)
8983                    draw_info->dash_pattern[i]=(double)
8984                      SvNV(*(av_fetch(av,i,0)));
8985                  draw_info->dash_pattern[i]=0.0;
8986                }
8987            }
8988          if (attribute_flag[23] != 0)
8989            image->interpolate=(InterpolatePixelMethod)
8990              argument_list[23].integer_reference;
8991          if ((attribute_flag[24] != 0) &&
8992              (draw_info->fill_pattern != (Image *) NULL))
8993            flags=ParsePageGeometry(draw_info->fill_pattern,
8994              argument_list[24].string_reference,
8995              &draw_info->fill_pattern->tile_offset,exception);
8996          if (attribute_flag[25] != 0)
8997            {
8998              (void) ConcatenateString(&draw_info->primitive," '");
8999              (void) ConcatenateString(&draw_info->primitive,
9000                argument_list[25].string_reference);
9001              (void) ConcatenateString(&draw_info->primitive,"'");
9002            }
9003          if (attribute_flag[26] != 0)
9004            draw_info->fill_pattern=CloneImage(
9005              argument_list[26].image_reference,0,0,MagickTrue,exception);
9006          if (attribute_flag[27] != 0)
9007            draw_info->stroke_pattern=CloneImage(
9008              argument_list[27].image_reference,0,0,MagickTrue,exception);
9009          if (attribute_flag[28] != 0)
9010            (void) CloneString(&draw_info->primitive,
9011              argument_list[28].string_reference);
9012          if (attribute_flag[29] != 0)
9013            draw_info->kerning=argument_list[29].real_reference;
9014          if (attribute_flag[30] != 0)
9015            draw_info->interline_spacing=argument_list[30].real_reference;
9016          if (attribute_flag[31] != 0)
9017            draw_info->interword_spacing=argument_list[31].real_reference;
9018          if (attribute_flag[32] != 0)
9019            draw_info->direction=(DirectionType)
9020              argument_list[32].integer_reference;
9021          DrawImage(image,draw_info);
9022          draw_info=DestroyDrawInfo(draw_info);
9023          break;
9024        }
9025        case 39:  /* Equalize */
9026        {
9027          if (attribute_flag[0] != 0)
9028            channel=(ChannelType) argument_list[0].integer_reference;
9029          EqualizeImageChannel(image,channel);
9030          break;
9031        }
9032        case 40:  /* Gamma */
9033        {
9034          if (attribute_flag[1] != 0)
9035            channel=(ChannelType) argument_list[1].integer_reference;
9036          if (attribute_flag[2] == 0)
9037            argument_list[2].real_reference=1.0;
9038          if (attribute_flag[3] == 0)
9039            argument_list[3].real_reference=1.0;
9040          if (attribute_flag[4] == 0)
9041            argument_list[4].real_reference=1.0;
9042          if (attribute_flag[0] == 0)
9043            {
9044              (void) FormatLocaleString(message,MaxTextExtent,
9045                "%.20g,%.15g,%.15g",(double) argument_list[2].real_reference,
9046                (double) argument_list[3].real_reference,
9047                (double) argument_list[4].real_reference);
9048              argument_list[0].string_reference=message;
9049            }
9050          if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
9051            (void) GammaImage(image,argument_list[0].string_reference);
9052          else
9053            (void) GammaImageChannel(image,channel,StringToDouble(
9054              argument_list[0].string_reference,(char **) NULL));
9055          break;
9056        }
9057        case 41:  /* Map */
9058        {
9059          QuantizeInfo
9060            *quantize_info;
9061
9062          if (attribute_flag[0] == 0)
9063            {
9064              ThrowPerlException(exception,OptionError,"MapImageRequired",
9065                PackageName);
9066              goto PerlException;
9067            }
9068          quantize_info=AcquireQuantizeInfo(info->image_info);
9069          if (attribute_flag[1] != 0)
9070            quantize_info->dither=(MagickBooleanType)
9071              argument_list[1].integer_reference;
9072          if (attribute_flag[2] != 0)
9073            quantize_info->dither_method=(DitherMethod)
9074              argument_list[2].integer_reference;
9075          (void) RemapImages(quantize_info,image,
9076            argument_list[0].image_reference);
9077          quantize_info=DestroyQuantizeInfo(quantize_info);
9078          break;
9079        }
9080        case 42:  /* MatteFloodfill */
9081        {
9082          DrawInfo
9083            *draw_info;
9084
9085          MagickBooleanType
9086            invert;
9087
9088          MagickPixelPacket
9089            target;
9090
9091          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9092            (DrawInfo *) NULL);
9093          if (attribute_flag[0] != 0)
9094            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9095              &geometry,exception);
9096          if (attribute_flag[1] != 0)
9097            geometry.x=argument_list[1].integer_reference;
9098          if (attribute_flag[2] != 0)
9099            geometry.y=argument_list[2].integer_reference;
9100          if (image->matte == MagickFalse)
9101            (void) SetImageOpacity(image,OpaqueOpacity);
9102          (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
9103            exception);
9104          if (attribute_flag[4] != 0)
9105            QueryMagickColor(argument_list[4].string_reference,&target,
9106              exception);
9107          if (attribute_flag[3] != 0)
9108            target.opacity=StringToDoubleInterval(
9109              argument_list[3].string_reference,(double) QuantumRange+1.0);
9110          if (attribute_flag[5] != 0)
9111            image->fuzz=StringToDoubleInterval(
9112              argument_list[5].string_reference,(double) QuantumRange+1.0);
9113          invert=MagickFalse;
9114          if (attribute_flag[6] != 0)
9115            invert=(MagickBooleanType) argument_list[6].integer_reference;
9116          (void) FloodfillPaintImage(image,OpacityChannel,draw_info,&target,
9117            geometry.x,geometry.y,invert);
9118          draw_info=DestroyDrawInfo(draw_info);
9119          break;
9120        }
9121        case 43:  /* Modulate */
9122        {
9123          char
9124            modulate[MaxTextExtent];
9125
9126          geometry_info.rho=100.0;
9127          geometry_info.sigma=100.0;
9128          geometry_info.xi=100.0;
9129          if (attribute_flag[0] != 0)
9130            (void)ParseGeometry(argument_list[0].string_reference,
9131              &geometry_info);
9132          if (attribute_flag[1] != 0)
9133            geometry_info.xi=argument_list[1].real_reference;
9134          if (attribute_flag[2] != 0)
9135            geometry_info.sigma=argument_list[2].real_reference;
9136          if (attribute_flag[3] != 0)
9137            {
9138              geometry_info.sigma=argument_list[3].real_reference;
9139              SetImageArtifact(image,"modulate:colorspace","HWB");
9140            }
9141          if (attribute_flag[4] != 0)
9142            {
9143              geometry_info.rho=argument_list[4].real_reference;
9144              SetImageArtifact(image,"modulate:colorspace","HSB");
9145            }
9146          if (attribute_flag[5] != 0)
9147            {
9148              geometry_info.sigma=argument_list[5].real_reference;
9149              SetImageArtifact(image,"modulate:colorspace","HSL");
9150            }
9151          if (attribute_flag[6] != 0)
9152            {
9153              geometry_info.rho=argument_list[6].real_reference;
9154              SetImageArtifact(image,"modulate:colorspace","HWB");
9155            }
9156          (void) FormatLocaleString(modulate,MaxTextExtent,"%.20g,%.15g,%.15g",
9157            geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9158          (void) ModulateImage(image,modulate);
9159          break;
9160        }
9161        case 44:  /* Negate */
9162        {
9163          if (attribute_flag[0] == 0)
9164            argument_list[0].integer_reference=0;
9165          if (attribute_flag[1] != 0)
9166            channel=(ChannelType) argument_list[1].integer_reference;
9167          (void) NegateImageChannel(image,channel,
9168            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
9169          break;
9170        }
9171        case 45:  /* Normalize */
9172        {
9173          if (attribute_flag[0] != 0)
9174            channel=(ChannelType) argument_list[0].integer_reference;
9175          NormalizeImageChannel(image,channel);
9176          break;
9177        }
9178        case 46:  /* NumberColors */
9179          break;
9180        case 47:  /* Opaque */
9181        {
9182          MagickBooleanType
9183            invert;
9184
9185          MagickPixelPacket
9186            fill_color,
9187            target;
9188
9189          (void) QueryMagickColor("none",&target,exception);
9190          (void) QueryMagickColor("none",&fill_color,exception);
9191          if (attribute_flag[0] != 0)
9192            (void) QueryMagickColor(argument_list[0].string_reference,
9193              &target,exception);
9194          if (attribute_flag[1] != 0)
9195            (void) QueryMagickColor(argument_list[1].string_reference,
9196              &fill_color,exception);
9197          if (attribute_flag[2] != 0)
9198            image->fuzz=StringToDoubleInterval(
9199              argument_list[2].string_reference,(double) QuantumRange+1.0);
9200          if (attribute_flag[3] != 0)
9201            channel=(ChannelType) argument_list[3].integer_reference;
9202          invert=MagickFalse;
9203          if (attribute_flag[4] != 0)
9204            invert=(MagickBooleanType) argument_list[4].integer_reference;
9205          (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
9206            invert);
9207          break;
9208        }
9209        case 48:  /* Quantize */
9210        {
9211          QuantizeInfo
9212            *quantize_info;
9213
9214          quantize_info=AcquireQuantizeInfo(info->image_info);
9215          if (attribute_flag[0] != 0)
9216            quantize_info->number_colors=(size_t)
9217              argument_list[0].integer_reference;
9218          if (attribute_flag[1] != 0)
9219            quantize_info->tree_depth=(size_t)
9220              argument_list[1].integer_reference;
9221          if (attribute_flag[2] != 0)
9222            quantize_info->colorspace=(ColorspaceType)
9223              argument_list[2].integer_reference;
9224          if (attribute_flag[3] != 0)
9225            quantize_info->dither=argument_list[3].integer_reference != 0 ?
9226              MagickTrue : MagickFalse;
9227          if (attribute_flag[4] != 0)
9228            quantize_info->measure_error=
9229              argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9230          if (attribute_flag[6] != 0)
9231            (void) QueryColorDatabase(argument_list[6].string_reference,
9232              &image->transparent_color,exception);
9233          if (attribute_flag[7] != 0)
9234            quantize_info->dither_method=(DitherMethod)
9235              argument_list[7].integer_reference;
9236          if (attribute_flag[5] && argument_list[5].integer_reference)
9237              (void) QuantizeImages(quantize_info,image);
9238          else if ((image->storage_class == DirectClass) ||
9239              (image->colors > quantize_info->number_colors) ||
9240              (quantize_info->colorspace == GRAYColorspace))
9241            (void) QuantizeImage(quantize_info,image);
9242          else
9243            CompressImageColormap(image);
9244          quantize_info=DestroyQuantizeInfo(quantize_info);
9245          break;
9246        }
9247        case 49:  /* Raise */
9248        {
9249          if (attribute_flag[0] != 0)
9250            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9251              &geometry,exception);
9252          if (attribute_flag[1] != 0)
9253            geometry.width=argument_list[1].integer_reference;
9254          if (attribute_flag[2] != 0)
9255            geometry.height=argument_list[2].integer_reference;
9256          if (attribute_flag[3] == 0)
9257            argument_list[3].integer_reference=1;
9258          (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
9259            0 ? MagickTrue : MagickFalse);
9260          break;
9261        }
9262        case 50:  /* Segment */
9263        {
9264          ColorspaceType
9265            colorspace;
9266
9267          double
9268            cluster_threshold,
9269            smoothing_threshold;
9270
9271          MagickBooleanType
9272            verbose;
9273
9274          cluster_threshold=1.0;
9275          smoothing_threshold=1.5;
9276          colorspace=sRGBColorspace;
9277          verbose=MagickFalse;
9278          if (attribute_flag[0] != 0)
9279            {
9280              flags=ParseGeometry(argument_list[0].string_reference,
9281                &geometry_info);
9282              cluster_threshold=geometry_info.rho;
9283              if (flags & SigmaValue)
9284                smoothing_threshold=geometry_info.sigma;
9285            }
9286          if (attribute_flag[1] != 0)
9287            cluster_threshold=argument_list[1].real_reference;
9288          if (attribute_flag[2] != 0)
9289            smoothing_threshold=argument_list[2].real_reference;
9290          if (attribute_flag[3] != 0)
9291            colorspace=(ColorspaceType) argument_list[3].integer_reference;
9292          if (attribute_flag[4] != 0)
9293            verbose=argument_list[4].integer_reference != 0 ?
9294              MagickTrue : MagickFalse;
9295          (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9296            smoothing_threshold);
9297          break;
9298        }
9299        case 51:  /* Signature */
9300        {
9301          (void) SignatureImage(image);
9302          break;
9303        }
9304        case 52:  /* Solarize */
9305        {
9306          geometry_info.rho=QuantumRange/2.0;
9307          if (attribute_flag[0] != 0)
9308            flags=ParseGeometry(argument_list[0].string_reference,
9309              &geometry_info);
9310          if (attribute_flag[1] != 0)
9311            geometry_info.rho=StringToDoubleInterval(
9312             argument_list[1].string_reference,(double) QuantumRange+1.0);
9313          if (attribute_flag[2] != 0)
9314            channel=(ChannelType) argument_list[2].integer_reference;
9315          (void) SolarizeImageChannel(image,channel,geometry_info.rho,
9316            exception);
9317          break;
9318        }
9319        case 53:  /* Sync */
9320        {
9321          (void) SyncImage(image);
9322          break;
9323        }
9324        case 54:  /* Texture */
9325        {
9326          if (attribute_flag[0] == 0)
9327            break;
9328          TextureImage(image,argument_list[0].image_reference);
9329          break;
9330        }
9331        case 55:  /* Evalute */
9332        {
9333          MagickEvaluateOperator
9334            op;
9335
9336          op=SetEvaluateOperator;
9337          if (attribute_flag[0] == MagickFalse)
9338            argument_list[0].real_reference=0.0;
9339          if (attribute_flag[1] != MagickFalse)
9340            op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9341          if (attribute_flag[2] != MagickFalse)
9342            channel=(ChannelType) argument_list[2].integer_reference;
9343          (void) EvaluateImageChannel(image,channel,op,
9344            argument_list[0].real_reference,exception);
9345          break;
9346        }
9347        case 56:  /* Transparent */
9348        {
9349          double
9350            opacity;
9351
9352          MagickBooleanType
9353            invert;
9354
9355          MagickPixelPacket
9356            target;
9357
9358          (void) QueryMagickColor("none",&target,exception);
9359          if (attribute_flag[0] != 0)
9360            (void) QueryMagickColor(argument_list[0].string_reference,&target,
9361              exception);
9362          opacity=TransparentOpacity;
9363          if (attribute_flag[1] != 0)
9364            opacity=StringToDoubleInterval(argument_list[1].string_reference,
9365              (double) QuantumRange+1.0);
9366          if (attribute_flag[2] != 0)
9367            image->fuzz=StringToDoubleInterval(
9368              argument_list[2].string_reference,(double) QuantumRange+1.0);
9369          if (attribute_flag[3] == 0)
9370            argument_list[3].integer_reference=0;
9371          invert=MagickFalse;
9372          if (attribute_flag[3] != 0)
9373            invert=(MagickBooleanType) argument_list[3].integer_reference;
9374          (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9375            invert);
9376          break;
9377        }
9378        case 57:  /* Threshold */
9379        {
9380          double
9381            threshold;
9382
9383          if (attribute_flag[0] == 0)
9384            argument_list[0].string_reference="50%";
9385          if (attribute_flag[1] != 0)
9386            channel=(ChannelType) argument_list[1].integer_reference;
9387          threshold=StringToDoubleInterval(argument_list[0].string_reference,
9388            (double) QuantumRange+1.0);
9389          (void) BilevelImageChannel(image,channel,threshold);
9390          break;
9391        }
9392        case 58:  /* Charcoal */
9393        {
9394          if (attribute_flag[0] != 0)
9395            {
9396              flags=ParseGeometry(argument_list[0].string_reference,
9397                &geometry_info);
9398              if ((flags & SigmaValue) == 0)
9399                geometry_info.sigma=1.0;
9400            }
9401          if (attribute_flag[1] != 0)
9402            geometry_info.rho=argument_list[1].real_reference;
9403          if (attribute_flag[2] != 0)
9404            geometry_info.sigma=argument_list[2].real_reference;
9405          image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9406            exception);
9407          break;
9408        }
9409        case 59:  /* Trim */
9410        {
9411          if (attribute_flag[0] != 0)
9412            image->fuzz=StringToDoubleInterval(
9413              argument_list[0].string_reference,(double) QuantumRange+1.0);
9414          image=TrimImage(image,exception);
9415          break;
9416        }
9417        case 60:  /* Wave */
9418        {
9419          if (attribute_flag[0] != 0)
9420            {
9421              flags=ParseGeometry(argument_list[0].string_reference,
9422                &geometry_info);
9423              if ((flags & SigmaValue) == 0)
9424                geometry_info.sigma=1.0;
9425            }
9426          if (attribute_flag[1] != 0)
9427            geometry_info.rho=argument_list[1].real_reference;
9428          if (attribute_flag[2] != 0)
9429            geometry_info.sigma=argument_list[2].real_reference;
9430          if (attribute_flag[3] != 0)
9431            image->interpolate=(InterpolatePixelMethod)
9432              argument_list[3].integer_reference;
9433          image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9434            exception);
9435          break;
9436        }
9437        case 61:  /* Separate */
9438        {
9439          if (attribute_flag[0] != 0)
9440            channel=(ChannelType) argument_list[0].integer_reference;
9441          (void) SeparateImageChannel(image,channel);
9442          break;
9443        }
9444        case 63:  /* Stereo */
9445        {
9446          if (attribute_flag[0] == 0)
9447            {
9448              ThrowPerlException(exception,OptionError,"StereoImageRequired",
9449                PackageName);
9450              goto PerlException;
9451            }
9452          if (attribute_flag[1] != 0)
9453            geometry.x=argument_list[1].integer_reference;
9454          if (attribute_flag[2] != 0)
9455            geometry.y=argument_list[2].integer_reference;
9456          image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9457            geometry.x,geometry.y,exception);
9458          break;
9459        }
9460        case 64:  /* Stegano */
9461        {
9462          if (attribute_flag[0] == 0)
9463            {
9464              ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9465                PackageName);
9466              goto PerlException;
9467            }
9468          if (attribute_flag[1] == 0)
9469            argument_list[1].integer_reference=0;
9470          image->offset=argument_list[1].integer_reference;
9471          image=SteganoImage(image,argument_list[0].image_reference,exception);
9472          break;
9473        }
9474        case 65:  /* Deconstruct */
9475        {
9476          image=DeconstructImages(image,exception);
9477          break;
9478        }
9479        case 66:  /* GaussianBlur */
9480        {
9481          if (attribute_flag[0] != 0)
9482            {
9483              flags=ParseGeometry(argument_list[0].string_reference,
9484                &geometry_info);
9485              if ((flags & SigmaValue) == 0)
9486                geometry_info.sigma=1.0;
9487            }
9488          if (attribute_flag[1] != 0)
9489            geometry_info.rho=argument_list[1].real_reference;
9490          if (attribute_flag[2] != 0)
9491            geometry_info.sigma=argument_list[2].real_reference;
9492          if (attribute_flag[3] != 0)
9493            channel=(ChannelType) argument_list[3].integer_reference;
9494          image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9495            geometry_info.sigma,exception);
9496          break;
9497        }
9498        case 67:  /* Convolve */
9499        {
9500          AV
9501            *av;
9502
9503          double
9504            *kernel;
9505
9506          size_t
9507            order;
9508
9509          if (attribute_flag[0] == 0)
9510            break;
9511          if (attribute_flag[1] != 0)
9512            channel=(ChannelType) argument_list[1].integer_reference;
9513          if (attribute_flag[2] != 0)
9514            image->bias=StringToDoubleInterval(
9515              argument_list[2].string_reference,(double) QuantumRange+1.0);
9516          av=(AV *) argument_list[0].array_reference;
9517          order=(size_t) sqrt(av_len(av)+1);
9518          kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9519          if (kernel == (double *) NULL)
9520            {
9521              ThrowPerlException(exception,ResourceLimitFatalError,
9522                "MemoryAllocationFailed",PackageName);
9523              goto PerlException;
9524            }
9525          for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9526            kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9527          for ( ; j < (ssize_t) (order*order); j++)
9528            kernel[j]=0.0;
9529          image=ConvolveImageChannel(image,channel,order,kernel,exception);
9530          kernel=(double *) RelinquishMagickMemory(kernel);
9531          break;
9532        }
9533        case 68:  /* Profile */
9534        {
9535          const char
9536            *name;
9537
9538          Image
9539            *profile_image;
9540
9541          ImageInfo
9542            *profile_info;
9543
9544          StringInfo
9545            *profile;
9546
9547          name="*";
9548          if (attribute_flag[0] != 0)
9549            name=argument_list[0].string_reference;
9550          if (attribute_flag[2] != 0)
9551            image->rendering_intent=(RenderingIntent)
9552              argument_list[2].integer_reference;
9553          if (attribute_flag[3] != 0)
9554            image->black_point_compensation=
9555              argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9556          if (attribute_flag[1] != 0)
9557            {
9558              if (argument_list[1].length == 0)
9559                {
9560                  /*
9561                    Remove a profile from the image.
9562                  */
9563                  (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9564                    MagickTrue);
9565                  break;
9566                }
9567              /*
9568                Associate user supplied profile with the image.
9569              */
9570              profile=AcquireStringInfo(argument_list[1].length);
9571              SetStringInfoDatum(profile,(const unsigned char *)
9572                argument_list[1].string_reference);
9573              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9574                (size_t) GetStringInfoLength(profile),MagickFalse);
9575              profile=DestroyStringInfo(profile);
9576              break;
9577            }
9578          /*
9579            Associate a profile with the image.
9580          */
9581          profile_info=
9582            CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9583          (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9584          profile_image=ReadImages(profile_info,&image->exception);
9585          if (profile_image == (Image *) NULL)
9586            break;
9587          ResetImageProfileIterator(profile_image);
9588          name=GetNextImageProfile(profile_image);
9589          while (name != (const char *) NULL)
9590          {
9591            const StringInfo
9592              *profile;
9593
9594            profile=GetImageProfile(profile_image,name);
9595            if (profile != (const StringInfo *) NULL)
9596              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9597                (size_t) GetStringInfoLength(profile),MagickFalse);
9598            name=GetNextImageProfile(profile_image);
9599          }
9600          profile_image=DestroyImage(profile_image);
9601          profile_info=DestroyImageInfo(profile_info);
9602          break;
9603        }
9604        case 69:  /* UnsharpMask */
9605        {
9606          if (attribute_flag[0] != 0)
9607            {
9608              flags=ParseGeometry(argument_list[0].string_reference,
9609                &geometry_info);
9610              if ((flags & SigmaValue) == 0)
9611                geometry_info.sigma=1.0;
9612              if ((flags & XiValue) == 0)
9613                geometry_info.xi=1.0;
9614              if ((flags & PsiValue) == 0)
9615                geometry_info.psi=0.5;
9616            }
9617          if (attribute_flag[1] != 0)
9618            geometry_info.rho=argument_list[1].real_reference;
9619          if (attribute_flag[2] != 0)
9620            geometry_info.sigma=argument_list[2].real_reference;
9621          if (attribute_flag[3] != 0)
9622            geometry_info.xi=argument_list[3].real_reference;
9623          if (attribute_flag[4] != 0)
9624            geometry_info.psi=argument_list[4].real_reference;
9625          if (attribute_flag[5] != 0)
9626            channel=(ChannelType) argument_list[5].integer_reference;
9627          image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9628            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9629          break;
9630        }
9631        case 70:  /* MotionBlur */
9632        {
9633          if (attribute_flag[0] != 0)
9634            {
9635              flags=ParseGeometry(argument_list[0].string_reference,
9636                &geometry_info);
9637              if ((flags & SigmaValue) == 0)
9638                geometry_info.sigma=1.0;
9639              if ((flags & XiValue) == 0)
9640                geometry_info.xi=1.0;
9641            }
9642          if (attribute_flag[1] != 0)
9643            geometry_info.rho=argument_list[1].real_reference;
9644          if (attribute_flag[2] != 0)
9645            geometry_info.sigma=argument_list[2].real_reference;
9646          if (attribute_flag[3] != 0)
9647            geometry_info.xi=argument_list[3].real_reference;
9648          if (attribute_flag[4] != 0)
9649            channel=(ChannelType) argument_list[4].integer_reference;
9650          image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9651            geometry_info.sigma,geometry_info.xi,exception);
9652          break;
9653        }
9654        case 71:  /* OrderedDither */
9655        {
9656          if (attribute_flag[0] == 0)
9657            argument_list[0].string_reference="o8x8";
9658          if (attribute_flag[1] != 0)
9659            channel=(ChannelType) argument_list[1].integer_reference;
9660          (void) OrderedPosterizeImageChannel(image,channel,
9661            argument_list[0].string_reference,exception);
9662          break;
9663        }
9664        case 72:  /* Shave */
9665        {
9666          if (attribute_flag[0] != 0)
9667            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9668              &geometry,exception);
9669          if (attribute_flag[1] != 0)
9670            geometry.width=argument_list[1].integer_reference;
9671          if (attribute_flag[2] != 0)
9672            geometry.height=argument_list[2].integer_reference;
9673          image=ShaveImage(image,&geometry,exception);
9674          break;
9675        }
9676        case 73:  /* Level */
9677        {
9678          double
9679            black_point,
9680            gamma,
9681            white_point;
9682
9683          black_point=0.0;
9684          white_point=(MagickRealType) image->columns*image->rows;
9685          gamma=1.0;
9686          if (attribute_flag[0] != 0)
9687            {
9688              flags=ParseGeometry(argument_list[0].string_reference,
9689                &geometry_info);
9690              black_point=geometry_info.rho;
9691              if ((flags & SigmaValue) != 0)
9692                white_point=geometry_info.sigma;
9693              if ((flags & XiValue) != 0)
9694                gamma=geometry_info.xi;
9695              if ((flags & PercentValue) != 0)
9696                {
9697                  black_point*=(double) (QuantumRange/100.0);
9698                  white_point*=(double) (QuantumRange/100.0);
9699                }
9700              if ((flags & SigmaValue) == 0)
9701                white_point=(double) QuantumRange-black_point;
9702            }
9703          if (attribute_flag[1] != 0)
9704            black_point=argument_list[1].real_reference;
9705          if (attribute_flag[2] != 0)
9706            white_point=argument_list[2].real_reference;
9707          if (attribute_flag[3] != 0)
9708            gamma=argument_list[3].real_reference;
9709          if (attribute_flag[4] != 0)
9710            channel=(ChannelType) argument_list[4].integer_reference;
9711          if (attribute_flag[5] != 0)
9712            {
9713              argument_list[0].real_reference=argument_list[5].real_reference;
9714              attribute_flag[0]=attribute_flag[5];
9715            }
9716          (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9717          break;
9718        }
9719        case 74:  /* Clip */
9720        {
9721          if (attribute_flag[0] == 0)
9722            argument_list[0].string_reference="#1";
9723          if (attribute_flag[1] == 0)
9724            argument_list[1].integer_reference=MagickTrue;
9725          (void) ClipImagePath(image,argument_list[0].string_reference,
9726            argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9727          break;
9728        }
9729        case 75:  /* AffineTransform */
9730        {
9731          DrawInfo
9732            *draw_info;
9733
9734          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9735            (DrawInfo *) NULL);
9736          if (attribute_flag[0] != 0)
9737            {
9738              AV
9739                *av;
9740
9741              av=(AV *) argument_list[0].array_reference;
9742              if ((av_len(av) != 3) && (av_len(av) != 5))
9743                {
9744                  ThrowPerlException(exception,OptionError,
9745                    "affine matrix must have 4 or 6 elements",PackageName);
9746                  goto PerlException;
9747                }
9748              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9749              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9750              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9751              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9752              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9753                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9754                {
9755                  ThrowPerlException(exception,OptionError,
9756                    "affine matrix is singular",PackageName);
9757                   goto PerlException;
9758                }
9759              if (av_len(av) == 5)
9760                {
9761                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9762                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9763                }
9764            }
9765          for (j=1; j < 6; j++)
9766          {
9767            if (attribute_flag[j] == 0)
9768              continue;
9769            value=argument_list[j].string_reference;
9770            angle=argument_list[j].real_reference;
9771            current=draw_info->affine;
9772            GetAffineMatrix(&affine);
9773            switch (j)
9774            {
9775              case 1:
9776              {
9777                /*
9778                  Translate.
9779                */
9780                flags=ParseGeometry(value,&geometry_info);
9781                affine.tx=geometry_info.xi;
9782                affine.ty=geometry_info.psi;
9783                if ((flags & PsiValue) == 0)
9784                  affine.ty=affine.tx;
9785                break;
9786              }
9787              case 2:
9788              {
9789                /*
9790                  Scale.
9791                */
9792                flags=ParseGeometry(value,&geometry_info);
9793                affine.sx=geometry_info.rho;
9794                affine.sy=geometry_info.sigma;
9795                if ((flags & SigmaValue) == 0)
9796                  affine.sy=affine.sx;
9797                break;
9798              }
9799              case 3:
9800              {
9801                /*
9802                  Rotate.
9803                */
9804                if (angle == 0.0)
9805                  break;
9806                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9807                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9808                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9809                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9810                break;
9811              }
9812              case 4:
9813              {
9814                /*
9815                  SkewX.
9816                */
9817                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9818                break;
9819              }
9820              case 5:
9821              {
9822                /*
9823                  SkewY.
9824                */
9825                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9826                break;
9827              }
9828            }
9829            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9830            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9831            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9832            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9833            draw_info->affine.tx=
9834              current.sx*affine.tx+current.ry*affine.ty+current.tx;
9835            draw_info->affine.ty=
9836              current.rx*affine.tx+current.sy*affine.ty+current.ty;
9837          }
9838          if (attribute_flag[6] != 0)
9839            image->interpolate=(InterpolatePixelMethod)
9840              argument_list[6].integer_reference;
9841          if (attribute_flag[7] != 0)
9842            QueryColorDatabase(argument_list[7].string_reference,
9843              &image->background_color,exception);
9844          image=AffineTransformImage(image,&draw_info->affine,exception);
9845          draw_info=DestroyDrawInfo(draw_info);
9846          break;
9847        }
9848        case 76:  /* Difference */
9849        {
9850          if (attribute_flag[0] == 0)
9851            {
9852              ThrowPerlException(exception,OptionError,
9853                "ReferenceImageRequired",PackageName);
9854              goto PerlException;
9855            }
9856          if (attribute_flag[1] != 0)
9857            image->fuzz=StringToDoubleInterval(
9858              argument_list[1].string_reference,(double) QuantumRange+1.0);
9859          (void) IsImagesEqual(image,argument_list[0].image_reference);
9860          break;
9861        }
9862        case 77:  /* AdaptiveThreshold */
9863        {
9864          if (attribute_flag[0] != 0)
9865            {
9866              flags=ParseGeometry(argument_list[0].string_reference,
9867                &geometry_info);
9868              if ((flags & PercentValue) != 0)
9869                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9870            }
9871          if (attribute_flag[1] != 0)
9872            geometry_info.rho=argument_list[1].integer_reference;
9873          if (attribute_flag[2] != 0)
9874            geometry_info.sigma=argument_list[2].integer_reference;
9875          if (attribute_flag[3] != 0)
9876            geometry_info.xi=argument_list[3].integer_reference;;
9877          image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9878            (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9879            exception);
9880          break;
9881        }
9882        case 78:  /* Resample */
9883        {
9884          size_t
9885            height,
9886            width;
9887
9888          if (attribute_flag[0] != 0)
9889            {
9890              flags=ParseGeometry(argument_list[0].string_reference,
9891                &geometry_info);
9892              if ((flags & SigmaValue) == 0)
9893                geometry_info.sigma=geometry_info.rho;
9894            }
9895          if (attribute_flag[1] != 0)
9896            geometry_info.rho=argument_list[1].real_reference;
9897          if (attribute_flag[2] != 0)
9898            geometry_info.sigma=argument_list[2].real_reference;
9899          if (attribute_flag[3] == 0)
9900            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9901          if (attribute_flag[4] == 0)
9902            SetImageArtifact(image,"filter:support",
9903              argument_list[4].string_reference);
9904          if (attribute_flag[5] != 0)
9905            argument_list[5].real_reference=1.0;
9906          width=(size_t) (geometry_info.rho*image->columns/
9907            (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9908          height=(size_t) (geometry_info.sigma*image->rows/
9909            (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9910          image=ResizeImage(image,width,height,(FilterTypes)
9911            argument_list[3].integer_reference,argument_list[5].real_reference,
9912            exception);
9913          if (image != (Image *) NULL)
9914            {
9915              image->x_resolution=geometry_info.rho;
9916              image->y_resolution=geometry_info.sigma;
9917            }
9918          break;
9919        }
9920        case 79:  /* Describe */
9921        {
9922          if (attribute_flag[0] == 0)
9923            argument_list[0].file_reference=(FILE *) NULL;
9924          (void) IdentifyImage(image,argument_list[0].file_reference,
9925            MagickTrue);
9926          break;
9927        }
9928        case 80:  /* BlackThreshold */
9929        {
9930          if (attribute_flag[0] == 0)
9931            argument_list[0].string_reference="50%";
9932          if (attribute_flag[2] != 0)
9933            channel=(ChannelType) argument_list[2].integer_reference;
9934          BlackThresholdImageChannel(image,channel,
9935            argument_list[0].string_reference,exception);
9936          break;
9937        }
9938        case 81:  /* WhiteThreshold */
9939        {
9940          if (attribute_flag[0] == 0)
9941            argument_list[0].string_reference="50%";
9942          if (attribute_flag[2] != 0)
9943            channel=(ChannelType) argument_list[2].integer_reference;
9944          WhiteThresholdImageChannel(image,channel,
9945            argument_list[0].string_reference,exception);
9946          break;
9947        }
9948        case 82:  /* RotationalBlur */
9949        {
9950          if (attribute_flag[0] != 0)
9951            {
9952              flags=ParseGeometry(argument_list[0].string_reference,
9953                &geometry_info);
9954              if ((flags & SigmaValue) == 0)
9955                geometry_info.sigma=1.0;
9956            }
9957          if (attribute_flag[1] != 0)
9958            geometry_info.rho=argument_list[1].real_reference;
9959          if (attribute_flag[2] != 0)
9960            channel=(ChannelType) argument_list[2].integer_reference;
9961          image=RotationalBlurImageChannel(image,channel,geometry_info.rho,
9962            exception);
9963          break;
9964        }
9965        case 83:  /* Thumbnail */
9966        {
9967          if (attribute_flag[0] != 0)
9968            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9969              &geometry,exception);
9970          if (attribute_flag[1] != 0)
9971            geometry.width=argument_list[1].integer_reference;
9972          if (attribute_flag[2] != 0)
9973            geometry.height=argument_list[2].integer_reference;
9974          image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9975          break;
9976        }
9977        case 84:  /* Strip */
9978        {
9979          (void) StripImage(image);
9980          break;
9981        }
9982        case 85:  /* Tint */
9983        {
9984          PixelPacket
9985            target;
9986
9987          (void) GetOneVirtualPixel(image,0,0,&target,exception);
9988          if (attribute_flag[0] != 0)
9989            (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9990              exception);
9991          if (attribute_flag[1] == 0)
9992            argument_list[1].string_reference="100";
9993          image=TintImage(image,argument_list[1].string_reference,target,
9994            exception);
9995          break;
9996        }
9997        case 86:  /* Channel */
9998        {
9999          if (attribute_flag[0] != 0)
10000            channel=(ChannelType) argument_list[0].integer_reference;
10001          (void) SeparateImageChannel(image,channel);
10002          break;
10003        }
10004        case 87:  /* Splice */
10005        {
10006          if (attribute_flag[7] != 0)
10007            image->gravity=(GravityType) argument_list[7].integer_reference;
10008          if (attribute_flag[0] != 0)
10009            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10010              &geometry,exception);
10011          if (attribute_flag[1] != 0)
10012            geometry.width=argument_list[1].integer_reference;
10013          if (attribute_flag[2] != 0)
10014            geometry.height=argument_list[2].integer_reference;
10015          if (attribute_flag[3] != 0)
10016            geometry.x=argument_list[3].integer_reference;
10017          if (attribute_flag[4] != 0)
10018            geometry.y=argument_list[4].integer_reference;
10019          if (attribute_flag[5] != 0)
10020            image->fuzz=StringToDoubleInterval(
10021              argument_list[5].string_reference,(double) QuantumRange+1.0);
10022          if (attribute_flag[6] != 0)
10023            (void) QueryColorDatabase(argument_list[6].string_reference,
10024              &image->background_color,exception);
10025          image=SpliceImage(image,&geometry,exception);
10026          break;
10027        }
10028        case 88:  /* Posterize */
10029        {
10030          if (attribute_flag[0] == 0)
10031            argument_list[0].integer_reference=3;
10032          if (attribute_flag[1] == 0)
10033            argument_list[1].integer_reference=0;
10034          (void) PosterizeImage(image,argument_list[0].integer_reference,
10035            argument_list[1].integer_reference ? MagickTrue : MagickFalse);
10036          break;
10037        }
10038        case 89:  /* Shadow */
10039        {
10040          if (attribute_flag[0] != 0)
10041            {
10042              flags=ParseGeometry(argument_list[0].string_reference,
10043                &geometry_info);
10044              if ((flags & SigmaValue) == 0)
10045                geometry_info.sigma=1.0;
10046              if ((flags & XiValue) == 0)
10047                geometry_info.xi=4.0;
10048              if ((flags & PsiValue) == 0)
10049                geometry_info.psi=4.0;
10050            }
10051          if (attribute_flag[1] != 0)
10052            geometry_info.rho=argument_list[1].real_reference;
10053          if (attribute_flag[2] != 0)
10054            geometry_info.sigma=argument_list[2].real_reference;
10055          if (attribute_flag[3] != 0)
10056            geometry_info.xi=argument_list[3].integer_reference;
10057          if (attribute_flag[4] != 0)
10058            geometry_info.psi=argument_list[4].integer_reference;
10059          image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10060            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
10061            0.5),exception);
10062          break;
10063        }
10064        case 90:  /* Identify */
10065        {
10066          if (attribute_flag[0] == 0)
10067            argument_list[0].file_reference=(FILE *) NULL;
10068          if (attribute_flag[1] != 0)
10069            (void) SetImageArtifact(image,"identify:features",
10070              argument_list[1].string_reference);
10071          if ((attribute_flag[2] != 0) &&
10072              (argument_list[2].integer_reference != 0))
10073            (void) SetImageArtifact(image,"identify:moments","true");
10074          if ((attribute_flag[3] != 0) &&
10075              (argument_list[3].integer_reference != 0))
10076            (void) SetImageArtifact(image,"identify:unique","true");
10077          (void) IdentifyImage(image,argument_list[0].file_reference,
10078            MagickTrue);
10079          break;
10080        }
10081        case 91:  /* SepiaTone */
10082        {
10083          if (attribute_flag[0] == 0)
10084            argument_list[0].real_reference=80.0*QuantumRange/100.0;
10085          image=SepiaToneImage(image,argument_list[0].real_reference,
10086            exception);
10087          break;
10088        }
10089        case 92:  /* SigmoidalContrast */
10090        {
10091          MagickBooleanType
10092            sharpen;
10093
10094          if (attribute_flag[0] != 0)
10095            {
10096              flags=ParseGeometry(argument_list[0].string_reference,
10097                &geometry_info);
10098              if ((flags & SigmaValue) == 0)
10099                geometry_info.sigma=QuantumRange/2.0;
10100              if ((flags & PercentValue) != 0)
10101                geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10102            }
10103          if (attribute_flag[1] != 0)
10104            geometry_info.rho=argument_list[1].real_reference;
10105          if (attribute_flag[2] != 0)
10106            geometry_info.sigma=argument_list[2].real_reference;
10107          if (attribute_flag[3] != 0)
10108            channel=(ChannelType) argument_list[3].integer_reference;
10109          sharpen=MagickTrue;
10110          if (attribute_flag[4] != 0)
10111            sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10112              MagickFalse;
10113          (void) SigmoidalContrastImageChannel(image,channel,sharpen,
10114            geometry_info.rho,geometry_info.sigma);
10115          break;
10116        }
10117        case 93:  /* Extent */
10118        {
10119          if (attribute_flag[7] != 0)
10120            image->gravity=(GravityType) argument_list[7].integer_reference;
10121          if (attribute_flag[0] != 0)
10122            {
10123              int
10124                flags;
10125
10126              flags=ParseGravityGeometry(image,
10127                argument_list[0].string_reference,&geometry,exception);
10128              (void) flags;
10129              if (geometry.width == 0)
10130                geometry.width=image->columns;
10131              if (geometry.height == 0)
10132                geometry.height=image->rows;
10133            }
10134          if (attribute_flag[1] != 0)
10135            geometry.width=argument_list[1].integer_reference;
10136          if (attribute_flag[2] != 0)
10137            geometry.height=argument_list[2].integer_reference;
10138          if (attribute_flag[3] != 0)
10139            geometry.x=argument_list[3].integer_reference;
10140          if (attribute_flag[4] != 0)
10141            geometry.y=argument_list[4].integer_reference;
10142          if (attribute_flag[5] != 0)
10143            image->fuzz=StringToDoubleInterval(
10144              argument_list[5].string_reference,(double) QuantumRange+1.0);
10145          if (attribute_flag[6] != 0)
10146            (void) QueryColorDatabase(argument_list[6].string_reference,
10147              &image->background_color,exception);
10148          image=ExtentImage(image,&geometry,exception);
10149          break;
10150        }
10151        case 94:  /* Vignette */
10152        {
10153          if (attribute_flag[0] != 0)
10154            {
10155              flags=ParseGeometry(argument_list[0].string_reference,
10156                &geometry_info);
10157              if ((flags & SigmaValue) == 0)
10158                geometry_info.sigma=1.0;
10159              if ((flags & XiValue) == 0)
10160                geometry_info.xi=0.1*image->columns;
10161              if ((flags & PsiValue) == 0)
10162                geometry_info.psi=0.1*image->rows;
10163            }
10164          if (attribute_flag[1] != 0)
10165            geometry_info.rho=argument_list[1].real_reference;
10166          if (attribute_flag[2] != 0)
10167            geometry_info.sigma=argument_list[2].real_reference;
10168          if (attribute_flag[3] != 0)
10169            geometry_info.xi=argument_list[3].integer_reference;
10170          if (attribute_flag[4] != 0)
10171            geometry_info.psi=argument_list[4].integer_reference;
10172          if (attribute_flag[5] != 0)
10173            (void) QueryColorDatabase(argument_list[5].string_reference,
10174              &image->background_color,exception);
10175          image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10176            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
10177            0.5),exception);
10178          break;
10179        }
10180        case 95:  /* ContrastStretch */
10181        {
10182          double
10183            black_point,
10184            white_point;
10185
10186          black_point=0.0;
10187          white_point=(MagickRealType) image->columns*image->rows;
10188          if (attribute_flag[0] != 0)
10189            {
10190              flags=ParseGeometry(argument_list[0].string_reference,
10191                &geometry_info);
10192              black_point=geometry_info.rho;
10193              white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10194                black_point;
10195              if ((flags & PercentValue) != 0)
10196                {
10197                  black_point*=(double) image->columns*image->rows/100.0;
10198                  white_point*=(double) image->columns*image->rows/100.0;
10199                }
10200              white_point=(MagickRealType) image->columns*image->rows-
10201                white_point;
10202            }
10203          if (attribute_flag[1] != 0)
10204            black_point=argument_list[1].real_reference;
10205          if (attribute_flag[2] != 0)
10206            white_point=argument_list[2].real_reference;
10207          if (attribute_flag[4] != 0)
10208            channel=(ChannelType) argument_list[4].integer_reference;
10209          (void) ContrastStretchImageChannel(image,channel,black_point,
10210            white_point);
10211          break;
10212        }
10213        case 96:  /* Sans0 */
10214        {
10215          break;
10216        }
10217        case 97:  /* Sans1 */
10218        {
10219          break;
10220        }
10221        case 98:  /* AdaptiveSharpen */
10222        {
10223          if (attribute_flag[0] != 0)
10224            {
10225              flags=ParseGeometry(argument_list[0].string_reference,
10226                &geometry_info);
10227              if ((flags & SigmaValue) == 0)
10228                geometry_info.sigma=1.0;
10229            }
10230          if (attribute_flag[1] != 0)
10231            geometry_info.rho=argument_list[1].real_reference;
10232          if (attribute_flag[2] != 0)
10233            geometry_info.sigma=argument_list[2].real_reference;
10234          if (attribute_flag[3] != 0)
10235            channel=(ChannelType) argument_list[3].integer_reference;
10236          image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
10237            geometry_info.sigma,exception);
10238          break;
10239        }
10240        case 99:  /* Transpose */
10241        {
10242          image=TransposeImage(image,exception);
10243          break;
10244        }
10245        case 100:  /* Tranverse */
10246        {
10247          image=TransverseImage(image,exception);
10248          break;
10249        }
10250        case 101:  /* AutoOrient */
10251        {
10252          image=AutoOrientImage(image,image->orientation,exception);
10253          break;
10254        }
10255        case 102:  /* AdaptiveBlur */
10256        {
10257          if (attribute_flag[0] != 0)
10258            {
10259              flags=ParseGeometry(argument_list[0].string_reference,
10260                &geometry_info);
10261              if ((flags & SigmaValue) == 0)
10262                geometry_info.sigma=1.0;
10263            }
10264          if (attribute_flag[1] != 0)
10265            geometry_info.rho=argument_list[1].real_reference;
10266          if (attribute_flag[2] != 0)
10267            geometry_info.sigma=argument_list[2].real_reference;
10268          if (attribute_flag[3] != 0)
10269            channel=(ChannelType) argument_list[3].integer_reference;
10270          image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
10271            geometry_info.sigma,exception);
10272          break;
10273        }
10274        case 103:  /* Sketch */
10275        {
10276          if (attribute_flag[0] != 0)
10277            {
10278              flags=ParseGeometry(argument_list[0].string_reference,
10279                &geometry_info);
10280              if ((flags & SigmaValue) == 0)
10281                geometry_info.sigma=1.0;
10282              if ((flags & XiValue) == 0)
10283                geometry_info.xi=1.0;
10284            }
10285          if (attribute_flag[1] != 0)
10286            geometry_info.rho=argument_list[1].real_reference;
10287          if (attribute_flag[2] != 0)
10288            geometry_info.sigma=argument_list[2].real_reference;
10289          if (attribute_flag[3] != 0)
10290            geometry_info.xi=argument_list[3].real_reference;
10291          image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10292            geometry_info.xi,exception);
10293          break;
10294        }
10295        case 104:  /* UniqueColors */
10296        {
10297          image=UniqueImageColors(image,exception);
10298          break;
10299        }
10300        case 105:  /* AdaptiveResize */
10301        {
10302          if (attribute_flag[0] != 0)
10303            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10304              &geometry,exception);
10305          if (attribute_flag[1] != 0)
10306            geometry.width=argument_list[1].integer_reference;
10307          if (attribute_flag[2] != 0)
10308            geometry.height=argument_list[2].integer_reference;
10309          if (attribute_flag[3] != 0)
10310            image->filter=(FilterTypes) argument_list[4].integer_reference;
10311          if (attribute_flag[4] != 0)
10312            SetImageArtifact(image,"filter:support",
10313              argument_list[4].string_reference);
10314          if (attribute_flag[5] != 0)
10315            image->blur=argument_list[5].real_reference;
10316          image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10317            exception);
10318          break;
10319        }
10320        case 106:  /* ClipMask */
10321        {
10322          if (attribute_flag[0] == 0)
10323            {
10324              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10325                PackageName);
10326              goto PerlException;
10327            }
10328          image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10329            MagickTrue,exception);
10330          (void) NegateImage(image->clip_mask,MagickFalse);
10331          break;
10332        }
10333        case 107:  /* LinearStretch */
10334        {
10335           double
10336             black_point,
10337             white_point;
10338
10339           black_point=0.0;
10340           white_point=(MagickRealType) image->columns*image->rows;
10341           if (attribute_flag[0] != 0)
10342             {
10343               flags=ParseGeometry(argument_list[0].string_reference,
10344                 &geometry_info);
10345               if ((flags & SigmaValue) != 0)
10346                  white_point=geometry_info.sigma;
10347               if ((flags & PercentValue) != 0)
10348                 {
10349                   black_point*=(double) image->columns*image->rows/100.0;
10350                   white_point*=(double) image->columns*image->rows/100.0;
10351                 }
10352               if ((flags & SigmaValue) == 0)
10353                 white_point=(double) image->columns*image->rows-black_point;
10354             }
10355          if (attribute_flag[1] != 0)
10356            black_point=argument_list[1].real_reference;
10357          if (attribute_flag[2] != 0)
10358            white_point=argument_list[2].real_reference;
10359          (void) LinearStretchImage(image,black_point,white_point);
10360          break;
10361        }
10362        case 109:  /* Mask */
10363        {
10364          if (attribute_flag[0] == 0)
10365            {
10366              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10367                PackageName);
10368              goto PerlException;
10369            }
10370          image->mask=CloneImage(argument_list[0].image_reference,0,0,
10371            MagickTrue,exception);
10372          (void) NegateImage(image->mask,MagickFalse);
10373          break;
10374        }
10375        case 110:  /* Polaroid */
10376        {
10377          DrawInfo
10378            *draw_info;
10379
10380          double
10381            angle;
10382
10383          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10384            (DrawInfo *) NULL);
10385          if (attribute_flag[0] != 0)
10386            (void) SetImageProperty(image,"caption",InterpretImageProperties(
10387              info ? info->image_info : (ImageInfo *) NULL,image,
10388              argument_list[0].string_reference));
10389          angle=0.0;
10390          if (attribute_flag[1] != 0)
10391            angle=argument_list[1].real_reference;
10392          if (attribute_flag[2] != 0)
10393            (void) CloneString(&draw_info->font,
10394              argument_list[2].string_reference);
10395          if (attribute_flag[3] != 0)
10396            (void) QueryColorDatabase(argument_list[3].string_reference,
10397              &draw_info->stroke,exception);
10398          if (attribute_flag[4] != 0)
10399            (void) QueryColorDatabase(argument_list[4].string_reference,
10400              &draw_info->fill,exception);
10401          if (attribute_flag[5] != 0)
10402            draw_info->stroke_width=argument_list[5].real_reference;
10403          if (attribute_flag[6] != 0)
10404            draw_info->pointsize=argument_list[6].real_reference;
10405          if (attribute_flag[7] != 0)
10406            draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10407          if (attribute_flag[8] != 0)
10408            (void) QueryColorDatabase(argument_list[8].string_reference,
10409              &image->background_color,exception);
10410          image=PolaroidImage(image,draw_info,angle,exception);
10411          draw_info=DestroyDrawInfo(draw_info);
10412          break;
10413        }
10414        case 111:  /* FloodfillPaint */
10415        {
10416          DrawInfo
10417            *draw_info;
10418
10419          MagickBooleanType
10420            invert;
10421
10422          MagickPixelPacket
10423            target;
10424
10425          draw_info=CloneDrawInfo(info ? info->image_info :
10426            (ImageInfo *) NULL,(DrawInfo *) NULL);
10427          if (attribute_flag[0] != 0)
10428            flags=ParsePageGeometry(image,argument_list[0].string_reference,
10429              &geometry,exception);
10430          if (attribute_flag[1] != 0)
10431            geometry.x=argument_list[1].integer_reference;
10432          if (attribute_flag[2] != 0)
10433            geometry.y=argument_list[2].integer_reference;
10434          if (attribute_flag[3] != 0)
10435            (void) QueryColorDatabase(argument_list[3].string_reference,
10436              &draw_info->fill,exception);
10437          (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10438            exception);
10439          if (attribute_flag[4] != 0)
10440            QueryMagickColor(argument_list[4].string_reference,&target,
10441              exception);
10442          if (attribute_flag[5] != 0)
10443            image->fuzz=StringToDoubleInterval(
10444              argument_list[5].string_reference,(double) QuantumRange+1.0);
10445          if (attribute_flag[6] != 0)
10446            channel=(ChannelType) argument_list[6].integer_reference;
10447          invert=MagickFalse;
10448          if (attribute_flag[7] != 0)
10449            invert=(MagickBooleanType) argument_list[7].integer_reference;
10450          (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10451            geometry.y,invert);
10452          draw_info=DestroyDrawInfo(draw_info);
10453          break;
10454        }
10455        case 112:  /* Distort */
10456        {
10457          AV
10458            *av;
10459
10460          double
10461            *coordinates;
10462
10463          DistortImageMethod
10464            method;
10465
10466          size_t
10467            number_coordinates;
10468
10469          VirtualPixelMethod
10470            virtual_pixel;
10471
10472          if (attribute_flag[0] == 0)
10473            break;
10474          method=UndefinedDistortion;
10475          if (attribute_flag[1] != 0)
10476            method=(DistortImageMethod) argument_list[1].integer_reference;
10477          av=(AV *) argument_list[0].array_reference;
10478          number_coordinates=(size_t) av_len(av)+1;
10479          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10480            sizeof(*coordinates));
10481          if (coordinates == (double *) NULL)
10482            {
10483              ThrowPerlException(exception,ResourceLimitFatalError,
10484                "MemoryAllocationFailed",PackageName);
10485              goto PerlException;
10486            }
10487          for (j=0; j < (ssize_t) number_coordinates; j++)
10488            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10489          virtual_pixel=UndefinedVirtualPixelMethod;
10490          if (attribute_flag[2] != 0)
10491            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10492              argument_list[2].integer_reference);
10493          image=DistortImage(image,method,number_coordinates,coordinates,
10494            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10495            exception);
10496          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10497            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10498          coordinates=(double *) RelinquishMagickMemory(coordinates);
10499          break;
10500        }
10501        case 113:  /* Clut */
10502        {
10503          if (attribute_flag[0] == 0)
10504            {
10505              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10506                PackageName);
10507              goto PerlException;
10508            }
10509          if (attribute_flag[1] != 0)
10510            channel=(ChannelType) argument_list[1].integer_reference;
10511          (void) ClutImageChannel(image,channel,
10512            argument_list[0].image_reference);
10513          break;
10514        }
10515        case 114:  /* LiquidRescale */
10516        {
10517          if (attribute_flag[0] != 0)
10518            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10519              &geometry,exception);
10520          if (attribute_flag[1] != 0)
10521            geometry.width=argument_list[1].integer_reference;
10522          if (attribute_flag[2] != 0)
10523            geometry.height=argument_list[2].integer_reference;
10524          if (attribute_flag[3] == 0)
10525            argument_list[3].real_reference=1.0;
10526          if (attribute_flag[4] == 0)
10527            argument_list[4].real_reference=0.0;
10528          image=LiquidRescaleImage(image,geometry.width,geometry.height,
10529            argument_list[3].real_reference,argument_list[4].real_reference,
10530            exception);
10531          break;
10532        }
10533        case 115:  /* EncipherImage */
10534        {
10535          (void) EncipherImage(image,argument_list[0].string_reference,
10536            exception);
10537          break;
10538        }
10539        case 116:  /* DecipherImage */
10540        {
10541          (void) DecipherImage(image,argument_list[0].string_reference,
10542            exception);
10543          break;
10544        }
10545        case 117:  /* Deskew */
10546        {
10547          geometry_info.rho=QuantumRange/2.0;
10548          if (attribute_flag[0] != 0)
10549            flags=ParseGeometry(argument_list[0].string_reference,
10550              &geometry_info);
10551          if (attribute_flag[1] != 0)
10552            geometry_info.rho=StringToDoubleInterval(
10553              argument_list[1].string_reference,(double) QuantumRange+1.0);
10554          image=DeskewImage(image,geometry_info.rho,exception);
10555          break;
10556        }
10557        case 118:  /* Remap */
10558        {
10559          QuantizeInfo
10560            *quantize_info;
10561
10562          if (attribute_flag[0] == 0)
10563            {
10564              ThrowPerlException(exception,OptionError,"RemapImageRequired",
10565                PackageName);
10566              goto PerlException;
10567            }
10568          quantize_info=AcquireQuantizeInfo(info->image_info);
10569          if (attribute_flag[1] != 0)
10570            quantize_info->dither=(MagickBooleanType)
10571              argument_list[1].integer_reference;
10572          if (attribute_flag[2] != 0)
10573            quantize_info->dither_method=(DitherMethod)
10574              argument_list[2].integer_reference;
10575          (void) RemapImages(quantize_info,image,
10576            argument_list[0].image_reference);
10577          quantize_info=DestroyQuantizeInfo(quantize_info);
10578          break;
10579        }
10580        case 119:  /* SparseColor */
10581        {
10582          AV
10583            *av;
10584
10585          double
10586            *coordinates;
10587
10588          SparseColorMethod
10589            method;
10590
10591          size_t
10592            number_coordinates;
10593
10594          VirtualPixelMethod
10595            virtual_pixel;
10596
10597          if (attribute_flag[0] == 0)
10598            break;
10599          method=UndefinedColorInterpolate;
10600          if (attribute_flag[1] != 0)
10601            method=(SparseColorMethod) argument_list[1].integer_reference;
10602          av=(AV *) argument_list[0].array_reference;
10603          number_coordinates=(size_t) av_len(av)+1;
10604          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10605            sizeof(*coordinates));
10606          if (coordinates == (double *) NULL)
10607            {
10608              ThrowPerlException(exception,ResourceLimitFatalError,
10609                "MemoryAllocationFailed",PackageName);
10610              goto PerlException;
10611            }
10612          for (j=0; j < (ssize_t) number_coordinates; j++)
10613            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10614          virtual_pixel=UndefinedVirtualPixelMethod;
10615          if (attribute_flag[2] != 0)
10616            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10617              argument_list[2].integer_reference);
10618          if (attribute_flag[3] != 0)
10619            channel=(ChannelType) argument_list[3].integer_reference;
10620          image=SparseColorImage(image,channel,method,number_coordinates,
10621            coordinates,exception);
10622          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10623            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10624          coordinates=(double *) RelinquishMagickMemory(coordinates);
10625          break;
10626        }
10627        case 120:  /* Function */
10628        {
10629          AV
10630            *av;
10631
10632          double
10633            *parameters;
10634
10635          MagickFunction
10636            function;
10637
10638          size_t
10639            number_parameters;
10640
10641          VirtualPixelMethod
10642            virtual_pixel;
10643
10644          if (attribute_flag[0] == 0)
10645            break;
10646          function=UndefinedFunction;
10647          if (attribute_flag[1] != 0)
10648            function=(MagickFunction) argument_list[1].integer_reference;
10649          av=(AV *) argument_list[0].array_reference;
10650          number_parameters=(size_t) av_len(av)+1;
10651          parameters=(double *) AcquireQuantumMemory(number_parameters,
10652            sizeof(*parameters));
10653          if (parameters == (double *) NULL)
10654            {
10655              ThrowPerlException(exception,ResourceLimitFatalError,
10656                "MemoryAllocationFailed",PackageName);
10657              goto PerlException;
10658            }
10659          for (j=0; j < (ssize_t) number_parameters; j++)
10660            parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10661          virtual_pixel=UndefinedVirtualPixelMethod;
10662          if (attribute_flag[2] != 0)
10663            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10664              argument_list[2].integer_reference);
10665          (void) FunctionImage(image,function,number_parameters,parameters,
10666            exception);
10667          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10668            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10669          parameters=(double *) RelinquishMagickMemory(parameters);
10670          break;
10671        }
10672        case 121:  /* SelectiveBlur */
10673        {
10674          if (attribute_flag[0] != 0)
10675            {
10676              flags=ParseGeometry(argument_list[0].string_reference,
10677                &geometry_info);
10678              if ((flags & SigmaValue) == 0)
10679                geometry_info.sigma=1.0;
10680              if ((flags & PercentValue) != 0)
10681                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10682            }
10683          if (attribute_flag[1] != 0)
10684            geometry_info.rho=argument_list[1].real_reference;
10685          if (attribute_flag[2] != 0)
10686            geometry_info.sigma=argument_list[2].real_reference;
10687          if (attribute_flag[3] != 0)
10688            geometry_info.xi=argument_list[3].integer_reference;;
10689          if (attribute_flag[4] != 0)
10690            channel=(ChannelType) argument_list[4].integer_reference;
10691          image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10692            geometry_info.sigma,geometry_info.xi,exception);
10693          break;
10694        }
10695        case 122:  /* HaldClut */
10696        {
10697          if (attribute_flag[0] == 0)
10698            {
10699              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10700                PackageName);
10701              goto PerlException;
10702            }
10703          if (attribute_flag[1] != 0)
10704            channel=(ChannelType) argument_list[1].integer_reference;
10705          (void) HaldClutImageChannel(image,channel,
10706            argument_list[0].image_reference);
10707          break;
10708        }
10709        case 123:  /* BlueShift */
10710        {
10711          if (attribute_flag[0] != 0)
10712            (void) ParseGeometry(argument_list[0].string_reference,
10713              &geometry_info);
10714          image=BlueShiftImage(image,geometry_info.rho,exception);
10715          break;
10716        }
10717        case 124:  /* ForwardFourierTransformImage */
10718        {
10719          image=ForwardFourierTransformImage(image,
10720            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10721            exception);
10722          break;
10723        }
10724        case 125:  /* InverseFourierTransformImage */
10725        {
10726          image=InverseFourierTransformImage(image,image->next,
10727            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10728            exception);
10729          break;
10730        }
10731        case 126:  /* ColorDecisionList */
10732        {
10733          if (attribute_flag[0] == 0)
10734            argument_list[0].string_reference=(char *) NULL;
10735          (void) ColorDecisionListImage(image,
10736            argument_list[0].string_reference);
10737          break;
10738        }
10739        case 127:  /* AutoGamma */
10740        {
10741          if (attribute_flag[0] != 0)
10742            channel=(ChannelType) argument_list[0].integer_reference;
10743          (void) AutoGammaImageChannel(image,channel);
10744          break;
10745        }
10746        case 128:  /* AutoLevel */
10747        {
10748          if (attribute_flag[0] != 0)
10749            channel=(ChannelType) argument_list[0].integer_reference;
10750          (void) AutoLevelImageChannel(image,channel);
10751          break;
10752        }
10753        case 129:  /* LevelColors */
10754        {
10755          MagickPixelPacket
10756            black_point,
10757            white_point;
10758
10759          (void) QueryMagickColor("#000000",&black_point,exception);
10760          (void) QueryMagickColor("#ffffff",&white_point,exception);
10761          if (attribute_flag[1] != 0)
10762             (void) QueryMagickColor(argument_list[1].string_reference,
10763               &black_point,exception);
10764          if (attribute_flag[2] != 0)
10765             (void) QueryMagickColor(argument_list[2].string_reference,
10766               &white_point,exception);
10767          if (attribute_flag[3] != 0)
10768            channel=(ChannelType) argument_list[3].integer_reference;
10769          (void) LevelColorsImageChannel(image,channel,&black_point,
10770            &white_point,argument_list[0].integer_reference != 0 ? MagickTrue :
10771            MagickFalse);
10772          break;
10773        }
10774        case 130:  /* Clamp */
10775        {
10776          if (attribute_flag[0] != 0)
10777            channel=(ChannelType) argument_list[0].integer_reference;
10778          (void) ClampImageChannel(image,channel);
10779          break;
10780        }
10781        case 131:  /* Filter */
10782        {
10783          KernelInfo
10784            *kernel;
10785
10786          if (attribute_flag[0] == 0)
10787            break;
10788          kernel=AcquireKernelInfo(argument_list[0].string_reference);
10789          if (kernel == (KernelInfo *) NULL)
10790            break;
10791          if (attribute_flag[1] != 0)
10792            channel=(ChannelType) argument_list[1].integer_reference;
10793          if (attribute_flag[2] != 0)
10794            image->bias=StringToDoubleInterval(
10795              argument_list[2].string_reference,(double) QuantumRange+1.0);
10796          image=FilterImageChannel(image,channel,kernel,exception);
10797          kernel=DestroyKernelInfo(kernel);
10798          break;
10799        }
10800        case 132:  /* BrightnessContrast */
10801        {
10802          double
10803            brightness,
10804            contrast;
10805
10806          brightness=0.0;
10807          contrast=0.0;
10808          if (attribute_flag[0] != 0)
10809            {
10810              flags=ParseGeometry(argument_list[0].string_reference,
10811                &geometry_info);
10812              brightness=geometry_info.rho;
10813              if ((flags & SigmaValue) == 0)
10814                contrast=geometry_info.sigma;
10815            }
10816          if (attribute_flag[1] != 0)
10817            brightness=argument_list[1].real_reference;
10818          if (attribute_flag[2] != 0)
10819            contrast=argument_list[2].real_reference;
10820          if (attribute_flag[4] != 0)
10821            channel=(ChannelType) argument_list[4].integer_reference;
10822          (void) BrightnessContrastImageChannel(image,channel,brightness,
10823            contrast);
10824          break;
10825        }
10826        case 133:  /* Morphology */
10827        {
10828          KernelInfo
10829            *kernel;
10830
10831          MorphologyMethod
10832            method;
10833
10834          ssize_t
10835            iterations;
10836
10837          if (attribute_flag[0] == 0)
10838            break;
10839          kernel=AcquireKernelInfo(argument_list[0].string_reference);
10840          if (kernel == (KernelInfo *) NULL)
10841            break;
10842          if (attribute_flag[1] != 0)
10843            channel=(ChannelType) argument_list[1].integer_reference;
10844          method=UndefinedMorphology;
10845          if (attribute_flag[2] != 0)
10846            method=argument_list[2].integer_reference;
10847          iterations=1;
10848          if (attribute_flag[3] != 0)
10849            iterations=argument_list[3].integer_reference;
10850          image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10851            exception);
10852          kernel=DestroyKernelInfo(kernel);
10853          break;
10854        }
10855        case 108:  /* Recolor */
10856        case 134:  /* ColorMatrix */
10857        {
10858          AV
10859            *av;
10860
10861          double
10862            *color_matrix;
10863
10864          KernelInfo
10865            *kernel_info;
10866
10867          size_t
10868            order;
10869
10870          if (attribute_flag[0] == 0)
10871            break;
10872          av=(AV *) argument_list[0].array_reference;
10873          order=(size_t) sqrt(av_len(av)+1);
10874          color_matrix=(double *) AcquireQuantumMemory(order,order*
10875            sizeof(*color_matrix));
10876          if (color_matrix == (double *) NULL)
10877            {
10878              ThrowPerlException(exception,ResourceLimitFatalError,
10879                "MemoryAllocationFailed",PackageName);
10880              goto PerlException;
10881           }
10882          for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10883            color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10884          for ( ; j < (ssize_t) (order*order); j++)
10885            color_matrix[j]=0.0;
10886          kernel_info=AcquireKernelInfo("1");
10887          if (kernel_info == (KernelInfo *) NULL)
10888            break;
10889          kernel_info->width=order;
10890          kernel_info->height=order;
10891          kernel_info->values=color_matrix;
10892          image=ColorMatrixImage(image,kernel_info,exception);
10893          kernel_info->values=(double *) NULL;
10894          kernel_info=DestroyKernelInfo(kernel_info);
10895          color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10896          break;
10897        }
10898        case 135:  /* Color */
10899        {
10900          MagickPixelPacket
10901            color;
10902
10903          (void) QueryMagickColor("none",&color,exception);
10904          if (attribute_flag[0] != 0)
10905            (void) QueryMagickColor(argument_list[0].string_reference,
10906              &color,exception);
10907          (void) SetImageColor(image,&color);
10908          break;
10909        }
10910        case 136:  /* Mode */
10911        {
10912          if (attribute_flag[0] != 0)
10913            {
10914              flags=ParseGeometry(argument_list[0].string_reference,
10915                &geometry_info);
10916              if ((flags & SigmaValue) == 0)
10917                geometry_info.sigma=1.0;
10918            }
10919          if (attribute_flag[1] != 0)
10920            geometry_info.rho=argument_list[1].real_reference;
10921          if (attribute_flag[2] != 0)
10922            geometry_info.sigma=argument_list[2].real_reference;
10923          if (attribute_flag[3] != 0)
10924            channel=(ChannelType) argument_list[3].integer_reference;
10925          image=StatisticImageChannel(image,channel,ModeStatistic,
10926            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10927          break;
10928        }
10929        case 137:  /* Statistic */
10930        {
10931          StatisticType
10932            statistic;
10933
10934          statistic=UndefinedStatistic;
10935          if (attribute_flag[0] != 0)
10936            {
10937              flags=ParseGeometry(argument_list[0].string_reference,
10938                &geometry_info);
10939              if ((flags & SigmaValue) == 0)
10940                geometry_info.sigma=1.0;
10941            }
10942          if (attribute_flag[1] != 0)
10943            geometry_info.rho=argument_list[1].real_reference;
10944          if (attribute_flag[2] != 0)
10945            geometry_info.sigma=argument_list[2].real_reference;
10946          if (attribute_flag[3] != 0)
10947            channel=(ChannelType) argument_list[3].integer_reference;
10948          if (attribute_flag[4] != 0)
10949            statistic=(StatisticType) argument_list[4].integer_reference;
10950          image=StatisticImageChannel(image,channel,statistic,
10951            (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10952          break;
10953        }
10954        case 138:  /* Perceptible */
10955        {
10956          double
10957            epsilon;
10958
10959          epsilon=MagickEpsilon;
10960          if (attribute_flag[0] != 0)
10961            epsilon=argument_list[0].real_reference;
10962          if (attribute_flag[1] != 0)
10963            channel=(ChannelType) argument_list[1].integer_reference;
10964          (void) PerceptibleImageChannel(image,channel,epsilon);
10965          break;
10966        }
10967        case 139:  /* Poly */
10968        {
10969          AV
10970            *av;
10971
10972          double
10973            *terms;
10974
10975          size_t
10976            number_terms;
10977
10978          if (attribute_flag[0] == 0)
10979            break;
10980          if (attribute_flag[1] != 0)
10981            channel=(ChannelType) argument_list[1].integer_reference;
10982          av=(AV *) argument_list[0].array_reference;
10983          number_terms=(size_t) av_len(av);
10984          terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
10985          if (terms == (double *) NULL)
10986            {
10987              ThrowPerlException(exception,ResourceLimitFatalError,
10988                "MemoryAllocationFailed",PackageName);
10989              goto PerlException;
10990            }
10991          for (j=0; j < av_len(av); j++)
10992            terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
10993          image=PolynomialImageChannel(image,channel,number_terms >> 1,terms,
10994            exception);
10995          terms=(double *) RelinquishMagickMemory(terms);
10996          break;
10997        }
10998        case 140:  /* Grayscale */
10999        {
11000          PixelIntensityMethod
11001            method;
11002
11003          method=UndefinedPixelIntensityMethod;
11004          if (attribute_flag[0] != 0)
11005            method=(PixelIntensityMethod) argument_list[0].integer_reference;
11006          (void) GrayscaleImage(image,method);
11007          break;
11008        }
11009        case 141:  /* CannyEdge */
11010        {
11011          if (attribute_flag[0] != 0)
11012            {
11013              flags=ParseGeometry(argument_list[0].string_reference,
11014                &geometry_info);
11015              if ((flags & SigmaValue) == 0)
11016                geometry_info.sigma=1.0;
11017              if ((flags & XiValue) == 0)
11018                geometry_info.xi=0.10;
11019              if ((flags & PsiValue) == 0)
11020                geometry_info.psi=0.30;
11021              if ((flags & PercentValue) != 0)
11022                {
11023                  geometry_info.xi/=100.0;
11024                  geometry_info.psi/=100.0;
11025                }
11026            }
11027          if (attribute_flag[1] != 0)
11028            geometry_info.rho=argument_list[1].real_reference;
11029          if (attribute_flag[2] != 0)
11030            geometry_info.sigma=argument_list[2].real_reference;
11031          if (attribute_flag[3] != 0)
11032            geometry_info.xi=argument_list[3].real_reference;
11033          if (attribute_flag[4] != 0)
11034            geometry_info.psi=argument_list[4].real_reference;
11035          image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11036            geometry_info.xi,geometry_info.psi,exception);
11037          break;
11038        }
11039        case 142:  /* HoughLine */
11040        {
11041          if (attribute_flag[0] != 0)
11042            {
11043              flags=ParseGeometry(argument_list[0].string_reference,
11044                &geometry_info);
11045              if ((flags & SigmaValue) == 0)
11046                geometry_info.sigma=geometry_info.rho;
11047              if ((flags & XiValue) == 0)
11048                geometry_info.xi=40;
11049            }
11050          if (attribute_flag[1] != 0)
11051            geometry_info.rho=(double) argument_list[1].integer_reference;
11052          if (attribute_flag[2] != 0)
11053            geometry_info.sigma=(double) argument_list[2].integer_reference;
11054          if (attribute_flag[3] != 0)
11055            geometry_info.xi=(double) argument_list[3].integer_reference;
11056          image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11057            geometry_info.sigma,(size_t) geometry_info.xi,exception);
11058          break;
11059        }
11060        case 143:  /* MeanShift */
11061        {
11062          if (attribute_flag[0] != 0)
11063            {
11064              flags=ParseGeometry(argument_list[0].string_reference,
11065                &geometry_info);
11066              if ((flags & SigmaValue) == 0)
11067                geometry_info.sigma=geometry_info.rho;
11068              if ((flags & XiValue) == 0)
11069                geometry_info.xi=0.10*QuantumRange;
11070              if ((flags & PercentValue) != 0)
11071                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11072            }
11073          if (attribute_flag[1] != 0)
11074            geometry_info.rho=(double) argument_list[1].integer_reference;
11075          if (attribute_flag[2] != 0)
11076            geometry_info.sigma=(double) argument_list[2].integer_reference;
11077          if (attribute_flag[3] != 0)
11078            geometry_info.xi=(double) argument_list[3].real_reference;
11079          image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11080            geometry_info.sigma,geometry_info.xi,exception);
11081          break;
11082        }
11083        case 144:  /* Kuwahara */
11084        {
11085          if (attribute_flag[0] != 0)
11086            {
11087              flags=ParseGeometry(argument_list[0].string_reference,
11088                &geometry_info);
11089              if ((flags & SigmaValue) == 0)
11090                geometry_info.sigma=geometry_info.rho-0.5;
11091            }
11092          if (attribute_flag[1] != 0)
11093            geometry_info.rho=argument_list[1].real_reference;
11094          if (attribute_flag[2] != 0)
11095            geometry_info.sigma=argument_list[2].real_reference;
11096          if (attribute_flag[3] != 0)
11097            channel=(ChannelType) argument_list[3].integer_reference;
11098          image=KuwaharaImageChannel(image,channel,geometry_info.rho,
11099            geometry_info.sigma,exception);
11100          break;
11101        }
11102        case 145:  /* ConnectedComponent */
11103        {
11104          MagickBooleanType
11105            verbose;
11106
11107          size_t
11108            connectivity;
11109
11110          connectivity=4;
11111          verbose=MagickFalse;
11112          if (attribute_flag[0] != 0)
11113            connectivity=argument_list[0].integer_reference;
11114          if (attribute_flag[1] != 0)
11115            verbose=argument_list[4].integer_reference != 0 ?
11116              MagickTrue : MagickFalse;
11117          if (verbose != MagickFalse)
11118            SetImageArtifact(image,"connected-components","true");
11119          image=ConnectedComponentsImage(image,connectivity,exception);
11120          break;
11121        }
11122        case 146:  /* Copy */
11123        {
11124          Image
11125            *source_image;
11126
11127          OffsetInfo
11128            offset;
11129
11130          RectangleInfo
11131            offset_geometry;
11132
11133          source_image=image;
11134          if (attribute_flag[0] != 0)
11135            source_image=argument_list[0].image_reference;
11136          SetGeometry(source_image,&geometry);
11137          if (attribute_flag[1] != 0)
11138            flags=ParseGravityGeometry(source_image,
11139              argument_list[1].string_reference,&geometry,exception);
11140          if (attribute_flag[2] != 0)
11141            geometry.width=argument_list[2].integer_reference;
11142          if (attribute_flag[3] != 0)
11143            geometry.height=argument_list[3].integer_reference;
11144          if (attribute_flag[4] != 0)
11145            geometry.x=argument_list[4].integer_reference;
11146          if (attribute_flag[5] != 0)
11147            geometry.y=argument_list[5].integer_reference;
11148          if (attribute_flag[6] != 0)
11149            image->gravity=(GravityType) argument_list[6].integer_reference;
11150          SetGeometry(image,&offset_geometry);
11151          if (attribute_flag[7] != 0)
11152            flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11153              &offset_geometry,exception);
11154          offset.x=offset_geometry.x;
11155          offset.y=offset_geometry.y;
11156          if (attribute_flag[8] != 0)
11157            offset.x=argument_list[8].integer_reference;
11158          if (attribute_flag[9] != 0)
11159            offset.y=argument_list[9].integer_reference;
11160          (void) CopyImagePixels(image,source_image,&geometry,&offset,
11161            exception);
11162          break;
11163        }
11164        case 147:  /* WaveletDenoise */
11165        {
11166          if (attribute_flag[0] != 0)
11167            {
11168              flags=ParseGeometry(argument_list[0].string_reference,
11169                &geometry_info);
11170              if ((flags & PercentValue) != 0)
11171                {
11172                  geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11173                  geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11174                }
11175              if ((flags & SigmaValue) == 0)
11176                geometry_info.sigma=0.0;
11177            }
11178          if (attribute_flag[1] != 0)
11179            geometry_info.rho=argument_list[1].real_reference;
11180          if (attribute_flag[2] != 0)
11181            geometry_info.sigma=argument_list[2].real_reference;
11182          image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,            exception);
11183          break;
11184        }
11185        case 148:  /* Colorspace */
11186        {
11187          ColorspaceType
11188            colorspace;
11189
11190          colorspace=sRGBColorspace;
11191          if (attribute_flag[0] != 0)
11192            colorspace=(ColorspaceType) argument_list[0].integer_reference;
11193          (void) TransformImageColorspace(image,colorspace);
11194          break;
11195        }
11196        case 149:  /* AutoThreshold */
11197        {
11198          AutoThresholdMethod
11199            method;
11200
11201          method=UndefinedThresholdMethod;
11202          if (attribute_flag[0] != 0)
11203            method=(AutoThresholdMethod) argument_list[0].integer_reference;
11204          (void) AutoThresholdImage(image,method,exception);
11205          break;
11206        }
11207      }
11208      if (next != (Image *) NULL)
11209        (void) CatchImageException(next);
11210      if (region_image != (Image *) NULL)
11211        {
11212          /*
11213            Composite region.
11214          */
11215          status=CompositeImage(region_image,CopyCompositeOp,image,
11216            region_info.x,region_info.y);
11217          (void) status;
11218          (void) CatchImageException(region_image);
11219          image=DestroyImage(image);
11220          image=region_image;
11221        }
11222      if (image != (Image *) NULL)
11223        {
11224          number_images++;
11225          if (next && (next != image))
11226            {
11227              image->next=next->next;
11228              if (image->next != (Image *) NULL)
11229                image->next->previous=image;
11230              DeleteImageFromRegistry(*pv,next);
11231            }
11232          sv_setiv(*pv,PTR2IV(image));
11233          next=image;
11234        }
11235      if (*pv)
11236        pv++;
11237    }
11238
11239  PerlException:
11240    if (reference_vector)
11241      reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11242    InheritPerlException(exception,perl_exception);
11243    exception=DestroyExceptionInfo(exception);
11244    sv_setiv(perl_exception,(IV) number_images);
11245    SvPOK_on(perl_exception);
11246    ST(0)=sv_2mortal(perl_exception);
11247    XSRETURN(1);
11248  }
11249
11250#
11251###############################################################################
11252#                                                                             #
11253#                                                                             #
11254#                                                                             #
11255#   M o n t a g e                                                             #
11256#                                                                             #
11257#                                                                             #
11258#                                                                             #
11259###############################################################################
11260#
11261#
11262void
11263Montage(ref,...)
11264  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11265  ALIAS:
11266    MontageImage  = 1
11267    montage       = 2
11268    montageimage  = 3
11269  PPCODE:
11270  {
11271    AV
11272      *av;
11273
11274    char
11275      *attribute;
11276
11277    ExceptionInfo
11278      *exception;
11279
11280    HV
11281      *hv;
11282
11283    Image
11284      *image,
11285      *next;
11286
11287    MagickPixelPacket
11288      transparent_color;
11289
11290    MontageInfo
11291      *montage_info;
11292
11293    ssize_t
11294      i;
11295
11296    ssize_t
11297      sp;
11298
11299    struct PackageInfo
11300      *info;
11301
11302    SV
11303      *av_reference,
11304      *perl_exception,
11305      *reference,
11306      *rv,
11307      *sv;
11308
11309    PERL_UNUSED_VAR(ref);
11310    PERL_UNUSED_VAR(ix);
11311    exception=AcquireExceptionInfo();
11312    perl_exception=newSVpv("",0);
11313    sv=NULL;
11314    attribute=NULL;
11315    if (sv_isobject(ST(0)) == 0)
11316      {
11317        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11318          PackageName);
11319        goto PerlException;
11320      }
11321    reference=SvRV(ST(0));
11322    hv=SvSTASH(reference);
11323    av=newAV();
11324    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11325    SvREFCNT_dec(av);
11326    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11327    if (image == (Image *) NULL)
11328      {
11329        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11330          PackageName);
11331        goto PerlException;
11332      }
11333    /*
11334      Get options.
11335    */
11336    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11337    montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11338    (void) QueryMagickColor("none",&transparent_color,exception);
11339    for (i=2; i < items; i+=2)
11340    {
11341      attribute=(char *) SvPV(ST(i-1),na);
11342      switch (*attribute)
11343      {
11344        case 'B':
11345        case 'b':
11346        {
11347          if (LocaleCompare(attribute,"background") == 0)
11348            {
11349              (void) QueryColorDatabase(SvPV(ST(i),na),
11350                &montage_info->background_color,exception);
11351              for (next=image; next; next=next->next)
11352                next->background_color=montage_info->background_color;
11353              break;
11354            }
11355          if (LocaleCompare(attribute,"border") == 0)
11356            {
11357              montage_info->border_width=SvIV(ST(i));
11358              break;
11359            }
11360          if (LocaleCompare(attribute,"bordercolor") == 0)
11361            {
11362              (void) QueryColorDatabase(SvPV(ST(i),na),
11363                &montage_info->border_color,exception);
11364              for (next=image; next; next=next->next)
11365                next->border_color=montage_info->border_color;
11366              break;
11367            }
11368          if (LocaleCompare(attribute,"borderwidth") == 0)
11369            {
11370              montage_info->border_width=SvIV(ST(i));
11371              break;
11372            }
11373          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11374            attribute);
11375          break;
11376        }
11377        case 'C':
11378        case 'c':
11379        {
11380          if (LocaleCompare(attribute,"compose") == 0)
11381            {
11382              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11383                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11384              if (sp < 0)
11385                {
11386                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11387                    SvPV(ST(i),na));
11388                  break;
11389                }
11390              for (next=image; next; next=next->next)
11391                next->compose=(CompositeOperator) sp;
11392              break;
11393            }
11394          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11395            attribute);
11396          break;
11397        }
11398        case 'F':
11399        case 'f':
11400        {
11401          if (LocaleCompare(attribute,"fill") == 0)
11402            {
11403              (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
11404                exception);
11405              break;
11406            }
11407          if (LocaleCompare(attribute,"font") == 0)
11408            {
11409              (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11410              break;
11411            }
11412          if (LocaleCompare(attribute,"frame") == 0)
11413            {
11414              char
11415                *p;
11416
11417              p=SvPV(ST(i),na);
11418              if (IsGeometry(p) == MagickFalse)
11419                {
11420                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11421                    p);
11422                  break;
11423                }
11424              (void) CloneString(&montage_info->frame,p);
11425              if (*p == '\0')
11426                montage_info->frame=(char *) NULL;
11427              break;
11428            }
11429          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11430            attribute);
11431          break;
11432        }
11433        case 'G':
11434        case 'g':
11435        {
11436          if (LocaleCompare(attribute,"geometry") == 0)
11437            {
11438              char
11439                *p;
11440
11441              p=SvPV(ST(i),na);
11442              if (IsGeometry(p) == MagickFalse)
11443                {
11444                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11445                    p);
11446                  break;
11447                }
11448             (void) CloneString(&montage_info->geometry,p);
11449             if (*p == '\0')
11450               montage_info->geometry=(char *) NULL;
11451             break;
11452           }
11453         if (LocaleCompare(attribute,"gravity") == 0)
11454           {
11455             ssize_t
11456               in;
11457
11458             in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11459               MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11460             if (in < 0)
11461               {
11462                 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11463                   SvPV(ST(i),na));
11464                 return;
11465               }
11466             montage_info->gravity=(GravityType) in;
11467             for (next=image; next; next=next->next)
11468               next->gravity=(GravityType) in;
11469             break;
11470           }
11471          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11472            attribute);
11473          break;
11474        }
11475        case 'L':
11476        case 'l':
11477        {
11478          if (LocaleCompare(attribute,"label") == 0)
11479            {
11480              for (next=image; next; next=next->next)
11481                (void) SetImageProperty(next,"label",InterpretImageProperties(
11482                  info ? info->image_info : (ImageInfo *) NULL,next,
11483                  SvPV(ST(i),na)));
11484              break;
11485            }
11486          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11487            attribute);
11488          break;
11489        }
11490        case 'M':
11491        case 'm':
11492        {
11493          if (LocaleCompare(attribute,"mattecolor") == 0)
11494            {
11495              (void) QueryColorDatabase(SvPV(ST(i),na),
11496                &montage_info->matte_color,exception);
11497              for (next=image; next; next=next->next)
11498                next->matte_color=montage_info->matte_color;
11499              break;
11500            }
11501          if (LocaleCompare(attribute,"mode") == 0)
11502            {
11503              ssize_t
11504                in;
11505
11506              in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
11507                ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11508              switch (in)
11509              {
11510                default:
11511                {
11512                  ThrowPerlException(exception,OptionError,
11513                    "UnrecognizedModeType",SvPV(ST(i),na));
11514                  break;
11515                }
11516                case FrameMode:
11517                {
11518                  (void) CloneString(&montage_info->frame,"15x15+3+3");
11519                  montage_info->shadow=MagickTrue;
11520                  break;
11521                }
11522                case UnframeMode:
11523                {
11524                  montage_info->frame=(char *) NULL;
11525                  montage_info->shadow=MagickFalse;
11526                  montage_info->border_width=0;
11527                  break;
11528                }
11529                case ConcatenateMode:
11530                {
11531                  montage_info->frame=(char *) NULL;
11532                  montage_info->shadow=MagickFalse;
11533                  (void) CloneString(&montage_info->geometry,"+0+0");
11534                  montage_info->border_width=0;
11535                }
11536              }
11537              break;
11538            }
11539          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11540            attribute);
11541          break;
11542        }
11543        case 'P':
11544        case 'p':
11545        {
11546          if (LocaleCompare(attribute,"pointsize") == 0)
11547            {
11548              montage_info->pointsize=SvIV(ST(i));
11549              break;
11550            }
11551          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11552            attribute);
11553          break;
11554        }
11555        case 'S':
11556        case 's':
11557        {
11558          if (LocaleCompare(attribute,"shadow") == 0)
11559            {
11560              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11561                MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11562              if (sp < 0)
11563                {
11564                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11565                    SvPV(ST(i),na));
11566                  break;
11567                }
11568             montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11569             break;
11570            }
11571          if (LocaleCompare(attribute,"stroke") == 0)
11572            {
11573              (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11574                exception);
11575              break;
11576            }
11577          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11578            attribute);
11579          break;
11580        }
11581        case 'T':
11582        case 't':
11583        {
11584          if (LocaleCompare(attribute,"texture") == 0)
11585            {
11586              (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11587              break;
11588            }
11589          if (LocaleCompare(attribute,"tile") == 0)
11590            {
11591              char *p=SvPV(ST(i),na);
11592              if (IsGeometry(p) == MagickFalse)
11593                {
11594                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11595                    p);
11596                  break;
11597                }
11598              (void) CloneString(&montage_info->tile,p);
11599              if (*p == '\0')
11600                montage_info->tile=(char *) NULL;
11601              break;
11602            }
11603          if (LocaleCompare(attribute,"title") == 0)
11604            {
11605              (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11606              break;
11607            }
11608          if (LocaleCompare(attribute,"transparent") == 0)
11609            {
11610              MagickPixelPacket
11611                transparent_color;
11612
11613              QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11614              for (next=image; next; next=next->next)
11615                (void) TransparentPaintImage(next,&transparent_color,
11616                  TransparentOpacity,MagickFalse);
11617              break;
11618            }
11619          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11620            attribute);
11621          break;
11622        }
11623        default:
11624        {
11625          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11626            attribute);
11627          break;
11628        }
11629      }
11630    }
11631    image=MontageImageList(info->image_info,montage_info,image,exception);
11632    montage_info=DestroyMontageInfo(montage_info);
11633    if (image == (Image *) NULL)
11634      goto PerlException;
11635    if (transparent_color.opacity != TransparentOpacity)
11636      for (next=image; next; next=next->next)
11637        (void) TransparentPaintImage(next,&transparent_color,
11638          TransparentOpacity,MagickFalse);
11639    for (  ; image; image=image->next)
11640    {
11641      AddImageToRegistry(sv,image);
11642      rv=newRV(sv);
11643      av_push(av,sv_bless(rv,hv));
11644      SvREFCNT_dec(sv);
11645    }
11646    exception=DestroyExceptionInfo(exception);
11647    ST(0)=av_reference;
11648    SvREFCNT_dec(perl_exception);
11649    XSRETURN(1);
11650
11651  PerlException:
11652    InheritPerlException(exception,perl_exception);
11653    exception=DestroyExceptionInfo(exception);
11654    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11655    SvPOK_on(perl_exception);
11656    ST(0)=sv_2mortal(perl_exception);
11657    XSRETURN(1);
11658  }
11659
11660#
11661###############################################################################
11662#                                                                             #
11663#                                                                             #
11664#                                                                             #
11665#   M o r p h                                                                 #
11666#                                                                             #
11667#                                                                             #
11668#                                                                             #
11669###############################################################################
11670#
11671#
11672void
11673Morph(ref,...)
11674  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11675  ALIAS:
11676    MorphImage  = 1
11677    morph       = 2
11678    morphimage  = 3
11679  PPCODE:
11680  {
11681    AV
11682      *av;
11683
11684    char
11685      *attribute;
11686
11687    ExceptionInfo
11688      *exception;
11689
11690    HV
11691      *hv;
11692
11693    Image
11694      *image;
11695
11696    ssize_t
11697      i;
11698
11699    ssize_t
11700      number_frames;
11701
11702    struct PackageInfo
11703      *info;
11704
11705    SV
11706      *av_reference,
11707      *perl_exception,
11708      *reference,
11709      *rv,
11710      *sv;
11711
11712    PERL_UNUSED_VAR(ref);
11713    PERL_UNUSED_VAR(ix);
11714    exception=AcquireExceptionInfo();
11715    perl_exception=newSVpv("",0);
11716    sv=NULL;
11717    av=NULL;
11718    attribute=NULL;
11719    if (sv_isobject(ST(0)) == 0)
11720      {
11721        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11722          PackageName);
11723        goto PerlException;
11724      }
11725    reference=SvRV(ST(0));
11726    hv=SvSTASH(reference);
11727    av=newAV();
11728    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11729    SvREFCNT_dec(av);
11730    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11731    if (image == (Image *) NULL)
11732      {
11733        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11734          PackageName);
11735        goto PerlException;
11736      }
11737    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11738    /*
11739      Get attribute.
11740    */
11741    number_frames=30;
11742    for (i=2; i < items; i+=2)
11743    {
11744      attribute=(char *) SvPV(ST(i-1),na);
11745      switch (*attribute)
11746      {
11747        case 'F':
11748        case 'f':
11749        {
11750          if (LocaleCompare(attribute,"frames") == 0)
11751            {
11752              number_frames=SvIV(ST(i));
11753              break;
11754            }
11755          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11756            attribute);
11757          break;
11758        }
11759        default:
11760        {
11761          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11762            attribute);
11763          break;
11764        }
11765      }
11766    }
11767    image=MorphImages(image,number_frames,exception);
11768    if (image == (Image *) NULL)
11769      goto PerlException;
11770    for ( ; image; image=image->next)
11771    {
11772      AddImageToRegistry(sv,image);
11773      rv=newRV(sv);
11774      av_push(av,sv_bless(rv,hv));
11775      SvREFCNT_dec(sv);
11776    }
11777    exception=DestroyExceptionInfo(exception);
11778    ST(0)=av_reference;
11779    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11780    XSRETURN(1);
11781
11782  PerlException:
11783    InheritPerlException(exception,perl_exception);
11784    exception=DestroyExceptionInfo(exception);
11785    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11786    SvPOK_on(perl_exception);
11787    ST(0)=sv_2mortal(perl_exception);
11788    XSRETURN(1);
11789  }
11790
11791#
11792###############################################################################
11793#                                                                             #
11794#                                                                             #
11795#                                                                             #
11796#   M o s a i c                                                               #
11797#                                                                             #
11798#                                                                             #
11799#                                                                             #
11800###############################################################################
11801#
11802#
11803void
11804Mosaic(ref)
11805  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11806  ALIAS:
11807    MosaicImage   = 1
11808    mosaic        = 2
11809    mosaicimage   = 3
11810  PPCODE:
11811  {
11812    AV
11813      *av;
11814
11815    ExceptionInfo
11816      *exception;
11817
11818    HV
11819      *hv;
11820
11821    Image
11822      *image;
11823
11824    struct PackageInfo
11825      *info;
11826
11827    SV
11828      *perl_exception,
11829      *reference,
11830      *rv,
11831      *sv;
11832
11833    PERL_UNUSED_VAR(ref);
11834    PERL_UNUSED_VAR(ix);
11835    exception=AcquireExceptionInfo();
11836    perl_exception=newSVpv("",0);
11837    sv=NULL;
11838    if (sv_isobject(ST(0)) == 0)
11839      {
11840        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11841          PackageName);
11842        goto PerlException;
11843      }
11844    reference=SvRV(ST(0));
11845    hv=SvSTASH(reference);
11846    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11847    if (image == (Image *) NULL)
11848      {
11849        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11850          PackageName);
11851        goto PerlException;
11852      }
11853    image=MergeImageLayers(image,MosaicLayer,exception);
11854    /*
11855      Create blessed Perl array for the returned image.
11856    */
11857    av=newAV();
11858    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11859    SvREFCNT_dec(av);
11860    AddImageToRegistry(sv,image);
11861    rv=newRV(sv);
11862    av_push(av,sv_bless(rv,hv));
11863    SvREFCNT_dec(sv);
11864    (void) CopyMagickString(info->image_info->filename,image->filename,
11865      MaxTextExtent);
11866    SetImageInfo(info->image_info,0,&image->exception);
11867    exception=DestroyExceptionInfo(exception);
11868    SvREFCNT_dec(perl_exception);
11869    XSRETURN(1);
11870
11871  PerlException:
11872    InheritPerlException(exception,perl_exception);
11873    exception=DestroyExceptionInfo(exception);
11874    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11875    SvPOK_on(perl_exception);  /* return messages in string context */
11876    ST(0)=sv_2mortal(perl_exception);
11877    XSRETURN(1);
11878  }
11879
11880#
11881###############################################################################
11882#                                                                             #
11883#                                                                             #
11884#                                                                             #
11885#   P i n g                                                                   #
11886#                                                                             #
11887#                                                                             #
11888#                                                                             #
11889###############################################################################
11890#
11891#
11892void
11893Ping(ref,...)
11894  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11895  ALIAS:
11896    PingImage  = 1
11897    ping       = 2
11898    pingimage  = 3
11899  PPCODE:
11900  {
11901    AV
11902      *av;
11903
11904    char
11905      **keep,
11906      **list;
11907
11908    ExceptionInfo
11909      *exception;
11910
11911    Image
11912      *image,
11913      *next;
11914
11915    int
11916      n;
11917
11918    MagickBooleanType
11919      status;
11920
11921    char
11922      **p;
11923
11924    ssize_t
11925      i;
11926
11927    ssize_t
11928      ac;
11929
11930    STRLEN
11931      *length;
11932
11933    struct PackageInfo
11934      *info,
11935      *package_info;
11936
11937    SV
11938      *perl_exception,
11939      *reference;
11940
11941    size_t
11942      count;
11943
11944    PERL_UNUSED_VAR(ref);
11945    PERL_UNUSED_VAR(ix);
11946    exception=AcquireExceptionInfo();
11947    perl_exception=newSVpv("",0);
11948    package_info=(struct PackageInfo *) NULL;
11949    ac=(items < 2) ? 1 : items-1;
11950    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11951    keep=list;
11952    length=(STRLEN *) NULL;
11953    if (list == (char **) NULL)
11954      {
11955        ThrowPerlException(exception,ResourceLimitError,
11956          "MemoryAllocationFailed",PackageName);
11957        goto PerlException;
11958      }
11959    keep=list;
11960    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11961    if (length == (STRLEN *) NULL)
11962      {
11963        ThrowPerlException(exception,ResourceLimitError,
11964          "MemoryAllocationFailed",PackageName);
11965        goto PerlException;
11966      }
11967    if (sv_isobject(ST(0)) == 0)
11968      {
11969        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11970          PackageName);
11971        goto PerlException;
11972      }
11973    reference=SvRV(ST(0));
11974    if (SvTYPE(reference) != SVt_PVAV)
11975      {
11976        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11977          PackageName);
11978        goto PerlException;
11979      }
11980    av=(AV *) reference;
11981    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11982      exception);
11983    package_info=ClonePackageInfo(info,exception);
11984    n=1;
11985    if (items <= 1)
11986      *list=(char *) (*package_info->image_info->filename ?
11987        package_info->image_info->filename : "XC:black");
11988    else
11989      for (n=0, i=0; i < ac; i++)
11990      {
11991        list[n]=(char *) SvPV(ST(i+1),length[n]);
11992        if ((items >= 3) && strEQcase(list[n],"blob"))
11993          {
11994            void
11995              *blob;
11996
11997            i++;
11998            blob=(void *) (SvPV(ST(i+1),length[n]));
11999            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12000          }
12001        if ((items >= 3) && strEQcase(list[n],"filename"))
12002          continue;
12003        if ((items >= 3) && strEQcase(list[n],"file"))
12004          {
12005            FILE
12006              *file;
12007
12008            PerlIO
12009              *io_info;
12010
12011            i++;
12012            io_info=IoIFP(sv_2io(ST(i+1)));
12013            if (io_info == (PerlIO *) NULL)
12014              {
12015                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12016                  PackageName);
12017                continue;
12018              }
12019            file=PerlIO_findFILE(io_info);
12020            if (file == (FILE *) NULL)
12021              {
12022                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12023                  PackageName);
12024                continue;
12025              }
12026            SetImageInfoFile(package_info->image_info,file);
12027          }
12028        if ((items >= 3) && strEQcase(list[n],"magick"))
12029          continue;
12030        n++;
12031      }
12032    list[n]=(char *) NULL;
12033    keep=list;
12034    status=ExpandFilenames(&n,&list);
12035    if (status == MagickFalse)
12036      {
12037        ThrowPerlException(exception,ResourceLimitError,
12038          "MemoryAllocationFailed",PackageName);
12039        goto PerlException;
12040      }
12041    count=0;
12042    for (i=0; i < n; i++)
12043    {
12044      (void) CopyMagickString(package_info->image_info->filename,list[i],
12045        MaxTextExtent);
12046      image=PingImage(package_info->image_info,exception);
12047      if (image == (Image *) NULL)
12048        break;
12049      if ((package_info->image_info->file != (FILE *) NULL) ||
12050          (package_info->image_info->blob != (void *) NULL))
12051        DisassociateImageStream(image);
12052      count+=GetImageListLength(image);
12053      EXTEND(sp,4*count);
12054      for (next=image; next; next=next->next)
12055      {
12056        PUSHs(sv_2mortal(newSViv(next->columns)));
12057        PUSHs(sv_2mortal(newSViv(next->rows)));
12058        PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12059        PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12060      }
12061      image=DestroyImageList(image);
12062    }
12063    /*
12064      Free resources.
12065    */
12066    for (i=0; i < n; i++)
12067      if (list[i] != (char *) NULL)
12068        for (p=keep; list[i] != *p++; )
12069          if (*p == NULL)
12070            {
12071              list[i]=(char *) RelinquishMagickMemory(list[i]);
12072              break;
12073            }
12074
12075  PerlException:
12076    if (package_info != (struct PackageInfo *) NULL)
12077      DestroyPackageInfo(package_info);
12078    if (list && (list != keep))
12079      list=(char **) RelinquishMagickMemory(list);
12080    if (keep)
12081      keep=(char **) RelinquishMagickMemory(keep);
12082    if (length)
12083      length=(STRLEN *) RelinquishMagickMemory(length);
12084    InheritPerlException(exception,perl_exception);
12085    exception=DestroyExceptionInfo(exception);
12086    SvREFCNT_dec(perl_exception);  /* throw away all errors */
12087  }
12088
12089#
12090###############################################################################
12091#                                                                             #
12092#                                                                             #
12093#                                                                             #
12094#   P r e v i e w                                                             #
12095#                                                                             #
12096#                                                                             #
12097#                                                                             #
12098###############################################################################
12099#
12100#
12101void
12102Preview(ref,...)
12103  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12104  ALIAS:
12105    PreviewImage = 1
12106    preview      = 2
12107    previewimage = 3
12108  PPCODE:
12109  {
12110    AV
12111      *av;
12112
12113    ExceptionInfo
12114      *exception;
12115
12116    HV
12117      *hv;
12118
12119    Image
12120      *image,
12121      *preview_image;
12122
12123    PreviewType
12124      preview_type;
12125
12126    struct PackageInfo
12127      *info;
12128
12129    SV
12130      *av_reference,
12131      *perl_exception,
12132      *reference,
12133      *rv,
12134      *sv;
12135
12136    PERL_UNUSED_VAR(ref);
12137    PERL_UNUSED_VAR(ix);
12138    exception=AcquireExceptionInfo();
12139    perl_exception=newSVpv("",0);
12140    sv=NULL;
12141    av=NULL;
12142    if (sv_isobject(ST(0)) == 0)
12143      {
12144        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12145          PackageName);
12146        goto PerlException;
12147      }
12148    reference=SvRV(ST(0));
12149    hv=SvSTASH(reference);
12150    av=newAV();
12151    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12152    SvREFCNT_dec(av);
12153    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12154    if (image == (Image *) NULL)
12155      {
12156        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12157          PackageName);
12158        goto PerlException;
12159      }
12160    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12161    preview_type=GammaPreview;
12162    if (items > 1)
12163      preview_type=(PreviewType)
12164        ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12165    for ( ; image; image=image->next)
12166    {
12167      preview_image=PreviewImage(image,preview_type,exception);
12168      if (preview_image == (Image *) NULL)
12169        goto PerlException;
12170      AddImageToRegistry(sv,preview_image);
12171      rv=newRV(sv);
12172      av_push(av,sv_bless(rv,hv));
12173      SvREFCNT_dec(sv);
12174    }
12175    exception=DestroyExceptionInfo(exception);
12176    ST(0)=av_reference;
12177    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12178    XSRETURN(1);
12179
12180  PerlException:
12181    InheritPerlException(exception,perl_exception);
12182    exception=DestroyExceptionInfo(exception);
12183    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12184    SvPOK_on(perl_exception);
12185    ST(0)=sv_2mortal(perl_exception);
12186    XSRETURN(1);
12187  }
12188
12189#
12190###############################################################################
12191#                                                                             #
12192#                                                                             #
12193#                                                                             #
12194#   Q u e r y C o l o r                                                       #
12195#                                                                             #
12196#                                                                             #
12197#                                                                             #
12198###############################################################################
12199#
12200#
12201void
12202QueryColor(ref,...)
12203  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12204  ALIAS:
12205    querycolor = 1
12206  PPCODE:
12207  {
12208    char
12209      *name;
12210
12211    ExceptionInfo
12212      *exception;
12213
12214    MagickPixelPacket
12215      color;
12216
12217    ssize_t
12218      i;
12219
12220    SV
12221      *perl_exception;
12222
12223    PERL_UNUSED_VAR(ref);
12224    PERL_UNUSED_VAR(ix);
12225    exception=AcquireExceptionInfo();
12226    perl_exception=newSVpv("",0);
12227    if (items == 1)
12228      {
12229        const ColorInfo
12230          **colorlist;
12231
12232        size_t
12233          colors;
12234
12235        colorlist=GetColorInfoList("*",&colors,exception);
12236        EXTEND(sp,colors);
12237        for (i=0; i < (ssize_t) colors; i++)
12238        {
12239          PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12240        }
12241        colorlist=(const ColorInfo **)
12242          RelinquishMagickMemory((ColorInfo **) colorlist);
12243        goto PerlException;
12244      }
12245    EXTEND(sp,5*items);
12246    for (i=1; i < items; i++)
12247    {
12248      name=(char *) SvPV(ST(i),na);
12249      if (QueryMagickColor(name,&color,exception) == MagickFalse)
12250        {
12251          PUSHs(&sv_undef);
12252          continue;
12253        }
12254      PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12255      PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12256      PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12257      if (color.matte != MagickFalse)
12258        PUSHs(sv_2mortal(newSViv((size_t) floor(color.opacity+0.5))));
12259      if (color.colorspace == CMYKColorspace)
12260        PUSHs(sv_2mortal(newSViv((size_t) floor(color.index+0.5))));
12261    }
12262
12263  PerlException:
12264    InheritPerlException(exception,perl_exception);
12265    exception=DestroyExceptionInfo(exception);
12266    SvREFCNT_dec(perl_exception);
12267  }
12268
12269#
12270###############################################################################
12271#                                                                             #
12272#                                                                             #
12273#                                                                             #
12274#   Q u e r y C o l o r N a m e                                               #
12275#                                                                             #
12276#                                                                             #
12277#                                                                             #
12278###############################################################################
12279#
12280#
12281void
12282QueryColorname(ref,...)
12283  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12284  ALIAS:
12285    querycolorname = 1
12286  PPCODE:
12287  {
12288    AV
12289      *av;
12290
12291    char
12292      message[MaxTextExtent];
12293
12294    ExceptionInfo
12295      *exception;
12296
12297    Image
12298      *image;
12299
12300    PixelPacket
12301      target_color;
12302
12303    ssize_t
12304      i;
12305
12306    struct PackageInfo
12307      *info;
12308
12309    SV
12310      *perl_exception,
12311      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12312
12313    PERL_UNUSED_VAR(ref);
12314    PERL_UNUSED_VAR(ix);
12315    exception=AcquireExceptionInfo();
12316    perl_exception=newSVpv("",0);
12317    reference=SvRV(ST(0));
12318    av=(AV *) reference;
12319    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12320      exception);
12321    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12322    if (image == (Image *) NULL)
12323      {
12324        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12325          PackageName);
12326        goto PerlException;
12327      }
12328    EXTEND(sp,items);
12329    for (i=1; i < items; i++)
12330    {
12331      (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
12332      (void) QueryColorname(image,&target_color,SVGCompliance,message,
12333        exception);
12334      PUSHs(sv_2mortal(newSVpv(message,0)));
12335    }
12336
12337  PerlException:
12338    InheritPerlException(exception,perl_exception);
12339    exception=DestroyExceptionInfo(exception);
12340    SvREFCNT_dec(perl_exception);
12341  }
12342
12343#
12344###############################################################################
12345#                                                                             #
12346#                                                                             #
12347#                                                                             #
12348#   Q u e r y F o n t                                                         #
12349#                                                                             #
12350#                                                                             #
12351#                                                                             #
12352###############################################################################
12353#
12354#
12355void
12356QueryFont(ref,...)
12357  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12358  ALIAS:
12359    queryfont = 1
12360  PPCODE:
12361  {
12362    char
12363      *name,
12364      message[MaxTextExtent];
12365
12366    ExceptionInfo
12367      *exception;
12368
12369    ssize_t
12370      i;
12371
12372    SV
12373      *perl_exception;
12374
12375    volatile const TypeInfo
12376      *type_info;
12377
12378    PERL_UNUSED_VAR(ref);
12379    PERL_UNUSED_VAR(ix);
12380    exception=AcquireExceptionInfo();
12381    perl_exception=newSVpv("",0);
12382    if (items == 1)
12383      {
12384        const TypeInfo
12385          **typelist;
12386
12387        size_t
12388          types;
12389
12390        typelist=GetTypeInfoList("*",&types,exception);
12391        EXTEND(sp,types);
12392        for (i=0; i < (ssize_t) types; i++)
12393        {
12394          PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12395        }
12396        typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12397          typelist);
12398        goto PerlException;
12399      }
12400    EXTEND(sp,10*items);
12401    for (i=1; i < items; i++)
12402    {
12403      name=(char *) SvPV(ST(i),na);
12404      type_info=GetTypeInfo(name,exception);
12405      if (type_info == (TypeInfo *) NULL)
12406        {
12407          PUSHs(&sv_undef);
12408          continue;
12409        }
12410      if (type_info->name == (char *) NULL)
12411        PUSHs(&sv_undef);
12412      else
12413        PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12414      if (type_info->description == (char *) NULL)
12415        PUSHs(&sv_undef);
12416      else
12417        PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12418      if (type_info->family == (char *) NULL)
12419        PUSHs(&sv_undef);
12420      else
12421        PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12422      if (type_info->style == UndefinedStyle)
12423        PUSHs(&sv_undef);
12424      else
12425        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12426          type_info->style),0)));
12427      if (type_info->stretch == UndefinedStretch)
12428        PUSHs(&sv_undef);
12429      else
12430        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12431          type_info->stretch),0)));
12432      (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12433        type_info->weight);
12434      PUSHs(sv_2mortal(newSVpv(message,0)));
12435      if (type_info->encoding == (char *) NULL)
12436        PUSHs(&sv_undef);
12437      else
12438        PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12439      if (type_info->foundry == (char *) NULL)
12440        PUSHs(&sv_undef);
12441      else
12442        PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12443      if (type_info->format == (char *) NULL)
12444        PUSHs(&sv_undef);
12445      else
12446        PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12447      if (type_info->metrics == (char *) NULL)
12448        PUSHs(&sv_undef);
12449      else
12450        PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12451      if (type_info->glyphs == (char *) NULL)
12452        PUSHs(&sv_undef);
12453      else
12454        PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12455    }
12456
12457  PerlException:
12458    InheritPerlException(exception,perl_exception);
12459    exception=DestroyExceptionInfo(exception);
12460    SvREFCNT_dec(perl_exception);
12461  }
12462
12463#
12464###############################################################################
12465#                                                                             #
12466#                                                                             #
12467#                                                                             #
12468#   Q u e r y F o n t M e t r i c s                                           #
12469#                                                                             #
12470#                                                                             #
12471#                                                                             #
12472###############################################################################
12473#
12474#
12475void
12476QueryFontMetrics(ref,...)
12477  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12478  ALIAS:
12479    queryfontmetrics = 1
12480  PPCODE:
12481  {
12482    AffineMatrix
12483      affine,
12484      current;
12485
12486    AV
12487      *av;
12488
12489    char
12490      *attribute;
12491
12492    double
12493      x,
12494      y;
12495
12496    DrawInfo
12497      *draw_info;
12498
12499    ExceptionInfo
12500      *exception;
12501
12502    GeometryInfo
12503      geometry_info;
12504
12505    Image
12506      *image;
12507
12508    MagickBooleanType
12509      status;
12510
12511    MagickStatusType
12512      flags;
12513
12514    ssize_t
12515      i;
12516
12517    ssize_t
12518      type;
12519
12520    struct PackageInfo
12521      *info,
12522      *package_info;
12523
12524    SV
12525      *perl_exception,
12526      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12527
12528    TypeMetric
12529      metrics;
12530
12531    PERL_UNUSED_VAR(ref);
12532    PERL_UNUSED_VAR(ix);
12533    exception=AcquireExceptionInfo();
12534    package_info=(struct PackageInfo *) NULL;
12535    perl_exception=newSVpv("",0);
12536    reference=SvRV(ST(0));
12537    av=(AV *) reference;
12538    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12539      exception);
12540    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12541    if (image == (Image *) NULL)
12542      {
12543        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12544          PackageName);
12545        goto PerlException;
12546      }
12547    package_info=ClonePackageInfo(info,exception);
12548    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12549    CloneString(&draw_info->text,"");
12550    current=draw_info->affine;
12551    GetAffineMatrix(&affine);
12552    x=0.0;
12553    y=0.0;
12554    EXTEND(sp,7*items);
12555    for (i=2; i < items; i+=2)
12556    {
12557      attribute=(char *) SvPV(ST(i-1),na);
12558      switch (*attribute)
12559      {
12560        case 'A':
12561        case 'a':
12562        {
12563          if (LocaleCompare(attribute,"antialias") == 0)
12564            {
12565              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12566                SvPV(ST(i),na));
12567              if (type < 0)
12568                {
12569                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12570                    SvPV(ST(i),na));
12571                  break;
12572                }
12573              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12574              break;
12575            }
12576          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12577            attribute);
12578          break;
12579        }
12580        case 'd':
12581        case 'D':
12582        {
12583          if (LocaleCompare(attribute,"density") == 0)
12584            {
12585              CloneString(&draw_info->density,SvPV(ST(i),na));
12586              break;
12587            }
12588          if (LocaleCompare(attribute,"direction") == 0)
12589            {
12590              draw_info->direction=(DirectionType) ParseCommandOption(
12591                MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12592              break;
12593            }
12594          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12595            attribute);
12596          break;
12597        }
12598        case 'e':
12599        case 'E':
12600        {
12601          if (LocaleCompare(attribute,"encoding") == 0)
12602            {
12603              CloneString(&draw_info->encoding,SvPV(ST(i),na));
12604              break;
12605            }
12606          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12607            attribute);
12608          break;
12609        }
12610        case 'f':
12611        case 'F':
12612        {
12613          if (LocaleCompare(attribute,"family") == 0)
12614            {
12615              CloneString(&draw_info->family,SvPV(ST(i),na));
12616              break;
12617            }
12618          if (LocaleCompare(attribute,"fill") == 0)
12619            {
12620              if (info)
12621                (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12622                  &image->exception);
12623              break;
12624            }
12625          if (LocaleCompare(attribute,"font") == 0)
12626            {
12627              CloneString(&draw_info->font,SvPV(ST(i),na));
12628              break;
12629            }
12630          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12631            attribute);
12632          break;
12633        }
12634        case 'g':
12635        case 'G':
12636        {
12637          if (LocaleCompare(attribute,"geometry") == 0)
12638            {
12639              CloneString(&draw_info->geometry,SvPV(ST(i),na));
12640              break;
12641            }
12642          if (LocaleCompare(attribute,"gravity") == 0)
12643            {
12644              draw_info->gravity=(GravityType) ParseCommandOption(
12645                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12646              break;
12647            }
12648          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12649            attribute);
12650          break;
12651        }
12652        case 'i':
12653        case 'I':
12654        {
12655          if (LocaleCompare(attribute,"interline-spacing") == 0)
12656            {
12657              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12658              draw_info->interline_spacing=geometry_info.rho;
12659              break;
12660            }
12661          if (LocaleCompare(attribute,"interword-spacing") == 0)
12662            {
12663              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12664              draw_info->interword_spacing=geometry_info.rho;
12665              break;
12666            }
12667          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12668            attribute);
12669          break;
12670        }
12671        case 'k':
12672        case 'K':
12673        {
12674          if (LocaleCompare(attribute,"kerning") == 0)
12675            {
12676              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12677              draw_info->kerning=geometry_info.rho;
12678              break;
12679            }
12680          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12681            attribute);
12682          break;
12683        }
12684        case 'p':
12685        case 'P':
12686        {
12687          if (LocaleCompare(attribute,"pointsize") == 0)
12688            {
12689              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12690              draw_info->pointsize=geometry_info.rho;
12691              break;
12692            }
12693          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12694            attribute);
12695          break;
12696        }
12697        case 'r':
12698        case 'R':
12699        {
12700          if (LocaleCompare(attribute,"rotate") == 0)
12701            {
12702              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12703              affine.rx=geometry_info.rho;
12704              affine.ry=geometry_info.sigma;
12705              if ((flags & SigmaValue) == 0)
12706                affine.ry=affine.rx;
12707              break;
12708            }
12709          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12710            attribute);
12711          break;
12712        }
12713        case 's':
12714        case 'S':
12715        {
12716          if (LocaleCompare(attribute,"scale") == 0)
12717            {
12718              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12719              affine.sx=geometry_info.rho;
12720              affine.sy=geometry_info.sigma;
12721              if ((flags & SigmaValue) == 0)
12722                affine.sy=affine.sx;
12723              break;
12724            }
12725          if (LocaleCompare(attribute,"skew") == 0)
12726            {
12727              double
12728                x_angle,
12729                y_angle;
12730
12731              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12732              x_angle=geometry_info.rho;
12733              y_angle=geometry_info.sigma;
12734              if ((flags & SigmaValue) == 0)
12735                y_angle=x_angle;
12736              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12737              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12738              break;
12739            }
12740          if (LocaleCompare(attribute,"stroke") == 0)
12741            {
12742              if (info)
12743                (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12744                  &image->exception);
12745              break;
12746            }
12747          if (LocaleCompare(attribute,"style") == 0)
12748            {
12749              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12750                SvPV(ST(i),na));
12751              if (type < 0)
12752                {
12753                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12754                    SvPV(ST(i),na));
12755                  break;
12756                }
12757              draw_info->style=(StyleType) type;
12758              break;
12759            }
12760          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12761            attribute);
12762          break;
12763        }
12764        case 't':
12765        case 'T':
12766        {
12767          if (LocaleCompare(attribute,"text") == 0)
12768            {
12769              CloneString(&draw_info->text,SvPV(ST(i),na));
12770              break;
12771            }
12772          if (LocaleCompare(attribute,"translate") == 0)
12773            {
12774              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12775              affine.tx=geometry_info.rho;
12776              affine.ty=geometry_info.sigma;
12777              if ((flags & SigmaValue) == 0)
12778                affine.ty=affine.tx;
12779              break;
12780            }
12781          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12782            attribute);
12783          break;
12784        }
12785        case 'w':
12786        case 'W':
12787        {
12788          if (LocaleCompare(attribute,"weight") == 0)
12789            {
12790              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12791              draw_info->weight=(size_t) geometry_info.rho;
12792              break;
12793            }
12794          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12795            attribute);
12796          break;
12797        }
12798        case 'x':
12799        case 'X':
12800        {
12801          if (LocaleCompare(attribute,"x") == 0)
12802            {
12803              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12804              x=geometry_info.rho;
12805              break;
12806            }
12807          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12808            attribute);
12809          break;
12810        }
12811        case 'y':
12812        case 'Y':
12813        {
12814          if (LocaleCompare(attribute,"y") == 0)
12815            {
12816              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12817              y=geometry_info.rho;
12818              break;
12819            }
12820          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12821            attribute);
12822          break;
12823        }
12824        default:
12825        {
12826          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12827            attribute);
12828          break;
12829        }
12830      }
12831    }
12832    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12833    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12834    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12835    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12836    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12837    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12838    if (draw_info->geometry == (char *) NULL)
12839      {
12840        draw_info->geometry=AcquireString((char *) NULL);
12841        (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12842          "%.20g,%.15g",x,y);
12843      }
12844    status=GetTypeMetrics(image,draw_info,&metrics);
12845    (void) CatchImageException(image);
12846    if (status == MagickFalse)
12847      PUSHs(&sv_undef);
12848    else
12849      {
12850        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12851        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12852        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12853        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12854        PUSHs(sv_2mortal(newSVnv(metrics.width)));
12855        PUSHs(sv_2mortal(newSVnv(metrics.height)));
12856        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12857        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12858        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12859        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12860        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12861        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12862        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12863      }
12864    draw_info=DestroyDrawInfo(draw_info);
12865
12866  PerlException:
12867    if (package_info != (struct PackageInfo *) NULL)
12868      DestroyPackageInfo(package_info);
12869    InheritPerlException(exception,perl_exception);
12870    exception=DestroyExceptionInfo(exception);
12871    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12872  }
12873
12874#
12875###############################################################################
12876#                                                                             #
12877#                                                                             #
12878#                                                                             #
12879#   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                         #
12880#                                                                             #
12881#                                                                             #
12882#                                                                             #
12883###############################################################################
12884#
12885#
12886void
12887QueryMultilineFontMetrics(ref,...)
12888  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12889  ALIAS:
12890    querymultilinefontmetrics = 1
12891  PPCODE:
12892  {
12893    AffineMatrix
12894      affine,
12895      current;
12896
12897    AV
12898      *av;
12899
12900    char
12901      *attribute;
12902
12903    double
12904      x,
12905      y;
12906
12907    DrawInfo
12908      *draw_info;
12909
12910    ExceptionInfo
12911      *exception;
12912
12913    GeometryInfo
12914      geometry_info;
12915
12916    Image
12917      *image;
12918
12919    MagickBooleanType
12920      status;
12921
12922    MagickStatusType
12923      flags;
12924
12925    ssize_t
12926      i;
12927
12928    ssize_t
12929      type;
12930
12931    struct PackageInfo
12932      *info,
12933      *package_info;
12934
12935    SV
12936      *perl_exception,
12937      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12938
12939    TypeMetric
12940      metrics;
12941
12942    PERL_UNUSED_VAR(ref);
12943    PERL_UNUSED_VAR(ix);
12944    exception=AcquireExceptionInfo();
12945    package_info=(struct PackageInfo *) NULL;
12946    perl_exception=newSVpv("",0);
12947    reference=SvRV(ST(0));
12948    av=(AV *) reference;
12949    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12950      exception);
12951    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12952    if (image == (Image *) NULL)
12953      {
12954        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12955          PackageName);
12956        goto PerlException;
12957      }
12958    package_info=ClonePackageInfo(info,exception);
12959    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12960    CloneString(&draw_info->text,"");
12961    current=draw_info->affine;
12962    GetAffineMatrix(&affine);
12963    x=0.0;
12964    y=0.0;
12965    EXTEND(sp,7*items);
12966    for (i=2; i < items; i+=2)
12967    {
12968      attribute=(char *) SvPV(ST(i-1),na);
12969      switch (*attribute)
12970      {
12971        case 'A':
12972        case 'a':
12973        {
12974          if (LocaleCompare(attribute,"antialias") == 0)
12975            {
12976              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12977                SvPV(ST(i),na));
12978              if (type < 0)
12979                {
12980                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12981                    SvPV(ST(i),na));
12982                  break;
12983                }
12984              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12985              break;
12986            }
12987          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12988            attribute);
12989          break;
12990        }
12991        case 'd':
12992        case 'D':
12993        {
12994          if (LocaleCompare(attribute,"density") == 0)
12995            {
12996              CloneString(&draw_info->density,SvPV(ST(i),na));
12997              break;
12998            }
12999          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13000            attribute);
13001          break;
13002        }
13003        case 'e':
13004        case 'E':
13005        {
13006          if (LocaleCompare(attribute,"encoding") == 0)
13007            {
13008              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13009              break;
13010            }
13011          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13012            attribute);
13013          break;
13014        }
13015        case 'f':
13016        case 'F':
13017        {
13018          if (LocaleCompare(attribute,"family") == 0)
13019            {
13020              CloneString(&draw_info->family,SvPV(ST(i),na));
13021              break;
13022            }
13023          if (LocaleCompare(attribute,"fill") == 0)
13024            {
13025              if (info)
13026                (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
13027                  &image->exception);
13028              break;
13029            }
13030          if (LocaleCompare(attribute,"font") == 0)
13031            {
13032              CloneString(&draw_info->font,SvPV(ST(i),na));
13033              break;
13034            }
13035          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13036            attribute);
13037          break;
13038        }
13039        case 'g':
13040        case 'G':
13041        {
13042          if (LocaleCompare(attribute,"geometry") == 0)
13043            {
13044              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13045              break;
13046            }
13047          if (LocaleCompare(attribute,"gravity") == 0)
13048            {
13049              draw_info->gravity=(GravityType) ParseCommandOption(
13050                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13051              break;
13052            }
13053          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13054            attribute);
13055          break;
13056        }
13057        case 'p':
13058        case 'P':
13059        {
13060          if (LocaleCompare(attribute,"pointsize") == 0)
13061            {
13062              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13063              draw_info->pointsize=geometry_info.rho;
13064              break;
13065            }
13066          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13067            attribute);
13068          break;
13069        }
13070        case 'r':
13071        case 'R':
13072        {
13073          if (LocaleCompare(attribute,"rotate") == 0)
13074            {
13075              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13076              affine.rx=geometry_info.rho;
13077              affine.ry=geometry_info.sigma;
13078              if ((flags & SigmaValue) == 0)
13079                affine.ry=affine.rx;
13080              break;
13081            }
13082          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13083            attribute);
13084          break;
13085        }
13086        case 's':
13087        case 'S':
13088        {
13089          if (LocaleCompare(attribute,"scale") == 0)
13090            {
13091              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13092              affine.sx=geometry_info.rho;
13093              affine.sy=geometry_info.sigma;
13094              if ((flags & SigmaValue) == 0)
13095                affine.sy=affine.sx;
13096              break;
13097            }
13098          if (LocaleCompare(attribute,"skew") == 0)
13099            {
13100              double
13101                x_angle,
13102                y_angle;
13103
13104              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13105              x_angle=geometry_info.rho;
13106              y_angle=geometry_info.sigma;
13107              if ((flags & SigmaValue) == 0)
13108                y_angle=x_angle;
13109              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13110              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13111              break;
13112            }
13113          if (LocaleCompare(attribute,"stroke") == 0)
13114            {
13115              if (info)
13116                (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
13117                  &image->exception);
13118              break;
13119            }
13120          if (LocaleCompare(attribute,"style") == 0)
13121            {
13122              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13123                SvPV(ST(i),na));
13124              if (type < 0)
13125                {
13126                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13127                    SvPV(ST(i),na));
13128                  break;
13129                }
13130              draw_info->style=(StyleType) type;
13131              break;
13132            }
13133          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13134            attribute);
13135          break;
13136        }
13137        case 't':
13138        case 'T':
13139        {
13140          if (LocaleCompare(attribute,"text") == 0)
13141            {
13142              CloneString(&draw_info->text,SvPV(ST(i),na));
13143              break;
13144            }
13145          if (LocaleCompare(attribute,"translate") == 0)
13146            {
13147              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13148              affine.tx=geometry_info.rho;
13149              affine.ty=geometry_info.sigma;
13150              if ((flags & SigmaValue) == 0)
13151                affine.ty=affine.tx;
13152              break;
13153            }
13154          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13155            attribute);
13156          break;
13157        }
13158        case 'w':
13159        case 'W':
13160        {
13161          if (LocaleCompare(attribute,"weight") == 0)
13162            {
13163              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13164              draw_info->weight=(size_t) geometry_info.rho;
13165              break;
13166            }
13167          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13168            attribute);
13169          break;
13170        }
13171        case 'x':
13172        case 'X':
13173        {
13174          if (LocaleCompare(attribute,"x") == 0)
13175            {
13176              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13177              x=geometry_info.rho;
13178              break;
13179            }
13180          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13181            attribute);
13182          break;
13183        }
13184        case 'y':
13185        case 'Y':
13186        {
13187          if (LocaleCompare(attribute,"y") == 0)
13188            {
13189              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13190              y=geometry_info.rho;
13191              break;
13192            }
13193          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13194            attribute);
13195          break;
13196        }
13197        default:
13198        {
13199          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13200            attribute);
13201          break;
13202        }
13203      }
13204    }
13205    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13206    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13207    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13208    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13209    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13210    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13211    if (draw_info->geometry == (char *) NULL)
13212      {
13213        draw_info->geometry=AcquireString((char *) NULL);
13214        (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
13215          "%.20g,%.15g",x,y);
13216      }
13217    status=GetMultilineTypeMetrics(image,draw_info,&metrics);
13218    (void) CatchImageException(image);
13219    if (status == MagickFalse)
13220      PUSHs(&sv_undef);
13221    else
13222      {
13223        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13224        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13225        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13226        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13227        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13228        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13229        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13230        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13231        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13232        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13233        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13234        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13235        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13236      }
13237    draw_info=DestroyDrawInfo(draw_info);
13238
13239  PerlException:
13240    if (package_info != (struct PackageInfo *) NULL)
13241      DestroyPackageInfo(package_info);
13242    InheritPerlException(exception,perl_exception);
13243    exception=DestroyExceptionInfo(exception);
13244    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13245  }
13246
13247#
13248###############################################################################
13249#                                                                             #
13250#                                                                             #
13251#                                                                             #
13252#   Q u e r y F o r m a t                                                     #
13253#                                                                             #
13254#                                                                             #
13255#                                                                             #
13256###############################################################################
13257#
13258#
13259void
13260QueryFormat(ref,...)
13261  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13262  ALIAS:
13263    queryformat = 1
13264  PPCODE:
13265  {
13266    char
13267      *name;
13268
13269    ExceptionInfo
13270      *exception;
13271
13272    ssize_t
13273      i;
13274
13275    SV
13276      *perl_exception;
13277
13278    volatile const MagickInfo
13279      *magick_info;
13280
13281    PERL_UNUSED_VAR(ref);
13282    PERL_UNUSED_VAR(ix);
13283    exception=AcquireExceptionInfo();
13284    perl_exception=newSVpv("",0);
13285    if (items == 1)
13286      {
13287        char
13288          format[MaxTextExtent];
13289
13290        const MagickInfo
13291          **format_list;
13292
13293        size_t
13294          types;
13295
13296        format_list=GetMagickInfoList("*",&types,exception);
13297        EXTEND(sp,types);
13298        for (i=0; i < (ssize_t) types; i++)
13299        {
13300          (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13301          LocaleLower(format);
13302          PUSHs(sv_2mortal(newSVpv(format,0)));
13303        }
13304        format_list=(const MagickInfo **)
13305          RelinquishMagickMemory((MagickInfo *) format_list);
13306        goto PerlException;
13307      }
13308    EXTEND(sp,8*items);
13309    for (i=1; i < items; i++)
13310    {
13311      name=(char *) SvPV(ST(i),na);
13312      magick_info=GetMagickInfo(name,exception);
13313      if (magick_info == (const MagickInfo *) NULL)
13314        {
13315          PUSHs(&sv_undef);
13316          continue;
13317        }
13318      PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13319      PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13320      PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13321      PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13322      PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13323      if (magick_info->description == (char *) NULL)
13324        PUSHs(&sv_undef);
13325      else
13326        PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13327      if (magick_info->magick_module == (char *) NULL)
13328        PUSHs(&sv_undef);
13329      else
13330        PUSHs(sv_2mortal(newSVpv(magick_info->magick_module,0)));
13331    }
13332
13333  PerlException:
13334    InheritPerlException(exception,perl_exception);
13335    exception=DestroyExceptionInfo(exception);
13336    SvREFCNT_dec(perl_exception);
13337  }
13338
13339#
13340###############################################################################
13341#                                                                             #
13342#                                                                             #
13343#                                                                             #
13344#   Q u e r y O p t i o n                                                     #
13345#                                                                             #
13346#                                                                             #
13347#                                                                             #
13348###############################################################################
13349#
13350#
13351void
13352QueryOption(ref,...)
13353  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13354  ALIAS:
13355    queryoption = 1
13356  PPCODE:
13357  {
13358    char
13359      **options;
13360
13361    ExceptionInfo
13362      *exception;
13363
13364    ssize_t
13365      i;
13366
13367    ssize_t
13368      j,
13369      option;
13370
13371    SV
13372      *perl_exception;
13373
13374    PERL_UNUSED_VAR(ref);
13375    PERL_UNUSED_VAR(ix);
13376    exception=AcquireExceptionInfo();
13377    perl_exception=newSVpv("",0);
13378    EXTEND(sp,8*items);
13379    for (i=1; i < items; i++)
13380    {
13381      option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13382        SvPV(ST(i),na));
13383      options=GetCommandOptions((CommandOption) option);
13384      if (options == (char **) NULL)
13385        PUSHs(&sv_undef);
13386      else
13387        {
13388          for (j=0; options[j] != (char *) NULL; j++)
13389            PUSHs(sv_2mortal(newSVpv(options[j],0)));
13390          options=DestroyStringList(options);
13391        }
13392    }
13393
13394    InheritPerlException(exception,perl_exception);
13395    exception=DestroyExceptionInfo(exception);
13396    SvREFCNT_dec(perl_exception);
13397  }
13398
13399#
13400###############################################################################
13401#                                                                             #
13402#                                                                             #
13403#                                                                             #
13404#   R e a d                                                                   #
13405#                                                                             #
13406#                                                                             #
13407#                                                                             #
13408###############################################################################
13409#
13410#
13411void
13412Read(ref,...)
13413  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13414  ALIAS:
13415    ReadImage  = 1
13416    read       = 2
13417    readimage  = 3
13418  PPCODE:
13419  {
13420    AV
13421      *av;
13422
13423    char
13424      **keep,
13425      **list;
13426
13427    ExceptionInfo
13428      *exception;
13429
13430    HV
13431      *hv;
13432
13433    Image
13434      *image;
13435
13436    int
13437      n;
13438
13439    MagickBooleanType
13440      status;
13441
13442    char
13443      **p;
13444
13445    ssize_t
13446      i;
13447
13448    ssize_t
13449      ac,
13450      number_images;
13451
13452    STRLEN
13453      *length;
13454
13455    struct PackageInfo
13456      *info,
13457      *package_info;
13458
13459    SV
13460      *perl_exception,  /* Perl variable for storing messages */
13461      *reference,
13462      *rv,
13463      *sv;
13464
13465    PERL_UNUSED_VAR(ref);
13466    PERL_UNUSED_VAR(ix);
13467    exception=AcquireExceptionInfo();
13468    perl_exception=newSVpv("",0);
13469    sv=NULL;
13470    package_info=(struct PackageInfo *) NULL;
13471    number_images=0;
13472    ac=(items < 2) ? 1 : items-1;
13473    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13474    keep=list;
13475    length=(STRLEN *) NULL;
13476    if (list == (char **) NULL)
13477      {
13478        ThrowPerlException(exception,ResourceLimitError,
13479          "MemoryAllocationFailed",PackageName);
13480        goto PerlException;
13481      }
13482    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13483    if (length == (STRLEN *) NULL)
13484      {
13485        ThrowPerlException(exception,ResourceLimitError,
13486          "MemoryAllocationFailed",PackageName);
13487        goto PerlException;
13488      }
13489    if (sv_isobject(ST(0)) == 0)
13490      {
13491        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13492          PackageName);
13493        goto PerlException;
13494      }
13495    reference=SvRV(ST(0));
13496    hv=SvSTASH(reference);
13497    if (SvTYPE(reference) != SVt_PVAV)
13498      {
13499        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13500          PackageName);
13501        goto PerlException;
13502      }
13503    av=(AV *) reference;
13504    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13505      exception);
13506    package_info=ClonePackageInfo(info,exception);
13507    n=1;
13508    if (items <= 1)
13509      *list=(char *) (*package_info->image_info->filename ?
13510        package_info->image_info->filename : "XC:black");
13511    else
13512      for (n=0, i=0; i < ac; i++)
13513      {
13514        list[n]=(char *) SvPV(ST(i+1),length[n]);
13515        if ((items >= 3) && strEQcase(list[n],"blob"))
13516          {
13517            void
13518              *blob;
13519
13520            i++;
13521            blob=(void *) (SvPV(ST(i+1),length[n]));
13522            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13523          }
13524        if ((items >= 3) && strEQcase(list[n],"filename"))
13525          continue;
13526        if ((items >= 3) && strEQcase(list[n],"file"))
13527          {
13528            FILE
13529              *file;
13530
13531            PerlIO
13532              *io_info;
13533
13534            i++;
13535            io_info=IoIFP(sv_2io(ST(i+1)));
13536            if (io_info == (PerlIO *) NULL)
13537              {
13538                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13539                  PackageName);
13540                continue;
13541              }
13542            file=PerlIO_findFILE(io_info);
13543            if (file == (FILE *) NULL)
13544              {
13545                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13546                  PackageName);
13547                continue;
13548              }
13549            SetImageInfoFile(package_info->image_info,file);
13550          }
13551        if ((items >= 3) && strEQcase(list[n],"magick"))
13552          continue;
13553        n++;
13554      }
13555    list[n]=(char *) NULL;
13556    keep=list;
13557    status=ExpandFilenames(&n,&list);
13558    if (status == MagickFalse)
13559      {
13560        ThrowPerlException(exception,ResourceLimitError,
13561          "MemoryAllocationFailed",PackageName);
13562        goto PerlException;
13563      }
13564    number_images=0;
13565    for (i=0; i < n; i++)
13566    {
13567      if ((package_info->image_info->file != (FILE *) NULL) ||
13568          (package_info->image_info->blob != (void *) NULL))
13569        {
13570          image=ReadImages(package_info->image_info,exception);
13571          if (image != (Image *) NULL)
13572            DisassociateImageStream(image);
13573        }
13574      else
13575        {
13576          (void) CopyMagickString(package_info->image_info->filename,list[i],
13577            MaxTextExtent);
13578          image=ReadImages(package_info->image_info,exception);
13579        }
13580      if (image == (Image *) NULL)
13581        break;
13582      for ( ; image; image=image->next)
13583      {
13584        AddImageToRegistry(sv,image);
13585        rv=newRV(sv);
13586        av_push(av,sv_bless(rv,hv));
13587        SvREFCNT_dec(sv);
13588        number_images++;
13589      }
13590    }
13591    /*
13592      Free resources.
13593    */
13594    for (i=0; i < n; i++)
13595      if (list[i] != (char *) NULL)
13596        for (p=keep; list[i] != *p++; )
13597          if (*p == (char *) NULL)
13598            {
13599              list[i]=(char *) RelinquishMagickMemory(list[i]);
13600              break;
13601            }
13602
13603  PerlException:
13604    if (package_info != (struct PackageInfo *) NULL)
13605      DestroyPackageInfo(package_info);
13606    if (list && (list != keep))
13607      list=(char **) RelinquishMagickMemory(list);
13608    if (keep)
13609      keep=(char **) RelinquishMagickMemory(keep);
13610    if (length)
13611      length=(STRLEN *) RelinquishMagickMemory(length);
13612    InheritPerlException(exception,perl_exception);
13613    exception=DestroyExceptionInfo(exception);
13614    sv_setiv(perl_exception,(IV) number_images);
13615    SvPOK_on(perl_exception);
13616    ST(0)=sv_2mortal(perl_exception);
13617    XSRETURN(1);
13618  }
13619
13620#
13621###############################################################################
13622#                                                                             #
13623#                                                                             #
13624#                                                                             #
13625#   R e m o t e                                                               #
13626#                                                                             #
13627#                                                                             #
13628#                                                                             #
13629###############################################################################
13630#
13631#
13632void
13633Remote(ref,...)
13634  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13635  ALIAS:
13636    RemoteCommand  = 1
13637    remote         = 2
13638    remoteCommand  = 3
13639  PPCODE:
13640  {
13641    AV
13642      *av;
13643
13644    ExceptionInfo
13645      *exception;
13646
13647    ssize_t
13648      i;
13649
13650    SV
13651      *perl_exception,
13652      *reference;
13653
13654    struct PackageInfo
13655      *info;
13656
13657    PERL_UNUSED_VAR(ref);
13658    PERL_UNUSED_VAR(ix);
13659    exception=AcquireExceptionInfo();
13660    perl_exception=newSVpv("",0);
13661    reference=SvRV(ST(0));
13662    av=(AV *) reference;
13663    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13664      exception);
13665    for (i=1; i < items; i++)
13666      (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13667        SvPV(ST(i),na),exception);
13668    InheritPerlException(exception,perl_exception);
13669    exception=DestroyExceptionInfo(exception);
13670    SvREFCNT_dec(perl_exception);    /* throw away all errors */
13671  }
13672
13673#
13674###############################################################################
13675#                                                                             #
13676#                                                                             #
13677#                                                                             #
13678#   S e t                                                                     #
13679#                                                                             #
13680#                                                                             #
13681#                                                                             #
13682###############################################################################
13683#
13684#
13685void
13686Set(ref,...)
13687  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13688  ALIAS:
13689    SetAttributes  = 1
13690    SetAttribute   = 2
13691    set            = 3
13692    setattributes  = 4
13693    setattribute   = 5
13694  PPCODE:
13695  {
13696    ExceptionInfo
13697      *exception;
13698
13699    Image
13700      *image;
13701
13702    ssize_t
13703      i;
13704
13705    struct PackageInfo
13706      *info;
13707
13708    SV
13709      *perl_exception,
13710      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13711
13712    PERL_UNUSED_VAR(ref);
13713    PERL_UNUSED_VAR(ix);
13714    exception=AcquireExceptionInfo();
13715    perl_exception=newSVpv("",0);
13716    if (sv_isobject(ST(0)) == 0)
13717      {
13718        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13719          PackageName);
13720        goto PerlException;
13721      }
13722    reference=SvRV(ST(0));
13723    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13724    if (items == 2)
13725      SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13726    else
13727      for (i=2; i < items; i+=2)
13728        SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13729
13730  PerlException:
13731    InheritPerlException(exception,perl_exception);
13732    exception=DestroyExceptionInfo(exception);
13733    sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13734    SvPOK_on(perl_exception);
13735    ST(0)=sv_2mortal(perl_exception);
13736    XSRETURN(1);
13737  }
13738
13739#
13740###############################################################################
13741#                                                                             #
13742#                                                                             #
13743#                                                                             #
13744#   S e t P i x e l                                                           #
13745#                                                                             #
13746#                                                                             #
13747#                                                                             #
13748###############################################################################
13749#
13750#
13751void
13752SetPixel(ref,...)
13753  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13754  ALIAS:
13755    setpixel = 1
13756    setPixel = 2
13757  PPCODE:
13758  {
13759    AV
13760      *av;
13761
13762    char
13763      *attribute;
13764
13765    ChannelType
13766      channel;
13767
13768    ExceptionInfo
13769      *exception;
13770
13771    Image
13772      *image;
13773
13774    MagickBooleanType
13775      normalize;
13776
13777    RectangleInfo
13778      region;
13779
13780    IndexPacket
13781      *indexes;
13782
13783    ssize_t
13784      i;
13785
13786    PixelPacket
13787      *q;
13788
13789    ssize_t
13790      option;
13791
13792    struct PackageInfo
13793      *info;
13794
13795    SV
13796      *perl_exception,
13797      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13798
13799    PERL_UNUSED_VAR(ref);
13800    PERL_UNUSED_VAR(ix);
13801    exception=AcquireExceptionInfo();
13802    perl_exception=newSVpv("",0);
13803    reference=SvRV(ST(0));
13804    av=(AV *) reference;
13805    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13806      exception);
13807    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13808    if (image == (Image *) NULL)
13809      {
13810        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13811          PackageName);
13812        goto PerlException;
13813      }
13814    av=(AV *) NULL;
13815    channel=DefaultChannels;
13816    if (image->matte != MagickFalse)
13817      channel|=OpacityChannel;
13818    normalize=MagickTrue;
13819    region.x=0;
13820    region.y=0;
13821    region.width=image->columns;
13822    region.height=1;
13823    if (items == 1)
13824      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13825    for (i=2; i < items; i+=2)
13826    {
13827      attribute=(char *) SvPV(ST(i-1),na);
13828      switch (*attribute)
13829      {
13830        case 'C':
13831        case 'c':
13832        {
13833          if (LocaleCompare(attribute,"channel") == 0)
13834            {
13835              ssize_t
13836                option;
13837
13838              option=ParseChannelOption(SvPV(ST(i),na));
13839              if (option < 0)
13840                {
13841                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13842                    SvPV(ST(i),na));
13843                  return;
13844                }
13845               channel=(ChannelType) option;
13846              break;
13847            }
13848          if (LocaleCompare(attribute,"color") == 0)
13849            {
13850              if (SvTYPE(ST(i)) != SVt_RV)
13851                {
13852                  char
13853                    message[MaxTextExtent];
13854
13855                  (void) FormatLocaleString(message,MaxTextExtent,
13856                    "invalid %.60s value",attribute);
13857                  ThrowPerlException(exception,OptionError,message,
13858                    SvPV(ST(i),na));
13859                }
13860              av=(AV *) SvRV(ST(i));
13861              break;
13862            }
13863          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13864            attribute);
13865          break;
13866        }
13867        case 'g':
13868        case 'G':
13869        {
13870          if (LocaleCompare(attribute,"geometry") == 0)
13871            {
13872              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13873              break;
13874            }
13875          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13876            attribute);
13877          break;
13878        }
13879        case 'N':
13880        case 'n':
13881        {
13882          if (LocaleCompare(attribute,"normalize") == 0)
13883            {
13884              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13885                SvPV(ST(i),na));
13886              if (option < 0)
13887                {
13888                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13889                    SvPV(ST(i),na));
13890                  break;
13891                }
13892             normalize=option != 0 ? MagickTrue : MagickFalse;
13893             break;
13894            }
13895          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13896            attribute);
13897          break;
13898        }
13899        case 'x':
13900        case 'X':
13901        {
13902          if (LocaleCompare(attribute,"x") == 0)
13903            {
13904              region.x=SvIV(ST(i));
13905              break;
13906            }
13907          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13908            attribute);
13909          break;
13910        }
13911        case 'y':
13912        case 'Y':
13913        {
13914          if (LocaleCompare(attribute,"y") == 0)
13915            {
13916              region.y=SvIV(ST(i));
13917              break;
13918            }
13919          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13920            attribute);
13921          break;
13922        }
13923        default:
13924        {
13925          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13926            attribute);
13927          break;
13928        }
13929      }
13930    }
13931    (void) SetImageStorageClass(image,DirectClass);
13932    q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13933    if ((q == (PixelPacket *) NULL) || (av == (AV *) NULL) ||
13934        (SvTYPE(av) != SVt_PVAV))
13935      PUSHs(&sv_undef);
13936    else
13937      {
13938        double
13939          scale;
13940
13941        ssize_t
13942          i;
13943
13944        i=0;
13945        indexes=GetAuthenticIndexQueue(image);
13946        scale=1.0;
13947        if (normalize != MagickFalse)
13948          scale=QuantumRange;
13949        if (((channel & RedChannel) != 0) && (i <= av_len(av)))
13950          {
13951            SetPixelRed(q,ClampToQuantum(scale*SvNV(*(
13952              av_fetch(av,i,0)))));
13953            i++;
13954          }
13955        if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
13956          {
13957            SetPixelGreen(q,ClampToQuantum(scale*SvNV(*(
13958              av_fetch(av,i,0)))));
13959            i++;
13960          }
13961        if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
13962          {
13963            SetPixelBlue(q,ClampToQuantum(scale*SvNV(*(
13964              av_fetch(av,i,0)))));
13965            i++;
13966          }
13967        if ((((channel & IndexChannel) != 0) &&
13968            (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13969          {
13970            SetPixelIndex(indexes,ClampToQuantum(scale*
13971              SvNV(*(av_fetch(av,i,0)))));
13972            i++;
13973          }
13974        if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
13975          {
13976            SetPixelOpacity(q,ClampToQuantum(scale*
13977              SvNV(*(av_fetch(av,i,0)))));
13978            i++;
13979          }
13980        (void) SyncAuthenticPixels(image,exception);
13981      }
13982
13983  PerlException:
13984    InheritPerlException(exception,perl_exception);
13985    exception=DestroyExceptionInfo(exception);
13986    SvREFCNT_dec(perl_exception);
13987  }
13988
13989#
13990###############################################################################
13991#                                                                             #
13992#                                                                             #
13993#                                                                             #
13994#   S m u s h                                                                 #
13995#                                                                             #
13996#                                                                             #
13997#                                                                             #
13998###############################################################################
13999#
14000#
14001void
14002Smush(ref,...)
14003  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14004  ALIAS:
14005    SmushImage  = 1
14006    smush       = 2
14007    smushimage  = 3
14008  PPCODE:
14009  {
14010    AV
14011      *av;
14012
14013    char
14014      *attribute;
14015
14016    ExceptionInfo
14017      *exception;
14018
14019    HV
14020      *hv;
14021
14022    Image
14023      *image;
14024
14025    ssize_t
14026      i;
14027
14028    ssize_t
14029      offset,
14030      stack;
14031
14032    struct PackageInfo
14033      *info;
14034
14035    SV
14036      *av_reference,
14037      *perl_exception,
14038      *reference,
14039      *rv,
14040      *sv;
14041
14042    PERL_UNUSED_VAR(ref);
14043    PERL_UNUSED_VAR(ix);
14044    exception=AcquireExceptionInfo();
14045    perl_exception=newSVpv("",0);
14046    sv=NULL;
14047    attribute=NULL;
14048    av=NULL;
14049    if (sv_isobject(ST(0)) == 0)
14050      {
14051        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14052          PackageName);
14053        goto PerlException;
14054      }
14055    reference=SvRV(ST(0));
14056    hv=SvSTASH(reference);
14057    av=newAV();
14058    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14059    SvREFCNT_dec(av);
14060    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14061    if (image == (Image *) NULL)
14062      {
14063        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14064          PackageName);
14065        goto PerlException;
14066      }
14067    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14068    /*
14069      Get options.
14070    */
14071    offset=0;
14072    stack=MagickTrue;
14073    for (i=2; i < items; i+=2)
14074    {
14075      attribute=(char *) SvPV(ST(i-1),na);
14076      switch (*attribute)
14077      {
14078        case 'O':
14079        case 'o':
14080        {
14081          if (LocaleCompare(attribute,"offset") == 0)
14082            {
14083              offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14084              break;
14085            }
14086          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14087            attribute);
14088          break;
14089        }
14090        case 'S':
14091        case 's':
14092        {
14093          if (LocaleCompare(attribute,"stack") == 0)
14094            {
14095              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14096                SvPV(ST(i),na));
14097              if (stack < 0)
14098                {
14099                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14100                    SvPV(ST(i),na));
14101                  return;
14102                }
14103              break;
14104            }
14105          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14106            attribute);
14107          break;
14108        }
14109        default:
14110        {
14111          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14112            attribute);
14113          break;
14114        }
14115      }
14116    }
14117    image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14118      exception);
14119    if (image == (Image *) NULL)
14120      goto PerlException;
14121    for ( ; image; image=image->next)
14122    {
14123      AddImageToRegistry(sv,image);
14124      rv=newRV(sv);
14125      av_push(av,sv_bless(rv,hv));
14126      SvREFCNT_dec(sv);
14127    }
14128    exception=DestroyExceptionInfo(exception);
14129    ST(0)=av_reference;
14130    SvREFCNT_dec(perl_exception);
14131    XSRETURN(1);
14132
14133  PerlException:
14134    InheritPerlException(exception,perl_exception);
14135    exception=DestroyExceptionInfo(exception);
14136    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14137    SvPOK_on(perl_exception);
14138    ST(0)=sv_2mortal(perl_exception);
14139    XSRETURN(1);
14140  }
14141
14142#
14143###############################################################################
14144#                                                                             #
14145#                                                                             #
14146#                                                                             #
14147#   S t a t i s t i c s                                                       #
14148#                                                                             #
14149#                                                                             #
14150#                                                                             #
14151###############################################################################
14152#
14153#
14154void
14155Statistics(ref)
14156  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14157  ALIAS:
14158    StatisticsImage = 1
14159    statistics      = 2
14160    statisticsimage = 3
14161  PPCODE:
14162  {
14163#define ChannelStatistics(channel) \
14164{ \
14165  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14166    (double) channel_statistics[channel].depth); \
14167  PUSHs(sv_2mortal(newSVpv(message,0))); \
14168  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14169    channel_statistics[channel].minima/scale); \
14170  PUSHs(sv_2mortal(newSVpv(message,0))); \
14171  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14172    channel_statistics[channel].maxima/scale); \
14173  PUSHs(sv_2mortal(newSVpv(message,0))); \
14174  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14175    channel_statistics[channel].mean/scale); \
14176  PUSHs(sv_2mortal(newSVpv(message,0))); \
14177  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14178    channel_statistics[channel].standard_deviation/scale); \
14179  PUSHs(sv_2mortal(newSVpv(message,0))); \
14180  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14181    channel_statistics[channel].kurtosis); \
14182  PUSHs(sv_2mortal(newSVpv(message,0))); \
14183  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14184    channel_statistics[channel].skewness); \
14185  PUSHs(sv_2mortal(newSVpv(message,0))); \
14186  (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14187    channel_statistics[channel].entropy); \
14188  PUSHs(sv_2mortal(newSVpv(message,0))); \
14189}
14190
14191    AV
14192      *av;
14193
14194    char
14195      message[MaxTextExtent];
14196
14197    ChannelStatistics
14198      *channel_statistics;
14199
14200    double
14201      scale;
14202
14203    ExceptionInfo
14204      *exception;
14205
14206    Image
14207      *image;
14208
14209    ssize_t
14210      count;
14211
14212    struct PackageInfo
14213      *info;
14214
14215    SV
14216      *perl_exception,
14217      *reference;
14218
14219    PERL_UNUSED_VAR(ref);
14220    PERL_UNUSED_VAR(ix);
14221    exception=AcquireExceptionInfo();
14222    perl_exception=newSVpv("",0);
14223    av=NULL;
14224    if (sv_isobject(ST(0)) == 0)
14225      {
14226        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14227          PackageName);
14228        goto PerlException;
14229      }
14230    reference=SvRV(ST(0));
14231    av=newAV();
14232    SvREFCNT_dec(av);
14233    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14234    if (image == (Image *) NULL)
14235      {
14236        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14237          PackageName);
14238        goto PerlException;
14239      }
14240    count=0;
14241    for ( ; image; image=image->next)
14242    {
14243      channel_statistics=GetImageChannelStatistics(image,&image->exception);
14244      if (channel_statistics == (ChannelStatistics *) NULL)
14245        continue;
14246      count++;
14247      EXTEND(sp,40*count);
14248      scale=(double) QuantumRange;
14249      ChannelStatistics(RedChannel);
14250      ChannelStatistics(GreenChannel);
14251      ChannelStatistics(BlueChannel);
14252      if (image->colorspace == CMYKColorspace)
14253        ChannelStatistics(IndexChannel);
14254      if (image->matte != MagickFalse)
14255        ChannelStatistics(OpacityChannel);
14256      channel_statistics=(ChannelStatistics *)
14257        RelinquishMagickMemory(channel_statistics);
14258    }
14259
14260  PerlException:
14261    InheritPerlException(exception,perl_exception);
14262    exception=DestroyExceptionInfo(exception);
14263    SvREFCNT_dec(perl_exception);
14264  }
14265
14266#
14267###############################################################################
14268#                                                                             #
14269#                                                                             #
14270#                                                                             #
14271#   S y n c A u t h e n t i c P i x e l s                                     #
14272#                                                                             #
14273#                                                                             #
14274#                                                                             #
14275###############################################################################
14276#
14277#
14278void
14279SyncAuthenticPixels(ref,...)
14280  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14281  ALIAS:
14282    Syncauthenticpixels = 1
14283    SyncImagePixels = 2
14284    syncimagepixels = 3
14285  CODE:
14286  {
14287    ExceptionInfo
14288      *exception;
14289
14290    Image
14291      *image;
14292
14293    MagickBooleanType
14294      status;
14295
14296    struct PackageInfo
14297      *info;
14298
14299    SV
14300      *perl_exception,
14301      *reference;
14302
14303    PERL_UNUSED_VAR(ref);
14304    PERL_UNUSED_VAR(ix);
14305    exception=AcquireExceptionInfo();
14306    perl_exception=newSVpv("",0);
14307    if (sv_isobject(ST(0)) == 0)
14308      {
14309        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14310          PackageName);
14311        goto PerlException;
14312      }
14313
14314    reference=SvRV(ST(0));
14315    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14316    if (image == (Image *) NULL)
14317      {
14318        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14319          PackageName);
14320        goto PerlException;
14321      }
14322
14323    status=SyncAuthenticPixels(image,exception);
14324    if (status != MagickFalse)
14325      return;
14326    InheritException(exception,&image->exception);
14327
14328  PerlException:
14329    InheritPerlException(exception,perl_exception);
14330    exception=DestroyExceptionInfo(exception);
14331    SvREFCNT_dec(perl_exception);  /* throw away all errors */
14332  }
14333
14334#
14335###############################################################################
14336#                                                                             #
14337#                                                                             #
14338#                                                                             #
14339#   T r a n s f o r m                                                         #
14340#                                                                             #
14341#                                                                             #
14342#                                                                             #
14343###############################################################################
14344#
14345#
14346void
14347Transform(ref,...)
14348  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14349  ALIAS:
14350    TransformImage = 1
14351    transform      = 2
14352    transformimage = 3
14353  PPCODE:
14354  {
14355    AV
14356      *av;
14357
14358    char
14359      *attribute,
14360      *crop_geometry,
14361      *geometry;
14362
14363    ExceptionInfo
14364      *exception;
14365
14366    HV
14367      *hv;
14368
14369    Image
14370      *clone,
14371      *image;
14372
14373    ssize_t
14374      i;
14375
14376    struct PackageInfo
14377      *info;
14378
14379    SV
14380      *av_reference,
14381      *perl_exception,
14382      *reference,
14383      *rv,
14384      *sv;
14385
14386    PERL_UNUSED_VAR(ref);
14387    PERL_UNUSED_VAR(ix);
14388    exception=AcquireExceptionInfo();
14389    perl_exception=newSVpv("",0);
14390    sv=NULL;
14391    av=NULL;
14392    attribute=NULL;
14393    if (sv_isobject(ST(0)) == 0)
14394      {
14395        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14396          PackageName);
14397        goto PerlException;
14398      }
14399    reference=SvRV(ST(0));
14400    hv=SvSTASH(reference);
14401    av=newAV();
14402    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14403    SvREFCNT_dec(av);
14404    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14405    if (image == (Image *) NULL)
14406      {
14407        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14408          PackageName);
14409        goto PerlException;
14410      }
14411    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14412    /*
14413      Get attribute.
14414    */
14415    crop_geometry=(char *) NULL;
14416    geometry=(char *) NULL;
14417    for (i=2; i < items; i+=2)
14418    {
14419      attribute=(char *) SvPV(ST(i-1),na);
14420      switch (*attribute)
14421      {
14422        case 'c':
14423        case 'C':
14424        {
14425          if (LocaleCompare(attribute,"crop") == 0)
14426            {
14427              crop_geometry=SvPV(ST(i),na);
14428              break;
14429            }
14430          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14431            attribute);
14432          break;
14433        }
14434        case 'g':
14435        case 'G':
14436        {
14437          if (LocaleCompare(attribute,"geometry") == 0)
14438            {
14439              geometry=SvPV(ST(i),na);
14440              break;
14441            }
14442          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14443            attribute);
14444          break;
14445        }
14446        default:
14447        {
14448          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14449            attribute);
14450          break;
14451        }
14452      }
14453    }
14454    for ( ; image; image=image->next)
14455    {
14456      clone=CloneImage(image,0,0,MagickTrue,exception);
14457      if (clone == (Image *) NULL)
14458        goto PerlException;
14459      TransformImage(&clone,crop_geometry,geometry);
14460      for ( ; clone; clone=clone->next)
14461      {
14462        AddImageToRegistry(sv,clone);
14463        rv=newRV(sv);
14464        av_push(av,sv_bless(rv,hv));
14465        SvREFCNT_dec(sv);
14466      }
14467    }
14468    exception=DestroyExceptionInfo(exception);
14469    ST(0)=av_reference;
14470    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14471    XSRETURN(1);
14472
14473  PerlException:
14474    InheritPerlException(exception,perl_exception);
14475    exception=DestroyExceptionInfo(exception);
14476    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14477    SvPOK_on(perl_exception);
14478    ST(0)=sv_2mortal(perl_exception);
14479    XSRETURN(1);
14480  }
14481
14482#
14483###############################################################################
14484#                                                                             #
14485#                                                                             #
14486#                                                                             #
14487#   W r i t e                                                                 #
14488#                                                                             #
14489#                                                                             #
14490#                                                                             #
14491###############################################################################
14492#
14493#
14494void
14495Write(ref,...)
14496  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14497  ALIAS:
14498    WriteImage    = 1
14499    write         = 2
14500    writeimage    = 3
14501  PPCODE:
14502  {
14503    char
14504      filename[MaxTextExtent];
14505
14506    ExceptionInfo
14507      *exception;
14508
14509    Image
14510      *image,
14511      *next;
14512
14513    ssize_t
14514      i;
14515
14516    ssize_t
14517      number_images,
14518      scene;
14519
14520    struct PackageInfo
14521      *info,
14522      *package_info;
14523
14524    SV
14525      *perl_exception,
14526      *reference;
14527
14528    PERL_UNUSED_VAR(ref);
14529    PERL_UNUSED_VAR(ix);
14530    exception=AcquireExceptionInfo();
14531    perl_exception=newSVpv("",0);
14532    number_images=0;
14533    package_info=(struct PackageInfo *) NULL;
14534    if (sv_isobject(ST(0)) == 0)
14535      {
14536        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14537          PackageName);
14538        goto PerlException;
14539      }
14540    reference=SvRV(ST(0));
14541    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14542    if (image == (Image *) NULL)
14543      {
14544        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14545          PackageName);
14546        goto PerlException;
14547      }
14548    scene=0;
14549    for (next=image; next; next=next->next)
14550      next->scene=scene++;
14551    package_info=ClonePackageInfo(info,exception);
14552    if (items == 2)
14553      SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14554    else
14555      if (items > 2)
14556        for (i=2; i < items; i+=2)
14557          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14558            exception);
14559    (void) CopyMagickString(filename,package_info->image_info->filename,
14560      MaxTextExtent);
14561    for (next=image; next; next=next->next)
14562      (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14563    *package_info->image_info->magick='\0';
14564    SetImageInfo(package_info->image_info,(unsigned int)
14565      GetImageListLength(image),&image->exception);
14566    for (next=image; next; next=next->next)
14567    {
14568      (void) WriteImage(package_info->image_info,next);
14569      if (next->exception.severity >= ErrorException)
14570        InheritException(exception,&next->exception);
14571      GetImageException(next,exception);
14572      number_images++;
14573      if (package_info->image_info->adjoin)
14574        break;
14575    }
14576
14577  PerlException:
14578    if (package_info != (struct PackageInfo *) NULL)
14579      DestroyPackageInfo(package_info);
14580    InheritPerlException(exception,perl_exception);
14581    exception=DestroyExceptionInfo(exception);
14582    sv_setiv(perl_exception,(IV) number_images);
14583    SvPOK_on(perl_exception);
14584    ST(0)=sv_2mortal(perl_exception);
14585    XSRETURN(1);
14586  }
14587