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 <MagickCore/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[MagickPathExtent]; \
117 \
118  if ((exception)->severity != UndefinedException) \
119    { \
120      (void) FormatLocaleString(message,MagickPathExtent,"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  double
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_NAME@ 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}, {"attenuate", RealReference},
212      {"channel", MagickChannelOptions} } },
213    { "Colorize", { {"fill", StringReference}, {"blend", 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}, {"sigma", 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},
252      {"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 } } },
271    { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
272      {"height", IntegerReference}, {"filter", MagickFilterOptions},
273      {"support", RealReference } } },
274    { "Annotate", { {"text", StringReference}, {"font", StringReference},
275      {"pointsize", RealReference}, {"density", StringReference},
276      {"undercolor", StringReference}, {"stroke", StringReference},
277      {"fill", StringReference}, {"geometry", StringReference},
278      {"sans", 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}, {"clip-to-self", MagickBooleanOptions} } },
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},
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", MagickDitherOptions}, {"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} } },
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      {"kernel", StringReference} } },
391    { "Profile", { {"name", StringReference}, {"profile", StringReference},
392      { "rendering-intent", MagickIntentOptions},
393      { "black-point-compensation", MagickBooleanOptions} } },
394    { "UnsharpMask", { {"geometry", StringReference},
395      {"radius", RealReference}, {"sigma", RealReference},
396      {"gain", RealReference}, {"threshold", RealReference},
397      {"channel", MagickChannelOptions} } },
398    { "MotionBlur", { {"geometry", StringReference},
399      {"radius", RealReference}, {"sigma", RealReference},
400      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401    { "OrderedDither", { {"threshold", StringReference},
402      {"channel", MagickChannelOptions} } },
403    { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404      {"height", IntegerReference} } },
405    { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406      {"white-point", RealReference}, {"gamma", RealReference},
407      {"channel", MagickChannelOptions}, {"level", StringReference} } },
408    { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409    { "AffineTransform", { {"affine", ArrayReference},
410      {"translate", StringReference}, {"scale", StringReference},
411      {"rotate", RealReference}, {"skewX", RealReference},
412      {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413      {"background", StringReference} } },
414    { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415    { "AdaptiveThreshold", { {"geometry", StringReference},
416      {"width", IntegerReference}, {"height", IntegerReference},
417      {"bias", RealReference} } },
418    { "Resample", { {"density", StringReference}, {"x", RealReference},
419      {"y", RealReference}, {"filter", MagickFilterOptions},
420      {"support", RealReference } } },
421    { "Describe", { {"file", FileReference} } },
422    { "BlackThreshold", { {"threshold", StringReference},
423      {"channel", MagickChannelOptions} } },
424    { "WhiteThreshold", { {"threshold", StringReference},
425      {"channel", MagickChannelOptions} } },
426    { "RotationalBlur", { {"geometry", StringReference},
427      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
428    { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429      {"height", IntegerReference} } },
430    { "Strip", { { (const char *) NULL, NullReference } } },
431    { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
432    { "Channel", { {"channel", MagickChannelOptions} } },
433    { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434      {"height", IntegerReference}, {"x", IntegerReference},
435      {"y", IntegerReference}, {"fuzz", StringReference},
436      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437    { "Posterize", { {"levels", IntegerReference},
438      {"dither", MagickBooleanOptions} } },
439    { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
440      {"sigma", RealReference}, {"x", IntegerReference},
441      {"y", IntegerReference} } },
442    { "Identify", { {"file", FileReference}, {"features", StringReference},
443      {"moments", MagickBooleanOptions}, {"unique", MagickBooleanOptions} } },
444    { "SepiaTone", { {"threshold", RealReference} } },
445    { "SigmoidalContrast", { {"geometry", StringReference},
446      {"contrast", RealReference}, {"mid-point", RealReference},
447      {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448    { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449      {"height", IntegerReference}, {"x", IntegerReference},
450      {"y", IntegerReference}, {"fuzz", StringReference},
451      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452    { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453      {"sigma", RealReference}, {"x", IntegerReference},
454      {"y", IntegerReference}, {"background", StringReference} } },
455    { "ContrastStretch", { {"levels", StringReference},
456      {"black-point", RealReference},{"white-point", RealReference},
457      {"channel", MagickChannelOptions} } },
458    { "Sans0", { { (const char *) NULL, NullReference } } },
459    { "Sans1", { { (const char *) NULL, NullReference } } },
460    { "AdaptiveSharpen", { {"geometry", StringReference},
461      {"radius", RealReference}, {"sigma", RealReference},
462      {"bias", RealReference}, {"channel", MagickChannelOptions} } },
463    { "Transpose", { { (const char *) NULL, NullReference } } },
464    { "Transverse", { { (const char *) NULL, NullReference } } },
465    { "AutoOrient", { { (const char *) NULL, NullReference } } },
466    { "AdaptiveBlur", { {"geometry", StringReference},
467      {"radius", RealReference}, {"sigma", RealReference},
468      {"channel", MagickChannelOptions} } },
469    { "Sketch", { {"geometry", StringReference},
470      {"radius", RealReference}, {"sigma", RealReference},
471      {"angle", RealReference} } },
472    { "UniqueColors", { { (const char *) NULL, NullReference } } },
473    { "AdaptiveResize", { {"geometry", StringReference},
474      {"width", IntegerReference}, {"height", IntegerReference},
475      {"filter", MagickFilterOptions}, {"support", StringReference },
476      {"blur", RealReference } } },
477    { "ClipMask", { {"mask", ImageReference} } },
478    { "LinearStretch", { {"levels", StringReference},
479      {"black-point", RealReference},{"white-point", RealReference} } },
480    { "ColorMatrix", { {"matrix", ArrayReference} } },
481    { "Mask", { {"mask", ImageReference} } },
482    { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483      {"font", StringReference}, {"stroke", StringReference},
484      {"fill", StringReference}, {"strokewidth", RealReference},
485      {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486      {"background", StringReference},
487      {"interpolate", MagickInterpolateOptions} } },
488    { "FloodfillPaint", { {"geometry", StringReference},
489      {"x", IntegerReference}, {"y", IntegerReference},
490      {"fill", StringReference}, {"bordercolor", StringReference},
491      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492      {"invert", MagickBooleanOptions} } },
493    { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494      {"virtual-pixel", MagickVirtualPixelOptions},
495      {"best-fit", MagickBooleanOptions} } },
496    { "Clut", { {"image", ImageReference},
497      {"interpolate", MagickInterpolateOptions},
498      {"channel", MagickChannelOptions} } },
499    { "LiquidRescale", { {"geometry", StringReference},
500      {"width", IntegerReference}, {"height", IntegerReference},
501      {"delta-x", RealReference}, {"rigidity", RealReference } } },
502    { "Encipher", { {"passphrase", StringReference} } },
503    { "Decipher", { {"passphrase", StringReference} } },
504    { "Deskew", { {"geometry", StringReference},
505      {"threshold", StringReference} } },
506    { "Remap", { {"image", ImageReference},
507      {"dither-method", MagickDitherOptions} } },
508    { "SparseColor", { {"points", ArrayReference},
509      {"method", MagickSparseColorOptions},
510      {"virtual-pixel", MagickVirtualPixelOptions},
511      {"channel", MagickChannelOptions} } },
512    { "Function", { {"parameters", ArrayReference},
513      {"function", MagickFunctionOptions},
514      {"virtual-pixel", MagickVirtualPixelOptions} } },
515    { "SelectiveBlur", { {"geometry", StringReference},
516      {"radius", RealReference}, {"sigma", RealReference},
517      {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
518    { "HaldClut", { {"image", ImageReference},
519      {"channel", MagickChannelOptions} } },
520    { "BlueShift", { {"factor", StringReference} } },
521    { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
522    { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523    { "ColorDecisionList", {
524      {"color-correction-collection", StringReference} } },
525    { "AutoGamma", { {"channel", MagickChannelOptions} } },
526    { "AutoLevel", { {"channel", MagickChannelOptions} } },
527    { "LevelColors", { {"invert", MagickBooleanOptions},
528      {"black-point", StringReference}, {"white-point", StringReference},
529      {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
530    { "Clamp", { {"channel", MagickChannelOptions} } },
531    { "BrightnessContrast", { {"levels", StringReference},
532      {"brightness", RealReference},{"contrast", RealReference},
533      {"channel", MagickChannelOptions} } },
534    { "Morphology", { {"kernel", StringReference},
535      {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
536      {"iterations", IntegerReference} } },
537    { "Mode", { {"geometry", StringReference},
538      {"width", IntegerReference},{"height", IntegerReference},
539      {"channel", MagickChannelOptions} } },
540    { "Statistic", { {"geometry", StringReference},
541      {"width", IntegerReference},{"height", IntegerReference},
542      {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
543    { "Perceptible", { {"epsilon", RealReference},
544      {"channel", MagickChannelOptions} } },
545    { "Poly", { {"terms", ArrayReference},
546      {"channel", MagickChannelOptions} } },
547    { "Grayscale", { {"method", MagickNoiseOptions} } },
548    { "CannyEdge", { {"geometry", StringReference},
549      {"radius", RealReference}, {"sigma", RealReference},
550      {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
551    { "HoughLine", { {"geometry", StringReference},
552      {"width", IntegerReference}, {"height", IntegerReference},
553      {"threshold", IntegerReference} } },
554    { "MeanShift", { {"geometry", StringReference},
555      {"width", IntegerReference}, {"height", IntegerReference},
556      {"distance", RealReference} } },
557    { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
558      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
559    { "ConnectedComponents", { {"connectivity", IntegerReference} } },
560    { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
561      {"width", IntegerReference}, {"height", IntegerReference},
562      {"x", IntegerReference}, {"y", IntegerReference},
563      {"gravity", MagickGravityOptions}, {"offset", StringReference},
564      {"dx", IntegerReference}, {"dy", IntegerReference} } },
565    { "Color", { {"color", StringReference} } },
566    { "WaveletDenoise", {  {"geometry", StringReference},
567      {"threshold", RealReference}, {"softness", RealReference},
568      {"channel", MagickChannelOptions} } },
569    { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
570    { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } },
571    { "RangeThreshold", { {"geometry", StringReference},
572      {"low-black", RealReference}, {"low-white", RealReference},
573      {"high-white", RealReference}, {"high-black", RealReference},
574      {"channel", MagickChannelOptions} } },
575    { "CLAHE", { {"geometry", StringReference}, {"width", IntegerReference},
576      {"height", IntegerReference}, {"number-bins", IntegerReference},
577      {"clip-limit", RealReference} } },
578    { "Kmeans", { {"geometry", StringReference}, {"colors", IntegerReference},
579      {"iterations", IntegerReference}, {"tolerance", RealReference} } },
580    { "ColorThreshold", { {"start-color", StringReference},
581      {"stop-color", StringReference}, {"channel", MagickChannelOptions} } },
582    { "WhiteBalance", { { (const char *) NULL, NullReference } } },
583    { "BilateralBlur", { {"geometry", StringReference},
584      {"width", IntegerReference}, {"height", IntegerReference},
585      {"intensity-sigma", RealReference}, {"spatial-sigma", RealReference},
586      {"channel", MagickChannelOptions} } },
587    { "SortPixels", { { (const char *) NULL, NullReference } } },
588  };
589
590static SplayTreeInfo
591  *magick_registry = (SplayTreeInfo *) NULL;
592
593/*
594  Forward declarations.
595*/
596static Image
597  *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
598
599static ssize_t
600  strEQcase(const char *,const char *);
601
602/*
603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604%                                                                             %
605%                                                                             %
606%                                                                             %
607%   C l o n e P a c k a g e I n f o                                           %
608%                                                                             %
609%                                                                             %
610%                                                                             %
611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612%
613%  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
614%  a new one.
615%
616%  The format of the ClonePackageInfo routine is:
617%
618%      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
619%        exception)
620%
621%  A description of each parameter follows:
622%
623%    o info: a structure of type info.
624%
625%    o exception: Return any errors or warnings in this structure.
626%
627*/
628static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
629  ExceptionInfo *exception)
630{
631  struct PackageInfo
632    *clone_info;
633
634  clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
635  if (clone_info == (struct PackageInfo *) NULL)
636    {
637      ThrowPerlException(exception,ResourceLimitError,
638        "UnableToClonePackageInfo",PackageName);
639      return((struct PackageInfo *) NULL);
640    }
641  if (info == (struct PackageInfo *) NULL)
642    {
643      clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
644      return(clone_info);
645    }
646  *clone_info=(*info);
647  clone_info->image_info=CloneImageInfo(info->image_info);
648  return(clone_info);
649}
650
651/*
652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653%                                                                             %
654%                                                                             %
655%                                                                             %
656%   c o n s t a n t                                                           %
657%                                                                             %
658%                                                                             %
659%                                                                             %
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661%
662%  constant() returns a double value for the specified name.
663%
664%  The format of the constant routine is:
665%
666%      double constant(char *name,ssize_t sans)
667%
668%  A description of each parameter follows:
669%
670%    o value: Method constant returns a double value for the specified name.
671%
672%    o name: The name of the constant.
673%
674%    o sans: This integer value is not used.
675%
676*/
677static double constant(char *name,ssize_t sans)
678{
679  (void) sans;
680  errno=0;
681  switch (*name)
682  {
683    case 'B':
684    {
685      if (strEQ(name,"BlobError"))
686        return(BlobError);
687      if (strEQ(name,"BlobWarning"))
688        return(BlobWarning);
689      break;
690    }
691    case 'C':
692    {
693      if (strEQ(name,"CacheError"))
694        return(CacheError);
695      if (strEQ(name,"CacheWarning"))
696        return(CacheWarning);
697      if (strEQ(name,"CoderError"))
698        return(CoderError);
699      if (strEQ(name,"CoderWarning"))
700        return(CoderWarning);
701      if (strEQ(name,"ConfigureError"))
702        return(ConfigureError);
703      if (strEQ(name,"ConfigureWarning"))
704        return(ConfigureWarning);
705      if (strEQ(name,"CorruptImageError"))
706        return(CorruptImageError);
707      if (strEQ(name,"CorruptImageWarning"))
708        return(CorruptImageWarning);
709      break;
710    }
711    case 'D':
712    {
713      if (strEQ(name,"DelegateError"))
714        return(DelegateError);
715      if (strEQ(name,"DelegateWarning"))
716        return(DelegateWarning);
717      if (strEQ(name,"DrawError"))
718        return(DrawError);
719      if (strEQ(name,"DrawWarning"))
720        return(DrawWarning);
721      break;
722    }
723    case 'E':
724    {
725      if (strEQ(name,"ErrorException"))
726        return(ErrorException);
727      if (strEQ(name,"ExceptionError"))
728        return(CoderError);
729      if (strEQ(name,"ExceptionWarning"))
730        return(CoderWarning);
731      break;
732    }
733    case 'F':
734    {
735      if (strEQ(name,"FatalErrorException"))
736        return(FatalErrorException);
737      if (strEQ(name,"FileOpenError"))
738        return(FileOpenError);
739      if (strEQ(name,"FileOpenWarning"))
740        return(FileOpenWarning);
741      break;
742    }
743    case 'I':
744    {
745      if (strEQ(name,"ImageError"))
746        return(ImageError);
747      if (strEQ(name,"ImageWarning"))
748        return(ImageWarning);
749      break;
750    }
751    case 'M':
752    {
753      if (strEQ(name,"MaxRGB"))
754        return(QuantumRange);
755      if (strEQ(name,"MissingDelegateError"))
756        return(MissingDelegateError);
757      if (strEQ(name,"MissingDelegateWarning"))
758        return(MissingDelegateWarning);
759      if (strEQ(name,"ModuleError"))
760        return(ModuleError);
761      if (strEQ(name,"ModuleWarning"))
762        return(ModuleWarning);
763      break;
764    }
765    case 'O':
766    {
767      if (strEQ(name,"Opaque"))
768        return(OpaqueAlpha);
769      if (strEQ(name,"OptionError"))
770        return(OptionError);
771      if (strEQ(name,"OptionWarning"))
772        return(OptionWarning);
773      break;
774    }
775    case 'Q':
776    {
777      if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
778        return(MAGICKCORE_QUANTUM_DEPTH);
779      if (strEQ(name,"QuantumDepth"))
780        return(MAGICKCORE_QUANTUM_DEPTH);
781      if (strEQ(name,"QuantumRange"))
782        return(QuantumRange);
783      break;
784    }
785    case 'R':
786    {
787      if (strEQ(name,"ResourceLimitError"))
788        return(ResourceLimitError);
789      if (strEQ(name,"ResourceLimitWarning"))
790        return(ResourceLimitWarning);
791      if (strEQ(name,"RegistryError"))
792        return(RegistryError);
793      if (strEQ(name,"RegistryWarning"))
794        return(RegistryWarning);
795      break;
796    }
797    case 'S':
798    {
799      if (strEQ(name,"StreamError"))
800        return(StreamError);
801      if (strEQ(name,"StreamWarning"))
802        return(StreamWarning);
803      if (strEQ(name,"Success"))
804        return(0);
805      break;
806    }
807    case 'T':
808    {
809      if (strEQ(name,"Transparent"))
810        return(TransparentAlpha);
811      if (strEQ(name,"TypeError"))
812        return(TypeError);
813      if (strEQ(name,"TypeWarning"))
814        return(TypeWarning);
815      break;
816    }
817    case 'W':
818    {
819      if (strEQ(name,"WarningException"))
820        return(WarningException);
821      break;
822    }
823    case 'X':
824    {
825      if (strEQ(name,"XServerError"))
826        return(XServerError);
827      if (strEQ(name,"XServerWarning"))
828        return(XServerWarning);
829      break;
830    }
831  }
832  errno=EINVAL;
833  return(0);
834}
835
836/*
837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838%                                                                             %
839%                                                                             %
840%                                                                             %
841%   D e s t r o y P a c k a g e I n f o                                       %
842%                                                                             %
843%                                                                             %
844%                                                                             %
845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
846%
847%  Method DestroyPackageInfo frees a previously created info structure.
848%
849%  The format of the DestroyPackageInfo routine is:
850%
851%      DestroyPackageInfo(struct PackageInfo *info)
852%
853%  A description of each parameter follows:
854%
855%    o info: a structure of type info.
856%
857*/
858static void DestroyPackageInfo(struct PackageInfo *info)
859{
860  info->image_info=DestroyImageInfo(info->image_info);
861  info=(struct PackageInfo *) RelinquishMagickMemory(info);
862}
863
864/*
865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866%                                                                             %
867%                                                                             %
868%                                                                             %
869%   G e t L i s t                                                             %
870%                                                                             %
871%                                                                             %
872%                                                                             %
873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874%
875%  Method GetList is recursively called by SetupList to traverse the
876%  Image__Magick reference.  If building an reference_vector (see SetupList),
877%  *current is the current position in *reference_vector and *last is the final
878%  entry in *reference_vector.
879%
880%  The format of the GetList routine is:
881%
882%      GetList(info)
883%
884%  A description of each parameter follows:
885%
886%    o info: a structure of type info.
887%
888*/
889static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
890  ssize_t *current,ssize_t *last,ExceptionInfo *exception)
891{
892  Image
893    *image;
894
895  if (reference == (SV *) NULL)
896    return(NULL);
897  switch (SvTYPE(reference))
898  {
899    case SVt_PVAV:
900    {
901      AV
902        *av;
903
904      Image
905        *head,
906        *previous;
907
908      ssize_t
909        i;
910
911      ssize_t
912        n;
913
914      /*
915        Array of images.
916      */
917      previous=(Image *) NULL;
918      head=(Image *) NULL;
919      av=(AV *) reference;
920      n=av_len(av);
921      for (i=0; i <= n; i++)
922      {
923        SV
924          **rv;
925
926        rv=av_fetch(av,i,0);
927        if (rv && *rv && sv_isobject(*rv))
928          {
929            image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
930              exception);
931            if (image == (Image *) NULL)
932              continue;
933            if (image == previous)
934              {
935                image=CloneImage(image,0,0,MagickTrue,exception);
936                if (image == (Image *) NULL)
937                  return(NULL);
938              }
939            image->previous=previous;
940            *(previous ? &previous->next : &head)=image;
941            for (previous=image; previous->next; previous=previous->next) ;
942          }
943      }
944      return(head);
945    }
946    case SVt_PVMG:
947    {
948      /*
949        Blessed scalar, one image.
950      */
951      image=INT2PTR(Image *,SvIV(reference));
952      if (image == (Image *) NULL)
953        return(NULL);
954      image->previous=(Image *) NULL;
955      image->next=(Image *) NULL;
956      if (reference_vector)
957        {
958          if (*current == *last)
959            {
960              *last+=256;
961              if (*reference_vector == (SV **) NULL)
962                *reference_vector=(SV **) AcquireQuantumMemory(*last,
963                  sizeof(*reference_vector));
964              else
965                *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
966                  *last,sizeof(*reference_vector));
967            }
968          if (*reference_vector == (SV **) NULL)
969            {
970              ThrowPerlException(exception,ResourceLimitError,
971                "MemoryAllocationFailed",PackageName);
972              return((Image *) NULL);
973            }
974          (*reference_vector)[*current]=reference;
975          (*reference_vector)[++(*current)]=NULL;
976        }
977      return(image);
978    }
979    default:
980      break;
981  }
982  (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
983    (double) SvTYPE(reference));
984  return((Image *) NULL);
985}
986
987/*
988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989%                                                                             %
990%                                                                             %
991%                                                                             %
992%   G e t P a c k a g e I n f o                                               %
993%                                                                             %
994%                                                                             %
995%                                                                             %
996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997%
998%  Method GetPackageInfo looks up or creates an info structure for the given
999%  Image__Magick reference.  If it does create a new one, the information in
1000%  package_info is used to initialize it.
1001%
1002%  The format of the GetPackageInfo routine is:
1003%
1004%      struct PackageInfo *GetPackageInfo(void *reference,
1005%        struct PackageInfo *package_info,ExceptionInfo *exception)
1006%
1007%  A description of each parameter follows:
1008%
1009%    o info: a structure of type info.
1010%
1011%    o exception: Return any errors or warnings in this structure.
1012%
1013*/
1014static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1015  struct PackageInfo *package_info,ExceptionInfo *exception)
1016{
1017  char
1018    message[MagickPathExtent];
1019
1020  struct PackageInfo
1021    *clone_info;
1022
1023  SV
1024    *sv;
1025
1026  (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1027    PackageName,XS_VERSION,reference);
1028  sv=perl_get_sv(message,(TRUE | 0x02));
1029  if (sv == (SV *) NULL)
1030    {
1031      ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1032        message);
1033      return(package_info);
1034    }
1035  if (SvREFCNT(sv) == 0)
1036    (void) SvREFCNT_inc(sv);
1037  if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1038    return(clone_info);
1039  clone_info=ClonePackageInfo(package_info,exception);
1040  sv_setiv(sv,PTR2IV(clone_info));
1041  return(clone_info);
1042}
1043
1044/*
1045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046%                                                                             %
1047%                                                                             %
1048%                                                                             %
1049%   S e t A t t r i b u t e                                                   %
1050%                                                                             %
1051%                                                                             %
1052%                                                                             %
1053%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054%
1055%  SetAttribute() sets the attribute to the value in sval.  This can change
1056%  either or both of image or info.
1057%
1058%  The format of the SetAttribute routine is:
1059%
1060%      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1061%        SV *sval,ExceptionInfo *exception)
1062%
1063%  A description of each parameter follows:
1064%
1065%    o list: a list of strings.
1066%
1067%    o string: a character string.
1068%
1069*/
1070
1071static double SiPrefixToDoubleInterval(const char *string,const double interval)
1072{
1073  char
1074    *q;
1075
1076  double
1077    value;
1078
1079  value=InterpretSiPrefixValue(string,&q);
1080  if (*q == '%')
1081    value*=interval/100.0;
1082  return(value);
1083}
1084
1085static inline double StringToDouble(const char *string,char **sentinal)
1086{
1087  return(InterpretLocaleValue(string,sentinal));
1088}
1089
1090static double StringToDoubleInterval(const char *string,const double interval)
1091{
1092  char
1093    *q;
1094
1095  double
1096    value;
1097
1098  value=InterpretLocaleValue(string,&q);
1099  if (*q == '%')
1100    value*=interval/100.0;
1101  return(value);
1102}
1103
1104static inline ssize_t StringToLong(const char *value)
1105{
1106  return(strtol(value,(char **) NULL,10));
1107}
1108
1109static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1110  const char *attribute,SV *sval,ExceptionInfo *exception)
1111{
1112  GeometryInfo
1113    geometry_info;
1114
1115  long
1116    x,
1117    y;
1118
1119  PixelInfo
1120    pixel;
1121
1122  MagickStatusType
1123    flags;
1124
1125  PixelInfo
1126    *color,
1127    target_color;
1128
1129  ssize_t
1130    sp;
1131
1132  switch (*attribute)
1133  {
1134    case 'A':
1135    case 'a':
1136    {
1137      if (LocaleCompare(attribute,"adjoin") == 0)
1138        {
1139          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1140            SvPV(sval,na)) : SvIV(sval);
1141          if (sp < 0)
1142            {
1143              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1144                SvPV(sval,na));
1145              break;
1146            }
1147          if (info)
1148            info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1149          break;
1150        }
1151      if (LocaleCompare(attribute,"alpha") == 0)
1152        {
1153          sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1154            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1155          if (sp < 0)
1156            {
1157              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1158                SvPV(sval,na));
1159              break;
1160            }
1161          for ( ; image; image=image->next)
1162            (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1163              exception);
1164          break;
1165        }
1166      if (LocaleCompare(attribute,"antialias") == 0)
1167        {
1168          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1169            SvPV(sval,na)) : SvIV(sval);
1170          if (sp < 0)
1171            {
1172              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1173                SvPV(sval,na));
1174              break;
1175            }
1176          if (info)
1177            info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1178          break;
1179        }
1180      if (LocaleCompare(attribute,"area-limit") == 0)
1181        {
1182          MagickSizeType
1183            limit;
1184
1185          limit=MagickResourceInfinity;
1186          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1187            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1188              100.0);
1189          (void) SetMagickResourceLimit(AreaResource,limit);
1190          break;
1191        }
1192      if (LocaleCompare(attribute,"attenuate") == 0)
1193        {
1194          if (info)
1195            (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1196          break;
1197        }
1198      if (LocaleCompare(attribute,"authenticate") == 0)
1199        {
1200          if (info)
1201            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1202          break;
1203        }
1204      if (info)
1205        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1206      for ( ; image; image=image->next)
1207      {
1208        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1209        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1210      }
1211      break;
1212    }
1213    case 'B':
1214    case 'b':
1215    {
1216      if (LocaleCompare(attribute,"background") == 0)
1217        {
1218          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1219            exception);
1220          if (info)
1221            info->image_info->background_color=target_color;
1222          for ( ; image; image=image->next)
1223            image->background_color=target_color;
1224          break;
1225        }
1226      if (LocaleCompare(attribute,"blue-primary") == 0)
1227        {
1228          for ( ; image; image=image->next)
1229          {
1230            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1231            image->chromaticity.blue_primary.x=geometry_info.rho;
1232            image->chromaticity.blue_primary.y=geometry_info.sigma;
1233            if ((flags & SigmaValue) == 0)
1234              image->chromaticity.blue_primary.y=
1235                image->chromaticity.blue_primary.x;
1236          }
1237          break;
1238        }
1239      if (LocaleCompare(attribute,"bordercolor") == 0)
1240        {
1241          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1242            exception);
1243          if (info)
1244            info->image_info->border_color=target_color;
1245          for ( ; image; image=image->next)
1246            image->border_color=target_color;
1247          break;
1248        }
1249      if (info)
1250        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1251      for ( ; image; image=image->next)
1252      {
1253        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1254        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1255      }
1256      break;
1257    }
1258    case 'C':
1259    case 'c':
1260    {
1261      if (LocaleCompare(attribute,"cache-threshold") == 0)
1262        {
1263          (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1264            SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1265          (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1266            (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1267          break;
1268        }
1269      if (LocaleCompare(attribute,"clip-mask") == 0)
1270        {
1271          Image
1272            *clip_mask;
1273
1274          clip_mask=(Image *) NULL;
1275          if (SvPOK(sval))
1276            clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1277          for ( ; image; image=image->next)
1278            SetImageMask(image,ReadPixelMask,clip_mask,exception);
1279          break;
1280        }
1281      if (LocaleNCompare(attribute,"colormap",8) == 0)
1282        {
1283          for ( ; image; image=image->next)
1284          {
1285            int
1286              items;
1287
1288            long
1289              i;
1290
1291            if (image->storage_class == DirectClass)
1292              continue;
1293            i=0;
1294            items=sscanf(attribute,"%*[^[][%ld",&i);
1295            (void) items;
1296            if (i > (ssize_t) image->colors)
1297              i%=image->colors;
1298            if ((strchr(SvPV(sval,na),',') == 0) ||
1299                (strchr(SvPV(sval,na),')') != 0))
1300              QueryColorCompliance(SvPV(sval,na),AllCompliance,
1301                image->colormap+i,exception);
1302            else
1303              {
1304                color=image->colormap+i;
1305                pixel.red=color->red;
1306                pixel.green=color->green;
1307                pixel.blue=color->blue;
1308                flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1309                pixel.red=geometry_info.rho;
1310                pixel.green=geometry_info.sigma;
1311                pixel.blue=geometry_info.xi;
1312                color->red=ClampToQuantum(pixel.red);
1313                color->green=ClampToQuantum(pixel.green);
1314                color->blue=ClampToQuantum(pixel.blue);
1315              }
1316          }
1317          break;
1318        }
1319      if (LocaleCompare(attribute,"colorspace") == 0)
1320        {
1321          sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1322            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1323          if (sp < 0)
1324            {
1325              ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1326                SvPV(sval,na));
1327              break;
1328            }
1329          for ( ; image; image=image->next)
1330            (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
1331          break;
1332        }
1333      if (LocaleCompare(attribute,"comment") == 0)
1334        {
1335          for ( ; image; image=image->next)
1336            (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1337              info ? info->image_info : (ImageInfo *) NULL,image,
1338              SvPV(sval,na),exception),exception);
1339          break;
1340        }
1341      if (LocaleCompare(attribute,"compression") == 0)
1342        {
1343          sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1344            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1345          if (sp < 0)
1346            {
1347              ThrowPerlException(exception,OptionError,
1348                "UnrecognizedImageCompression",SvPV(sval,na));
1349              break;
1350            }
1351          if (info)
1352            info->image_info->compression=(CompressionType) sp;
1353          for ( ; image; image=image->next)
1354            image->compression=(CompressionType) sp;
1355          break;
1356        }
1357      if (info)
1358        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1359      for ( ; image; image=image->next)
1360      {
1361        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1362        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1363      }
1364      break;
1365    }
1366    case 'D':
1367    case 'd':
1368    {
1369      if (LocaleCompare(attribute,"debug") == 0)
1370        {
1371          SetLogEventMask(SvPV(sval,na));
1372          break;
1373        }
1374      if (LocaleCompare(attribute,"delay") == 0)
1375        {
1376          flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1377          for ( ; image; image=image->next)
1378          {
1379            image->delay=(size_t) floor(geometry_info.rho+0.5);
1380            if ((flags & SigmaValue) != 0)
1381              image->ticks_per_second=(ssize_t)
1382                floor(geometry_info.sigma+0.5);
1383          }
1384          break;
1385        }
1386      if (LocaleCompare(attribute,"disk-limit") == 0)
1387        {
1388          MagickSizeType
1389            limit;
1390
1391          limit=MagickResourceInfinity;
1392          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1393            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1394              100.0);
1395          (void) SetMagickResourceLimit(DiskResource,limit);
1396          break;
1397        }
1398      if (LocaleCompare(attribute,"density") == 0)
1399        {
1400          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1401            {
1402              ThrowPerlException(exception,OptionError,"MissingGeometry",
1403                SvPV(sval,na));
1404              break;
1405            }
1406          if (info)
1407            (void) CloneString(&info->image_info->density,SvPV(sval,na));
1408          for ( ; image; image=image->next)
1409          {
1410            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1411            image->resolution.x=geometry_info.rho;
1412            image->resolution.y=geometry_info.sigma;
1413            if ((flags & SigmaValue) == 0)
1414              image->resolution.y=image->resolution.x;
1415          }
1416          break;
1417        }
1418      if (LocaleCompare(attribute,"depth") == 0)
1419        {
1420          if (info)
1421            info->image_info->depth=SvIV(sval);
1422          for ( ; image; image=image->next)
1423            (void) SetImageDepth(image,SvIV(sval),exception);
1424          break;
1425        }
1426      if (LocaleCompare(attribute,"dispose") == 0)
1427        {
1428          sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1429            SvPV(sval,na)) : SvIV(sval);
1430          if (sp < 0)
1431            {
1432              ThrowPerlException(exception,OptionError,
1433                "UnrecognizedDisposeMethod",SvPV(sval,na));
1434              break;
1435            }
1436          for ( ; image; image=image->next)
1437            image->dispose=(DisposeType) sp;
1438          break;
1439        }
1440      if (LocaleCompare(attribute,"dither") == 0)
1441        {
1442          if (info)
1443            {
1444              sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1445                MagickFalse,SvPV(sval,na)) : SvIV(sval);
1446              if (sp < 0)
1447                {
1448                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
1449                    SvPV(sval,na));
1450                  break;
1451                }
1452              info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1453            }
1454          break;
1455        }
1456      if (LocaleCompare(attribute,"display") == 0)
1457        {
1458          display:
1459          if (info)
1460            (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1461          break;
1462        }
1463      if (info)
1464        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1465      for ( ; image; image=image->next)
1466      {
1467        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1468        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1469      }
1470      break;
1471    }
1472    case 'E':
1473    case 'e':
1474    {
1475      if (LocaleCompare(attribute,"endian") == 0)
1476        {
1477          sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1478            SvPV(sval,na)) : SvIV(sval);
1479          if (sp < 0)
1480            {
1481              ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1482                SvPV(sval,na));
1483              break;
1484            }
1485          if (info)
1486            info->image_info->endian=(EndianType) sp;
1487          for ( ; image; image=image->next)
1488            image->endian=(EndianType) sp;
1489          break;
1490        }
1491      if (LocaleCompare(attribute,"extract") == 0)
1492        {
1493          /*
1494            Set image extract geometry.
1495          */
1496          (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1497          break;
1498        }
1499      if (info)
1500        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1501      for ( ; image; image=image->next)
1502      {
1503        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1504        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1505      }
1506      break;
1507    }
1508    case 'F':
1509    case 'f':
1510    {
1511      if (LocaleCompare(attribute,"filename") == 0)
1512        {
1513          if (info)
1514            (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1515              MagickPathExtent);
1516          for ( ; image; image=image->next)
1517            (void) CopyMagickString(image->filename,SvPV(sval,na),
1518              MagickPathExtent);
1519          break;
1520        }
1521      if (LocaleCompare(attribute,"file") == 0)
1522        {
1523          FILE
1524            *file;
1525
1526          PerlIO
1527            *io_info;
1528
1529          if (info == (struct PackageInfo *) NULL)
1530            break;
1531          io_info=IoIFP(sv_2io(sval));
1532          if (io_info == (PerlIO *) NULL)
1533            {
1534              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1535                PackageName);
1536              break;
1537            }
1538          file=PerlIO_findFILE(io_info);
1539          if (file == (FILE *) NULL)
1540            {
1541              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1542                PackageName);
1543              break;
1544            }
1545          SetImageInfoFile(info->image_info,file);
1546          break;
1547        }
1548      if (LocaleCompare(attribute,"fill") == 0)
1549        {
1550          if (info)
1551            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1552          break;
1553        }
1554      if (LocaleCompare(attribute,"font") == 0)
1555        {
1556          if (info)
1557            (void) CloneString(&info->image_info->font,SvPV(sval,na));
1558          break;
1559        }
1560      if (LocaleCompare(attribute,"foreground") == 0)
1561        break;
1562      if (LocaleCompare(attribute,"fuzz") == 0)
1563        {
1564          if (info)
1565            info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1566              QuantumRange+1.0);
1567          for ( ; image; image=image->next)
1568            image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1569              QuantumRange+1.0);
1570          break;
1571        }
1572      if (info)
1573        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1574      for ( ; image; image=image->next)
1575      {
1576        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1577        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1578      }
1579      break;
1580    }
1581    case 'G':
1582    case 'g':
1583    {
1584      if (LocaleCompare(attribute,"gamma") == 0)
1585        {
1586          for ( ; image; image=image->next)
1587            image->gamma=SvNV(sval);
1588          break;
1589        }
1590      if (LocaleCompare(attribute,"gravity") == 0)
1591        {
1592          sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1593            SvPV(sval,na)) : SvIV(sval);
1594          if (sp < 0)
1595            {
1596              ThrowPerlException(exception,OptionError,
1597                "UnrecognizedGravityType",SvPV(sval,na));
1598              break;
1599            }
1600          if (info)
1601            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1602          for ( ; image; image=image->next)
1603            image->gravity=(GravityType) sp;
1604          break;
1605        }
1606      if (LocaleCompare(attribute,"green-primary") == 0)
1607        {
1608          for ( ; image; image=image->next)
1609          {
1610            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1611            image->chromaticity.green_primary.x=geometry_info.rho;
1612            image->chromaticity.green_primary.y=geometry_info.sigma;
1613            if ((flags & SigmaValue) == 0)
1614              image->chromaticity.green_primary.y=
1615                image->chromaticity.green_primary.x;
1616          }
1617          break;
1618        }
1619      if (info)
1620        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1621      for ( ; image; image=image->next)
1622      {
1623        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1624        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1625      }
1626      break;
1627    }
1628    case 'I':
1629    case 'i':
1630    {
1631      if (LocaleNCompare(attribute,"index",5) == 0)
1632        {
1633          int
1634            items;
1635
1636          long
1637            index;
1638
1639          Quantum
1640            *q;
1641
1642          CacheView
1643            *image_view;
1644
1645          for ( ; image; image=image->next)
1646          {
1647            if (image->storage_class != PseudoClass)
1648              continue;
1649            x=0;
1650            y=0;
1651            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1652            (void) items;
1653            image_view=AcquireAuthenticCacheView(image,exception);
1654            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1655            if (q != (Quantum *) NULL)
1656              {
1657                items=sscanf(SvPV(sval,na),"%ld",&index);
1658                if ((index >= 0) && (index < (ssize_t) image->colors))
1659                  SetPixelIndex(image,index,q);
1660                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1661              }
1662            image_view=DestroyCacheView(image_view);
1663          }
1664          break;
1665        }
1666      if (LocaleCompare(attribute,"iterations") == 0)
1667        {
1668  iterations:
1669          for ( ; image; image=image->next)
1670            image->iterations=SvIV(sval);
1671          break;
1672        }
1673      if (LocaleCompare(attribute,"interlace") == 0)
1674        {
1675          sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1676            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1677          if (sp < 0)
1678            {
1679              ThrowPerlException(exception,OptionError,
1680                "UnrecognizedInterlaceType",SvPV(sval,na));
1681              break;
1682            }
1683          if (info)
1684            info->image_info->interlace=(InterlaceType) sp;
1685          for ( ; image; image=image->next)
1686            image->interlace=(InterlaceType) sp;
1687          break;
1688        }
1689      if (info)
1690        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1691      for ( ; image; image=image->next)
1692        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1693      break;
1694    }
1695    case 'L':
1696    case 'l':
1697    {
1698      if (LocaleCompare(attribute,"label") == 0)
1699        {
1700          for ( ; image; image=image->next)
1701            (void) SetImageProperty(image,"label",InterpretImageProperties(
1702              info ? info->image_info : (ImageInfo *) NULL,image,
1703              SvPV(sval,na),exception),exception);
1704          break;
1705        }
1706      if (LocaleCompare(attribute,"loop") == 0)
1707        goto iterations;
1708      if (info)
1709        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1710      for ( ; image; image=image->next)
1711      {
1712        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1713        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1714      }
1715      break;
1716    }
1717    case 'M':
1718    case 'm':
1719    {
1720      if (LocaleCompare(attribute,"magick") == 0)
1721        {
1722          if (info)
1723            (void) FormatLocaleString(info->image_info->filename,
1724              MagickPathExtent,"%s:",SvPV(sval,na));
1725          for ( ; image; image=image->next)
1726            (void) CopyMagickString(image->magick,SvPV(sval,na),
1727              MagickPathExtent);
1728          break;
1729        }
1730      if (LocaleCompare(attribute,"map-limit") == 0)
1731        {
1732          MagickSizeType
1733            limit;
1734
1735          limit=MagickResourceInfinity;
1736          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1737            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1738              100.0);
1739          (void) SetMagickResourceLimit(MapResource,limit);
1740          break;
1741        }
1742      if (LocaleCompare(attribute,"mask") == 0)
1743        {
1744          Image
1745            *mask;
1746
1747          mask=(Image *) NULL;
1748          if (SvPOK(sval))
1749            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1750          for ( ; image; image=image->next)
1751            SetImageMask(image,ReadPixelMask,mask,exception);
1752          break;
1753        }
1754      if (LocaleCompare(attribute,"mattecolor") == 0)
1755        {
1756          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1757            exception);
1758          if (info)
1759            info->image_info->alpha_color=target_color;
1760          for ( ; image; image=image->next)
1761            image->alpha_color=target_color;
1762          break;
1763        }
1764      if (LocaleCompare(attribute,"matte") == 0)
1765        {
1766          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1767            SvPV(sval,na)) : SvIV(sval);
1768          if (sp < 0)
1769            {
1770              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1771                SvPV(sval,na));
1772              break;
1773            }
1774          for ( ; image; image=image->next)
1775            image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1776          break;
1777        }
1778      if (LocaleCompare(attribute,"memory-limit") == 0)
1779        {
1780          MagickSizeType
1781            limit;
1782
1783          limit=MagickResourceInfinity;
1784          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1785            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1786              100.0);
1787          (void) SetMagickResourceLimit(MemoryResource,limit);
1788          break;
1789        }
1790      if (LocaleCompare(attribute,"monochrome") == 0)
1791        {
1792          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1793            SvPV(sval,na)) : SvIV(sval);
1794          if (sp < 0)
1795            {
1796              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1797                SvPV(sval,na));
1798              break;
1799            }
1800          if (info)
1801            info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1802          for ( ; image; image=image->next)
1803            (void) SetImageType(image,BilevelType,exception);
1804          break;
1805        }
1806      if (info)
1807        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1808      for ( ; image; image=image->next)
1809      {
1810        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1811        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1812      }
1813      break;
1814    }
1815    case 'O':
1816    case 'o':
1817    {
1818      if (LocaleCompare(attribute,"option") == 0)
1819        {
1820          if (info)
1821            DefineImageOption(info->image_info,SvPV(sval,na));
1822          break;
1823        }
1824      if (LocaleCompare(attribute,"orientation") == 0)
1825        {
1826          sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1827            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1828          if (sp < 0)
1829            {
1830              ThrowPerlException(exception,OptionError,
1831                "UnrecognizedOrientationType",SvPV(sval,na));
1832              break;
1833            }
1834          if (info)
1835            info->image_info->orientation=(OrientationType) sp;
1836          for ( ; image; image=image->next)
1837            image->orientation=(OrientationType) sp;
1838          break;
1839        }
1840      if (info)
1841        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1842      for ( ; image; image=image->next)
1843      {
1844        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1845        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1846      }
1847      break;
1848    }
1849    case 'P':
1850    case 'p':
1851    {
1852      if (LocaleCompare(attribute,"page") == 0)
1853        {
1854          char
1855            *geometry;
1856
1857          geometry=GetPageGeometry(SvPV(sval,na));
1858          if (info)
1859            (void) CloneString(&info->image_info->page,geometry);
1860          for ( ; image; image=image->next)
1861            (void) ParsePageGeometry(image,geometry,&image->page,exception);
1862          geometry=(char *) RelinquishMagickMemory(geometry);
1863          break;
1864        }
1865      if (LocaleNCompare(attribute,"pixel",5) == 0)
1866        {
1867          int
1868            items;
1869
1870          PixelInfo
1871            pixel;
1872
1873          Quantum
1874            *q;
1875
1876          CacheView
1877            *image_view;
1878
1879          for ( ; image; image=image->next)
1880          {
1881            if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1882              break;
1883            x=0;
1884            y=0;
1885            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1886            (void) items;
1887            image_view=AcquireVirtualCacheView(image,exception);
1888            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1889            if (q != (Quantum *) NULL)
1890              {
1891                if ((strchr(SvPV(sval,na),',') == 0) ||
1892                    (strchr(SvPV(sval,na),')') != 0))
1893                  QueryColorCompliance(SvPV(sval,na),AllCompliance,
1894                    &pixel,exception);
1895                else
1896                  {
1897                    GetPixelInfo(image,&pixel);
1898                    flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1899                    pixel.red=geometry_info.rho;
1900                    if ((flags & SigmaValue) != 0)
1901                      pixel.green=geometry_info.sigma;
1902                    if ((flags & XiValue) != 0)
1903                      pixel.blue=geometry_info.xi;
1904                    if ((flags & PsiValue) != 0)
1905                      pixel.alpha=geometry_info.psi;
1906                    if ((flags & ChiValue) != 0)
1907                      pixel.black=geometry_info.chi;
1908                  }
1909                SetPixelRed(image,ClampToQuantum(pixel.red),q);
1910                SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1911                SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1912                if (image->colorspace == CMYKColorspace)
1913                  SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1914                SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1915                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1916              }
1917            image_view=DestroyCacheView(image_view);
1918          }
1919          break;
1920        }
1921      if (LocaleCompare(attribute,"pointsize") == 0)
1922        {
1923          if (info)
1924            {
1925              (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1926              info->image_info->pointsize=geometry_info.rho;
1927            }
1928          break;
1929        }
1930      if (LocaleCompare(attribute,"precision") == 0)
1931        {
1932          (void) SetMagickPrecision(SvIV(sval));
1933          break;
1934        }
1935      if (info)
1936        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1937      for ( ; image; image=image->next)
1938      {
1939        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1940        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1941      }
1942      break;
1943    }
1944    case 'Q':
1945    case 'q':
1946    {
1947      if (LocaleCompare(attribute,"quality") == 0)
1948        {
1949          if (info)
1950            info->image_info->quality=SvIV(sval);
1951          for ( ; image; image=image->next)
1952            image->quality=SvIV(sval);
1953          break;
1954        }
1955      if (info)
1956        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1957      for ( ; image; image=image->next)
1958      {
1959        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1960        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1961      }
1962      break;
1963    }
1964    case 'R':
1965    case 'r':
1966    {
1967      if (LocaleCompare(attribute,"read-mask") == 0)
1968        {
1969          Image
1970            *mask;
1971
1972          mask=(Image *) NULL;
1973          if (SvPOK(sval))
1974            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1975          for ( ; image; image=image->next)
1976            SetImageMask(image,ReadPixelMask,mask,exception);
1977          break;
1978        }
1979      if (LocaleCompare(attribute,"red-primary") == 0)
1980        {
1981          for ( ; image; image=image->next)
1982          {
1983            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1984            image->chromaticity.red_primary.x=geometry_info.rho;
1985            image->chromaticity.red_primary.y=geometry_info.sigma;
1986            if ((flags & SigmaValue) == 0)
1987              image->chromaticity.red_primary.y=
1988                image->chromaticity.red_primary.x;
1989          }
1990          break;
1991        }
1992      if (LocaleCompare(attribute,"render") == 0)
1993        {
1994          sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1995            SvPV(sval,na)) : SvIV(sval);
1996          if (sp < 0)
1997            {
1998              ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1999                SvPV(sval,na));
2000              break;
2001            }
2002         for ( ; image; image=image->next)
2003           image->rendering_intent=(RenderingIntent) sp;
2004         break;
2005       }
2006      if (LocaleCompare(attribute,"repage") == 0)
2007        {
2008          RectangleInfo
2009            geometry;
2010
2011          for ( ; image; image=image->next)
2012          {
2013            flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2014            if ((flags & WidthValue) != 0)
2015              {
2016                if ((flags & HeightValue) == 0)
2017                  geometry.height=geometry.width;
2018                image->page.width=geometry.width;
2019                image->page.height=geometry.height;
2020              }
2021            if ((flags & AspectValue) != 0)
2022              {
2023                if ((flags & XValue) != 0)
2024                  image->page.x+=geometry.x;
2025                if ((flags & YValue) != 0)
2026                  image->page.y+=geometry.y;
2027              }
2028            else
2029              {
2030                if ((flags & XValue) != 0)
2031                  {
2032                    image->page.x=geometry.x;
2033                    if (((flags & WidthValue) != 0) && (geometry.x > 0))
2034                      image->page.width=image->columns+geometry.x;
2035                  }
2036                if ((flags & YValue) != 0)
2037                  {
2038                    image->page.y=geometry.y;
2039                    if (((flags & HeightValue) != 0) && (geometry.y > 0))
2040                      image->page.height=image->rows+geometry.y;
2041                  }
2042              }
2043          }
2044          break;
2045        }
2046      if (info)
2047        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2048      for ( ; image; image=image->next)
2049      {
2050        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2051        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2052      }
2053      break;
2054    }
2055    case 'S':
2056    case 's':
2057    {
2058      if (LocaleCompare(attribute,"sampling-factor") == 0)
2059        {
2060          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2061            {
2062              ThrowPerlException(exception,OptionError,"MissingGeometry",
2063                SvPV(sval,na));
2064              break;
2065            }
2066          if (info)
2067            (void) CloneString(&info->image_info->sampling_factor,
2068              SvPV(sval,na));
2069          break;
2070        }
2071      if (LocaleCompare(attribute,"scene") == 0)
2072        {
2073          for ( ; image; image=image->next)
2074            image->scene=SvIV(sval);
2075          break;
2076        }
2077      if (LocaleCompare(attribute,"server") == 0)
2078        goto display;
2079      if (LocaleCompare(attribute,"size") == 0)
2080        {
2081          if (info)
2082            {
2083              if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2084                {
2085                  ThrowPerlException(exception,OptionError,"MissingGeometry",
2086                    SvPV(sval,na));
2087                  break;
2088                }
2089              (void) CloneString(&info->image_info->size,SvPV(sval,na));
2090            }
2091          break;
2092        }
2093      if (LocaleCompare(attribute,"stroke") == 0)
2094        {
2095          if (info)
2096            (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2097          break;
2098        }
2099      if (info)
2100        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2101      for ( ; image; image=image->next)
2102      {
2103        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2104        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2105      }
2106      break;
2107    }
2108    case 'T':
2109    case 't':
2110    {
2111      if (LocaleCompare(attribute,"texture") == 0)
2112        {
2113          if (info)
2114            (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2115          break;
2116        }
2117      if (LocaleCompare(attribute,"thread-limit") == 0)
2118        {
2119          MagickSizeType
2120            limit;
2121
2122          limit=MagickResourceInfinity;
2123          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2124            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2125              100.0);
2126          (void) SetMagickResourceLimit(ThreadResource,limit);
2127          break;
2128        }
2129      if (LocaleCompare(attribute,"tile-offset") == 0)
2130        {
2131          char
2132            *geometry;
2133
2134          geometry=GetPageGeometry(SvPV(sval,na));
2135          if (info)
2136            (void) CloneString(&info->image_info->page,geometry);
2137          for ( ; image; image=image->next)
2138            (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2139              exception);
2140          geometry=(char *) RelinquishMagickMemory(geometry);
2141          break;
2142        }
2143      if (LocaleCompare(attribute,"time-limit") == 0)
2144        {
2145          MagickSizeType
2146            limit;
2147
2148          limit=MagickResourceInfinity;
2149          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2150            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2151              100.0);
2152          (void) SetMagickResourceLimit(TimeResource,limit);
2153          break;
2154        }
2155      if (LocaleCompare(attribute,"transparent-color") == 0)
2156        {
2157          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2158            exception);
2159          if (info)
2160            info->image_info->transparent_color=target_color;
2161          for ( ; image; image=image->next)
2162            image->transparent_color=target_color;
2163          break;
2164        }
2165      if (LocaleCompare(attribute,"type") == 0)
2166        {
2167          sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2168            SvPV(sval,na)) : SvIV(sval);
2169          if (sp < 0)
2170            {
2171              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2172                SvPV(sval,na));
2173              break;
2174            }
2175          if (info)
2176            info->image_info->type=(ImageType) sp;
2177          for ( ; image; image=image->next)
2178            SetImageType(image,(ImageType) sp,exception);
2179          break;
2180        }
2181      if (info)
2182        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2183      for ( ; image; image=image->next)
2184      {
2185        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2186        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2187      }
2188      break;
2189    }
2190    case 'U':
2191    case 'u':
2192    {
2193      if (LocaleCompare(attribute,"units") == 0)
2194        {
2195          sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2196            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2197          if (sp < 0)
2198            {
2199              ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2200                SvPV(sval,na));
2201              break;
2202            }
2203          if (info)
2204            info->image_info->units=(ResolutionType) sp;
2205          for ( ; image; image=image->next)
2206          {
2207            ResolutionType
2208              units;
2209
2210            units=(ResolutionType) sp;
2211            if (image->units != units)
2212              switch (image->units)
2213              {
2214                case UndefinedResolution:
2215                case PixelsPerInchResolution:
2216                {
2217                  if (units == PixelsPerCentimeterResolution)
2218                    {
2219                      image->resolution.x*=2.54;
2220                      image->resolution.y*=2.54;
2221                    }
2222                  break;
2223                }
2224                case PixelsPerCentimeterResolution:
2225                {
2226                  if (units == PixelsPerInchResolution)
2227                    {
2228                      image->resolution.x/=2.54;
2229                      image->resolution.y/=2.54;
2230                    }
2231                  break;
2232                }
2233              }
2234            image->units=units;
2235          }
2236          break;
2237        }
2238      if (info)
2239        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2240      for ( ; image; image=image->next)
2241      {
2242        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2243        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2244      }
2245      break;
2246    }
2247    case 'V':
2248    case 'v':
2249    {
2250      if (LocaleCompare(attribute,"verbose") == 0)
2251        {
2252          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2253            SvPV(sval,na)) : SvIV(sval);
2254          if (sp < 0)
2255            {
2256              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2257                SvPV(sval,na));
2258              break;
2259            }
2260          if (info)
2261            info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2262          break;
2263        }
2264      if (LocaleCompare(attribute,"virtual-pixel") == 0)
2265        {
2266          sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2267            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2268          if (sp < 0)
2269            {
2270              ThrowPerlException(exception,OptionError,
2271                "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2272              break;
2273            }
2274          for ( ; image; image=image->next)
2275            SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2276          break;
2277        }
2278      if (info)
2279        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2280      for ( ; image; image=image->next)
2281      {
2282        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2283        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2284      }
2285      break;
2286    }
2287    case 'W':
2288    case 'w':
2289    {
2290      if (LocaleCompare(attribute,"white-point") == 0)
2291        {
2292          for ( ; image; image=image->next)
2293          {
2294            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2295            image->chromaticity.white_point.x=geometry_info.rho;
2296            image->chromaticity.white_point.y=geometry_info.sigma;
2297            if ((flags & SigmaValue) == 0)
2298              image->chromaticity.white_point.y=
2299                image->chromaticity.white_point.x;
2300          }
2301          break;
2302        }
2303      if (LocaleCompare(attribute,"write-mask") == 0)
2304        {
2305          Image
2306            *mask;
2307
2308          mask=(Image *) NULL;
2309          if (SvPOK(sval))
2310            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2311          for ( ; image; image=image->next)
2312            SetImageMask(image,WritePixelMask,mask,exception);
2313          break;
2314        }
2315      if (info)
2316        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2317      for ( ; image; image=image->next)
2318      {
2319        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2320        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2321      }
2322      break;
2323    }
2324    default:
2325    {
2326      if (info)
2327        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2328      for ( ; image; image=image->next)
2329      {
2330        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2331        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2332      }
2333      break;
2334    }
2335  }
2336}
2337
2338/*
2339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2340%                                                                             %
2341%                                                                             %
2342%                                                                             %
2343%   S e t u p L i s t                                                         %
2344%                                                                             %
2345%                                                                             %
2346%                                                                             %
2347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2348%
2349%  Method SetupList returns the list of all the images linked by their
2350%  image->next and image->previous link lists for use with ImageMagick.  If
2351%  info is non-NULL, an info structure is returned in *info.  If
2352%  reference_vector is non-NULL,an array of SV* are returned in
2353%  *reference_vector.  Reference_vector is used when the images are going to be
2354%  replaced with new Image*'s.
2355%
2356%  The format of the SetupList routine is:
2357%
2358%      Image *SetupList(SV *reference,struct PackageInfo **info,
2359%        SV ***reference_vector,ExceptionInfo *exception)
2360%
2361%  A description of each parameter follows:
2362%
2363%    o list: a list of strings.
2364%
2365%    o string: a character string.
2366%
2367%    o exception: Return any errors or warnings in this structure.
2368%
2369*/
2370static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2371  SV ***reference_vector,ExceptionInfo *exception)
2372{
2373  Image
2374    *image;
2375
2376  ssize_t
2377    current,
2378    last;
2379
2380  if (reference_vector)
2381    *reference_vector=NULL;
2382  if (info)
2383    *info=NULL;
2384  current=0;
2385  last=0;
2386  image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2387  if (info && (SvTYPE(reference) == SVt_PVAV))
2388    *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2389      exception);
2390  return(image);
2391}
2392
2393/*
2394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2395%                                                                             %
2396%                                                                             %
2397%                                                                             %
2398%   s t r E Q c a s e                                                         %
2399%                                                                             %
2400%                                                                             %
2401%                                                                             %
2402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2403%
2404%  strEQcase() compares two strings and returns 0 if they are the
2405%  same or if the second string runs out first.  The comparison is case
2406%  insensitive.
2407%
2408%  The format of the strEQcase routine is:
2409%
2410%      ssize_t strEQcase(const char *p,const char *q)
2411%
2412%  A description of each parameter follows:
2413%
2414%    o p: a character string.
2415%
2416%    o q: a character string.
2417%
2418%
2419*/
2420static ssize_t strEQcase(const char *p,const char *q)
2421{
2422  char
2423    c;
2424
2425  ssize_t
2426    i;
2427
2428  for (i=0 ; (c=(*q)) != 0; i++)
2429  {
2430    if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2431        (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2432      return(0);
2433    p++;
2434    q++;
2435  }
2436  return(((*q == 0) && (*p == 0)) ? i : 0);
2437}
2438
2439/*
2440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2441%                                                                             %
2442%                                                                             %
2443%                                                                             %
2444%   I m a g e : : M a g i c k                                                 %
2445%                                                                             %
2446%                                                                             %
2447%                                                                             %
2448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2449%
2450%
2451*/
2452MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2453
2454PROTOTYPES: ENABLE
2455
2456BOOT:
2457  MagickCoreGenesis("PerlMagick",MagickFalse);
2458  SetWarningHandler(NULL);
2459  SetErrorHandler(NULL);
2460  magick_registry=NewSplayTree((int (*)(const void *,const void *))
2461    NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2462
2463void
2464UNLOAD()
2465  PPCODE:
2466  {
2467    if (magick_registry != (SplayTreeInfo *) NULL)
2468      magick_registry=DestroySplayTree(magick_registry);
2469    MagickCoreTerminus();
2470  }
2471
2472double
2473constant(name,argument)
2474  char *name
2475  ssize_t argument
2476
2477#
2478###############################################################################
2479#                                                                             #
2480#                                                                             #
2481#                                                                             #
2482#   A n i m a t e                                                             #
2483#                                                                             #
2484#                                                                             #
2485#                                                                             #
2486###############################################################################
2487#
2488#
2489void
2490Animate(ref,...)
2491  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2492  ALIAS:
2493    AnimateImage  = 1
2494    animate       = 2
2495    animateimage  = 3
2496  PPCODE:
2497  {
2498    ExceptionInfo
2499      *exception;
2500
2501    Image
2502      *image;
2503
2504    ssize_t
2505      i;
2506
2507    struct PackageInfo
2508      *info,
2509      *package_info;
2510
2511    SV
2512      *perl_exception,
2513      *reference;
2514
2515    PERL_UNUSED_VAR(ref);
2516    PERL_UNUSED_VAR(ix);
2517    exception=AcquireExceptionInfo();
2518    perl_exception=newSVpv("",0);
2519    package_info=(struct PackageInfo *) NULL;
2520    if (sv_isobject(ST(0)) == 0)
2521      {
2522        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2523          PackageName);
2524        goto PerlException;
2525      }
2526    reference=SvRV(ST(0));
2527    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2528    if (image == (Image *) NULL)
2529      {
2530        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2531          PackageName);
2532        goto PerlException;
2533      }
2534    package_info=ClonePackageInfo(info,exception);
2535    if (items == 2)
2536      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2537    else
2538      if (items > 2)
2539        for (i=2; i < items; i+=2)
2540          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2541            exception);
2542    (void) AnimateImages(package_info->image_info,image,exception);
2543    (void) CatchImageException(image);
2544
2545  PerlException:
2546    if (package_info != (struct PackageInfo *) NULL)
2547      DestroyPackageInfo(package_info);
2548    InheritPerlException(exception,perl_exception);
2549    exception=DestroyExceptionInfo(exception);
2550    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2551    SvPOK_on(perl_exception);
2552    ST(0)=sv_2mortal(perl_exception);
2553    XSRETURN(1);
2554  }
2555
2556#
2557###############################################################################
2558#                                                                             #
2559#                                                                             #
2560#                                                                             #
2561#   A p p e n d                                                               #
2562#                                                                             #
2563#                                                                             #
2564#                                                                             #
2565###############################################################################
2566#
2567#
2568void
2569Append(ref,...)
2570  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2571  ALIAS:
2572    AppendImage  = 1
2573    append       = 2
2574    appendimage  = 3
2575  PPCODE:
2576  {
2577    AV
2578      *av;
2579
2580    char
2581      *attribute;
2582
2583    ExceptionInfo
2584      *exception;
2585
2586    HV
2587      *hv;
2588
2589    Image
2590      *image;
2591
2592    ssize_t
2593      i;
2594
2595    ssize_t
2596      stack;
2597
2598    struct PackageInfo
2599      *info;
2600
2601    SV
2602      *av_reference,
2603      *perl_exception,
2604      *reference,
2605      *rv,
2606      *sv;
2607
2608    PERL_UNUSED_VAR(ref);
2609    PERL_UNUSED_VAR(ix);
2610    exception=AcquireExceptionInfo();
2611    perl_exception=newSVpv("",0);
2612    sv=NULL;
2613    attribute=NULL;
2614    av=NULL;
2615    if (sv_isobject(ST(0)) == 0)
2616      {
2617        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2618          PackageName);
2619        goto PerlException;
2620      }
2621    reference=SvRV(ST(0));
2622    hv=SvSTASH(reference);
2623    av=newAV();
2624    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2625    SvREFCNT_dec(av);
2626    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2627    if (image == (Image *) NULL)
2628      {
2629        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2630          PackageName);
2631        goto PerlException;
2632      }
2633    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2634    /*
2635      Get options.
2636    */
2637    stack=MagickTrue;
2638    for (i=2; i < items; i+=2)
2639    {
2640      attribute=(char *) SvPV(ST(i-1),na);
2641      switch (*attribute)
2642      {
2643        case 'S':
2644        case 's':
2645        {
2646          if (LocaleCompare(attribute,"stack") == 0)
2647            {
2648              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2649                SvPV(ST(i),na));
2650              if (stack < 0)
2651                {
2652                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
2653                    SvPV(ST(i),na));
2654                  return;
2655                }
2656              break;
2657            }
2658          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2659            attribute);
2660          break;
2661        }
2662        default:
2663        {
2664          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2665            attribute);
2666          break;
2667        }
2668      }
2669    }
2670    image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2671    if (image == (Image *) NULL)
2672      goto PerlException;
2673    for ( ; image; image=image->next)
2674    {
2675      AddImageToRegistry(sv,image);
2676      rv=newRV(sv);
2677      av_push(av,sv_bless(rv,hv));
2678      SvREFCNT_dec(sv);
2679    }
2680    exception=DestroyExceptionInfo(exception);
2681    ST(0)=av_reference;
2682    SvREFCNT_dec(perl_exception);
2683    XSRETURN(1);
2684
2685  PerlException:
2686    InheritPerlException(exception,perl_exception);
2687    exception=DestroyExceptionInfo(exception);
2688    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2689    SvPOK_on(perl_exception);
2690    ST(0)=sv_2mortal(perl_exception);
2691    XSRETURN(1);
2692  }
2693
2694#
2695###############################################################################
2696#                                                                             #
2697#                                                                             #
2698#                                                                             #
2699#   A v e r a g e                                                             #
2700#                                                                             #
2701#                                                                             #
2702#                                                                             #
2703###############################################################################
2704#
2705#
2706void
2707Average(ref)
2708  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2709  ALIAS:
2710    AverageImage   = 1
2711    average        = 2
2712    averageimage   = 3
2713  PPCODE:
2714  {
2715    AV
2716      *av;
2717
2718    char
2719      *p;
2720
2721    ExceptionInfo
2722      *exception;
2723
2724    HV
2725      *hv;
2726
2727    Image
2728      *image;
2729
2730    struct PackageInfo
2731      *info;
2732
2733    SV
2734      *perl_exception,
2735      *reference,
2736      *rv,
2737      *sv;
2738
2739    PERL_UNUSED_VAR(ref);
2740    PERL_UNUSED_VAR(ix);
2741    exception=AcquireExceptionInfo();
2742    perl_exception=newSVpv("",0);
2743    sv=NULL;
2744    if (sv_isobject(ST(0)) == 0)
2745      {
2746        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2747          PackageName);
2748        goto PerlException;
2749      }
2750    reference=SvRV(ST(0));
2751    hv=SvSTASH(reference);
2752    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2753    if (image == (Image *) NULL)
2754      {
2755        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2756          PackageName);
2757        goto PerlException;
2758      }
2759    image=EvaluateImages(image,MeanEvaluateOperator,exception);
2760    if (image == (Image *) NULL)
2761      goto PerlException;
2762    /*
2763      Create blessed Perl array for the returned image.
2764    */
2765    av=newAV();
2766    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2767    SvREFCNT_dec(av);
2768    AddImageToRegistry(sv,image);
2769    rv=newRV(sv);
2770    av_push(av,sv_bless(rv,hv));
2771    SvREFCNT_dec(sv);
2772    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2773    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2774      "average-%.*s",(int) (MagickPathExtent-9),
2775      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2776    (void) CopyMagickString(image->filename,info->image_info->filename,
2777      MagickPathExtent);
2778    SetImageInfo(info->image_info,0,exception);
2779    exception=DestroyExceptionInfo(exception);
2780    SvREFCNT_dec(perl_exception);
2781    XSRETURN(1);
2782
2783  PerlException:
2784    InheritPerlException(exception,perl_exception);
2785    exception=DestroyExceptionInfo(exception);
2786    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2787    SvPOK_on(perl_exception);
2788    ST(0)=sv_2mortal(perl_exception);
2789    XSRETURN(1);
2790  }
2791
2792#
2793###############################################################################
2794#                                                                             #
2795#                                                                             #
2796#                                                                             #
2797#   B l o b T o I m a g e                                                     #
2798#                                                                             #
2799#                                                                             #
2800#                                                                             #
2801###############################################################################
2802#
2803#
2804void
2805BlobToImage(ref,...)
2806  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2807  ALIAS:
2808    BlobToImage  = 1
2809    blobtoimage  = 2
2810    blobto       = 3
2811  PPCODE:
2812  {
2813    AV
2814      *av;
2815
2816    char
2817      **keep,
2818      **list;
2819
2820    ExceptionInfo
2821      *exception;
2822
2823    HV
2824      *hv;
2825
2826    Image
2827      *image;
2828
2829    char
2830      **p;
2831
2832    ssize_t
2833      i;
2834
2835    ssize_t
2836      ac,
2837      n,
2838      number_images;
2839
2840    STRLEN
2841      *length;
2842
2843    struct PackageInfo
2844      *info;
2845
2846    SV
2847      *perl_exception,
2848      *reference,
2849      *rv,
2850      *sv;
2851
2852    PERL_UNUSED_VAR(ref);
2853    PERL_UNUSED_VAR(ix);
2854    exception=AcquireExceptionInfo();
2855    perl_exception=newSVpv("",0);
2856    sv=NULL;
2857    number_images=0;
2858    ac=(items < 2) ? 1 : items-1;
2859    length=(STRLEN *) NULL;
2860    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2861    if (list == (char **) NULL)
2862      {
2863        ThrowPerlException(exception,ResourceLimitError,
2864          "MemoryAllocationFailed",PackageName);
2865        goto PerlException;
2866      }
2867    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2868    if (length == (STRLEN *) NULL)
2869      {
2870        ThrowPerlException(exception,ResourceLimitError,
2871          "MemoryAllocationFailed",PackageName);
2872        goto PerlException;
2873      }
2874    if (sv_isobject(ST(0)) == 0)
2875      {
2876        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2877          PackageName);
2878        goto PerlException;
2879      }
2880    reference=SvRV(ST(0));
2881    hv=SvSTASH(reference);
2882    if (SvTYPE(reference) != SVt_PVAV)
2883      {
2884        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2885          PackageName);
2886        goto PerlException;
2887      }
2888    av=(AV *) reference;
2889    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2890      exception);
2891    n=1;
2892    if (items <= 1)
2893      {
2894        ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2895        goto PerlException;
2896      }
2897    for (n=0, i=0; i < ac; i++)
2898    {
2899      list[n]=(char *) (SvPV(ST(i+1),length[n]));
2900      if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2901        {
2902          list[n]=(char *) (SvPV(ST(i+2),length[n]));
2903          continue;
2904        }
2905      n++;
2906    }
2907    list[n]=(char *) NULL;
2908    keep=list;
2909    for (i=number_images=0; i < n; i++)
2910    {
2911      image=BlobToImage(info->image_info,list[i],length[i],exception);
2912      if (image == (Image *) NULL)
2913        break;
2914      for ( ; image; image=image->next)
2915      {
2916        AddImageToRegistry(sv,image);
2917        rv=newRV(sv);
2918        av_push(av,sv_bless(rv,hv));
2919        SvREFCNT_dec(sv);
2920        number_images++;
2921      }
2922    }
2923    /*
2924      Free resources.
2925    */
2926    for (i=0; i < n; i++)
2927      if (list[i] != (char *) NULL)
2928        for (p=keep; list[i] != *p++; )
2929          if (*p == (char *) NULL)
2930            {
2931              list[i]=(char *) RelinquishMagickMemory(list[i]);
2932              break;
2933            }
2934
2935  PerlException:
2936    if (list)
2937      list=(char **) RelinquishMagickMemory(list);
2938    if (length)
2939      length=(STRLEN *) RelinquishMagickMemory(length);
2940    InheritPerlException(exception,perl_exception);
2941    exception=DestroyExceptionInfo(exception);
2942    sv_setiv(perl_exception,(IV) number_images);
2943    SvPOK_on(perl_exception);
2944    ST(0)=sv_2mortal(perl_exception);
2945    XSRETURN(1);
2946  }
2947
2948#
2949###############################################################################
2950#                                                                             #
2951#                                                                             #
2952#                                                                             #
2953#   C h a n n e l F x                                                         #
2954#                                                                             #
2955#                                                                             #
2956#                                                                             #
2957###############################################################################
2958#
2959#
2960void
2961ChannelFx(ref,...)
2962  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2963  ALIAS:
2964    ChannelFxImage  = 1
2965    channelfx       = 2
2966    channelfximage  = 3
2967  PPCODE:
2968  {
2969    AV
2970      *av;
2971
2972    char
2973      *attribute,
2974      expression[MagickPathExtent];
2975
2976    ChannelType
2977      channel,
2978      channel_mask;
2979
2980    ExceptionInfo
2981      *exception;
2982
2983    HV
2984      *hv;
2985
2986    Image
2987      *image;
2988
2989    ssize_t
2990      i;
2991
2992    struct PackageInfo
2993      *info;
2994
2995    SV
2996      *av_reference,
2997      *perl_exception,
2998      *reference,
2999      *rv,
3000      *sv;
3001
3002    PERL_UNUSED_VAR(ref);
3003    PERL_UNUSED_VAR(ix);
3004    exception=AcquireExceptionInfo();
3005    perl_exception=newSVpv("",0);
3006    sv=NULL;
3007    attribute=NULL;
3008    av=NULL;
3009    if (sv_isobject(ST(0)) == 0)
3010      {
3011        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3012          PackageName);
3013        goto PerlException;
3014      }
3015    reference=SvRV(ST(0));
3016    hv=SvSTASH(reference);
3017    av=newAV();
3018    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3019    SvREFCNT_dec(av);
3020    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3021    if (image == (Image *) NULL)
3022      {
3023        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3024          PackageName);
3025        goto PerlException;
3026      }
3027    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3028    /*
3029      Get options.
3030    */
3031    channel=DefaultChannels;
3032    (void) CopyMagickString(expression,"u",MagickPathExtent);
3033    if (items == 2)
3034      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
3035    else
3036      for (i=2; i < items; i+=2)
3037      {
3038        attribute=(char *) SvPV(ST(i-1),na);
3039        switch (*attribute)
3040        {
3041          case 'C':
3042          case 'c':
3043          {
3044            if (LocaleCompare(attribute,"channel") == 0)
3045              {
3046                ssize_t
3047                  option;
3048
3049                option=ParseChannelOption(SvPV(ST(i),na));
3050                if (option < 0)
3051                  {
3052                    ThrowPerlException(exception,OptionError,
3053                      "UnrecognizedType",SvPV(ST(i),na));
3054                    return;
3055                  }
3056                channel=(ChannelType) option;
3057                break;
3058              }
3059            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3060              attribute);
3061            break;
3062          }
3063          case 'E':
3064          case 'e':
3065          {
3066            if (LocaleCompare(attribute,"expression") == 0)
3067              {
3068                (void) CopyMagickString(expression,SvPV(ST(i),na),
3069                  MagickPathExtent);
3070                break;
3071              }
3072            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3073              attribute);
3074            break;
3075          }
3076          default:
3077          {
3078            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3079              attribute);
3080            break;
3081          }
3082        }
3083      }
3084    channel_mask=SetImageChannelMask(image,channel);
3085    image=ChannelFxImage(image,expression,exception);
3086    if (image != (Image *) NULL)
3087      (void) SetImageChannelMask(image,channel_mask);
3088    if (image == (Image *) NULL)
3089      goto PerlException;
3090    for ( ; image; image=image->next)
3091    {
3092      AddImageToRegistry(sv,image);
3093      rv=newRV(sv);
3094      av_push(av,sv_bless(rv,hv));
3095      SvREFCNT_dec(sv);
3096    }
3097    exception=DestroyExceptionInfo(exception);
3098    ST(0)=av_reference;
3099    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3100    XSRETURN(1);
3101
3102  PerlException:
3103    InheritPerlException(exception,perl_exception);
3104    exception=DestroyExceptionInfo(exception);
3105    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3106    SvPOK_on(perl_exception);
3107    ST(0)=sv_2mortal(perl_exception);
3108    XSRETURN(1);
3109  }
3110
3111#
3112###############################################################################
3113#                                                                             #
3114#                                                                             #
3115#                                                                             #
3116#   C l o n e                                                                 #
3117#                                                                             #
3118#                                                                             #
3119#                                                                             #
3120###############################################################################
3121#
3122#
3123void
3124Clone(ref)
3125  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3126  ALIAS:
3127    CopyImage   = 1
3128    copy        = 2
3129    copyimage   = 3
3130    CloneImage  = 4
3131    clone       = 5
3132    cloneimage  = 6
3133    Clone       = 7
3134  PPCODE:
3135  {
3136    AV
3137      *av;
3138
3139    ExceptionInfo
3140      *exception;
3141
3142    HV
3143      *hv;
3144
3145    Image
3146      *clone,
3147      *image;
3148
3149    struct PackageInfo
3150      *info;
3151
3152    SV
3153      *perl_exception,
3154      *reference,
3155      *rv,
3156      *sv;
3157
3158    PERL_UNUSED_VAR(ref);
3159    PERL_UNUSED_VAR(ix);
3160    exception=AcquireExceptionInfo();
3161    perl_exception=newSVpv("",0);
3162    sv=NULL;
3163    if (sv_isobject(ST(0)) == 0)
3164      {
3165        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3166          PackageName);
3167        goto PerlException;
3168      }
3169    reference=SvRV(ST(0));
3170    hv=SvSTASH(reference);
3171    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3172    if (image == (Image *) NULL)
3173      {
3174        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3175          PackageName);
3176        goto PerlException;
3177      }
3178    /*
3179      Create blessed Perl array for the returned image.
3180    */
3181    av=newAV();
3182    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3183    SvREFCNT_dec(av);
3184    for ( ; image; image=image->next)
3185    {
3186      clone=CloneImage(image,0,0,MagickTrue,exception);
3187      if (clone == (Image *) NULL)
3188        break;
3189      AddImageToRegistry(sv,clone);
3190      rv=newRV(sv);
3191      av_push(av,sv_bless(rv,hv));
3192      SvREFCNT_dec(sv);
3193    }
3194    exception=DestroyExceptionInfo(exception);
3195    SvREFCNT_dec(perl_exception);
3196    XSRETURN(1);
3197
3198  PerlException:
3199    InheritPerlException(exception,perl_exception);
3200    exception=DestroyExceptionInfo(exception);
3201    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3202    SvPOK_on(perl_exception);
3203    ST(0)=sv_2mortal(perl_exception);
3204    XSRETURN(1);
3205  }
3206
3207#
3208###############################################################################
3209#                                                                             #
3210#                                                                             #
3211#                                                                             #
3212#   C L O N E                                                                 #
3213#                                                                             #
3214#                                                                             #
3215#                                                                             #
3216###############################################################################
3217#
3218#
3219void
3220CLONE(ref,...)
3221  SV *ref;
3222  CODE:
3223  {
3224    PERL_UNUSED_VAR(ref);
3225    if (magick_registry != (SplayTreeInfo *) NULL)
3226      {
3227        Image
3228          *p;
3229
3230        ResetSplayTreeIterator(magick_registry);
3231        p=(Image *) GetNextKeyInSplayTree(magick_registry);
3232        while (p != (Image *) NULL)
3233        {
3234          ReferenceImage(p);
3235          p=(Image *) GetNextKeyInSplayTree(magick_registry);
3236        }
3237      }
3238  }
3239
3240#
3241###############################################################################
3242#                                                                             #
3243#                                                                             #
3244#                                                                             #
3245#   C o a l e s c e                                                           #
3246#                                                                             #
3247#                                                                             #
3248#                                                                             #
3249###############################################################################
3250#
3251#
3252void
3253Coalesce(ref)
3254  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3255  ALIAS:
3256    CoalesceImage   = 1
3257    coalesce        = 2
3258    coalesceimage   = 3
3259  PPCODE:
3260  {
3261    AV
3262      *av;
3263
3264    ExceptionInfo
3265      *exception;
3266
3267    HV
3268      *hv;
3269
3270    Image
3271      *image;
3272
3273    struct PackageInfo
3274      *info;
3275
3276    SV
3277      *av_reference,
3278      *perl_exception,
3279      *reference,
3280      *rv,
3281      *sv;
3282
3283    PERL_UNUSED_VAR(ref);
3284    PERL_UNUSED_VAR(ix);
3285    exception=AcquireExceptionInfo();
3286    perl_exception=newSVpv("",0);
3287    sv=NULL;
3288    if (sv_isobject(ST(0)) == 0)
3289      {
3290        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3291          PackageName);
3292        goto PerlException;
3293      }
3294    reference=SvRV(ST(0));
3295    hv=SvSTASH(reference);
3296    av=newAV();
3297    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3298    SvREFCNT_dec(av);
3299    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3300    if (image == (Image *) NULL)
3301      {
3302        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3303          PackageName);
3304        goto PerlException;
3305      }
3306    image=CoalesceImages(image,exception);
3307    if (image == (Image *) NULL)
3308      goto PerlException;
3309    for ( ; image; image=image->next)
3310    {
3311      AddImageToRegistry(sv,image);
3312      rv=newRV(sv);
3313      av_push(av,sv_bless(rv,hv));
3314      SvREFCNT_dec(sv);
3315    }
3316    exception=DestroyExceptionInfo(exception);
3317    ST(0)=av_reference;
3318    SvREFCNT_dec(perl_exception);
3319    XSRETURN(1);
3320
3321  PerlException:
3322    InheritPerlException(exception,perl_exception);
3323    exception=DestroyExceptionInfo(exception);
3324    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3325    SvPOK_on(perl_exception);
3326    ST(0)=sv_2mortal(perl_exception);
3327    XSRETURN(1);
3328  }
3329
3330#
3331###############################################################################
3332#                                                                             #
3333#                                                                             #
3334#                                                                             #
3335#   C o m p a r e                                                             #
3336#                                                                             #
3337#                                                                             #
3338#                                                                             #
3339###############################################################################
3340#
3341#
3342void
3343Compare(ref,...)
3344  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3345  ALIAS:
3346    CompareImages = 1
3347    compare      = 2
3348    compareimage = 3
3349  PPCODE:
3350  {
3351    AV
3352      *av;
3353
3354    char
3355      *attribute;
3356
3357    double
3358      distortion;
3359
3360    ExceptionInfo
3361      *exception;
3362
3363    HV
3364      *hv;
3365
3366    Image
3367      *difference_image,
3368      *image,
3369      *reconstruct_image;
3370
3371    MetricType
3372      metric;
3373
3374    ssize_t
3375      i;
3376
3377    ssize_t
3378      option;
3379
3380    struct PackageInfo
3381      *info;
3382
3383    SV
3384      *av_reference,
3385      *perl_exception,
3386      *reference,
3387      *rv,
3388      *sv;
3389
3390    PERL_UNUSED_VAR(ref);
3391    PERL_UNUSED_VAR(ix);
3392    exception=AcquireExceptionInfo();
3393    perl_exception=newSVpv("",0);
3394    sv=NULL;
3395    av=NULL;
3396    attribute=NULL;
3397    if (sv_isobject(ST(0)) == 0)
3398      {
3399        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3400          PackageName);
3401        goto PerlException;
3402      }
3403    reference=SvRV(ST(0));
3404    hv=SvSTASH(reference);
3405    av=newAV();
3406    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3407    SvREFCNT_dec(av);
3408    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3409    if (image == (Image *) NULL)
3410      {
3411        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3412          PackageName);
3413        goto PerlException;
3414      }
3415    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3416    /*
3417      Get attribute.
3418    */
3419    reconstruct_image=image;
3420    metric=RootMeanSquaredErrorMetric;
3421    for (i=2; i < items; i+=2)
3422    {
3423      attribute=(char *) SvPV(ST(i-1),na);
3424      switch (*attribute)
3425      {
3426        case 'C':
3427        case 'c':
3428        {
3429          if (LocaleCompare(attribute,"channel") == 0)
3430            {
3431              ssize_t
3432                option;
3433
3434              option=ParseChannelOption(SvPV(ST(i),na));
3435              if (option < 0)
3436                {
3437                  ThrowPerlException(exception,OptionError,
3438                    "UnrecognizedType",SvPV(ST(i),na));
3439                  return;
3440                }
3441              (void) SetPixelChannelMask(image,(ChannelType) option);
3442              break;
3443            }
3444          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3445            attribute);
3446          break;
3447        }
3448        case 'F':
3449        case 'f':
3450        {
3451          if (LocaleCompare(attribute,"fuzz") == 0)
3452            {
3453              image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3454              break;
3455            }
3456          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3457            attribute);
3458          break;
3459        }
3460        case 'I':
3461        case 'i':
3462        {
3463          if (LocaleCompare(attribute,"image") == 0)
3464            {
3465              reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3466                (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3467              break;
3468            }
3469          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3470            attribute);
3471          break;
3472        }
3473        case 'M':
3474        case 'm':
3475        {
3476          if (LocaleCompare(attribute,"metric") == 0)
3477            {
3478              option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3479                SvPV(ST(i),na));
3480              if (option < 0)
3481                {
3482                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3483                    SvPV(ST(i),na));
3484                  break;
3485                }
3486              metric=(MetricType) option;
3487              break;
3488            }
3489          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3490            attribute);
3491          break;
3492        }
3493        default:
3494        {
3495          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3496            attribute);
3497          break;
3498        }
3499      }
3500    }
3501    difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3502      exception);
3503    if (difference_image != (Image *) NULL)
3504      {
3505        difference_image->error.mean_error_per_pixel=distortion;
3506        AddImageToRegistry(sv,difference_image);
3507        rv=newRV(sv);
3508        av_push(av,sv_bless(rv,hv));
3509        SvREFCNT_dec(sv);
3510      }
3511    exception=DestroyExceptionInfo(exception);
3512    ST(0)=av_reference;
3513    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3514    XSRETURN(1);
3515
3516  PerlException:
3517    InheritPerlException(exception,perl_exception);
3518    exception=DestroyExceptionInfo(exception);
3519    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3520    SvPOK_on(perl_exception);
3521    ST(0)=sv_2mortal(perl_exception);
3522    XSRETURN(1);
3523  }
3524
3525#
3526###############################################################################
3527#                                                                             #
3528#                                                                             #
3529#                                                                             #
3530#   C o m p l e x I m a g e s                                                 #
3531#                                                                             #
3532#                                                                             #
3533#                                                                             #
3534###############################################################################
3535#
3536#
3537void
3538ComplexImages(ref,...)
3539  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3540  ALIAS:
3541    ComplexImages   = 1
3542    compleximages   = 2
3543  PPCODE:
3544  {
3545    AV
3546      *av;
3547
3548    char
3549      *attribute,
3550      *p;
3551
3552    ComplexOperator
3553      op;
3554
3555    ExceptionInfo
3556      *exception;
3557
3558    HV
3559      *hv;
3560
3561    Image
3562      *image;
3563
3564    ssize_t
3565      i;
3566
3567    struct PackageInfo
3568      *info;
3569
3570    SV
3571      *perl_exception,
3572      *reference,
3573      *rv,
3574      *sv;
3575
3576    PERL_UNUSED_VAR(ref);
3577    PERL_UNUSED_VAR(ix);
3578    exception=AcquireExceptionInfo();
3579    perl_exception=newSVpv("",0);
3580    sv=NULL;
3581    if (sv_isobject(ST(0)) == 0)
3582      {
3583        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3584          PackageName);
3585        goto PerlException;
3586      }
3587    reference=SvRV(ST(0));
3588    hv=SvSTASH(reference);
3589    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3590    if (image == (Image *) NULL)
3591      {
3592        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3593          PackageName);
3594        goto PerlException;
3595      }
3596    op=UndefinedComplexOperator;
3597    if (items == 2)
3598      {
3599        ssize_t
3600          in;
3601
3602        in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3603          SvPV(ST(1),na));
3604        if (in < 0)
3605          {
3606            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3607              SvPV(ST(1),na));
3608            return;
3609          }
3610        op=(ComplexOperator) in;
3611      }
3612    else
3613      for (i=2; i < items; i+=2)
3614      {
3615        attribute=(char *) SvPV(ST(i-1),na);
3616        switch (*attribute)
3617        {
3618          case 'O':
3619          case 'o':
3620          {
3621            if (LocaleCompare(attribute,"operator") == 0)
3622              {
3623                ssize_t
3624                  in;
3625
3626                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3627                  MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3628                if (in < 0)
3629                  {
3630                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
3631                      SvPV(ST(i),na));
3632                    return;
3633                  }
3634                op=(ComplexOperator) in;
3635                break;
3636              }
3637            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3638              attribute);
3639            break;
3640          }
3641          default:
3642          {
3643            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3644              attribute);
3645            break;
3646          }
3647        }
3648      }
3649    image=ComplexImages(image,op,exception);
3650    if (image == (Image *) NULL)
3651      goto PerlException;
3652    /*
3653      Create blessed Perl array for the returned image.
3654    */
3655    av=newAV();
3656    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3657    SvREFCNT_dec(av);
3658    AddImageToRegistry(sv,image);
3659    rv=newRV(sv);
3660    av_push(av,sv_bless(rv,hv));
3661    SvREFCNT_dec(sv);
3662    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3663    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3664      "complex-%.*s",(int) (MagickPathExtent-9),
3665      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3666    (void) CopyMagickString(image->filename,info->image_info->filename,
3667      MagickPathExtent);
3668    SetImageInfo(info->image_info,0,exception);
3669    exception=DestroyExceptionInfo(exception);
3670    SvREFCNT_dec(perl_exception);
3671    XSRETURN(1);
3672
3673  PerlException:
3674    InheritPerlException(exception,perl_exception);
3675    exception=DestroyExceptionInfo(exception);
3676    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3677    SvPOK_on(perl_exception);
3678    ST(0)=sv_2mortal(perl_exception);
3679    XSRETURN(1);
3680  }
3681
3682#
3683###############################################################################
3684#                                                                             #
3685#                                                                             #
3686#                                                                             #
3687#   C o m p a r e L a y e r s                                                 #
3688#                                                                             #
3689#                                                                             #
3690#                                                                             #
3691###############################################################################
3692#
3693#
3694void
3695CompareLayers(ref,...)
3696  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3697  ALIAS:
3698    CompareImagesLayers   = 1
3699    comparelayers        = 2
3700    compareimagelayers   = 3
3701  PPCODE:
3702  {
3703    AV
3704      *av;
3705
3706    char
3707      *attribute;
3708
3709    ExceptionInfo
3710      *exception;
3711
3712    HV
3713      *hv;
3714
3715    Image
3716      *image;
3717
3718    LayerMethod
3719      method;
3720
3721    ssize_t
3722      i;
3723
3724    ssize_t
3725      option;
3726
3727    struct PackageInfo
3728      *info;
3729
3730    SV
3731      *av_reference,
3732      *perl_exception,
3733      *reference,
3734      *rv,
3735      *sv;
3736
3737    PERL_UNUSED_VAR(ref);
3738    PERL_UNUSED_VAR(ix);
3739    exception=AcquireExceptionInfo();
3740    perl_exception=newSVpv("",0);
3741    sv=NULL;
3742    if (sv_isobject(ST(0)) == 0)
3743      {
3744        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3745          PackageName);
3746        goto PerlException;
3747      }
3748    reference=SvRV(ST(0));
3749    hv=SvSTASH(reference);
3750    av=newAV();
3751    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3752    SvREFCNT_dec(av);
3753    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3754    if (image == (Image *) NULL)
3755      {
3756        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3757          PackageName);
3758        goto PerlException;
3759      }
3760    method=CompareAnyLayer;
3761    for (i=2; i < items; i+=2)
3762    {
3763      attribute=(char *) SvPV(ST(i-1),na);
3764      switch (*attribute)
3765      {
3766        case 'M':
3767        case 'm':
3768        {
3769          if (LocaleCompare(attribute,"method") == 0)
3770            {
3771              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3772                SvPV(ST(i),na));
3773              if (option < 0)
3774                {
3775                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3776                    SvPV(ST(i),na));
3777                  break;
3778                }
3779               method=(LayerMethod) option;
3780              break;
3781            }
3782          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3783            attribute);
3784          break;
3785        }
3786        default:
3787        {
3788          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3789            attribute);
3790          break;
3791        }
3792      }
3793    }
3794    image=CompareImagesLayers(image,method,exception);
3795    if (image == (Image *) NULL)
3796      goto PerlException;
3797    for ( ; image; image=image->next)
3798    {
3799      AddImageToRegistry(sv,image);
3800      rv=newRV(sv);
3801      av_push(av,sv_bless(rv,hv));
3802      SvREFCNT_dec(sv);
3803    }
3804    exception=DestroyExceptionInfo(exception);
3805    ST(0)=av_reference;
3806    SvREFCNT_dec(perl_exception);
3807    XSRETURN(1);
3808
3809  PerlException:
3810    InheritPerlException(exception,perl_exception);
3811    exception=DestroyExceptionInfo(exception);
3812    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3813    SvPOK_on(perl_exception);
3814    ST(0)=sv_2mortal(perl_exception);
3815    XSRETURN(1);
3816  }
3817
3818#
3819###############################################################################
3820#                                                                             #
3821#                                                                             #
3822#                                                                             #
3823#   D e s t r o y                                                             #
3824#                                                                             #
3825#                                                                             #
3826#                                                                             #
3827###############################################################################
3828#
3829#
3830void
3831DESTROY(ref)
3832  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3833  PPCODE:
3834  {
3835    SV
3836      *reference;
3837
3838    PERL_UNUSED_VAR(ref);
3839    if (sv_isobject(ST(0)) == 0)
3840      croak("ReferenceIsNotMyType");
3841    reference=SvRV(ST(0));
3842    switch (SvTYPE(reference))
3843    {
3844      case SVt_PVAV:
3845      {
3846        char
3847          message[MagickPathExtent];
3848
3849        const SV
3850          *key;
3851
3852        HV
3853          *hv;
3854
3855        GV
3856          **gvp;
3857
3858        struct PackageInfo
3859          *info;
3860
3861        SV
3862          *sv;
3863
3864        /*
3865          Array (AV *) reference
3866        */
3867        (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3868          XS_VERSION,reference);
3869        hv=gv_stashpv(PackageName, FALSE);
3870        if (!hv)
3871          break;
3872        gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3873        if (!gvp)
3874          break;
3875        sv=GvSV(*gvp);
3876        if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3877          {
3878            info=INT2PTR(struct PackageInfo *,SvIV(sv));
3879            DestroyPackageInfo(info);
3880          }
3881        key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3882        (void) key;
3883        break;
3884      }
3885      case SVt_PVMG:
3886      {
3887        Image
3888          *image;
3889
3890        /*
3891          Blessed scalar = (Image *) SvIV(reference)
3892        */
3893        image=INT2PTR(Image *,SvIV(reference));
3894        if (image != (Image *) NULL)
3895          DeleteImageFromRegistry(reference,image);
3896        break;
3897      }
3898      default:
3899        break;
3900    }
3901  }
3902
3903#
3904###############################################################################
3905#                                                                             #
3906#                                                                             #
3907#                                                                             #
3908#   D i s p l a y                                                             #
3909#                                                                             #
3910#                                                                             #
3911#                                                                             #
3912###############################################################################
3913#
3914#
3915void
3916Display(ref,...)
3917  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3918  ALIAS:
3919    DisplayImage  = 1
3920    display       = 2
3921    displayimage  = 3
3922  PPCODE:
3923  {
3924    ExceptionInfo
3925      *exception;
3926
3927    Image
3928      *image;
3929
3930    ssize_t
3931      i;
3932
3933    struct PackageInfo
3934      *info,
3935      *package_info;
3936
3937    SV
3938      *perl_exception,
3939      *reference;
3940
3941    PERL_UNUSED_VAR(ref);
3942    PERL_UNUSED_VAR(ix);
3943    exception=AcquireExceptionInfo();
3944    perl_exception=newSVpv("",0);
3945    package_info=(struct PackageInfo *) NULL;
3946    if (sv_isobject(ST(0)) == 0)
3947      {
3948        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3949          PackageName);
3950        goto PerlException;
3951      }
3952    reference=SvRV(ST(0));
3953    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3954    if (image == (Image *) NULL)
3955      {
3956        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3957          PackageName);
3958        goto PerlException;
3959      }
3960    package_info=ClonePackageInfo(info,exception);
3961    if (items == 2)
3962      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3963    else
3964      if (items > 2)
3965        for (i=2; i < items; i+=2)
3966          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3967            exception);
3968    (void) DisplayImages(package_info->image_info,image,exception);
3969    (void) CatchImageException(image);
3970
3971  PerlException:
3972    if (package_info != (struct PackageInfo *) NULL)
3973      DestroyPackageInfo(package_info);
3974    InheritPerlException(exception,perl_exception);
3975    exception=DestroyExceptionInfo(exception);
3976    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3977    SvPOK_on(perl_exception);
3978    ST(0)=sv_2mortal(perl_exception);
3979    XSRETURN(1);
3980  }
3981
3982#
3983###############################################################################
3984#                                                                             #
3985#                                                                             #
3986#                                                                             #
3987#   E v a l u a t e I m a g e s                                               #
3988#                                                                             #
3989#                                                                             #
3990#                                                                             #
3991###############################################################################
3992#
3993#
3994void
3995EvaluateImages(ref,...)
3996  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3997  ALIAS:
3998    EvaluateImages   = 1
3999    evaluateimages   = 2
4000  PPCODE:
4001  {
4002    AV
4003      *av;
4004
4005    char
4006      *attribute,
4007      *p;
4008
4009    ExceptionInfo
4010      *exception;
4011
4012    HV
4013      *hv;
4014
4015    Image
4016      *image;
4017
4018    MagickEvaluateOperator
4019      op;
4020
4021    ssize_t
4022      i;
4023
4024    struct PackageInfo
4025      *info;
4026
4027    SV
4028      *perl_exception,
4029      *reference,
4030      *rv,
4031      *sv;
4032
4033    PERL_UNUSED_VAR(ref);
4034    PERL_UNUSED_VAR(ix);
4035    exception=AcquireExceptionInfo();
4036    perl_exception=newSVpv("",0);
4037    sv=NULL;
4038    if (sv_isobject(ST(0)) == 0)
4039      {
4040        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4041          PackageName);
4042        goto PerlException;
4043      }
4044    reference=SvRV(ST(0));
4045    hv=SvSTASH(reference);
4046    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4047    if (image == (Image *) NULL)
4048      {
4049        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4050          PackageName);
4051        goto PerlException;
4052      }
4053    op=MeanEvaluateOperator;
4054    if (items == 2)
4055      {
4056        ssize_t
4057          in;
4058
4059        in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4060          SvPV(ST(1),na));
4061        if (in < 0)
4062          {
4063            ThrowPerlException(exception,OptionError,"UnrecognizedType",
4064              SvPV(ST(1),na));
4065            return;
4066          }
4067        op=(MagickEvaluateOperator) in;
4068      }
4069    else
4070      for (i=2; i < items; i+=2)
4071      {
4072        attribute=(char *) SvPV(ST(i-1),na);
4073        switch (*attribute)
4074        {
4075          case 'O':
4076          case 'o':
4077          {
4078            if (LocaleCompare(attribute,"operator") == 0)
4079              {
4080                ssize_t
4081                  in;
4082
4083                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4084                  MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4085                if (in < 0)
4086                  {
4087                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
4088                      SvPV(ST(i),na));
4089                    return;
4090                  }
4091                op=(MagickEvaluateOperator) in;
4092                break;
4093              }
4094            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4095              attribute);
4096            break;
4097          }
4098          default:
4099          {
4100            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4101              attribute);
4102            break;
4103          }
4104        }
4105      }
4106    image=EvaluateImages(image,op,exception);
4107    if (image == (Image *) NULL)
4108      goto PerlException;
4109    /*
4110      Create blessed Perl array for the returned image.
4111    */
4112    av=newAV();
4113    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4114    SvREFCNT_dec(av);
4115    AddImageToRegistry(sv,image);
4116    rv=newRV(sv);
4117    av_push(av,sv_bless(rv,hv));
4118    SvREFCNT_dec(sv);
4119    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4120    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4121      "evaluate-%.*s",(int) (MagickPathExtent-9),
4122      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4123    (void) CopyMagickString(image->filename,info->image_info->filename,
4124      MagickPathExtent);
4125    SetImageInfo(info->image_info,0,exception);
4126    exception=DestroyExceptionInfo(exception);
4127    SvREFCNT_dec(perl_exception);
4128    XSRETURN(1);
4129
4130  PerlException:
4131    InheritPerlException(exception,perl_exception);
4132    exception=DestroyExceptionInfo(exception);
4133    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4134    SvPOK_on(perl_exception);
4135    ST(0)=sv_2mortal(perl_exception);
4136    XSRETURN(1);
4137  }
4138
4139#
4140###############################################################################
4141#                                                                             #
4142#                                                                             #
4143#                                                                             #
4144#   F e a t u r e s                                                           #
4145#                                                                             #
4146#                                                                             #
4147#                                                                             #
4148###############################################################################
4149#
4150#
4151void
4152Features(ref,...)
4153  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4154  ALIAS:
4155    FeaturesImage = 1
4156    features      = 2
4157    featuresimage = 3
4158  PPCODE:
4159  {
4160#define ChannelFeatures(channel,direction) \
4161{ \
4162  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4163    channel_features[channel].angular_second_moment[direction]); \
4164  PUSHs(sv_2mortal(newSVpv(message,0))); \
4165  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4166    channel_features[channel].contrast[direction]); \
4167  PUSHs(sv_2mortal(newSVpv(message,0))); \
4168  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4169    channel_features[channel].contrast[direction]); \
4170  PUSHs(sv_2mortal(newSVpv(message,0))); \
4171  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4172    channel_features[channel].variance_sum_of_squares[direction]); \
4173  PUSHs(sv_2mortal(newSVpv(message,0))); \
4174  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4175    channel_features[channel].inverse_difference_moment[direction]); \
4176  PUSHs(sv_2mortal(newSVpv(message,0))); \
4177  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4178    channel_features[channel].sum_average[direction]); \
4179  PUSHs(sv_2mortal(newSVpv(message,0))); \
4180  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4181    channel_features[channel].sum_variance[direction]); \
4182  PUSHs(sv_2mortal(newSVpv(message,0))); \
4183  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4184    channel_features[channel].sum_entropy[direction]); \
4185  PUSHs(sv_2mortal(newSVpv(message,0))); \
4186  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4187    channel_features[channel].entropy[direction]); \
4188  PUSHs(sv_2mortal(newSVpv(message,0))); \
4189  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4190    channel_features[channel].difference_variance[direction]); \
4191  PUSHs(sv_2mortal(newSVpv(message,0))); \
4192  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4193    channel_features[channel].difference_entropy[direction]); \
4194  PUSHs(sv_2mortal(newSVpv(message,0))); \
4195  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4196    channel_features[channel].measure_of_correlation_1[direction]); \
4197  PUSHs(sv_2mortal(newSVpv(message,0))); \
4198  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4199    channel_features[channel].measure_of_correlation_2[direction]); \
4200  PUSHs(sv_2mortal(newSVpv(message,0))); \
4201  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4202    channel_features[channel].maximum_correlation_coefficient[direction]); \
4203  PUSHs(sv_2mortal(newSVpv(message,0))); \
4204}
4205
4206    AV
4207      *av;
4208
4209    char
4210      *attribute,
4211      message[MagickPathExtent];
4212
4213    ChannelFeatures
4214      *channel_features;
4215
4216    double
4217      distance;
4218
4219    ExceptionInfo
4220      *exception;
4221
4222    Image
4223      *image;
4224
4225    ssize_t
4226      i;
4227
4228    ssize_t
4229      count;
4230
4231    struct PackageInfo
4232      *info;
4233
4234    SV
4235      *perl_exception,
4236      *reference;
4237
4238    PERL_UNUSED_VAR(ref);
4239    PERL_UNUSED_VAR(ix);
4240    exception=AcquireExceptionInfo();
4241    perl_exception=newSVpv("",0);
4242    av=NULL;
4243    if (sv_isobject(ST(0)) == 0)
4244      {
4245        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4246          PackageName);
4247        goto PerlException;
4248      }
4249    reference=SvRV(ST(0));
4250    av=newAV();
4251    SvREFCNT_dec(av);
4252    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4253    if (image == (Image *) NULL)
4254      {
4255        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4256          PackageName);
4257        goto PerlException;
4258      }
4259    distance=1.0;
4260    for (i=2; i < items; i+=2)
4261    {
4262      attribute=(char *) SvPV(ST(i-1),na);
4263      switch (*attribute)
4264      {
4265        case 'D':
4266        case 'd':
4267        {
4268          if (LocaleCompare(attribute,"distance") == 0)
4269            {
4270              distance=StringToLong((char *) SvPV(ST(1),na));
4271              break;
4272            }
4273          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4274            attribute);
4275          break;
4276        }
4277        default:
4278        {
4279          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4280            attribute);
4281          break;
4282        }
4283      }
4284    }
4285    count=0;
4286    for ( ; image; image=image->next)
4287    {
4288      ssize_t
4289        j;
4290
4291      channel_features=GetImageFeatures(image,distance,exception);
4292      if (channel_features == (ChannelFeatures *) NULL)
4293        continue;
4294      count++;
4295      for (j=0; j < 4; j++)
4296      {
4297        for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4298        {
4299          PixelChannel channel=GetPixelChannelChannel(image,i);
4300          PixelTrait traits=GetPixelChannelTraits(image,channel);
4301          if (traits == UndefinedPixelTrait)
4302            continue;
4303          EXTEND(sp,14*(i+1)*count);
4304          ChannelFeatures(channel,j);
4305        }
4306      }
4307      channel_features=(ChannelFeatures *)
4308        RelinquishMagickMemory(channel_features);
4309    }
4310
4311  PerlException:
4312    InheritPerlException(exception,perl_exception);
4313    exception=DestroyExceptionInfo(exception);
4314    SvREFCNT_dec(perl_exception);
4315  }
4316
4317#
4318###############################################################################
4319#                                                                             #
4320#                                                                             #
4321#                                                                             #
4322#   F l a t t e n                                                             #
4323#                                                                             #
4324#                                                                             #
4325#                                                                             #
4326###############################################################################
4327#
4328#
4329void
4330Flatten(ref,...)
4331  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4332  ALIAS:
4333    FlattenImage   = 1
4334    flatten        = 2
4335    flattenimage   = 3
4336  PPCODE:
4337  {
4338    AV
4339      *av;
4340
4341    char
4342      *attribute,
4343      *p;
4344
4345    ExceptionInfo
4346      *exception;
4347
4348    HV
4349      *hv;
4350
4351    Image
4352      *image;
4353
4354    PixelInfo
4355      background_color;
4356
4357    ssize_t
4358      i;
4359
4360    struct PackageInfo
4361      *info;
4362
4363    SV
4364      *perl_exception,
4365      *reference,
4366      *rv,
4367      *sv;
4368
4369    PERL_UNUSED_VAR(ref);
4370    PERL_UNUSED_VAR(ix);
4371    exception=AcquireExceptionInfo();
4372    perl_exception=newSVpv("",0);
4373    sv=NULL;
4374    if (sv_isobject(ST(0)) == 0)
4375      {
4376        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4377          PackageName);
4378        goto PerlException;
4379      }
4380    reference=SvRV(ST(0));
4381    hv=SvSTASH(reference);
4382    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4383    if (image == (Image *) NULL)
4384      {
4385        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4386          PackageName);
4387        goto PerlException;
4388      }
4389    background_color=image->background_color;
4390    if (items == 2)
4391      (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4392        &background_color,exception);
4393    else
4394      for (i=2; i < items; i+=2)
4395      {
4396        attribute=(char *) SvPV(ST(i-1),na);
4397        switch (*attribute)
4398        {
4399          case 'B':
4400          case 'b':
4401          {
4402            if (LocaleCompare(attribute,"background") == 0)
4403              {
4404                (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4405                  AllCompliance,&background_color,exception);
4406                break;
4407              }
4408            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4409              attribute);
4410            break;
4411          }
4412          default:
4413          {
4414            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4415              attribute);
4416            break;
4417          }
4418        }
4419      }
4420    image->background_color=background_color;
4421    image=MergeImageLayers(image,FlattenLayer,exception);
4422    if (image == (Image *) NULL)
4423      goto PerlException;
4424    /*
4425      Create blessed Perl array for the returned image.
4426    */
4427    av=newAV();
4428    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4429    SvREFCNT_dec(av);
4430    AddImageToRegistry(sv,image);
4431    rv=newRV(sv);
4432    av_push(av,sv_bless(rv,hv));
4433    SvREFCNT_dec(sv);
4434    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4435    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4436      "flatten-%.*s",(int) (MagickPathExtent-9),
4437      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4438    (void) CopyMagickString(image->filename,info->image_info->filename,
4439      MagickPathExtent);
4440    SetImageInfo(info->image_info,0,exception);
4441    exception=DestroyExceptionInfo(exception);
4442    SvREFCNT_dec(perl_exception);
4443    XSRETURN(1);
4444
4445  PerlException:
4446    InheritPerlException(exception,perl_exception);
4447    exception=DestroyExceptionInfo(exception);
4448    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4449    SvPOK_on(perl_exception);  /* return messages in string context */
4450    ST(0)=sv_2mortal(perl_exception);
4451    XSRETURN(1);
4452  }
4453
4454#
4455###############################################################################
4456#                                                                             #
4457#                                                                             #
4458#                                                                             #
4459#   F x                                                                       #
4460#                                                                             #
4461#                                                                             #
4462#                                                                             #
4463###############################################################################
4464#
4465#
4466void
4467Fx(ref,...)
4468  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4469  ALIAS:
4470    FxImage  = 1
4471    fx       = 2
4472    fximage  = 3
4473  PPCODE:
4474  {
4475    AV
4476      *av;
4477
4478    char
4479      *attribute,
4480      expression[MagickPathExtent];
4481
4482    ChannelType
4483      channel,
4484      channel_mask;
4485
4486    ExceptionInfo
4487      *exception;
4488
4489    HV
4490      *hv;
4491
4492    Image
4493      *image;
4494
4495    ssize_t
4496      i;
4497
4498    struct PackageInfo
4499      *info;
4500
4501    SV
4502      *av_reference,
4503      *perl_exception,
4504      *reference,
4505      *rv,
4506      *sv;
4507
4508    PERL_UNUSED_VAR(ref);
4509    PERL_UNUSED_VAR(ix);
4510    exception=AcquireExceptionInfo();
4511    perl_exception=newSVpv("",0);
4512    sv=NULL;
4513    attribute=NULL;
4514    av=NULL;
4515    if (sv_isobject(ST(0)) == 0)
4516      {
4517        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4518          PackageName);
4519        goto PerlException;
4520      }
4521    reference=SvRV(ST(0));
4522    hv=SvSTASH(reference);
4523    av=newAV();
4524    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4525    SvREFCNT_dec(av);
4526    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4527    if (image == (Image *) NULL)
4528      {
4529        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4530          PackageName);
4531        goto PerlException;
4532      }
4533    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4534    /*
4535      Get options.
4536    */
4537    channel=DefaultChannels;
4538    (void) CopyMagickString(expression,"u",MagickPathExtent);
4539    if (items == 2)
4540      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),
4541        MagickPathExtent);
4542    else
4543      for (i=2; i < items; i+=2)
4544      {
4545        attribute=(char *) SvPV(ST(i-1),na);
4546        switch (*attribute)
4547        {
4548          case 'C':
4549          case 'c':
4550          {
4551            if (LocaleCompare(attribute,"channel") == 0)
4552              {
4553                ssize_t
4554                  option;
4555
4556                option=ParseChannelOption(SvPV(ST(i),na));
4557                if (option < 0)
4558                  {
4559                    ThrowPerlException(exception,OptionError,
4560                      "UnrecognizedType",SvPV(ST(i),na));
4561                    return;
4562                  }
4563                channel=(ChannelType) option;
4564                break;
4565              }
4566            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4567              attribute);
4568            break;
4569          }
4570          case 'E':
4571          case 'e':
4572          {
4573            if (LocaleCompare(attribute,"expression") == 0)
4574              {
4575                (void) CopyMagickString(expression,SvPV(ST(i),na),
4576                  MagickPathExtent);
4577                break;
4578              }
4579            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4580              attribute);
4581            break;
4582          }
4583          default:
4584          {
4585            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4586              attribute);
4587            break;
4588          }
4589        }
4590      }
4591    channel_mask=SetImageChannelMask(image,channel);
4592    image=FxImage(image,expression,exception);
4593    if (image != (Image *) NULL)
4594      (void) SetImageChannelMask(image,channel_mask);
4595    if (image == (Image *) NULL)
4596      goto PerlException;
4597    for ( ; image; image=image->next)
4598    {
4599      AddImageToRegistry(sv,image);
4600      rv=newRV(sv);
4601      av_push(av,sv_bless(rv,hv));
4602      SvREFCNT_dec(sv);
4603    }
4604    exception=DestroyExceptionInfo(exception);
4605    ST(0)=av_reference;
4606    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4607    XSRETURN(1);
4608
4609  PerlException:
4610    InheritPerlException(exception,perl_exception);
4611    exception=DestroyExceptionInfo(exception);
4612    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4613    SvPOK_on(perl_exception);
4614    ST(0)=sv_2mortal(perl_exception);
4615    XSRETURN(1);
4616  }
4617
4618#
4619###############################################################################
4620#                                                                             #
4621#                                                                             #
4622#                                                                             #
4623#   G e t                                                                     #
4624#                                                                             #
4625#                                                                             #
4626#                                                                             #
4627###############################################################################
4628#
4629#
4630void
4631Get(ref,...)
4632  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4633  ALIAS:
4634    GetAttributes = 1
4635    GetAttribute  = 2
4636    get           = 3
4637    getattributes = 4
4638    getattribute  = 5
4639  PPCODE:
4640  {
4641    char
4642      *attribute,
4643      color[MagickPathExtent];
4644
4645    const char
4646      *value;
4647
4648    ExceptionInfo
4649      *exception;
4650
4651    Image
4652      *image;
4653
4654    long
4655      j;
4656
4657    ssize_t
4658      i;
4659
4660    struct PackageInfo
4661      *info;
4662
4663    SV
4664      *perl_exception,
4665      *reference,
4666      *s;
4667
4668    PERL_UNUSED_VAR(ref);
4669    PERL_UNUSED_VAR(ix);
4670    exception=AcquireExceptionInfo();
4671    perl_exception=newSVpv("",0);
4672    if (sv_isobject(ST(0)) == 0)
4673      {
4674        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4675          PackageName);
4676        XSRETURN_EMPTY;
4677      }
4678    reference=SvRV(ST(0));
4679    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4680    if (image == (Image *) NULL && !info)
4681      XSRETURN_EMPTY;
4682    EXTEND(sp,items);
4683    for (i=1; i < items; i++)
4684    {
4685      attribute=(char *) SvPV(ST(i),na);
4686      s=NULL;
4687      switch (*attribute)
4688      {
4689        case 'A':
4690        case 'a':
4691        {
4692          if (LocaleCompare(attribute,"adjoin") == 0)
4693            {
4694              if (info)
4695                s=newSViv((ssize_t) info->image_info->adjoin);
4696              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4697              continue;
4698            }
4699          if (LocaleCompare(attribute,"antialias") == 0)
4700            {
4701              if (info)
4702                s=newSViv((ssize_t) info->image_info->antialias);
4703              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4704              continue;
4705            }
4706          if (LocaleCompare(attribute,"area") == 0)
4707            {
4708              s=newSViv(GetMagickResource(AreaResource));
4709              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4710              continue;
4711            }
4712          if (LocaleCompare(attribute,"attenuate") == 0)
4713            {
4714              const char
4715                *value;
4716
4717              value=GetImageProperty(image,attribute,exception);
4718              if (value != (const char *) NULL)
4719                s=newSVpv(value,0);
4720              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4721              continue;
4722            }
4723          if (LocaleCompare(attribute,"authenticate") == 0)
4724            {
4725              if (info)
4726                {
4727                  const char
4728                    *option;
4729
4730                  option=GetImageOption(info->image_info,attribute);
4731                  if (option != (const char *) NULL)
4732                    s=newSVpv(option,0);
4733                }
4734              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4735              continue;
4736            }
4737          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4738            attribute);
4739          break;
4740        }
4741        case 'B':
4742        case 'b':
4743        {
4744          if (LocaleCompare(attribute,"background") == 0)
4745            {
4746              if (image == (Image *) NULL)
4747                break;
4748              (void) FormatLocaleString(color,MagickPathExtent,
4749                "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4750                (double) image->background_color.green,
4751                (double) image->background_color.blue,
4752                (double) image->background_color.alpha);
4753              s=newSVpv(color,0);
4754              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755              continue;
4756            }
4757          if (LocaleCompare(attribute,"base-columns") == 0)
4758            {
4759              if (image != (Image *) NULL)
4760                s=newSViv((ssize_t) image->magick_columns);
4761              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4762              continue;
4763            }
4764          if (LocaleCompare(attribute,"base-filename") == 0)
4765            {
4766              if (image != (Image *) NULL)
4767                s=newSVpv(image->magick_filename,0);
4768              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4769              continue;
4770            }
4771          if (LocaleCompare(attribute,"base-height") == 0)
4772            {
4773              if (image != (Image *) NULL)
4774                s=newSViv((ssize_t) image->magick_rows);
4775              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4776              continue;
4777            }
4778          if (LocaleCompare(attribute,"base-rows") == 0)
4779            {
4780              if (image != (Image *) NULL)
4781                s=newSViv((ssize_t) image->magick_rows);
4782              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4783              continue;
4784            }
4785          if (LocaleCompare(attribute,"base-width") == 0)
4786            {
4787              if (image != (Image *) NULL)
4788                s=newSViv((ssize_t) image->magick_columns);
4789              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4790              continue;
4791            }
4792          if (LocaleCompare(attribute,"blue-primary") == 0)
4793            {
4794              if (image == (Image *) NULL)
4795                break;
4796              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
4797                image->chromaticity.blue_primary.x,
4798                image->chromaticity.blue_primary.y);
4799              s=newSVpv(color,0);
4800              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4801              continue;
4802            }
4803          if (LocaleCompare(attribute,"bordercolor") == 0)
4804            {
4805              if (image == (Image *) NULL)
4806                break;
4807              (void) FormatLocaleString(color,MagickPathExtent,
4808                "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4809                (double) image->border_color.green,
4810                (double) image->border_color.blue,
4811                (double) image->border_color.alpha);
4812              s=newSVpv(color,0);
4813              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4814              continue;
4815            }
4816          if (LocaleCompare(attribute,"bounding-box") == 0)
4817            {
4818              char
4819                geometry[MagickPathExtent];
4820
4821              RectangleInfo
4822                page;
4823
4824              if (image == (Image *) NULL)
4825                break;
4826              page=GetImageBoundingBox(image,exception);
4827              (void) FormatLocaleString(geometry,MagickPathExtent,
4828                "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4829                page.height,(double) page.x,(double) page.y);
4830              s=newSVpv(geometry,0);
4831              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4832              continue;
4833            }
4834          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4835            attribute);
4836          break;
4837        }
4838        case 'C':
4839        case 'c':
4840        {
4841          if (LocaleCompare(attribute,"class") == 0)
4842            {
4843              if (image == (Image *) NULL)
4844                break;
4845              s=newSViv(image->storage_class);
4846              (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4847                image->storage_class));
4848              SvIOK_on(s);
4849              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4850              continue;
4851            }
4852          if (LocaleCompare(attribute,"clip-mask") == 0)
4853            {
4854              if (image != (Image *) NULL)
4855                {
4856                  Image
4857                    *mask_image;
4858
4859                  SV
4860                    *sv;
4861
4862                  sv=NULL;
4863                  if ((image->channels & WriteMaskChannel) == 0)
4864                    (void) ClipImage(image,exception);
4865                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4866                  if (mask_image != (Image *) NULL)
4867                    {
4868                      AddImageToRegistry(sv,mask_image);
4869                      s=sv_bless(newRV(sv),SvSTASH(reference));
4870                    }
4871                }
4872              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4873              continue;
4874            }
4875          if (LocaleCompare(attribute,"clip-path") == 0)
4876            {
4877              if (image != (Image *) NULL)
4878                {
4879                  Image
4880                    *mask_image;
4881
4882                  SV
4883                    *sv;
4884
4885                  sv=NULL;
4886                  if ((image->channels & WriteMaskChannel) == 0)
4887                    (void) ClipImage(image,exception);
4888                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4889                  if (mask_image != (Image *) NULL)
4890                    {
4891                      AddImageToRegistry(sv,mask_image);
4892                      s=sv_bless(newRV(sv),SvSTASH(reference));
4893                    }
4894                }
4895              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896              continue;
4897            }
4898          if (LocaleCompare(attribute,"compression") == 0)
4899            {
4900              j=info ? info->image_info->compression : image ?
4901                image->compression : UndefinedCompression;
4902              if (info)
4903                if (info->image_info->compression == UndefinedCompression)
4904                  j=image->compression;
4905              s=newSViv(j);
4906              (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4907                j));
4908              SvIOK_on(s);
4909              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4910              continue;
4911            }
4912          if (LocaleCompare(attribute,"colorspace") == 0)
4913            {
4914              j=image ? image->colorspace : RGBColorspace;
4915              s=newSViv(j);
4916              (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4917                j));
4918              SvIOK_on(s);
4919              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4920              continue;
4921            }
4922          if (LocaleCompare(attribute,"colors") == 0)
4923            {
4924              if (image != (Image *) NULL)
4925                s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4926                  exception));
4927              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4928              continue;
4929            }
4930          if (LocaleNCompare(attribute,"colormap",8) == 0)
4931            {
4932              int
4933                items;
4934
4935              if (image == (Image *) NULL || !image->colormap)
4936                break;
4937              j=0;
4938              items=sscanf(attribute,"%*[^[][%ld",&j);
4939              (void) items;
4940              if (j > (ssize_t) image->colors)
4941                j%=image->colors;
4942              (void) FormatLocaleString(color,MagickPathExtent,
4943                "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4944                (double) image->colormap[j].green,
4945                (double) image->colormap[j].blue,
4946                (double) image->colormap[j].alpha);
4947              s=newSVpv(color,0);
4948              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4949              continue;
4950            }
4951          if (LocaleCompare(attribute,"columns") == 0)
4952            {
4953              if (image != (Image *) NULL)
4954                s=newSViv((ssize_t) image->columns);
4955              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4956              continue;
4957            }
4958          if (LocaleCompare(attribute,"comment") == 0)
4959            {
4960              const char
4961                *value;
4962
4963              value=GetImageProperty(image,attribute,exception);
4964              if (value != (const char *) NULL)
4965                s=newSVpv(value,0);
4966              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4967              continue;
4968            }
4969          if (LocaleCompare(attribute,"copyright") == 0)
4970            {
4971              s=newSVpv(GetMagickCopyright(),0);
4972              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4973              continue;
4974            }
4975          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4976            attribute);
4977          break;
4978        }
4979        case 'D':
4980        case 'd':
4981        {
4982          if (LocaleCompare(attribute,"density") == 0)
4983            {
4984              char
4985                geometry[MagickPathExtent];
4986
4987              if (image == (Image *) NULL)
4988                break;
4989              (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
4990                image->resolution.x,image->resolution.y);
4991              s=newSVpv(geometry,0);
4992              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4993              continue;
4994            }
4995          if (LocaleCompare(attribute,"delay") == 0)
4996            {
4997              if (image != (Image *) NULL)
4998                s=newSViv((ssize_t) image->delay);
4999              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000              continue;
5001            }
5002          if (LocaleCompare(attribute,"depth") == 0)
5003            {
5004              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5005              if (image != (Image *) NULL)
5006                s=newSViv((ssize_t) GetImageDepth(image,exception));
5007              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5008              continue;
5009            }
5010          if (LocaleCompare(attribute,"directory") == 0)
5011            {
5012              if (image && image->directory)
5013                s=newSVpv(image->directory,0);
5014              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5015              continue;
5016            }
5017          if (LocaleCompare(attribute,"dispose") == 0)
5018            {
5019              if (image == (Image *) NULL)
5020                break;
5021
5022              s=newSViv(image->dispose);
5023              (void) sv_setpv(s,
5024                CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5025              SvIOK_on(s);
5026              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5027              continue;
5028            }
5029          if (LocaleCompare(attribute,"disk") == 0)
5030            {
5031              s=newSViv(GetMagickResource(DiskResource));
5032              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5033              continue;
5034            }
5035          if (LocaleCompare(attribute,"dither") == 0)
5036            {
5037              if (info)
5038                s=newSViv((ssize_t) info->image_info->dither);
5039              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5040              continue;
5041            }
5042          if (LocaleCompare(attribute,"display") == 0)  /* same as server */
5043            {
5044              if (info && info->image_info->server_name)
5045                s=newSVpv(info->image_info->server_name,0);
5046              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047              continue;
5048            }
5049          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5050            attribute);
5051          break;
5052        }
5053        case 'E':
5054        case 'e':
5055        {
5056          if (LocaleCompare(attribute,"elapsed-time") == 0)
5057            {
5058              if (image != (Image *) NULL)
5059                s=newSVnv(GetElapsedTime(&image->timer));
5060              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5061              continue;
5062            }
5063          if (LocaleCompare(attribute,"endian") == 0)
5064            {
5065              j=info ? info->image_info->endian : image ? image->endian :
5066                UndefinedEndian;
5067              if (info)
5068                if (info->image_info->endian == UndefinedEndian)
5069                  j=image->endian;
5070              s=newSViv(j);
5071              (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5072              SvIOK_on(s);
5073              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074              continue;
5075            }
5076          if (LocaleCompare(attribute,"error") == 0)
5077            {
5078              if (image != (Image *) NULL)
5079                s=newSVnv(image->error.mean_error_per_pixel);
5080              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5081              continue;
5082            }
5083          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5084            attribute);
5085          break;
5086        }
5087        case 'F':
5088        case 'f':
5089        {
5090          if (LocaleCompare(attribute,"filesize") == 0)
5091            {
5092              if (image != (Image *) NULL)
5093                s=newSViv((ssize_t) GetBlobSize(image));
5094              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095              continue;
5096            }
5097          if (LocaleCompare(attribute,"filename") == 0)
5098            {
5099              if (image != (Image *) NULL)
5100                s=newSVpv(image->filename,0);
5101              else
5102                if (info && *info->image_info->filename)
5103                  s=newSVpv(info->image_info->filename,0);
5104              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5105              continue;
5106            }
5107          if (LocaleCompare(attribute,"filter") == 0)
5108            {
5109              s=image ? newSViv(image->filter) : newSViv(0);
5110              (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5111                image->filter));
5112              SvIOK_on(s);
5113              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5114              continue;
5115            }
5116          if (LocaleCompare(attribute,"font") == 0)
5117            {
5118              if (info && info->image_info->font)
5119                s=newSVpv(info->image_info->font,0);
5120              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5121              continue;
5122            }
5123          if (LocaleCompare(attribute,"foreground") == 0)
5124            continue;
5125          if (LocaleCompare(attribute,"format") == 0)
5126            {
5127              const MagickInfo
5128                *magick_info;
5129
5130              magick_info=(const MagickInfo *) NULL;
5131              if (info && (*info->image_info->magick != '\0'))
5132                magick_info=GetMagickInfo(info->image_info->magick,exception);
5133              if (image != (Image *) NULL)
5134                magick_info=GetMagickInfo(image->magick,exception);
5135              if ((magick_info != (const MagickInfo *) NULL) &&
5136                  (*magick_info->description != '\0'))
5137                s=newSVpv((char *) magick_info->description,0);
5138              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5139              continue;
5140            }
5141          if (LocaleCompare(attribute,"fuzz") == 0)
5142            {
5143              if (info)
5144                s=newSVnv(info->image_info->fuzz);
5145              if (image != (Image *) NULL)
5146                s=newSVnv(image->fuzz);
5147              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148              continue;
5149            }
5150          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5151            attribute);
5152          break;
5153        }
5154        case 'G':
5155        case 'g':
5156        {
5157          if (LocaleCompare(attribute,"gamma") == 0)
5158            {
5159              if (image != (Image *) NULL)
5160                s=newSVnv(image->gamma);
5161              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5162              continue;
5163            }
5164          if (LocaleCompare(attribute,"geometry") == 0)
5165            {
5166              if (image && image->geometry)
5167                s=newSVpv(image->geometry,0);
5168              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5169              continue;
5170            }
5171          if (LocaleCompare(attribute,"gravity") == 0)
5172            {
5173              s=image ? newSViv(image->gravity) : newSViv(0);
5174              (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5175                image->gravity));
5176              SvIOK_on(s);
5177              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5178              continue;
5179            }
5180          if (LocaleCompare(attribute,"green-primary") == 0)
5181            {
5182              if (image == (Image *) NULL)
5183                break;
5184              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5185                image->chromaticity.green_primary.x,
5186                image->chromaticity.green_primary.y);
5187              s=newSVpv(color,0);
5188              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5189              continue;
5190            }
5191          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5192            attribute);
5193          break;
5194        }
5195        case 'H':
5196        case 'h':
5197        {
5198          if (LocaleCompare(attribute,"height") == 0)
5199            {
5200              if (image != (Image *) NULL)
5201                s=newSViv((ssize_t) image->rows);
5202              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5203              continue;
5204            }
5205          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5206            attribute);
5207          break;
5208        }
5209        case 'I':
5210        case 'i':
5211        {
5212          if (LocaleCompare(attribute,"icc") == 0)
5213            {
5214              if (image != (Image *) NULL)
5215                {
5216                  const StringInfo
5217                    *profile;
5218
5219                  profile=GetImageProfile(image,"icc");
5220                  if (profile != (StringInfo *) NULL)
5221                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5222                      GetStringInfoLength(profile));
5223                }
5224              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5225              continue;
5226            }
5227          if (LocaleCompare(attribute,"icm") == 0)
5228            {
5229              if (image != (Image *) NULL)
5230                {
5231                  const StringInfo
5232                    *profile;
5233
5234                  profile=GetImageProfile(image,"icm");
5235                  if (profile != (const StringInfo *) NULL)
5236                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5237                      GetStringInfoLength(profile));
5238                }
5239              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240              continue;
5241            }
5242          if (LocaleCompare(attribute,"id") == 0)
5243            {
5244              if (image != (Image *) NULL)
5245                {
5246                  char
5247                    key[MagickPathExtent];
5248
5249                  MagickBooleanType
5250                    status;
5251
5252                  static ssize_t
5253                    id = 0;
5254
5255                  (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5256                    id);
5257                  status=SetImageRegistry(ImageRegistryType,key,image,
5258                    exception);
5259                  (void) status;
5260                  s=newSViv(id++);
5261                }
5262              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263              continue;
5264            }
5265          if (LocaleNCompare(attribute,"index",5) == 0)
5266            {
5267              char
5268                name[MagickPathExtent];
5269
5270              int
5271                items;
5272
5273              long
5274                x,
5275                y;
5276
5277              const Quantum
5278                *p;
5279
5280              CacheView
5281                *image_view;
5282
5283              if (image == (Image *) NULL)
5284                break;
5285              if (image->storage_class != PseudoClass)
5286                break;
5287              x=0;
5288              y=0;
5289              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5290              (void) items;
5291              image_view=AcquireVirtualCacheView(image,exception);
5292              p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5293              if (p != (const Quantum *) NULL)
5294                {
5295                  (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5296                    GetPixelIndex(image,p));
5297                  s=newSVpv(name,0);
5298                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5299                }
5300              image_view=DestroyCacheView(image_view);
5301              continue;
5302            }
5303          if (LocaleCompare(attribute,"iptc") == 0)
5304            {
5305              if (image != (Image *) NULL)
5306                {
5307                  const StringInfo
5308                    *profile;
5309
5310                  profile=GetImageProfile(image,"iptc");
5311                  if (profile != (const StringInfo *) NULL)
5312                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5313                      GetStringInfoLength(profile));
5314                }
5315              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316              continue;
5317            }
5318          if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5319            {
5320              if (image != (Image *) NULL)
5321                s=newSViv((ssize_t) image->iterations);
5322              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5323              continue;
5324            }
5325          if (LocaleCompare(attribute,"interlace") == 0)
5326            {
5327              j=info ? info->image_info->interlace : image ? image->interlace :
5328                UndefinedInterlace;
5329              if (info)
5330                if (info->image_info->interlace == UndefinedInterlace)
5331                  j=image->interlace;
5332              s=newSViv(j);
5333              (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5334                j));
5335              SvIOK_on(s);
5336              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337              continue;
5338            }
5339          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5340            attribute);
5341          break;
5342        }
5343        case 'L':
5344        case 'l':
5345        {
5346          if (LocaleCompare(attribute,"label") == 0)
5347            {
5348              const char
5349                *value;
5350
5351              if (image == (Image *) NULL)
5352                break;
5353              value=GetImageProperty(image,"Label",exception);
5354              if (value != (const char *) NULL)
5355                s=newSVpv(value,0);
5356              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5357              continue;
5358            }
5359          if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5360            {
5361              if (image != (Image *) NULL)
5362                s=newSViv((ssize_t) image->iterations);
5363              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5364              continue;
5365            }
5366          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5367            attribute);
5368          break;
5369        }
5370        case 'M':
5371        case 'm':
5372        {
5373          if (LocaleCompare(attribute,"magick") == 0)
5374            {
5375              if (info && *info->image_info->magick)
5376                s=newSVpv(info->image_info->magick,0);
5377              if (image != (Image *) NULL)
5378                s=newSVpv(image->magick,0);
5379              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5380              continue;
5381            }
5382          if (LocaleCompare(attribute,"map") == 0)
5383            {
5384              s=newSViv(GetMagickResource(MapResource));
5385              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386              continue;
5387            }
5388          if (LocaleCompare(attribute,"maximum-error") == 0)
5389            {
5390              if (image != (Image *) NULL)
5391                s=newSVnv(image->error.normalized_maximum_error);
5392              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5393              continue;
5394            }
5395          if (LocaleCompare(attribute,"memory") == 0)
5396            {
5397              s=newSViv(GetMagickResource(MemoryResource));
5398              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5399              continue;
5400            }
5401          if (LocaleCompare(attribute,"mean-error") == 0)
5402            {
5403              if (image != (Image *) NULL)
5404                s=newSVnv(image->error.normalized_mean_error);
5405              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5406              continue;
5407            }
5408          if (LocaleCompare(attribute,"mime") == 0)
5409            {
5410              if (info && *info->image_info->magick)
5411                s=newSVpv(MagickToMime(info->image_info->magick),0);
5412              if (image != (Image *) NULL)
5413                s=newSVpv(MagickToMime(image->magick),0);
5414              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415              continue;
5416            }
5417          if (LocaleCompare(attribute,"mattecolor") == 0)
5418            {
5419              if (image == (Image *) NULL)
5420                break;
5421              (void) FormatLocaleString(color,MagickPathExtent,
5422                "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5423                (double) image->alpha_color.green,
5424                (double) image->alpha_color.blue,
5425                (double) image->alpha_color.alpha);
5426              s=newSVpv(color,0);
5427              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5428              continue;
5429            }
5430          if (LocaleCompare(attribute,"matte") == 0)
5431            {
5432              if (image != (Image *) NULL)
5433                s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5434                  1 : 0);
5435              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5436              continue;
5437            }
5438          if (LocaleCompare(attribute,"mime") == 0)
5439            {
5440              const char
5441                *magick;
5442
5443              magick=NULL;
5444              if (info && *info->image_info->magick)
5445                magick=info->image_info->magick;
5446              if (image != (Image *) NULL)
5447                magick=image->magick;
5448              if (magick)
5449                {
5450                  char
5451                    *mime;
5452
5453                  mime=MagickToMime(magick);
5454                  s=newSVpv(mime,0);
5455                  mime=(char *) RelinquishMagickMemory(mime);
5456                }
5457              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5458              continue;
5459            }
5460          if (LocaleCompare(attribute,"monochrome") == 0)
5461            {
5462              if (image == (Image *) NULL)
5463                continue;
5464              j=info ? info->image_info->monochrome :
5465                SetImageMonochrome(image,exception);
5466              s=newSViv(j);
5467              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5468              continue;
5469            }
5470          if (LocaleCompare(attribute,"montage") == 0)
5471            {
5472              if (image && image->montage)
5473                s=newSVpv(image->montage,0);
5474              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5475              continue;
5476            }
5477          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5478            attribute);
5479          break;
5480        }
5481        case 'O':
5482        case 'o':
5483        {
5484          if (LocaleCompare(attribute,"orientation") == 0)
5485            {
5486              j=info ? info->image_info->orientation : image ?
5487                image->orientation : UndefinedOrientation;
5488              if (info)
5489                if (info->image_info->orientation == UndefinedOrientation)
5490                  j=image->orientation;
5491              s=newSViv(j);
5492              (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5493                j));
5494              SvIOK_on(s);
5495              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5496              continue;
5497            }
5498          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5499            attribute);
5500          break;
5501        }
5502        case 'P':
5503        case 'p':
5504        {
5505          if (LocaleCompare(attribute,"page") == 0)
5506            {
5507              if (info && info->image_info->page)
5508                s=newSVpv(info->image_info->page,0);
5509              if (image != (Image *) NULL)
5510                {
5511                  char
5512                    geometry[MagickPathExtent];
5513
5514                  (void) FormatLocaleString(geometry,MagickPathExtent,
5515                    "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5516                    (double) image->page.height,(double) image->page.x,(double)
5517                    image->page.y);
5518                  s=newSVpv(geometry,0);
5519                }
5520              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5521              continue;
5522            }
5523          if (LocaleCompare(attribute,"page.x") == 0)
5524            {
5525              if (image != (Image *) NULL)
5526                s=newSViv((ssize_t) image->page.x);
5527              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5528              continue;
5529            }
5530          if (LocaleCompare(attribute,"page.y") == 0)
5531            {
5532              if (image != (Image *) NULL)
5533                s=newSViv((ssize_t) image->page.y);
5534              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5535              continue;
5536            }
5537          if (LocaleNCompare(attribute,"pixel",5) == 0)
5538            {
5539              char
5540                tuple[MagickPathExtent];
5541
5542              int
5543                items;
5544
5545              long
5546                x,
5547                y;
5548
5549              const Quantum
5550                *p;
5551
5552              if (image == (Image *) NULL)
5553                break;
5554              x=0;
5555              y=0;
5556              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5557              (void) items;
5558              p=GetVirtualPixels(image,x,y,1,1,exception);
5559              if (image->colorspace != CMYKColorspace)
5560                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5561                  QuantumFormat "," QuantumFormat "," QuantumFormat,
5562                  GetPixelRed(image,p),GetPixelGreen(image,p),
5563                  GetPixelBlue(image,p),GetPixelAlpha(image,p));
5564              else
5565                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5566                  QuantumFormat "," QuantumFormat "," QuantumFormat ","
5567                  QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5568                  GetPixelBlue(image,p),GetPixelBlack(image,p),
5569                  GetPixelAlpha(image,p));
5570              s=newSVpv(tuple,0);
5571              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5572              continue;
5573            }
5574          if (LocaleCompare(attribute,"pointsize") == 0)
5575            {
5576              if (info)
5577                s=newSViv((ssize_t) info->image_info->pointsize);
5578              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579              continue;
5580            }
5581          if (LocaleCompare(attribute,"precision") == 0)
5582            {
5583              s=newSViv((ssize_t) GetMagickPrecision());
5584              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5585              continue;
5586            }
5587          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5588            attribute);
5589          break;
5590        }
5591        case 'Q':
5592        case 'q':
5593        {
5594          if (LocaleCompare(attribute,"quality") == 0)
5595            {
5596              if (info)
5597                s=newSViv((ssize_t) info->image_info->quality);
5598              if (image != (Image *) NULL)
5599                s=newSViv((ssize_t) image->quality);
5600              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5601              continue;
5602            }
5603          if (LocaleCompare(attribute,"quantum") == 0)
5604            {
5605              if (info)
5606                s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5607              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5608              continue;
5609            }
5610          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5611            attribute);
5612          break;
5613        }
5614        case 'R':
5615        case 'r':
5616        {
5617          if (LocaleCompare(attribute,"rendering-intent") == 0)
5618            {
5619              s=newSViv(image->rendering_intent);
5620              (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5621                image->rendering_intent));
5622              SvIOK_on(s);
5623              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5624              continue;
5625            }
5626          if (LocaleCompare(attribute,"red-primary") == 0)
5627            {
5628              if (image == (Image *) NULL)
5629                break;
5630              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5631                image->chromaticity.red_primary.x,
5632                image->chromaticity.red_primary.y);
5633              s=newSVpv(color,0);
5634              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5635              continue;
5636            }
5637          if (LocaleCompare(attribute,"rows") == 0)
5638            {
5639              if (image != (Image *) NULL)
5640                s=newSViv((ssize_t) image->rows);
5641              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5642              continue;
5643            }
5644          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5645            attribute);
5646          break;
5647        }
5648        case 'S':
5649        case 's':
5650        {
5651          if (LocaleCompare(attribute,"sampling-factor") == 0)
5652            {
5653              if (info && info->image_info->sampling_factor)
5654                s=newSVpv(info->image_info->sampling_factor,0);
5655              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5656              continue;
5657            }
5658          if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5659            {
5660              if (info && info->image_info->server_name)
5661                s=newSVpv(info->image_info->server_name,0);
5662              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5663              continue;
5664            }
5665          if (LocaleCompare(attribute,"size") == 0)
5666            {
5667              if (info && info->image_info->size)
5668                s=newSVpv(info->image_info->size,0);
5669              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5670              continue;
5671            }
5672          if (LocaleCompare(attribute,"scene") == 0)
5673            {
5674              if (image != (Image *) NULL)
5675                s=newSViv((ssize_t) image->scene);
5676              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5677              continue;
5678            }
5679          if (LocaleCompare(attribute,"scenes") == 0)
5680            {
5681              if (image != (Image *) NULL)
5682                s=newSViv((ssize_t) info->image_info->number_scenes);
5683              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5684              continue;
5685            }
5686          if (LocaleCompare(attribute,"signature") == 0)
5687            {
5688              const char
5689                *value;
5690
5691              if (image == (Image *) NULL)
5692                break;
5693              (void) SignatureImage(image,exception);
5694              value=GetImageProperty(image,"Signature",exception);
5695              if (value != (const char *) NULL)
5696                s=newSVpv(value,0);
5697              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698              continue;
5699            }
5700          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5701            attribute);
5702          break;
5703        }
5704        case 'T':
5705        case 't':
5706        {
5707          if (LocaleCompare(attribute,"taint") == 0)
5708            {
5709              if (image != (Image *) NULL)
5710                s=newSViv((ssize_t) IsTaintImage(image));
5711              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5712              continue;
5713            }
5714          if (LocaleCompare(attribute,"texture") == 0)
5715            {
5716              if (info && info->image_info->texture)
5717                s=newSVpv(info->image_info->texture,0);
5718              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5719              continue;
5720            }
5721          if (LocaleCompare(attribute,"total-ink-density") == 0)
5722            {
5723              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5724              if (image != (Image *) NULL)
5725                s=newSVnv(GetImageTotalInkDensity(image,exception));
5726              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5727              continue;
5728            }
5729          if (LocaleCompare(attribute,"transparent-color") == 0)
5730            {
5731              if (image == (Image *) NULL)
5732                break;
5733              (void) FormatLocaleString(color,MagickPathExtent,
5734                "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5735                (double) image->transparent_color.green,
5736                (double) image->transparent_color.blue,
5737                (double) image->transparent_color.alpha);
5738              s=newSVpv(color,0);
5739              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5740              continue;
5741            }
5742          if (LocaleCompare(attribute,"type") == 0)
5743            {
5744              if (image == (Image *) NULL)
5745                break;
5746              j=(ssize_t) GetImageType(image);
5747              s=newSViv(j);
5748              (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5749              SvIOK_on(s);
5750              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5751              continue;
5752            }
5753          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5754            attribute);
5755          break;
5756        }
5757        case 'U':
5758        case 'u':
5759        {
5760          if (LocaleCompare(attribute,"units") == 0)
5761            {
5762              j=info ? info->image_info->units : image ? image->units :
5763                UndefinedResolution;
5764              if (info)
5765                if (info->image_info->units == UndefinedResolution)
5766                  j=image->units;
5767              if (j == UndefinedResolution)
5768                s=newSVpv("undefined units",0);
5769              else
5770                if (j == PixelsPerInchResolution)
5771                  s=newSVpv("pixels / inch",0);
5772                else
5773                  s=newSVpv("pixels / centimeter",0);
5774              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5775              continue;
5776            }
5777          if (LocaleCompare(attribute,"user-time") == 0)
5778            {
5779              if (image != (Image *) NULL)
5780                s=newSVnv(GetUserTime(&image->timer));
5781              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5782              continue;
5783            }
5784          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5785            attribute);
5786          break;
5787        }
5788        case 'V':
5789        case 'v':
5790        {
5791          if (LocaleCompare(attribute,"verbose") == 0)
5792            {
5793              if (info)
5794                s=newSViv((ssize_t) info->image_info->verbose);
5795              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5796              continue;
5797            }
5798          if (LocaleCompare(attribute,"version") == 0)
5799            {
5800              s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5801              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5802              continue;
5803            }
5804          if (LocaleCompare(attribute,"virtual-pixel") == 0)
5805            {
5806              if (image == (Image *) NULL)
5807                break;
5808              j=(ssize_t) GetImageVirtualPixelMethod(image);
5809              s=newSViv(j);
5810              (void) sv_setpv(s,CommandOptionToMnemonic(
5811                MagickVirtualPixelOptions,j));
5812              SvIOK_on(s);
5813              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5814              continue;
5815            }
5816          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5817            attribute);
5818          break;
5819        }
5820        case 'W':
5821        case 'w':
5822        {
5823          if (LocaleCompare(attribute,"white-point") == 0)
5824            {
5825              if (image == (Image *) NULL)
5826                break;
5827              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5828                image->chromaticity.white_point.x,
5829                image->chromaticity.white_point.y);
5830              s=newSVpv(color,0);
5831              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5832              continue;
5833            }
5834          if (LocaleCompare(attribute,"width") == 0)
5835            {
5836              if (image != (Image *) NULL)
5837                s=newSViv((ssize_t) image->columns);
5838              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5839              continue;
5840            }
5841          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5842             attribute);
5843          break;
5844        }
5845        case 'X':
5846        case 'x':
5847        {
5848          if (LocaleCompare(attribute,"xmp") == 0)
5849            {
5850              if (image != (Image *) NULL)
5851                {
5852                  const StringInfo
5853                    *profile;
5854
5855                  profile=GetImageProfile(image,"xmp");
5856                  if (profile != (StringInfo *) NULL)
5857                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5858                      GetStringInfoLength(profile));
5859                }
5860              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5861              continue;
5862            }
5863          if (LocaleCompare(attribute,"x-resolution") == 0)
5864            {
5865              if (image != (Image *) NULL)
5866                s=newSVnv(image->resolution.x);
5867              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5868              continue;
5869            }
5870          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5871            attribute);
5872          break;
5873        }
5874        case 'Y':
5875        case 'y':
5876        {
5877          if (LocaleCompare(attribute,"y-resolution") == 0)
5878            {
5879              if (image != (Image *) NULL)
5880                s=newSVnv(image->resolution.y);
5881              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5882              continue;
5883            }
5884          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5885            attribute);
5886          break;
5887        }
5888        default:
5889          break;
5890      }
5891      if (image == (Image *) NULL)
5892        ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5893          attribute)
5894      else
5895        {
5896          value=GetImageProperty(image,attribute,exception);
5897          if (value != (const char *) NULL)
5898            {
5899              s=newSVpv(value,0);
5900              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5901            }
5902          else
5903            if (*attribute != '%')
5904              ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5905                attribute)
5906            else
5907              {
5908                 char
5909                   *meta;
5910
5911                 meta=InterpretImageProperties(info ? info->image_info :
5912                   (ImageInfo *) NULL,image,attribute,exception);
5913                 s=newSVpv(meta,0);
5914                 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5915                 meta=(char *) RelinquishMagickMemory(meta);
5916              }
5917        }
5918    }
5919    exception=DestroyExceptionInfo(exception);
5920    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5921  }
5922
5923#
5924###############################################################################
5925#                                                                             #
5926#                                                                             #
5927#                                                                             #
5928#   G e t A u t h e n t i c P i x e l s                                       #
5929#                                                                             #
5930#                                                                             #
5931#                                                                             #
5932###############################################################################
5933#
5934#
5935void *
5936GetAuthenticPixels(ref,...)
5937  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5938  ALIAS:
5939    getauthenticpixels = 1
5940    GetImagePixels = 2
5941    getimagepixels = 3
5942  CODE:
5943  {
5944    char
5945      *attribute;
5946
5947    ExceptionInfo
5948      *exception;
5949
5950    Image
5951      *image;
5952
5953    RectangleInfo
5954      region;
5955
5956    ssize_t
5957      i;
5958
5959    struct PackageInfo
5960      *info;
5961
5962    SV
5963      *perl_exception,
5964      *reference;
5965
5966    void
5967      *blob = NULL;
5968
5969    PERL_UNUSED_VAR(ref);
5970    PERL_UNUSED_VAR(ix);
5971    exception=AcquireExceptionInfo();
5972    perl_exception=newSVpv("",0);
5973    if (sv_isobject(ST(0)) == 0)
5974      {
5975        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5976          PackageName);
5977        goto PerlException;
5978      }
5979    reference=SvRV(ST(0));
5980
5981    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5982    if (image == (Image *) NULL)
5983      {
5984        ThrowPerlException(exception,OptionError,"NoImagesDefined",
5985          PackageName);
5986        goto PerlException;
5987      }
5988
5989    region.x=0;
5990    region.y=0;
5991    region.width=image->columns;
5992    region.height=1;
5993    if (items == 1)
5994      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5995    for (i=2; i < items; i+=2)
5996    {
5997      attribute=(char *) SvPV(ST(i-1),na);
5998      switch (*attribute)
5999      {
6000        case 'g':
6001        case 'G':
6002        {
6003          if (LocaleCompare(attribute,"geometry") == 0)
6004            {
6005              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6006              break;
6007            }
6008          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6009            attribute);
6010          break;
6011        }
6012        case 'H':
6013        case 'h':
6014        {
6015          if (LocaleCompare(attribute,"height") == 0)
6016            {
6017              region.height=SvIV(ST(i));
6018              continue;
6019            }
6020          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6021            attribute);
6022          break;
6023        }
6024        case 'X':
6025        case 'x':
6026        {
6027          if (LocaleCompare(attribute,"x") == 0)
6028            {
6029              region.x=SvIV(ST(i));
6030              continue;
6031            }
6032          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6033            attribute);
6034          break;
6035        }
6036        case 'Y':
6037        case 'y':
6038        {
6039          if (LocaleCompare(attribute,"y") == 0)
6040            {
6041              region.y=SvIV(ST(i));
6042              continue;
6043            }
6044          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6045            attribute);
6046          break;
6047        }
6048        case 'W':
6049        case 'w':
6050        {
6051          if (LocaleCompare(attribute,"width") == 0)
6052            {
6053              region.width=SvIV(ST(i));
6054              continue;
6055            }
6056          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6057            attribute);
6058          break;
6059        }
6060      }
6061    }
6062    blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6063      region.height,exception);
6064    if (blob != (void *) NULL)
6065      goto PerlEnd;
6066
6067  PerlException:
6068    InheritPerlException(exception,perl_exception);
6069    exception=DestroyExceptionInfo(exception);
6070    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6071
6072  PerlEnd:
6073    RETVAL = blob;
6074  }
6075  OUTPUT:
6076    RETVAL
6077
6078#
6079###############################################################################
6080#                                                                             #
6081#                                                                             #
6082#                                                                             #
6083#   G e t V i r t u a l P i x e l s                                           #
6084#                                                                             #
6085#                                                                             #
6086#                                                                             #
6087###############################################################################
6088#
6089#
6090void *
6091GetVirtualPixels(ref,...)
6092  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6093  ALIAS:
6094    getvirtualpixels = 1
6095    AcquireImagePixels = 2
6096    acquireimagepixels = 3
6097  CODE:
6098  {
6099    char
6100      *attribute;
6101
6102    const void
6103      *blob = NULL;
6104
6105    ExceptionInfo
6106      *exception;
6107
6108    Image
6109      *image;
6110
6111    RectangleInfo
6112      region;
6113
6114    ssize_t
6115      i;
6116
6117    struct PackageInfo
6118      *info;
6119
6120    SV
6121      *perl_exception,
6122      *reference;
6123
6124    PERL_UNUSED_VAR(ref);
6125    PERL_UNUSED_VAR(ix);
6126    exception=AcquireExceptionInfo();
6127    perl_exception=newSVpv("",0);
6128    if (sv_isobject(ST(0)) == 0)
6129      {
6130        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6131          PackageName);
6132        goto PerlException;
6133      }
6134    reference=SvRV(ST(0));
6135
6136    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6137    if (image == (Image *) NULL)
6138      {
6139        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6140          PackageName);
6141        goto PerlException;
6142      }
6143
6144    region.x=0;
6145    region.y=0;
6146    region.width=image->columns;
6147    region.height=1;
6148    if (items == 1)
6149      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6150    for (i=2; i < items; i+=2)
6151    {
6152      attribute=(char *) SvPV(ST(i-1),na);
6153      switch (*attribute)
6154      {
6155        case 'g':
6156        case 'G':
6157        {
6158          if (LocaleCompare(attribute,"geometry") == 0)
6159            {
6160              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6161              break;
6162            }
6163          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6164            attribute);
6165          break;
6166        }
6167        case 'H':
6168        case 'h':
6169        {
6170          if (LocaleCompare(attribute,"height") == 0)
6171            {
6172              region.height=SvIV(ST(i));
6173              continue;
6174            }
6175          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6176            attribute);
6177          break;
6178        }
6179        case 'X':
6180        case 'x':
6181        {
6182          if (LocaleCompare(attribute,"x") == 0)
6183            {
6184              region.x=SvIV(ST(i));
6185              continue;
6186            }
6187          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6188            attribute);
6189          break;
6190        }
6191        case 'Y':
6192        case 'y':
6193        {
6194          if (LocaleCompare(attribute,"y") == 0)
6195            {
6196              region.y=SvIV(ST(i));
6197              continue;
6198            }
6199          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6200            attribute);
6201          break;
6202        }
6203        case 'W':
6204        case 'w':
6205        {
6206          if (LocaleCompare(attribute,"width") == 0)
6207            {
6208              region.width=SvIV(ST(i));
6209              continue;
6210            }
6211          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6212            attribute);
6213          break;
6214        }
6215      }
6216    }
6217    blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6218      region.height,exception);
6219    if (blob != (void *) NULL)
6220      goto PerlEnd;
6221
6222  PerlException:
6223    InheritPerlException(exception,perl_exception);
6224    exception=DestroyExceptionInfo(exception);
6225    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6226
6227  PerlEnd:
6228    RETVAL = (void *) blob;
6229  }
6230  OUTPUT:
6231    RETVAL
6232
6233#
6234###############################################################################
6235#                                                                             #
6236#                                                                             #
6237#                                                                             #
6238#   G e t A u t h e n t i c M e t a c o n t e n t                             #
6239#                                                                             #
6240#                                                                             #
6241#                                                                             #
6242###############################################################################
6243#
6244#
6245void *
6246GetAuthenticMetacontent(ref,...)
6247  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6248  ALIAS:
6249    getauthenticmetacontent = 1
6250    GetMetacontent = 2
6251    getmetacontent = 3
6252  CODE:
6253  {
6254    ExceptionInfo
6255      *exception;
6256
6257    Image
6258      *image;
6259
6260    struct PackageInfo
6261      *info;
6262
6263    SV
6264      *perl_exception,
6265      *reference;
6266
6267    void
6268      *blob = NULL;
6269
6270    PERL_UNUSED_VAR(ref);
6271    PERL_UNUSED_VAR(ix);
6272    exception=AcquireExceptionInfo();
6273    perl_exception=newSVpv("",0);
6274    if (sv_isobject(ST(0)) == 0)
6275      {
6276        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6277          PackageName);
6278        goto PerlException;
6279      }
6280    reference=SvRV(ST(0));
6281
6282    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6283    if (image == (Image *) NULL)
6284      {
6285        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6286          PackageName);
6287        goto PerlException;
6288      }
6289
6290    blob=(void *) GetAuthenticMetacontent(image);
6291    if (blob != (void *) NULL)
6292      goto PerlEnd;
6293
6294  PerlException:
6295    InheritPerlException(exception,perl_exception);
6296    exception=DestroyExceptionInfo(exception);
6297    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6298
6299  PerlEnd:
6300    RETVAL = blob;
6301  }
6302  OUTPUT:
6303    RETVAL
6304
6305#
6306###############################################################################
6307#                                                                             #
6308#                                                                             #
6309#                                                                             #
6310#   G e t V i r t u a l M e t a c o n t e n t                                 #
6311#                                                                             #
6312#                                                                             #
6313#                                                                             #
6314###############################################################################
6315#
6316#
6317void *
6318GetVirtualMetacontent(ref,...)
6319  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6320  ALIAS:
6321    getvirtualmetacontent = 1
6322  CODE:
6323  {
6324    ExceptionInfo
6325      *exception;
6326
6327    Image
6328      *image;
6329
6330    struct PackageInfo
6331      *info;
6332
6333    SV
6334      *perl_exception,
6335      *reference;
6336
6337    void
6338      *blob = NULL;
6339
6340    PERL_UNUSED_VAR(ref);
6341    PERL_UNUSED_VAR(ix);
6342    exception=AcquireExceptionInfo();
6343    perl_exception=newSVpv("",0);
6344    if (sv_isobject(ST(0)) == 0)
6345      {
6346        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6347          PackageName);
6348        goto PerlException;
6349      }
6350    reference=SvRV(ST(0));
6351
6352    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6353    if (image == (Image *) NULL)
6354      {
6355        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6356          PackageName);
6357        goto PerlException;
6358      }
6359
6360    blob=(void *) GetVirtualMetacontent(image);
6361    if (blob != (void *) NULL)
6362      goto PerlEnd;
6363
6364  PerlException:
6365    InheritPerlException(exception,perl_exception);
6366    exception=DestroyExceptionInfo(exception);
6367    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6368
6369  PerlEnd:
6370    RETVAL = blob;
6371  }
6372  OUTPUT:
6373    RETVAL
6374
6375#
6376###############################################################################
6377#                                                                             #
6378#                                                                             #
6379#                                                                             #
6380#   H i s t o g r a m                                                         #
6381#                                                                             #
6382#                                                                             #
6383#                                                                             #
6384###############################################################################
6385#
6386#
6387void
6388Histogram(ref,...)
6389  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6390  ALIAS:
6391    HistogramImage = 1
6392    histogram      = 2
6393    histogramimage = 3
6394  PPCODE:
6395  {
6396    AV
6397      *av;
6398
6399    char
6400      message[MagickPathExtent];
6401
6402    PixelInfo
6403      *histogram;
6404
6405    ExceptionInfo
6406      *exception;
6407
6408    Image
6409      *image;
6410
6411    ssize_t
6412      i;
6413
6414    ssize_t
6415      count;
6416
6417    struct PackageInfo
6418      *info;
6419
6420    SV
6421      *perl_exception,
6422      *reference;
6423
6424    size_t
6425      number_colors;
6426
6427    PERL_UNUSED_VAR(ref);
6428    PERL_UNUSED_VAR(ix);
6429    exception=AcquireExceptionInfo();
6430    perl_exception=newSVpv("",0);
6431    av=NULL;
6432    if (sv_isobject(ST(0)) == 0)
6433      {
6434        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6435          PackageName);
6436        goto PerlException;
6437      }
6438    reference=SvRV(ST(0));
6439    av=newAV();
6440    SvREFCNT_dec(av);
6441    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6442    if (image == (Image *) NULL)
6443      {
6444        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6445          PackageName);
6446        goto PerlException;
6447      }
6448    count=0;
6449    for ( ; image; image=image->next)
6450    {
6451      histogram=GetImageHistogram(image,&number_colors,exception);
6452      if (histogram == (PixelInfo *) NULL)
6453        continue;
6454      count+=(ssize_t) number_colors;
6455      EXTEND(sp,6*count);
6456      for (i=0; i < (ssize_t) number_colors; i++)
6457      {
6458        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6459          histogram[i].red);
6460        PUSHs(sv_2mortal(newSVpv(message,0)));
6461        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6462          histogram[i].green);
6463        PUSHs(sv_2mortal(newSVpv(message,0)));
6464        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6465          histogram[i].blue);
6466        PUSHs(sv_2mortal(newSVpv(message,0)));
6467        if (image->colorspace == CMYKColorspace)
6468          {
6469            (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6470              histogram[i].black);
6471            PUSHs(sv_2mortal(newSVpv(message,0)));
6472          }
6473        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6474          histogram[i].alpha);
6475        PUSHs(sv_2mortal(newSVpv(message,0)));
6476        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6477          histogram[i].count);
6478        PUSHs(sv_2mortal(newSVpv(message,0)));
6479      }
6480      histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6481    }
6482
6483  PerlException:
6484    InheritPerlException(exception,perl_exception);
6485    exception=DestroyExceptionInfo(exception);
6486    SvREFCNT_dec(perl_exception);
6487  }
6488
6489#
6490###############################################################################
6491#                                                                             #
6492#                                                                             #
6493#                                                                             #
6494#   G e t P i x e l                                                           #
6495#                                                                             #
6496#                                                                             #
6497#                                                                             #
6498###############################################################################
6499#
6500#
6501void
6502GetPixel(ref,...)
6503  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6504  ALIAS:
6505    getpixel = 1
6506    getPixel = 2
6507  PPCODE:
6508  {
6509    AV
6510      *av;
6511
6512    char
6513      *attribute;
6514
6515    ExceptionInfo
6516      *exception;
6517
6518    Image
6519      *image;
6520
6521    MagickBooleanType
6522      normalize;
6523
6524    RectangleInfo
6525      region;
6526
6527    const Quantum
6528      *p;
6529
6530    ssize_t
6531      i;
6532
6533    ssize_t
6534      option;
6535
6536    struct PackageInfo
6537      *info;
6538
6539    SV
6540      *perl_exception,
6541      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6542
6543    PERL_UNUSED_VAR(ref);
6544    PERL_UNUSED_VAR(ix);
6545    exception=AcquireExceptionInfo();
6546    perl_exception=newSVpv("",0);
6547    reference=SvRV(ST(0));
6548    av=(AV *) reference;
6549    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6550      exception);
6551    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6552    if (image == (Image *) NULL)
6553      {
6554        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6555          PackageName);
6556        goto PerlException;
6557      }
6558    normalize=MagickTrue;
6559    region.x=0;
6560    region.y=0;
6561    region.width=image->columns;
6562    region.height=1;
6563    if (items == 1)
6564      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6565    for (i=2; i < items; i+=2)
6566    {
6567      attribute=(char *) SvPV(ST(i-1),na);
6568      switch (*attribute)
6569      {
6570        case 'C':
6571        case 'c':
6572        {
6573          if (LocaleCompare(attribute,"channel") == 0)
6574            {
6575              ssize_t
6576                option;
6577
6578              option=ParseChannelOption(SvPV(ST(i),na));
6579              if (option < 0)
6580                {
6581                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6582                    SvPV(ST(i),na));
6583                  return;
6584                }
6585              (void) SetPixelChannelMask(image,(ChannelType) option);
6586              break;
6587            }
6588          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6589            attribute);
6590          break;
6591        }
6592        case 'g':
6593        case 'G':
6594        {
6595          if (LocaleCompare(attribute,"geometry") == 0)
6596            {
6597              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6598              break;
6599            }
6600          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6601            attribute);
6602          break;
6603        }
6604        case 'N':
6605        case 'n':
6606        {
6607          if (LocaleCompare(attribute,"normalize") == 0)
6608            {
6609              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6610                SvPV(ST(i),na));
6611              if (option < 0)
6612                {
6613                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6614                    SvPV(ST(i),na));
6615                  break;
6616                }
6617             normalize=option != 0 ? MagickTrue : MagickFalse;
6618             break;
6619            }
6620          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6621            attribute);
6622          break;
6623        }
6624        case 'x':
6625        case 'X':
6626        {
6627          if (LocaleCompare(attribute,"x") == 0)
6628            {
6629              region.x=SvIV(ST(i));
6630              break;
6631            }
6632          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6633            attribute);
6634          break;
6635        }
6636        case 'y':
6637        case 'Y':
6638        {
6639          if (LocaleCompare(attribute,"y") == 0)
6640            {
6641              region.y=SvIV(ST(i));
6642              break;
6643            }
6644          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6645            attribute);
6646          break;
6647        }
6648        default:
6649        {
6650          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6651            attribute);
6652          break;
6653        }
6654      }
6655    }
6656    p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6657    if (p == (const Quantum *) NULL)
6658      PUSHs(&sv_undef);
6659    else
6660      {
6661        double
6662          scale;
6663
6664        scale=1.0;
6665        if (normalize != MagickFalse)
6666          scale=1.0/QuantumRange;
6667        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6668          PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6669        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6670          PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6671        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6672          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6673        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6674            (image->colorspace == CMYKColorspace))
6675          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6676        if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6677          PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6678      }
6679
6680  PerlException:
6681    InheritPerlException(exception,perl_exception);
6682    exception=DestroyExceptionInfo(exception);
6683    SvREFCNT_dec(perl_exception);
6684  }
6685
6686#
6687###############################################################################
6688#                                                                             #
6689#                                                                             #
6690#                                                                             #
6691#   G e t P i x e l s                                                         #
6692#                                                                             #
6693#                                                                             #
6694#                                                                             #
6695###############################################################################
6696#
6697#
6698void
6699GetPixels(ref,...)
6700  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6701  ALIAS:
6702    getpixels = 1
6703    getPixels = 2
6704  PPCODE:
6705  {
6706    AV
6707      *av;
6708
6709    char
6710      *attribute;
6711
6712    const char
6713      *map;
6714
6715    ExceptionInfo
6716      *exception;
6717
6718    Image
6719      *image;
6720
6721    MagickBooleanType
6722      normalize,
6723      status;
6724
6725    RectangleInfo
6726      region;
6727
6728    ssize_t
6729      i;
6730
6731    ssize_t
6732      option;
6733
6734    struct PackageInfo
6735      *info;
6736
6737    SV
6738      *perl_exception,
6739      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6740
6741    PERL_UNUSED_VAR(ref);
6742    PERL_UNUSED_VAR(ix);
6743    exception=AcquireExceptionInfo();
6744    perl_exception=newSVpv("",0);
6745    reference=SvRV(ST(0));
6746    av=(AV *) reference;
6747    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6748      exception);
6749    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6750    if (image == (Image *) NULL)
6751      {
6752        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6753          PackageName);
6754        goto PerlException;
6755      }
6756    map="RGB";
6757    if (image->alpha_trait != UndefinedPixelTrait)
6758      map="RGBA";
6759    if (image->colorspace == CMYKColorspace)
6760      {
6761        map="CMYK";
6762        if (image->alpha_trait != UndefinedPixelTrait)
6763          map="CMYKA";
6764      }
6765    normalize=MagickFalse;
6766    region.x=0;
6767    region.y=0;
6768    region.width=image->columns;
6769    region.height=1;
6770    if (items == 1)
6771      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6772    for (i=2; i < items; i+=2)
6773    {
6774      attribute=(char *) SvPV(ST(i-1),na);
6775      switch (*attribute)
6776      {
6777        case 'g':
6778        case 'G':
6779        {
6780          if (LocaleCompare(attribute,"geometry") == 0)
6781            {
6782              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6783              break;
6784            }
6785          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6786            attribute);
6787          break;
6788        }
6789        case 'H':
6790        case 'h':
6791        {
6792          if (LocaleCompare(attribute,"height") == 0)
6793            {
6794              region.height=SvIV(ST(i));
6795              break;
6796            }
6797          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6798            attribute);
6799          break;
6800        }
6801        case 'M':
6802        case 'm':
6803        {
6804          if (LocaleCompare(attribute,"map") == 0)
6805            {
6806              map=SvPV(ST(i),na);
6807              break;
6808            }
6809          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6810            attribute);
6811          break;
6812        }
6813        case 'N':
6814        case 'n':
6815        {
6816          if (LocaleCompare(attribute,"normalize") == 0)
6817            {
6818              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6819                SvPV(ST(i),na));
6820              if (option < 0)
6821                {
6822                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6823                    SvPV(ST(i),na));
6824                  break;
6825                }
6826             normalize=option != 0 ? MagickTrue : MagickFalse;
6827             break;
6828            }
6829          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6830            attribute);
6831          break;
6832        }
6833        case 'W':
6834        case 'w':
6835        {
6836          if (LocaleCompare(attribute,"width") == 0)
6837            {
6838              region.width=SvIV(ST(i));
6839              break;
6840            }
6841          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6842            attribute);
6843          break;
6844        }
6845        case 'x':
6846        case 'X':
6847        {
6848          if (LocaleCompare(attribute,"x") == 0)
6849            {
6850              region.x=SvIV(ST(i));
6851              break;
6852            }
6853          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6854            attribute);
6855          break;
6856        }
6857        case 'y':
6858        case 'Y':
6859        {
6860          if (LocaleCompare(attribute,"y") == 0)
6861            {
6862              region.y=SvIV(ST(i));
6863              break;
6864            }
6865          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6866            attribute);
6867          break;
6868        }
6869        default:
6870        {
6871          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6872            attribute);
6873          break;
6874        }
6875      }
6876    }
6877    if (normalize != MagickFalse)
6878      {
6879        float
6880          *pixels;
6881
6882        MemoryInfo
6883          *pixels_info;
6884
6885        pixels_info=AcquireVirtualMemory(strlen(map)*region.width,
6886          region.height*sizeof(*pixels));
6887        if (pixels_info == (MemoryInfo *) NULL)
6888          {
6889            ThrowPerlException(exception,ResourceLimitError,
6890              "MemoryAllocationFailed",PackageName);
6891            goto PerlException;
6892          }
6893        pixels=(float *) GetVirtualMemoryBlob(pixels_info);
6894        status=ExportImagePixels(image,region.x,region.y,region.width,
6895          region.height,map,FloatPixel,pixels,exception);
6896        if (status == MagickFalse)
6897          PUSHs(&sv_undef);
6898        else
6899          {
6900            EXTEND(sp,strlen(map)*region.width*region.height);
6901            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6902              PUSHs(sv_2mortal(newSVnv(pixels[i])));
6903          }
6904        pixels_info=RelinquishVirtualMemory(pixels_info);
6905      }
6906    else
6907      {
6908        MemoryInfo
6909          *pixels_info;
6910
6911        Quantum
6912          *pixels;
6913
6914        pixels_info=AcquireVirtualMemory(strlen(map)*region.width,
6915          region.height*sizeof(*pixels));
6916        if (pixels_info == (MemoryInfo *) NULL)
6917          {
6918            ThrowPerlException(exception,ResourceLimitError,
6919              "MemoryAllocationFailed",PackageName);
6920            goto PerlException;
6921          }
6922        pixels=(Quantum *) GetVirtualMemoryBlob(pixels_info);
6923        status=ExportImagePixels(image,region.x,region.y,region.width,
6924          region.height,map,QuantumPixel,pixels,exception);
6925        if (status == MagickFalse)
6926          PUSHs(&sv_undef);
6927        else
6928          {
6929            EXTEND(sp,strlen(map)*region.width*region.height);
6930            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6931              PUSHs(sv_2mortal(newSViv(pixels[i])));
6932          }
6933        pixels_info=RelinquishVirtualMemory(pixels_info);
6934      }
6935
6936  PerlException:
6937    InheritPerlException(exception,perl_exception);
6938    exception=DestroyExceptionInfo(exception);
6939    SvREFCNT_dec(perl_exception);
6940  }
6941
6942#
6943###############################################################################
6944#                                                                             #
6945#                                                                             #
6946#                                                                             #
6947#   I m a g e T o B l o b                                                     #
6948#                                                                             #
6949#                                                                             #
6950#                                                                             #
6951###############################################################################
6952#
6953#
6954void
6955ImageToBlob(ref,...)
6956  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6957  ALIAS:
6958    ImageToBlob  = 1
6959    imagetoblob  = 2
6960    toblob       = 3
6961    blob         = 4
6962  PPCODE:
6963  {
6964    char
6965      filename[MagickPathExtent];
6966
6967    ExceptionInfo
6968      *exception;
6969
6970    Image
6971      *image,
6972      *next;
6973
6974    ssize_t
6975      i;
6976
6977    struct PackageInfo
6978      *info,
6979      *package_info;
6980
6981    size_t
6982      length;
6983
6984    ssize_t
6985      scene;
6986
6987    SV
6988      *perl_exception,
6989      *reference;
6990
6991    void
6992      *blob;
6993
6994    PERL_UNUSED_VAR(ref);
6995    PERL_UNUSED_VAR(ix);
6996    exception=AcquireExceptionInfo();
6997    perl_exception=newSVpv("",0);
6998    package_info=(struct PackageInfo *) NULL;
6999    if (sv_isobject(ST(0)) == 0)
7000      {
7001        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7002          PackageName);
7003        goto PerlException;
7004      }
7005    reference=SvRV(ST(0));
7006    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7007    if (image == (Image *) NULL)
7008      {
7009        ThrowPerlException(exception,OptionError,"NoImagesDefined",
7010          PackageName);
7011        goto PerlException;
7012      }
7013    package_info=ClonePackageInfo(info,exception);
7014    for (i=2; i < items; i+=2)
7015      SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
7016    (void) CopyMagickString(filename,package_info->image_info->filename,
7017      MagickPathExtent);
7018    scene=0;
7019    for (next=image; next; next=next->next)
7020    {
7021      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
7022      next->scene=scene++;
7023    }
7024    SetImageInfo(package_info->image_info,(unsigned int)
7025      GetImageListLength(image),exception);
7026    EXTEND(sp,(ssize_t) GetImageListLength(image));
7027    for ( ; image; image=image->next)
7028    {
7029      length=0;
7030      blob=ImagesToBlob(package_info->image_info,image,&length,exception);
7031      if (blob != (char *) NULL)
7032        {
7033          PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
7034          blob=(unsigned char *) RelinquishMagickMemory(blob);
7035        }
7036      if (package_info->image_info->adjoin)
7037        break;
7038    }
7039
7040  PerlException:
7041    if (package_info != (struct PackageInfo *) NULL)
7042      DestroyPackageInfo(package_info);
7043    InheritPerlException(exception,perl_exception);
7044    exception=DestroyExceptionInfo(exception);
7045    SvREFCNT_dec(perl_exception);  /* throw away all errors */
7046  }
7047
7048#
7049###############################################################################
7050#                                                                             #
7051#                                                                             #
7052#                                                                             #
7053#   L a y e r s                                                               #
7054#                                                                             #
7055#                                                                             #
7056#                                                                             #
7057###############################################################################
7058#
7059#
7060void
7061Layers(ref,...)
7062  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7063  ALIAS:
7064    Layers                = 1
7065    layers           = 2
7066    OptimizeImageLayers   = 3
7067    optimizelayers        = 4
7068    optimizeimagelayers   = 5
7069  PPCODE:
7070  {
7071    AV
7072      *av;
7073
7074    char
7075      *attribute;
7076
7077    CompositeOperator
7078      compose;
7079
7080    ExceptionInfo
7081      *exception;
7082
7083    HV
7084      *hv;
7085
7086    Image
7087      *image,
7088      *layers;
7089
7090    LayerMethod
7091      method;
7092
7093    ssize_t
7094      i;
7095
7096    ssize_t
7097      option,
7098      sp;
7099
7100    struct PackageInfo
7101      *info;
7102
7103    SV
7104      *av_reference,
7105      *perl_exception,
7106      *reference,
7107      *rv,
7108      *sv;
7109
7110    PERL_UNUSED_VAR(ref);
7111    PERL_UNUSED_VAR(ix);
7112    exception=AcquireExceptionInfo();
7113    perl_exception=newSVpv("",0);
7114    sv=NULL;
7115    if (sv_isobject(ST(0)) == 0)
7116      {
7117        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7118          PackageName);
7119        goto PerlException;
7120      }
7121    reference=SvRV(ST(0));
7122    hv=SvSTASH(reference);
7123    av=newAV();
7124    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7125    SvREFCNT_dec(av);
7126    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7127    if (image == (Image *) NULL)
7128      {
7129        ThrowPerlException(exception,OptionError,"NoImagesDefined",
7130          PackageName);
7131        goto PerlException;
7132      }
7133    compose=image->compose;
7134    method=OptimizeLayer;
7135    for (i=2; i < items; i+=2)
7136    {
7137      attribute=(char *) SvPV(ST(i-1),na);
7138      switch (*attribute)
7139      {
7140        case 'C':
7141        case 'c':
7142        {
7143          if (LocaleCompare(attribute,"compose") == 0)
7144            {
7145              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7146                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7147              if (sp < 0)
7148                {
7149                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7150                    SvPV(ST(i),na));
7151                  break;
7152                }
7153              compose=(CompositeOperator) sp;
7154              break;
7155            }
7156          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7157            attribute);
7158          break;
7159        }
7160        case 'M':
7161        case 'm':
7162        {
7163          if (LocaleCompare(attribute,"method") == 0)
7164            {
7165              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7166                SvPV(ST(i),na));
7167              if (option < 0)
7168                {
7169                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7170                    SvPV(ST(i),na));
7171                  break;
7172                }
7173              method=(LayerMethod) option;
7174              break;
7175            }
7176          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7177            attribute);
7178          break;
7179        }
7180        default:
7181        {
7182          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7183            attribute);
7184          break;
7185        }
7186      }
7187    }
7188    layers=(Image *) NULL;
7189    switch (method)
7190    {
7191      case CompareAnyLayer:
7192      case CompareClearLayer:
7193      case CompareOverlayLayer:
7194      default:
7195      {
7196        layers=CompareImagesLayers(image,method,exception);
7197        break;
7198      }
7199      case MergeLayer:
7200      case FlattenLayer:
7201      case MosaicLayer:
7202      {
7203        layers=MergeImageLayers(image,method,exception);
7204        break;
7205      }
7206      case DisposeLayer:
7207      {
7208        layers=DisposeImages(image,exception);
7209        break;
7210      }
7211      case OptimizeImageLayer:
7212      {
7213        layers=OptimizeImageLayers(image,exception);
7214        break;
7215      }
7216      case OptimizePlusLayer:
7217      {
7218        layers=OptimizePlusImageLayers(image,exception);
7219        break;
7220      }
7221      case OptimizeTransLayer:
7222      {
7223        OptimizeImageTransparency(image,exception);
7224        break;
7225      }
7226      case RemoveDupsLayer:
7227      {
7228        RemoveDuplicateLayers(&image,exception);
7229        break;
7230      }
7231      case RemoveZeroLayer:
7232      {
7233        RemoveZeroDelayLayers(&image,exception);
7234        break;
7235      }
7236      case OptimizeLayer:
7237      {
7238        QuantizeInfo
7239          *quantize_info;
7240
7241        /*
7242          General Purpose, GIF Animation Optimizer.
7243        */
7244        layers=CoalesceImages(image,exception);
7245        if (layers == (Image *) NULL)
7246          break;
7247        image=layers;
7248        layers=OptimizeImageLayers(image,exception);
7249        if (layers == (Image *) NULL)
7250          break;
7251        image=DestroyImageList(image);
7252        image=layers;
7253        layers=(Image *) NULL;
7254        OptimizeImageTransparency(image,exception);
7255        quantize_info=AcquireQuantizeInfo(info->image_info);
7256        (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7257        quantize_info=DestroyQuantizeInfo(quantize_info);
7258        break;
7259      }
7260      case CompositeLayer:
7261      {
7262        Image
7263          *source;
7264
7265        RectangleInfo
7266          geometry;
7267
7268        /*
7269          Split image sequence at the first 'NULL:' image.
7270        */
7271        source=image;
7272        while (source != (Image *) NULL)
7273        {
7274          source=GetNextImageInList(source);
7275          if ((source != (Image *) NULL) &&
7276              (LocaleCompare(source->magick,"NULL") == 0))
7277            break;
7278        }
7279        if (source != (Image *) NULL)
7280          {
7281            if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7282                (GetNextImageInList(source) == (Image *) NULL))
7283              source=(Image *) NULL;
7284            else
7285              {
7286                /*
7287                  Separate the two lists, junk the null: image.
7288                */
7289                source=SplitImageList(source->previous);
7290                DeleteImageFromList(&source);
7291              }
7292          }
7293        if (source == (Image *) NULL)
7294          {
7295            (void) ThrowMagickException(exception,GetMagickModule(),
7296              OptionError,"MissingNullSeparator","layers Composite");
7297            break;
7298          }
7299        /*
7300          Adjust offset with gravity and virtual canvas.
7301        */
7302        SetGeometry(image,&geometry);
7303        (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7304        geometry.width=source->page.width != 0 ? source->page.width :
7305          source->columns;
7306        geometry.height=source->page.height != 0 ? source->page.height :
7307          source->rows;
7308        GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7309          image->columns,image->page.height != 0 ? image->page.height :
7310          image->rows,image->gravity,&geometry);
7311        CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7312        source=DestroyImageList(source);
7313        break;
7314      }
7315    }
7316    if (layers != (Image *) NULL)
7317      image=layers;
7318    else
7319      image=CloneImage(image,0,0,MagickTrue,exception);
7320    if (image == (Image *) NULL)
7321      goto PerlException;
7322    for ( ; image; image=image->next)
7323    {
7324      AddImageToRegistry(sv,image);
7325      rv=newRV(sv);
7326      av_push(av,sv_bless(rv,hv));
7327      SvREFCNT_dec(sv);
7328    }
7329    exception=DestroyExceptionInfo(exception);
7330    ST(0)=av_reference;
7331    SvREFCNT_dec(perl_exception);
7332    XSRETURN(1);
7333
7334  PerlException:
7335    InheritPerlException(exception,perl_exception);
7336    exception=DestroyExceptionInfo(exception);
7337    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7338    SvPOK_on(perl_exception);
7339    ST(0)=sv_2mortal(perl_exception);
7340    XSRETURN(1);
7341  }
7342
7343#
7344###############################################################################
7345#                                                                             #
7346#                                                                             #
7347#                                                                             #
7348#   M a g i c k T o M i m e                                                   #
7349#                                                                             #
7350#                                                                             #
7351#                                                                             #
7352###############################################################################
7353#
7354#
7355SV *
7356MagickToMime(ref,name)
7357  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7358  char *name
7359  ALIAS:
7360    magicktomime = 1
7361  CODE:
7362  {
7363    char
7364      *mime;
7365
7366    PERL_UNUSED_VAR(ref);
7367    PERL_UNUSED_VAR(ix);
7368    mime=MagickToMime(name);
7369    RETVAL=newSVpv(mime,0);
7370    mime=(char *) RelinquishMagickMemory(mime);
7371  }
7372  OUTPUT:
7373    RETVAL
7374
7375#
7376###############################################################################
7377#                                                                             #
7378#                                                                             #
7379#                                                                             #
7380#   M o g r i f y                                                             #
7381#                                                                             #
7382#                                                                             #
7383#                                                                             #
7384###############################################################################
7385#
7386#
7387void
7388Mogrify(ref,...)
7389  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7390  ALIAS:
7391    Comment            =   1
7392    CommentImage       =   2
7393    Label              =   3
7394    LabelImage         =   4
7395    AddNoise           =   5
7396    AddNoiseImage      =   6
7397    Colorize           =   7
7398    ColorizeImage      =   8
7399    Border             =   9
7400    BorderImage        =  10
7401    Blur               =  11
7402    BlurImage          =  12
7403    Chop               =  13
7404    ChopImage          =  14
7405    Crop               =  15
7406    CropImage          =  16
7407    Despeckle          =  17
7408    DespeckleImage     =  18
7409    Edge               =  19
7410    EdgeImage          =  20
7411    Emboss             =  21
7412    EmbossImage        =  22
7413    Enhance            =  23
7414    EnhanceImage       =  24
7415    Flip               =  25
7416    FlipImage          =  26
7417    Flop               =  27
7418    FlopImage          =  28
7419    Frame              =  29
7420    FrameImage         =  30
7421    Implode            =  31
7422    ImplodeImage       =  32
7423    Magnify            =  33
7424    MagnifyImage       =  34
7425    MedianFilter       =  35
7426    MedianConvolveImage  =  36
7427    Minify             =  37
7428    MinifyImage        =  38
7429    OilPaint           =  39
7430    OilPaintImage      =  40
7431    ReduceNoise        =  41
7432    ReduceNoiseImage   =  42
7433    Roll               =  43
7434    RollImage          =  44
7435    Rotate             =  45
7436    RotateImage        =  46
7437    Sample             =  47
7438    SampleImage        =  48
7439    Scale              =  49
7440    ScaleImage         =  50
7441    Shade              =  51
7442    ShadeImage         =  52
7443    Sharpen            =  53
7444    SharpenImage       =  54
7445    Shear              =  55
7446    ShearImage         =  56
7447    Spread             =  57
7448    SpreadImage        =  58
7449    Swirl              =  59
7450    SwirlImage         =  60
7451    Resize             =  61
7452    ResizeImage        =  62
7453    Zoom               =  63
7454    ZoomImage          =  64
7455    Annotate           =  65
7456    AnnotateImage      =  66
7457    ColorFloodfill     =  67
7458    ColorFloodfillImage=  68
7459    Composite          =  69
7460    CompositeImage     =  70
7461    Contrast           =  71
7462    ContrastImage      =  72
7463    CycleColormap      =  73
7464    CycleColormapImage =  74
7465    Draw               =  75
7466    DrawImage          =  76
7467    Equalize           =  77
7468    EqualizeImage      =  78
7469    Gamma              =  79
7470    GammaImage         =  80
7471    Map                =  81
7472    MapImage           =  82
7473    MatteFloodfill     =  83
7474    MatteFloodfillImage=  84
7475    Modulate           =  85
7476    ModulateImage      =  86
7477    Negate             =  87
7478    NegateImage        =  88
7479    Normalize          =  89
7480    NormalizeImage     =  90
7481    NumberColors       =  91
7482    NumberColorsImage  =  92
7483    Opaque             =  93
7484    OpaqueImage        =  94
7485    Quantize           =  95
7486    QuantizeImage      =  96
7487    Raise              =  97
7488    RaiseImage         =  98
7489    Segment            =  99
7490    SegmentImage       = 100
7491    Signature          = 101
7492    SignatureImage     = 102
7493    Solarize           = 103
7494    SolarizeImage      = 104
7495    Sync               = 105
7496    SyncImage          = 106
7497    Texture            = 107
7498    TextureImage       = 108
7499    Evaluate           = 109
7500    EvaluateImage      = 110
7501    Transparent        = 111
7502    TransparentImage   = 112
7503    Threshold          = 113
7504    ThresholdImage     = 114
7505    Charcoal           = 115
7506    CharcoalImage      = 116
7507    Trim               = 117
7508    TrimImage          = 118
7509    Wave               = 119
7510    WaveImage          = 120
7511    Separate           = 121
7512    SeparateImage      = 122
7513    Stereo             = 125
7514    StereoImage        = 126
7515    Stegano            = 127
7516    SteganoImage       = 128
7517    Deconstruct        = 129
7518    DeconstructImage   = 130
7519    GaussianBlur       = 131
7520    GaussianBlurImage  = 132
7521    Convolve           = 133
7522    ConvolveImage      = 134
7523    Profile            = 135
7524    ProfileImage       = 136
7525    UnsharpMask        = 137
7526    UnsharpMaskImage   = 138
7527    MotionBlur         = 139
7528    MotionBlurImage    = 140
7529    OrderedDither      = 141
7530    OrderedDitherImage = 142
7531    Shave              = 143
7532    ShaveImage         = 144
7533    Level              = 145
7534    LevelImage         = 146
7535    Clip               = 147
7536    ClipImage          = 148
7537    AffineTransform    = 149
7538    AffineTransformImage = 150
7539    Difference         = 151
7540    DifferenceImage    = 152
7541    AdaptiveThreshold  = 153
7542    AdaptiveThresholdImage = 154
7543    Resample           = 155
7544    ResampleImage      = 156
7545    Describe           = 157
7546    DescribeImage      = 158
7547    BlackThreshold     = 159
7548    BlackThresholdImage= 160
7549    WhiteThreshold     = 161
7550    WhiteThresholdImage= 162
7551    RotationalBlur     = 163
7552    RotationalBlurImage= 164
7553    Thumbnail          = 165
7554    ThumbnailImage     = 166
7555    Strip              = 167
7556    StripImage         = 168
7557    Tint               = 169
7558    TintImage          = 170
7559    Channel            = 171
7560    ChannelImage       = 172
7561    Splice             = 173
7562    SpliceImage        = 174
7563    Posterize          = 175
7564    PosterizeImage     = 176
7565    Shadow             = 177
7566    ShadowImage        = 178
7567    Identify           = 179
7568    IdentifyImage      = 180
7569    SepiaTone          = 181
7570    SepiaToneImage     = 182
7571    SigmoidalContrast  = 183
7572    SigmoidalContrastImage = 184
7573    Extent             = 185
7574    ExtentImage        = 186
7575    Vignette           = 187
7576    VignetteImage      = 188
7577    ContrastStretch    = 189
7578    ContrastStretchImage = 190
7579    Sans0              = 191
7580    Sans0Image         = 192
7581    Sans1              = 193
7582    Sans1Image         = 194
7583    AdaptiveSharpen    = 195
7584    AdaptiveSharpenImage = 196
7585    Transpose          = 197
7586    TransposeImage     = 198
7587    Transverse         = 199
7588    TransverseImage    = 200
7589    AutoOrient         = 201
7590    AutoOrientImage    = 202
7591    AdaptiveBlur       = 203
7592    AdaptiveBlurImage  = 204
7593    Sketch             = 205
7594    SketchImage        = 206
7595    UniqueColors       = 207
7596    UniqueColorsImage  = 208
7597    AdaptiveResize     = 209
7598    AdaptiveResizeImage= 210
7599    ClipMask           = 211
7600    ClipMaskImage      = 212
7601    LinearStretch      = 213
7602    LinearStretchImage = 214
7603    ColorMatrix        = 215
7604    ColorMatrixImage   = 216
7605    Mask               = 217
7606    MaskImage          = 218
7607    Polaroid           = 219
7608    PolaroidImage      = 220
7609    FloodfillPaint     = 221
7610    FloodfillPaintImage= 222
7611    Distort            = 223
7612    DistortImage       = 224
7613    Clut               = 225
7614    ClutImage          = 226
7615    LiquidRescale      = 227
7616    LiquidRescaleImage = 228
7617    Encipher           = 229
7618    EncipherImage      = 230
7619    Decipher           = 231
7620    DecipherImage      = 232
7621    Deskew             = 233
7622    DeskewImage        = 234
7623    Remap              = 235
7624    RemapImage         = 236
7625    SparseColor        = 237
7626    SparseColorImage   = 238
7627    Function           = 239
7628    FunctionImage      = 240
7629    SelectiveBlur      = 241
7630    SelectiveBlurImage = 242
7631    HaldClut           = 243
7632    HaldClutImage      = 244
7633    BlueShift          = 245
7634    BlueShiftImage     = 246
7635    ForwardFourierTransform  = 247
7636    ForwardFourierTransformImage = 248
7637    InverseFourierTransform = 249
7638    InverseFourierTransformImage = 250
7639    ColorDecisionList  = 251
7640    ColorDecisionListImage = 252
7641    AutoGamma          = 253
7642    AutoGammaImage     = 254
7643    AutoLevel          = 255
7644    AutoLevelImage     = 256
7645    LevelColors        = 257
7646    LevelImageColors   = 258
7647    Clamp              = 259
7648    ClampImage         = 260
7649    BrightnessContrast = 261
7650    BrightnessContrastImage = 262
7651    Morphology         = 263
7652    MorphologyImage    = 264
7653    Mode               = 265
7654    ModeImage          = 266
7655    Statistic          = 267
7656    StatisticImage     = 268
7657    Perceptible        = 269
7658    PerceptibleImage   = 270
7659    Poly               = 271
7660    PolyImage          = 272
7661    Grayscale          = 273
7662    GrayscaleImage     = 274
7663    CannyEdge          = 275
7664    CannyEdgeImage     = 276
7665    HoughLine          = 277
7666    HoughLineImage     = 278
7667    MeanShift          = 279
7668    MeanShiftImage     = 280
7669    Kuwahara           = 281
7670    KuwaharaImage      = 282
7671    ConnectedComponents = 283
7672    ConnectedComponentsImage = 284
7673    CopyPixels         = 285
7674    CopyImagePixels    = 286
7675    Color              = 287
7676    ColorImage         = 288
7677    WaveletDenoise     = 289
7678    WaveletDenoiseImage= 290
7679    Colorspace         = 291
7680    ColorspaceImage    = 292
7681    AutoThreshold      = 293
7682    AutoThresholdImage = 294
7683    RangeThreshold     = 295
7684    RangeThresholdImage= 296
7685    CLAHE              = 297
7686    CLAHEImage         = 298
7687    Kmeans             = 299
7688    KMeansImage        = 300
7689    ColorThreshold     = 301
7690    ColorThresholdImage= 302
7691    WhiteBalance       = 303
7692    WhiteBalanceImage  = 304
7693    BilateralBlur      = 305
7694    BilateralBlurImage = 306
7695    SortPixels         = 307
7696    SortPixelsImage    = 308
7697    MogrifyRegion      = 666
7698  PPCODE:
7699  {
7700    AffineMatrix
7701      affine,
7702      current;
7703
7704    char
7705      attribute_flag[MaxArguments],
7706      message[MagickPathExtent];
7707
7708    ChannelType
7709      channel,
7710      channel_mask;
7711
7712    CompositeOperator
7713      compose;
7714
7715    const char
7716      *attribute,
7717      *value;
7718
7719    double
7720      angle;
7721
7722    ExceptionInfo
7723      *exception;
7724
7725    GeometryInfo
7726      geometry_info;
7727
7728    Image
7729      *image,
7730      *next;
7731
7732    MagickStatusType
7733      flags;
7734
7735    PixelInfo
7736      fill_color;
7737
7738    RectangleInfo
7739      geometry,
7740      region_info;
7741
7742    ssize_t
7743      i;
7744
7745    ssize_t
7746      base,
7747      j,
7748      number_images;
7749
7750    struct Methods
7751      *rp;
7752
7753    struct PackageInfo
7754      *info;
7755
7756    SV
7757      *perl_exception,
7758      **pv,
7759      *reference,
7760      **reference_vector;
7761
7762    struct ArgumentList
7763      argument_list[MaxArguments];
7764
7765    PERL_UNUSED_VAR(ref);
7766    PERL_UNUSED_VAR(ix);
7767    exception=AcquireExceptionInfo();
7768    perl_exception=newSVpv("",0);
7769    reference_vector=NULL;
7770    number_images=0;
7771    base=2;
7772    if (sv_isobject(ST(0)) == 0)
7773      {
7774        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7775          PackageName);
7776        goto PerlException;
7777      }
7778    reference=SvRV(ST(0));
7779    region_info.width=0;
7780    region_info.height=0;
7781    region_info.x=0;
7782    region_info.y=0;
7783    image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7784    if (ix && (ix != 666))
7785      {
7786        /*
7787          Called as Method(...)
7788        */
7789        ix=(ix+1)/2;
7790        rp=(&Methods[ix-1]);
7791        attribute=rp->name;
7792      }
7793    else
7794      {
7795        /*
7796          Called as Mogrify("Method",...)
7797        */
7798        attribute=(char *) SvPV(ST(1),na);
7799        if (ix)
7800          {
7801            flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7802            attribute=(char *) SvPV(ST(2),na);
7803            base++;
7804          }
7805        for (rp=Methods; ; rp++)
7806        {
7807          if (rp >= EndOf(Methods))
7808            {
7809              ThrowPerlException(exception,OptionError,
7810                "UnrecognizedPerlMagickMethod",attribute);
7811              goto PerlException;
7812            }
7813          if (strEQcase(attribute,rp->name))
7814            break;
7815        }
7816        ix=rp-Methods+1;
7817        base++;
7818      }
7819    if (image == (Image *) NULL)
7820      {
7821        ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7822        goto PerlException;
7823      }
7824    Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7825    Zero(&attribute_flag,NumberOf(attribute_flag),char);
7826    for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7827    {
7828      Arguments
7829        *pp,
7830        *qq;
7831
7832      ssize_t
7833        ssize_test;
7834
7835      struct ArgumentList
7836        *al;
7837
7838      SV
7839        *sv;
7840
7841      sv=NULL;
7842      ssize_test=0;
7843      pp=(Arguments *) NULL;
7844      qq=rp->arguments;
7845      if (i == items)
7846        {
7847          pp=rp->arguments,
7848          sv=ST(i-1);
7849        }
7850      else
7851        for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7852        {
7853          if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7854            break;
7855          if (strEQcase(attribute,qq->method) > ssize_test)
7856            {
7857              pp=qq;
7858              ssize_test=strEQcase(attribute,qq->method);
7859            }
7860        }
7861      if (pp == (Arguments *) NULL)
7862        {
7863          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7864            attribute);
7865          goto continue_outer_loop;
7866        }
7867      al=(&argument_list[pp-rp->arguments]);
7868      switch (pp->type)
7869      {
7870        case ArrayReference:
7871        {
7872          if (SvTYPE(sv) != SVt_RV)
7873            {
7874              (void) FormatLocaleString(message,MagickPathExtent,
7875                "invalid %.60s value",pp->method);
7876              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7877              goto continue_outer_loop;
7878            }
7879          al->array_reference=SvRV(sv);
7880          break;
7881        }
7882        case RealReference:
7883        {
7884          al->real_reference=SvNV(sv);
7885          break;
7886        }
7887        case FileReference:
7888        {
7889          al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7890          break;
7891        }
7892        case ImageReference:
7893        {
7894          if (!sv_isobject(sv) ||
7895              !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7896                (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7897            {
7898              ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7899                PackageName);
7900              goto PerlException;
7901            }
7902          break;
7903        }
7904        case IntegerReference:
7905        {
7906          al->integer_reference=SvIV(sv);
7907          break;
7908        }
7909        case StringReference:
7910        {
7911          al->string_reference=(char *) SvPV(sv,al->length);
7912          if (sv_isobject(sv))
7913            al->image_reference=SetupList(aTHX_ SvRV(sv),
7914              (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7915          break;
7916        }
7917        default:
7918        {
7919          /*
7920            Is a string; look up name.
7921          */
7922          if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7923            {
7924              al->string_reference=(char *) SvPV(sv,al->length);
7925              al->integer_reference=(-1);
7926              break;
7927            }
7928          al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7929            MagickFalse,SvPV(sv,na));
7930          if (pp->type == MagickChannelOptions)
7931            al->integer_reference=ParseChannelOption(SvPV(sv,na));
7932          if ((al->integer_reference < 0) &&
7933              ((al->integer_reference=SvIV(sv)) <= 0))
7934            {
7935              (void) FormatLocaleString(message,MagickPathExtent,
7936                "invalid %.60s value",pp->method);
7937              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7938              goto continue_outer_loop;
7939            }
7940          break;
7941        }
7942      }
7943      attribute_flag[pp-rp->arguments]++;
7944      continue_outer_loop: ;
7945    }
7946    (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7947    pv=reference_vector;
7948    SetGeometryInfo(&geometry_info);
7949    channel=DefaultChannels;
7950    for (next=image; next; next=next->next)
7951    {
7952      image=next;
7953      SetGeometry(image,&geometry);
7954      if ((region_info.width*region_info.height) != 0)
7955        (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
7956      switch (ix)
7957      {
7958        default:
7959        {
7960          (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
7961            ix);
7962          ThrowPerlException(exception,OptionError,
7963            "UnrecognizedPerlMagickMethod",message);
7964          goto PerlException;
7965        }
7966        case 1:  /* Comment */
7967        {
7968          if (attribute_flag[0] == 0)
7969            argument_list[0].string_reference=(char *) NULL;
7970          (void) SetImageProperty(image,"comment",InterpretImageProperties(
7971            info ? info->image_info : (ImageInfo *) NULL,image,
7972            argument_list[0].string_reference,exception),exception);
7973          break;
7974        }
7975        case 2:  /* Label */
7976        {
7977          if (attribute_flag[0] == 0)
7978            argument_list[0].string_reference=(char *) NULL;
7979          (void) SetImageProperty(image,"label",InterpretImageProperties(
7980            info ? info->image_info : (ImageInfo *) NULL,image,
7981            argument_list[0].string_reference,exception),exception);
7982          break;
7983        }
7984        case 3:  /* AddNoise */
7985        {
7986          double
7987            attenuate;
7988
7989          if (attribute_flag[0] == 0)
7990            argument_list[0].integer_reference=UniformNoise;
7991          attenuate=1.0;
7992          if (attribute_flag[1] != 0)
7993            attenuate=argument_list[1].real_reference;
7994          if (attribute_flag[2] != 0)
7995            channel=(ChannelType) argument_list[2].integer_reference;
7996          channel_mask=SetImageChannelMask(image,channel);
7997          image=AddNoiseImage(image,(NoiseType)
7998            argument_list[0].integer_reference,attenuate,exception);
7999          if (image != (Image *) NULL)
8000            (void) SetImageChannelMask(image,channel_mask);
8001          break;
8002        }
8003        case 4:  /* Colorize */
8004        {
8005          PixelInfo
8006            target;
8007
8008          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,0,0,
8009            &target,exception);
8010          if (attribute_flag[0] != 0)
8011            (void) QueryColorCompliance(argument_list[0].string_reference,
8012              AllCompliance,&target,exception);
8013          if (attribute_flag[1] == 0)
8014            argument_list[1].string_reference="100%";
8015          image=ColorizeImage(image,argument_list[1].string_reference,&target,
8016            exception);
8017          break;
8018        }
8019        case 5:  /* Border */
8020        {
8021          CompositeOperator
8022            compose;
8023
8024          geometry.width=0;
8025          geometry.height=0;
8026          if (attribute_flag[0] != 0)
8027            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8028              &geometry,exception);
8029          if (attribute_flag[1] != 0)
8030            geometry.width=argument_list[1].integer_reference;
8031          if (attribute_flag[2] != 0)
8032            geometry.height=argument_list[2].integer_reference;
8033          if (attribute_flag[3] != 0)
8034            QueryColorCompliance(argument_list[3].string_reference,
8035              AllCompliance,&image->border_color,exception);
8036          if (attribute_flag[4] != 0)
8037            QueryColorCompliance(argument_list[4].string_reference,
8038              AllCompliance,&image->border_color,exception);
8039          if (attribute_flag[5] != 0)
8040            QueryColorCompliance(argument_list[5].string_reference,
8041              AllCompliance,&image->border_color,exception);
8042          compose=image->compose;
8043          if (attribute_flag[6] != 0)
8044            compose=(CompositeOperator) argument_list[6].integer_reference;
8045          image=BorderImage(image,&geometry,compose,exception);
8046          break;
8047        }
8048        case 6:  /* Blur */
8049        {
8050          if (attribute_flag[0] != 0)
8051            {
8052              flags=ParseGeometry(argument_list[0].string_reference,
8053                &geometry_info);
8054              if ((flags & SigmaValue) == 0)
8055                geometry_info.sigma=1.0;
8056            }
8057          if (attribute_flag[1] != 0)
8058            geometry_info.rho=argument_list[1].real_reference;
8059          if (attribute_flag[2] != 0)
8060            geometry_info.sigma=argument_list[2].real_reference;
8061          if (attribute_flag[3] != 0)
8062            channel=(ChannelType) argument_list[3].integer_reference;
8063          channel_mask=SetImageChannelMask(image,channel);
8064          image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8065            exception);
8066          if (image != (Image *) NULL)
8067            (void) SetImageChannelMask(image,channel_mask);
8068          break;
8069        }
8070        case 7:  /* Chop */
8071        {
8072          if (attribute_flag[5] != 0)
8073            image->gravity=(GravityType) argument_list[5].integer_reference;
8074          if (attribute_flag[0] != 0)
8075            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8076              &geometry,exception);
8077          if (attribute_flag[1] != 0)
8078            geometry.width=argument_list[1].integer_reference;
8079          if (attribute_flag[2] != 0)
8080            geometry.height=argument_list[2].integer_reference;
8081          if (attribute_flag[3] != 0)
8082            geometry.x=argument_list[3].integer_reference;
8083          if (attribute_flag[4] != 0)
8084            geometry.y=argument_list[4].integer_reference;
8085          image=ChopImage(image,&geometry,exception);
8086          break;
8087        }
8088        case 8:  /* Crop */
8089        {
8090          if (attribute_flag[6] != 0)
8091            image->gravity=(GravityType) argument_list[6].integer_reference;
8092          if (attribute_flag[0] != 0)
8093            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8094              &geometry,exception);
8095          if (attribute_flag[1] != 0)
8096            geometry.width=argument_list[1].integer_reference;
8097          if (attribute_flag[2] != 0)
8098            geometry.height=argument_list[2].integer_reference;
8099          if (attribute_flag[3] != 0)
8100            geometry.x=argument_list[3].integer_reference;
8101          if (attribute_flag[4] != 0)
8102            geometry.y=argument_list[4].integer_reference;
8103          if (attribute_flag[5] != 0)
8104            image->fuzz=StringToDoubleInterval(
8105              argument_list[5].string_reference,(double) QuantumRange+1.0);
8106          image=CropImage(image,&geometry,exception);
8107          break;
8108        }
8109        case 9:  /* Despeckle */
8110        {
8111          image=DespeckleImage(image,exception);
8112          break;
8113        }
8114        case 10:  /* Edge */
8115        {
8116          if (attribute_flag[0] != 0)
8117            geometry_info.rho=argument_list[0].real_reference;
8118          image=EdgeImage(image,geometry_info.rho,exception);
8119          break;
8120        }
8121        case 11:  /* Emboss */
8122        {
8123          if (attribute_flag[0] != 0)
8124            {
8125              flags=ParseGeometry(argument_list[0].string_reference,
8126                &geometry_info);
8127              if ((flags & SigmaValue) == 0)
8128                geometry_info.sigma=1.0;
8129            }
8130          if (attribute_flag[1] != 0)
8131            geometry_info.rho=argument_list[1].real_reference;
8132          if (attribute_flag[2] != 0)
8133            geometry_info.sigma=argument_list[2].real_reference;
8134          image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8135            exception);
8136          break;
8137        }
8138        case 12:  /* Enhance */
8139        {
8140          image=EnhanceImage(image,exception);
8141          break;
8142        }
8143        case 13:  /* Flip */
8144        {
8145          image=FlipImage(image,exception);
8146          break;
8147        }
8148        case 14:  /* Flop */
8149        {
8150          image=FlopImage(image,exception);
8151          break;
8152        }
8153        case 15:  /* Frame */
8154        {
8155          CompositeOperator
8156            compose;
8157
8158          FrameInfo
8159            frame_info;
8160
8161          if (attribute_flag[0] != 0)
8162            {
8163              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8164                &geometry,exception);
8165              frame_info.width=geometry.width;
8166              frame_info.height=geometry.height;
8167              frame_info.outer_bevel=geometry.x;
8168              frame_info.inner_bevel=geometry.y;
8169            }
8170          if (attribute_flag[1] != 0)
8171            frame_info.width=argument_list[1].integer_reference;
8172          if (attribute_flag[2] != 0)
8173            frame_info.height=argument_list[2].integer_reference;
8174          if (attribute_flag[3] != 0)
8175            frame_info.inner_bevel=argument_list[3].integer_reference;
8176          if (attribute_flag[4] != 0)
8177            frame_info.outer_bevel=argument_list[4].integer_reference;
8178          if (attribute_flag[5] != 0)
8179            QueryColorCompliance(argument_list[5].string_reference,
8180              AllCompliance,&fill_color,exception);
8181          if (attribute_flag[6] != 0)
8182            QueryColorCompliance(argument_list[6].string_reference,
8183              AllCompliance,&fill_color,exception);
8184          frame_info.x=(ssize_t) frame_info.width;
8185          frame_info.y=(ssize_t) frame_info.height;
8186          frame_info.width=image->columns+2*frame_info.x;
8187          frame_info.height=image->rows+2*frame_info.y;
8188          if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8189            image->alpha_color=fill_color;
8190          compose=image->compose;
8191          if (attribute_flag[7] != 0)
8192            compose=(CompositeOperator) argument_list[7].integer_reference;
8193          image=FrameImage(image,&frame_info,compose,exception);
8194          break;
8195        }
8196        case 16:  /* Implode */
8197        {
8198          PixelInterpolateMethod
8199            method;
8200
8201          if (attribute_flag[0] == 0)
8202            argument_list[0].real_reference=0.5;
8203          method=UndefinedInterpolatePixel;
8204          if (attribute_flag[1] != 0)
8205            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8206          image=ImplodeImage(image,argument_list[0].real_reference,
8207            method,exception);
8208          break;
8209        }
8210        case 17:  /* Magnify */
8211        {
8212          image=MagnifyImage(image,exception);
8213          break;
8214        }
8215        case 18:  /* MedianFilter */
8216        {
8217          if (attribute_flag[0] != 0)
8218            {
8219              flags=ParseGeometry(argument_list[0].string_reference,
8220                &geometry_info);
8221              if ((flags & SigmaValue) == 0)
8222                geometry_info.sigma=geometry_info.rho;
8223            }
8224          if (attribute_flag[1] != 0)
8225            geometry_info.rho=argument_list[1].real_reference;
8226          if (attribute_flag[2] != 0)
8227            geometry_info.sigma=argument_list[2].real_reference;
8228          if (attribute_flag[3] != 0)
8229            channel=(ChannelType) argument_list[3].integer_reference;
8230          channel_mask=SetImageChannelMask(image,channel);
8231          image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8232            (size_t) geometry_info.sigma,exception);
8233          if (image != (Image *) NULL)
8234            (void) SetImageChannelMask(image,channel_mask);
8235          break;
8236        }
8237        case 19:  /* Minify */
8238        {
8239          image=MinifyImage(image,exception);
8240          break;
8241        }
8242        case 20:  /* OilPaint */
8243        {
8244          if (attribute_flag[0] == 0)
8245            argument_list[0].real_reference=0.0;
8246          if (attribute_flag[1] == 0)
8247            argument_list[1].real_reference=1.0;
8248          image=OilPaintImage(image,argument_list[0].real_reference,
8249            argument_list[1].real_reference,exception);
8250          break;
8251        }
8252        case 21:  /* ReduceNoise */
8253        {
8254          if (attribute_flag[0] != 0)
8255            {
8256              flags=ParseGeometry(argument_list[0].string_reference,
8257                &geometry_info);
8258              if ((flags & SigmaValue) == 0)
8259                geometry_info.sigma=1.0;
8260            }
8261          if (attribute_flag[1] != 0)
8262            geometry_info.rho=argument_list[1].real_reference;
8263          if (attribute_flag[2] != 0)
8264            geometry_info.sigma=argument_list[2].real_reference;
8265          if (attribute_flag[3] != 0)
8266            channel=(ChannelType) argument_list[3].integer_reference;
8267          channel_mask=SetImageChannelMask(image,channel);
8268          image=StatisticImage(image,NonpeakStatistic,(size_t)
8269            geometry_info.rho,(size_t) geometry_info.sigma,exception);
8270          if (image != (Image *) NULL)
8271            (void) SetImageChannelMask(image,channel_mask);
8272          break;
8273        }
8274        case 22:  /* Roll */
8275        {
8276          if (attribute_flag[0] != 0)
8277            {
8278              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8279                &geometry,exception);
8280              if ((flags & PercentValue) != 0)
8281                {
8282                  geometry.x*=(double) image->columns/100.0;
8283                  geometry.y*=(double) image->rows/100.0;
8284                }
8285            }
8286          if (attribute_flag[1] != 0)
8287            geometry.x=argument_list[1].integer_reference;
8288          if (attribute_flag[2] != 0)
8289            geometry.y=argument_list[2].integer_reference;
8290          image=RollImage(image,geometry.x,geometry.y,exception);
8291          break;
8292        }
8293        case 23:  /* Rotate */
8294        {
8295          if (attribute_flag[0] == 0)
8296            argument_list[0].real_reference=90.0;
8297          if (attribute_flag[1] != 0)
8298            {
8299              QueryColorCompliance(argument_list[1].string_reference,
8300                AllCompliance,&image->background_color,exception);
8301              if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8302                  (image->alpha_trait == UndefinedPixelTrait))
8303                (void) SetImageAlpha(image,OpaqueAlpha,exception);
8304            }
8305          image=RotateImage(image,argument_list[0].real_reference,exception);
8306          break;
8307        }
8308        case 24:  /* Sample */
8309        {
8310          if (attribute_flag[0] != 0)
8311            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8312              &geometry,exception);
8313          if (attribute_flag[1] != 0)
8314            geometry.width=argument_list[1].integer_reference;
8315          if (attribute_flag[2] != 0)
8316            geometry.height=argument_list[2].integer_reference;
8317          image=SampleImage(image,geometry.width,geometry.height,exception);
8318          break;
8319        }
8320        case 25:  /* Scale */
8321        {
8322          if (attribute_flag[0] != 0)
8323            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8324              &geometry,exception);
8325          if (attribute_flag[1] != 0)
8326            geometry.width=argument_list[1].integer_reference;
8327          if (attribute_flag[2] != 0)
8328            geometry.height=argument_list[2].integer_reference;
8329          image=ScaleImage(image,geometry.width,geometry.height,exception);
8330          break;
8331        }
8332        case 26:  /* Shade */
8333        {
8334          if (attribute_flag[0] != 0)
8335            {
8336              flags=ParseGeometry(argument_list[0].string_reference,
8337                &geometry_info);
8338              if ((flags & SigmaValue) == 0)
8339                geometry_info.sigma=0.0;
8340            }
8341          if (attribute_flag[1] != 0)
8342            geometry_info.rho=argument_list[1].real_reference;
8343          if (attribute_flag[2] != 0)
8344            geometry_info.sigma=argument_list[2].real_reference;
8345          image=ShadeImage(image,
8346            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8347            geometry_info.rho,geometry_info.sigma,exception);
8348          break;
8349        }
8350        case 27:  /* Sharpen */
8351        {
8352          if (attribute_flag[0] != 0)
8353            {
8354              flags=ParseGeometry(argument_list[0].string_reference,
8355                &geometry_info);
8356              if ((flags & SigmaValue) == 0)
8357                geometry_info.sigma=1.0;
8358            }
8359          if (attribute_flag[1] != 0)
8360            geometry_info.rho=argument_list[1].real_reference;
8361          if (attribute_flag[2] != 0)
8362            geometry_info.sigma=argument_list[2].real_reference;
8363          if (attribute_flag[3] != 0)
8364            channel=(ChannelType) argument_list[3].integer_reference;
8365          channel_mask=SetImageChannelMask(image,channel);
8366          image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8367            exception);
8368          if (image != (Image *) NULL)
8369            (void) SetImageChannelMask(image,channel_mask);
8370          break;
8371        }
8372        case 28:  /* Shear */
8373        {
8374          if (attribute_flag[0] != 0)
8375            {
8376              flags=ParseGeometry(argument_list[0].string_reference,
8377                &geometry_info);
8378              if ((flags & SigmaValue) == 0)
8379                geometry_info.sigma=geometry_info.rho;
8380            }
8381          if (attribute_flag[1] != 0)
8382            geometry_info.rho=argument_list[1].real_reference;
8383          if (attribute_flag[2] != 0)
8384            geometry_info.sigma=argument_list[2].real_reference;
8385          if (attribute_flag[3] != 0)
8386            QueryColorCompliance(argument_list[3].string_reference,
8387              AllCompliance,&image->background_color,exception);
8388          if (attribute_flag[4] != 0)
8389            QueryColorCompliance(argument_list[4].string_reference,
8390              AllCompliance,&image->background_color,exception);
8391          image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8392            exception);
8393          break;
8394        }
8395        case 29:  /* Spread */
8396        {
8397          PixelInterpolateMethod
8398            method;
8399
8400          if (attribute_flag[0] == 0)
8401            argument_list[0].real_reference=1.0;
8402          method=UndefinedInterpolatePixel;
8403          if (attribute_flag[1] != 0)
8404            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8405          image=SpreadImage(image,method,argument_list[0].real_reference,
8406            exception);
8407          break;
8408        }
8409        case 30:  /* Swirl */
8410        {
8411          PixelInterpolateMethod
8412            method;
8413
8414          if (attribute_flag[0] == 0)
8415            argument_list[0].real_reference=50.0;
8416          method=UndefinedInterpolatePixel;
8417          if (attribute_flag[1] != 0)
8418            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8419          image=SwirlImage(image,argument_list[0].real_reference,
8420            method,exception);
8421          break;
8422        }
8423        case 31:  /* Resize */
8424        case 32:  /* Zoom */
8425        {
8426          if (attribute_flag[0] != 0)
8427            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8428              &geometry,exception);
8429          if (attribute_flag[1] != 0)
8430            geometry.width=argument_list[1].integer_reference;
8431          if (attribute_flag[2] != 0)
8432            geometry.height=argument_list[2].integer_reference;
8433          if (attribute_flag[3] == 0)
8434            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8435          if (attribute_flag[4] != 0)
8436            SetImageArtifact(image,"filter:support",
8437              argument_list[4].string_reference);
8438          image=ResizeImage(image,geometry.width,geometry.height,
8439            (FilterType) argument_list[3].integer_reference,
8440            exception);
8441          break;
8442        }
8443        case 33:  /* Annotate */
8444        {
8445          DrawInfo
8446            *draw_info;
8447
8448          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8449            (DrawInfo *) NULL);
8450          if (attribute_flag[0] != 0)
8451            {
8452              char
8453                *text;
8454
8455              text=InterpretImageProperties(info ? info->image_info :
8456                (ImageInfo *) NULL,image,argument_list[0].string_reference,
8457                exception);
8458              (void) CloneString(&draw_info->text,text);
8459              text=DestroyString(text);
8460            }
8461          if (attribute_flag[1] != 0)
8462            (void) CloneString(&draw_info->font,
8463              argument_list[1].string_reference);
8464          if (attribute_flag[2] != 0)
8465            draw_info->pointsize=argument_list[2].real_reference;
8466          if (attribute_flag[3] != 0)
8467            (void) CloneString(&draw_info->density,
8468              argument_list[3].string_reference);
8469          if (attribute_flag[4] != 0)
8470            (void) QueryColorCompliance(argument_list[4].string_reference,
8471              AllCompliance,&draw_info->undercolor,exception);
8472          if (attribute_flag[5] != 0)
8473            {
8474              (void) QueryColorCompliance(argument_list[5].string_reference,
8475                AllCompliance,&draw_info->stroke,exception);
8476              if (argument_list[5].image_reference != (Image *) NULL)
8477                draw_info->stroke_pattern=CloneImage(
8478                  argument_list[5].image_reference,0,0,MagickTrue,exception);
8479            }
8480          if (attribute_flag[6] != 0)
8481            {
8482              (void) QueryColorCompliance(argument_list[6].string_reference,
8483                AllCompliance,&draw_info->fill,exception);
8484              if (argument_list[6].image_reference != (Image *) NULL)
8485                draw_info->fill_pattern=CloneImage(
8486                  argument_list[6].image_reference,0,0,MagickTrue,exception);
8487            }
8488          if (attribute_flag[7] != 0)
8489            {
8490              (void) CloneString(&draw_info->geometry,
8491                argument_list[7].string_reference);
8492              flags=ParsePageGeometry(image,argument_list[7].string_reference,
8493                &geometry,exception);
8494              if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8495                geometry_info.sigma=geometry_info.xi;
8496            }
8497          if (attribute_flag[8] != 0)
8498            (void) QueryColorCompliance(argument_list[8].string_reference,
8499              AllCompliance,&draw_info->fill,exception);
8500          if (attribute_flag[11] != 0)
8501            draw_info->gravity=(GravityType)
8502              argument_list[11].integer_reference;
8503          if (attribute_flag[25] != 0)
8504            {
8505              AV
8506                *av;
8507
8508              av=(AV *) argument_list[25].array_reference;
8509              if ((av_len(av) != 3) && (av_len(av) != 5))
8510                {
8511                  ThrowPerlException(exception,OptionError,
8512                    "affine matrix must have 4 or 6 elements",PackageName);
8513                  goto PerlException;
8514                }
8515              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8516              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8517              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8518              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8519              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8520                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8521                {
8522                  ThrowPerlException(exception,OptionError,
8523                    "affine matrix is singular",PackageName);
8524                   goto PerlException;
8525                }
8526              if (av_len(av) == 5)
8527                {
8528                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8529                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8530                }
8531            }
8532          for (j=12; j < 17; j++)
8533          {
8534            if (attribute_flag[j] == 0)
8535              continue;
8536            value=argument_list[j].string_reference;
8537            angle=argument_list[j].real_reference;
8538            current=draw_info->affine;
8539            GetAffineMatrix(&affine);
8540            switch (j)
8541            {
8542              case 12:
8543              {
8544                /*
8545                  Translate.
8546                */
8547                flags=ParseGeometry(value,&geometry_info);
8548                affine.tx=geometry_info.xi;
8549                affine.ty=geometry_info.psi;
8550                if ((flags & PsiValue) == 0)
8551                  affine.ty=affine.tx;
8552                break;
8553              }
8554              case 13:
8555              {
8556                /*
8557                  Scale.
8558                */
8559                flags=ParseGeometry(value,&geometry_info);
8560                affine.sx=geometry_info.rho;
8561                affine.sy=geometry_info.sigma;
8562                if ((flags & SigmaValue) == 0)
8563                  affine.sy=affine.sx;
8564                break;
8565              }
8566              case 14:
8567              {
8568                /*
8569                  Rotate.
8570                */
8571                if (angle == 0.0)
8572                  break;
8573                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8574                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8575                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8576                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8577                break;
8578              }
8579              case 15:
8580              {
8581                /*
8582                  SkewX.
8583                */
8584                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8585                break;
8586              }
8587              case 16:
8588              {
8589                /*
8590                  SkewY.
8591                */
8592                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8593                break;
8594              }
8595            }
8596            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8597            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8598            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8599            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8600            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8601              current.tx;
8602            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8603              current.ty;
8604          }
8605          if (attribute_flag[9] == 0)
8606            argument_list[9].real_reference=0.0;
8607          if (attribute_flag[10] == 0)
8608            argument_list[10].real_reference=0.0;
8609          if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8610            {
8611              char
8612                geometry[MagickPathExtent];
8613
8614              (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8615                (double) argument_list[9].real_reference+draw_info->affine.tx,
8616                (double) argument_list[10].real_reference+draw_info->affine.ty);
8617              (void) CloneString(&draw_info->geometry,geometry);
8618            }
8619          if (attribute_flag[17] != 0)
8620            draw_info->stroke_width=argument_list[17].real_reference;
8621          if (attribute_flag[18] != 0)
8622            {
8623              draw_info->text_antialias=
8624                argument_list[18].integer_reference != 0 ? MagickTrue :
8625                MagickFalse;
8626              draw_info->stroke_antialias=draw_info->text_antialias;
8627            }
8628          if (attribute_flag[19] != 0)
8629            (void) CloneString(&draw_info->family,
8630              argument_list[19].string_reference);
8631          if (attribute_flag[20] != 0)
8632            draw_info->style=(StyleType) argument_list[20].integer_reference;
8633          if (attribute_flag[21] != 0)
8634            draw_info->stretch=(StretchType)
8635              argument_list[21].integer_reference;
8636          if (attribute_flag[22] != 0)
8637            draw_info->weight=argument_list[22].integer_reference;
8638          if (attribute_flag[23] != 0)
8639            draw_info->align=(AlignType) argument_list[23].integer_reference;
8640          if (attribute_flag[24] != 0)
8641            (void) CloneString(&draw_info->encoding,
8642              argument_list[24].string_reference);
8643          if (attribute_flag[25] != 0)
8644            draw_info->fill_pattern=CloneImage(
8645              argument_list[25].image_reference,0,0,MagickTrue,exception);
8646          if (attribute_flag[26] != 0)
8647            draw_info->fill_pattern=CloneImage(
8648              argument_list[26].image_reference,0,0,MagickTrue,exception);
8649          if (attribute_flag[27] != 0)
8650            draw_info->stroke_pattern=CloneImage(
8651              argument_list[27].image_reference,0,0,MagickTrue,exception);
8652          if (attribute_flag[29] != 0)
8653            draw_info->kerning=argument_list[29].real_reference;
8654          if (attribute_flag[30] != 0)
8655            draw_info->interline_spacing=argument_list[30].real_reference;
8656          if (attribute_flag[31] != 0)
8657            draw_info->interword_spacing=argument_list[31].real_reference;
8658          if (attribute_flag[32] != 0)
8659            draw_info->direction=(DirectionType)
8660              argument_list[32].integer_reference;
8661          if (attribute_flag[33] != 0)
8662            draw_info->decorate=(DecorationType)
8663              argument_list[33].integer_reference;
8664          (void) AnnotateImage(image,draw_info,exception);
8665          draw_info=DestroyDrawInfo(draw_info);
8666          break;
8667        }
8668        case 34:  /* ColorFloodfill */
8669        {
8670          DrawInfo
8671            *draw_info;
8672
8673          MagickBooleanType
8674            invert;
8675
8676          PixelInfo
8677            target;
8678
8679          draw_info=CloneDrawInfo(info ? info->image_info :
8680            (ImageInfo *) NULL,(DrawInfo *) NULL);
8681          if (attribute_flag[0] != 0)
8682            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8683              &geometry,exception);
8684          if (attribute_flag[1] != 0)
8685            geometry.x=argument_list[1].integer_reference;
8686          if (attribute_flag[2] != 0)
8687            geometry.y=argument_list[2].integer_reference;
8688          if (attribute_flag[3] != 0)
8689            (void) QueryColorCompliance(argument_list[3].string_reference,
8690              AllCompliance,&draw_info->fill,exception);
8691          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8692            geometry.x,geometry.y,&target,exception);
8693          invert=MagickFalse;
8694          if (attribute_flag[4] != 0)
8695            {
8696              QueryColorCompliance(argument_list[4].string_reference,
8697                AllCompliance,&target,exception);
8698              invert=MagickTrue;
8699            }
8700          if (attribute_flag[5] != 0)
8701            image->fuzz=StringToDoubleInterval(
8702              argument_list[5].string_reference,(double) QuantumRange+1.0);
8703          if (attribute_flag[6] != 0)
8704            invert=(MagickBooleanType) argument_list[6].integer_reference;
8705          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8706            geometry.y,invert,exception);
8707          draw_info=DestroyDrawInfo(draw_info);
8708          break;
8709        }
8710        case 35:  /* Composite */
8711        {
8712          char
8713            composite_geometry[MagickPathExtent];
8714
8715          Image
8716            *composite_image,
8717            *rotate_image;
8718
8719          MagickBooleanType
8720            clip_to_self;
8721
8722          compose=OverCompositeOp;
8723          if (attribute_flag[0] != 0)
8724            composite_image=argument_list[0].image_reference;
8725          else
8726            {
8727              ThrowPerlException(exception,OptionError,
8728                "CompositeImageRequired",PackageName);
8729              goto PerlException;
8730            }
8731          /*
8732            Parameter Handling used for BOTH normal and tiled composition.
8733          */
8734          if (attribute_flag[1] != 0) /* compose */
8735            compose=(CompositeOperator) argument_list[1].integer_reference;
8736          if (attribute_flag[6] != 0) /* opacity  */
8737            {
8738              if (compose != DissolveCompositeOp)
8739                (void) SetImageAlpha(composite_image,(Quantum)
8740                  StringToDoubleInterval(argument_list[6].string_reference,
8741                  (double) QuantumRange+1.0),exception);
8742              else
8743                {
8744                  CacheView
8745                    *composite_view;
8746
8747                  double
8748                    opacity;
8749
8750                  MagickBooleanType
8751                    sync;
8752
8753                  ssize_t
8754                    x;
8755
8756                  Quantum
8757                    *q;
8758
8759                  ssize_t
8760                    y;
8761
8762                  /*
8763                    Handle dissolve composite operator (patch by
8764                    Kevin A. McGrail).
8765                  */
8766                  (void) CloneString(&image->geometry,
8767                    argument_list[6].string_reference);
8768                  opacity=(Quantum) StringToDoubleInterval(
8769                    argument_list[6].string_reference,(double) QuantumRange+
8770                    1.0);
8771                  if (composite_image->alpha_trait != UndefinedPixelTrait)
8772                    (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8773                  composite_view=AcquireAuthenticCacheView(composite_image,
8774                    exception);
8775                  for (y=0; y < (ssize_t) composite_image->rows ; y++)
8776                  {
8777                    q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8778                      composite_image->columns,1,exception);
8779                    for (x=0; x < (ssize_t) composite_image->columns; x++)
8780                    {
8781                      if (GetPixelAlpha(image,q) == OpaqueAlpha)
8782                        SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8783                          q);
8784                      q+=GetPixelChannels(composite_image);
8785                    }
8786                    sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8787                    if (sync == MagickFalse)
8788                      break;
8789                  }
8790                  composite_view=DestroyCacheView(composite_view);
8791                }
8792            }
8793          if (attribute_flag[9] != 0)    /* "color=>" */
8794            QueryColorCompliance(argument_list[9].string_reference,
8795              AllCompliance,&composite_image->background_color,exception);
8796          if (attribute_flag[12] != 0) /* "interpolate=>" */
8797            image->interpolate=(PixelInterpolateMethod)
8798              argument_list[12].integer_reference;
8799          if (attribute_flag[13] != 0)   /* "args=>" */
8800            (void) SetImageArtifact(composite_image,"compose:args",
8801              argument_list[13].string_reference);
8802          if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8803            (void) SetImageArtifact(composite_image,"compose:args",
8804              argument_list[14].string_reference);
8805          clip_to_self=MagickTrue;
8806          switch (compose)
8807          {
8808            case ClearCompositeOp:
8809            case SrcCompositeOp:
8810            case InCompositeOp:
8811            case SrcInCompositeOp:
8812            case OutCompositeOp:
8813            case SrcOutCompositeOp:
8814            case DstInCompositeOp:
8815            case DstAtopCompositeOp:
8816            case CopyAlphaCompositeOp:
8817            case ChangeMaskCompositeOp:
8818            case DissolveCompositeOp:
8819            case BlendCompositeOp:
8820            {
8821              clip_to_self=MagickFalse;
8822              break;
8823            }
8824            default:
8825              break;
8826          }
8827          if (attribute_flag[15] != 0)
8828            clip_to_self=(MagickBooleanType)
8829              argument_list[15].integer_reference;
8830          /*
8831            Tiling Composition (with orthogonal rotate).
8832          */
8833          rotate_image=(Image *) NULL;
8834          if (attribute_flag[8] != 0)   /* "rotate=>" */
8835            {
8836               /*
8837                 Rotate image.
8838               */
8839               rotate_image=RotateImage(composite_image,
8840                 argument_list[8].real_reference,exception);
8841               if (rotate_image == (Image *) NULL)
8842                 break;
8843            }
8844          if ((attribute_flag[7] != 0) &&
8845              (argument_list[7].integer_reference != 0)) /* tile */
8846            {
8847              ssize_t
8848                x,
8849                y;
8850
8851              /*
8852                Tile the composite image.
8853              */
8854             for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8855                for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8856                {
8857                  if (attribute_flag[8] != 0) /* rotate */
8858                    (void) CompositeImage(image,rotate_image,compose,
8859                      MagickTrue,x,y,exception);
8860                  else
8861                    (void) CompositeImage(image,composite_image,compose,
8862                      MagickTrue,x,y,exception);
8863                }
8864              if (attribute_flag[8] != 0) /* rotate */
8865                rotate_image=DestroyImage(rotate_image);
8866              break;
8867            }
8868          /*
8869            Parameter Handling used used ONLY for normal composition.
8870          */
8871          if (attribute_flag[5] != 0) /* gravity */
8872            image->gravity=(GravityType) argument_list[5].integer_reference;
8873          if (attribute_flag[2] != 0) /* geometry offset */
8874            {
8875              SetGeometry(image,&geometry);
8876              (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8877                &geometry);
8878              GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8879                &geometry);
8880            }
8881          if (attribute_flag[3] != 0) /* x offset */
8882            geometry.x=argument_list[3].integer_reference;
8883          if (attribute_flag[4] != 0) /* y offset */
8884            geometry.y=argument_list[4].integer_reference;
8885          if (attribute_flag[10] != 0) /* mask */
8886            {
8887              if ((image->compose == DisplaceCompositeOp) ||
8888                  (image->compose == DistortCompositeOp))
8889                {
8890                  /*
8891                    Merge Y displacement into X displacement image.
8892                  */
8893                  composite_image=CloneImage(composite_image,0,0,MagickTrue,
8894                    exception);
8895                  (void) CompositeImage(composite_image,
8896                    argument_list[10].image_reference,CopyGreenCompositeOp,
8897                    clip_to_self,0,0,exception);
8898                }
8899              else
8900                {
8901                  Image
8902                    *mask_image;
8903
8904                  /*
8905                    Set a blending mask for the composition.
8906                  */
8907                  mask_image=CloneImage(argument_list[10].image_reference,0,0,
8908                    MagickTrue,exception);
8909                  (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8910                    exception);
8911                  mask_image=DestroyImage(mask_image);
8912                }
8913            }
8914          if (attribute_flag[11] != 0) /* channel */
8915            channel=(ChannelType) argument_list[11].integer_reference;
8916          /*
8917            Composite two images (normal composition).
8918          */
8919          (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8920            "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8921            (double) composite_image->rows,(double) geometry.x,(double)
8922            geometry.y);
8923          flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8924            exception);
8925          channel_mask=SetImageChannelMask(image,channel);
8926          if (attribute_flag[8] == 0) /* no rotate */
8927            CompositeImage(image,composite_image,compose,clip_to_self,
8928              geometry.x,geometry.y,exception);
8929          else
8930            {
8931              /*
8932                Position adjust rotated image then composite.
8933              */
8934              geometry.x-=(ssize_t) (rotate_image->columns-
8935                composite_image->columns)/2;
8936              geometry.y-=(ssize_t) (rotate_image->rows-
8937                composite_image->rows)/2;
8938              CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8939                geometry.y,exception);
8940              rotate_image=DestroyImage(rotate_image);
8941            }
8942          if (attribute_flag[10] != 0) /* mask */
8943            {
8944              if ((image->compose == DisplaceCompositeOp) ||
8945                  (image->compose == DistortCompositeOp))
8946                composite_image=DestroyImage(composite_image);
8947              else
8948                (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8949                  exception);
8950            }
8951          (void) SetImageChannelMask(image,channel_mask);
8952          break;
8953        }
8954        case 36:  /* Contrast */
8955        {
8956          if (attribute_flag[0] == 0)
8957            argument_list[0].integer_reference=0;
8958          (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8959            MagickTrue : MagickFalse,exception);
8960          break;
8961        }
8962        case 37:  /* CycleColormap */
8963        {
8964          if (attribute_flag[0] == 0)
8965            argument_list[0].integer_reference=6;
8966          (void) CycleColormapImage(image,argument_list[0].integer_reference,
8967            exception);
8968          break;
8969        }
8970        case 38:  /* Draw */
8971        {
8972          DrawInfo
8973            *draw_info;
8974
8975          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8976            (DrawInfo *) NULL);
8977          (void) CloneString(&draw_info->primitive,"point");
8978          if (attribute_flag[0] != 0)
8979            {
8980              if (argument_list[0].integer_reference < 0)
8981                (void) CloneString(&draw_info->primitive,
8982                  argument_list[0].string_reference);
8983              else
8984                (void) CloneString(&draw_info->primitive,
8985                  CommandOptionToMnemonic(MagickPrimitiveOptions,
8986                  argument_list[0].integer_reference));
8987            }
8988          if (attribute_flag[1] != 0)
8989            {
8990              if (LocaleCompare(draw_info->primitive,"path") == 0)
8991                {
8992                  (void) ConcatenateString(&draw_info->primitive," '");
8993                  ConcatenateString(&draw_info->primitive,
8994                    argument_list[1].string_reference);
8995                  (void) ConcatenateString(&draw_info->primitive,"'");
8996                }
8997              else
8998                {
8999                  (void) ConcatenateString(&draw_info->primitive," ");
9000                  ConcatenateString(&draw_info->primitive,
9001                    argument_list[1].string_reference);
9002                }
9003            }
9004          if (attribute_flag[2] != 0)
9005            {
9006              (void) ConcatenateString(&draw_info->primitive," ");
9007              (void) ConcatenateString(&draw_info->primitive,
9008                CommandOptionToMnemonic(MagickMethodOptions,
9009                argument_list[2].integer_reference));
9010            }
9011          if (attribute_flag[3] != 0)
9012            {
9013              (void) QueryColorCompliance(argument_list[3].string_reference,
9014                AllCompliance,&draw_info->stroke,exception);
9015              if (argument_list[3].image_reference != (Image *) NULL)
9016                draw_info->stroke_pattern=CloneImage(
9017                  argument_list[3].image_reference,0,0,MagickTrue,exception);
9018            }
9019          if (attribute_flag[4] != 0)
9020            {
9021              (void) QueryColorCompliance(argument_list[4].string_reference,
9022                AllCompliance,&draw_info->fill,exception);
9023              if (argument_list[4].image_reference != (Image *) NULL)
9024                draw_info->fill_pattern=CloneImage(
9025                  argument_list[4].image_reference,0,0,MagickTrue,exception);
9026            }
9027          if (attribute_flag[5] != 0)
9028            draw_info->stroke_width=argument_list[5].real_reference;
9029          if (attribute_flag[6] != 0)
9030            (void) CloneString(&draw_info->font,
9031              argument_list[6].string_reference);
9032          if (attribute_flag[7] != 0)
9033            (void) QueryColorCompliance(argument_list[7].string_reference,
9034              AllCompliance,&draw_info->border_color,exception);
9035          if (attribute_flag[8] != 0)
9036            draw_info->affine.tx=argument_list[8].real_reference;
9037          if (attribute_flag[9] != 0)
9038            draw_info->affine.ty=argument_list[9].real_reference;
9039          if (attribute_flag[20] != 0)
9040            {
9041              AV
9042                *av;
9043
9044              av=(AV *) argument_list[20].array_reference;
9045              if ((av_len(av) != 3) && (av_len(av) != 5))
9046                {
9047                  ThrowPerlException(exception,OptionError,
9048                    "affine matrix must have 4 or 6 elements",PackageName);
9049                  goto PerlException;
9050                }
9051              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9052              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9053              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9054              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9055              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9056                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9057                {
9058                  ThrowPerlException(exception,OptionError,
9059                    "affine matrix is singular",PackageName);
9060                   goto PerlException;
9061                }
9062              if (av_len(av) == 5)
9063                {
9064                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9065                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9066                }
9067            }
9068          for (j=10; j < 15; j++)
9069          {
9070            if (attribute_flag[j] == 0)
9071              continue;
9072            value=argument_list[j].string_reference;
9073            angle=argument_list[j].real_reference;
9074            current=draw_info->affine;
9075            GetAffineMatrix(&affine);
9076            switch (j)
9077            {
9078              case 10:
9079              {
9080                /*
9081                  Translate.
9082                */
9083                flags=ParseGeometry(value,&geometry_info);
9084                affine.tx=geometry_info.xi;
9085                affine.ty=geometry_info.psi;
9086                if ((flags & PsiValue) == 0)
9087                  affine.ty=affine.tx;
9088                break;
9089              }
9090              case 11:
9091              {
9092                /*
9093                  Scale.
9094                */
9095                flags=ParseGeometry(value,&geometry_info);
9096                affine.sx=geometry_info.rho;
9097                affine.sy=geometry_info.sigma;
9098                if ((flags & SigmaValue) == 0)
9099                  affine.sy=affine.sx;
9100                break;
9101              }
9102              case 12:
9103              {
9104                /*
9105                  Rotate.
9106                */
9107                if (angle == 0.0)
9108                  break;
9109                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9110                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9111                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9112                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9113                break;
9114              }
9115              case 13:
9116              {
9117                /*
9118                  SkewX.
9119                */
9120                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9121                break;
9122              }
9123              case 14:
9124              {
9125                /*
9126                  SkewY.
9127                */
9128                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9129                break;
9130              }
9131            }
9132            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9133            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9134            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9135            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9136            draw_info->affine.tx=
9137              current.sx*affine.tx+current.ry*affine.ty+current.tx;
9138            draw_info->affine.ty=
9139              current.rx*affine.tx+current.sy*affine.ty+current.ty;
9140          }
9141          if (attribute_flag[15] != 0)
9142            draw_info->fill_pattern=CloneImage(
9143              argument_list[15].image_reference,0,0,MagickTrue,exception);
9144          if (attribute_flag[16] != 0)
9145            draw_info->pointsize=argument_list[16].real_reference;
9146          if (attribute_flag[17] != 0)
9147            {
9148              draw_info->stroke_antialias=
9149                argument_list[17].integer_reference != 0 ? MagickTrue :
9150                MagickFalse;
9151              draw_info->text_antialias=draw_info->stroke_antialias;
9152            }
9153          if (attribute_flag[18] != 0)
9154            (void) CloneString(&draw_info->density,
9155              argument_list[18].string_reference);
9156          if (attribute_flag[19] != 0)
9157            draw_info->stroke_width=argument_list[19].real_reference;
9158          if (attribute_flag[21] != 0)
9159            draw_info->dash_offset=argument_list[21].real_reference;
9160          if (attribute_flag[22] != 0)
9161            {
9162              AV
9163                *av;
9164
9165              av=(AV *) argument_list[22].array_reference;
9166              draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9167                av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9168              if (draw_info->dash_pattern != (double *) NULL)
9169                {
9170                  for (i=0; i <= av_len(av); i++)
9171                    draw_info->dash_pattern[i]=(double)
9172                      SvNV(*(av_fetch(av,i,0)));
9173                  draw_info->dash_pattern[i]=0.0;
9174                }
9175            }
9176          if (attribute_flag[23] != 0)
9177            image->interpolate=(PixelInterpolateMethod)
9178              argument_list[23].integer_reference;
9179          if ((attribute_flag[24] != 0) &&
9180              (draw_info->fill_pattern != (Image *) NULL))
9181            flags=ParsePageGeometry(draw_info->fill_pattern,
9182              argument_list[24].string_reference,
9183              &draw_info->fill_pattern->tile_offset,exception);
9184          if (attribute_flag[25] != 0)
9185            {
9186              (void) ConcatenateString(&draw_info->primitive," '");
9187              (void) ConcatenateString(&draw_info->primitive,
9188                argument_list[25].string_reference);
9189              (void) ConcatenateString(&draw_info->primitive,"'");
9190            }
9191          if (attribute_flag[26] != 0)
9192            draw_info->fill_pattern=CloneImage(
9193              argument_list[26].image_reference,0,0,MagickTrue,exception);
9194          if (attribute_flag[27] != 0)
9195            draw_info->stroke_pattern=CloneImage(
9196              argument_list[27].image_reference,0,0,MagickTrue,exception);
9197          if (attribute_flag[28] != 0)
9198            (void) CloneString(&draw_info->primitive,
9199              argument_list[28].string_reference);
9200          if (attribute_flag[29] != 0)
9201            draw_info->kerning=argument_list[29].real_reference;
9202          if (attribute_flag[30] != 0)
9203            draw_info->interline_spacing=argument_list[30].real_reference;
9204          if (attribute_flag[31] != 0)
9205            draw_info->interword_spacing=argument_list[31].real_reference;
9206          if (attribute_flag[32] != 0)
9207            draw_info->direction=(DirectionType)
9208              argument_list[32].integer_reference;
9209          DrawImage(image,draw_info,exception);
9210          draw_info=DestroyDrawInfo(draw_info);
9211          break;
9212        }
9213        case 39:  /* Equalize */
9214        {
9215          if (attribute_flag[0] != 0)
9216            channel=(ChannelType) argument_list[0].integer_reference;
9217          channel_mask=SetImageChannelMask(image,channel);
9218          (void) EqualizeImage(image,exception);
9219          (void) SetImageChannelMask(image,channel_mask);
9220          break;
9221        }
9222        case 40:  /* Gamma */
9223        {
9224          if (attribute_flag[1] != 0)
9225            channel=(ChannelType) argument_list[1].integer_reference;
9226          if (attribute_flag[2] == 0)
9227            argument_list[2].real_reference=1.0;
9228          if (attribute_flag[3] == 0)
9229            argument_list[3].real_reference=1.0;
9230          if (attribute_flag[4] == 0)
9231            argument_list[4].real_reference=1.0;
9232          if (attribute_flag[0] == 0)
9233            {
9234              (void) FormatLocaleString(message,MagickPathExtent,
9235                "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
9236                (double) argument_list[3].real_reference,
9237                (double) argument_list[4].real_reference);
9238              argument_list[0].string_reference=message;
9239            }
9240          (void) GammaImage(image,StringToDouble(
9241            argument_list[0].string_reference,(char **) NULL),exception);
9242          break;
9243        }
9244        case 41:  /* Map */
9245        {
9246          QuantizeInfo
9247            *quantize_info;
9248
9249          if (attribute_flag[0] == 0)
9250            {
9251              ThrowPerlException(exception,OptionError,"MapImageRequired",
9252                PackageName);
9253              goto PerlException;
9254            }
9255          quantize_info=AcquireQuantizeInfo(info->image_info);
9256          if (attribute_flag[1] != 0)
9257            quantize_info->dither_method=(DitherMethod)
9258              argument_list[1].integer_reference;
9259          (void) RemapImages(quantize_info,image,
9260            argument_list[0].image_reference,exception);
9261          quantize_info=DestroyQuantizeInfo(quantize_info);
9262          break;
9263        }
9264        case 42:  /* MatteFloodfill */
9265        {
9266          DrawInfo
9267            *draw_info;
9268
9269          MagickBooleanType
9270            invert;
9271
9272          PixelInfo
9273            target;
9274
9275          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9276            (DrawInfo *) NULL);
9277          if (attribute_flag[0] != 0)
9278            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9279              &geometry,exception);
9280          if (attribute_flag[1] != 0)
9281            geometry.x=argument_list[1].integer_reference;
9282          if (attribute_flag[2] != 0)
9283            geometry.y=argument_list[2].integer_reference;
9284          if (image->alpha_trait == UndefinedPixelTrait)
9285            (void) SetImageAlpha(image,OpaqueAlpha,exception);
9286          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9287            geometry.x,geometry.y,&target,exception);
9288          if (attribute_flag[4] != 0)
9289            QueryColorCompliance(argument_list[4].string_reference,
9290              AllCompliance,&target,exception);
9291          if (attribute_flag[3] != 0)
9292            target.alpha=StringToDoubleInterval(
9293              argument_list[3].string_reference,(double) (double) QuantumRange+
9294              1.0);
9295          if (attribute_flag[5] != 0)
9296            image->fuzz=StringToDoubleInterval(
9297              argument_list[5].string_reference,(double) QuantumRange+1.0);
9298          invert=MagickFalse;
9299          if (attribute_flag[6] != 0)
9300            invert=(MagickBooleanType) argument_list[6].integer_reference;
9301          channel_mask=SetImageChannelMask(image,AlphaChannel);
9302          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9303            geometry.y,invert,exception);
9304          (void) SetImageChannelMask(image,channel_mask);
9305          draw_info=DestroyDrawInfo(draw_info);
9306          break;
9307        }
9308        case 43:  /* Modulate */
9309        {
9310          char
9311            modulate[MagickPathExtent];
9312
9313          geometry_info.rho=100.0;
9314          geometry_info.sigma=100.0;
9315          geometry_info.xi=100.0;
9316          if (attribute_flag[0] != 0)
9317            (void)ParseGeometry(argument_list[0].string_reference,
9318              &geometry_info);
9319          if (attribute_flag[1] != 0)
9320            geometry_info.xi=argument_list[1].real_reference;
9321          if (attribute_flag[2] != 0)
9322            geometry_info.sigma=argument_list[2].real_reference;
9323          if (attribute_flag[3] != 0)
9324            {
9325              geometry_info.sigma=argument_list[3].real_reference;
9326              SetImageArtifact(image,"modulate:colorspace","HWB");
9327            }
9328          if (attribute_flag[4] != 0)
9329            {
9330              geometry_info.rho=argument_list[4].real_reference;
9331              SetImageArtifact(image,"modulate:colorspace","HSB");
9332            }
9333          if (attribute_flag[5] != 0)
9334            {
9335              geometry_info.sigma=argument_list[5].real_reference;
9336              SetImageArtifact(image,"modulate:colorspace","HSL");
9337            }
9338          if (attribute_flag[6] != 0)
9339            {
9340              geometry_info.rho=argument_list[6].real_reference;
9341              SetImageArtifact(image,"modulate:colorspace","HWB");
9342            }
9343          (void) FormatLocaleString(modulate,MagickPathExtent,
9344            "%.20g,%.20g,%.20g",geometry_info.rho,geometry_info.sigma,
9345            geometry_info.xi);
9346          (void) ModulateImage(image,modulate,exception);
9347          break;
9348        }
9349        case 44:  /* Negate */
9350        {
9351          if (attribute_flag[0] == 0)
9352            argument_list[0].integer_reference=0;
9353          if (attribute_flag[1] != 0)
9354            channel=(ChannelType) argument_list[1].integer_reference;
9355          channel_mask=SetImageChannelMask(image,channel);
9356          (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9357            MagickTrue : MagickFalse,exception);
9358          (void) SetImageChannelMask(image,channel_mask);
9359          break;
9360        }
9361        case 45:  /* Normalize */
9362        {
9363          if (attribute_flag[0] != 0)
9364            channel=(ChannelType) argument_list[0].integer_reference;
9365          channel_mask=SetImageChannelMask(image,channel);
9366          NormalizeImage(image,exception);
9367          (void) SetImageChannelMask(image,channel_mask);
9368          break;
9369        }
9370        case 46:  /* NumberColors */
9371          break;
9372        case 47:  /* Opaque */
9373        {
9374          MagickBooleanType
9375            invert;
9376
9377          PixelInfo
9378            fill_color,
9379            target;
9380
9381          (void) QueryColorCompliance("none",AllCompliance,&target,
9382             exception);
9383          (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9384            exception);
9385          if (attribute_flag[0] != 0)
9386            (void) QueryColorCompliance(argument_list[0].string_reference,
9387              AllCompliance,&target,exception);
9388          if (attribute_flag[1] != 0)
9389            (void) QueryColorCompliance(argument_list[1].string_reference,
9390              AllCompliance,&fill_color,exception);
9391          if (attribute_flag[2] != 0)
9392            image->fuzz=StringToDoubleInterval(
9393              argument_list[2].string_reference,(double) QuantumRange+1.0);
9394          if (attribute_flag[3] != 0)
9395            channel=(ChannelType) argument_list[3].integer_reference;
9396          invert=MagickFalse;
9397          if (attribute_flag[4] != 0)
9398            invert=(MagickBooleanType) argument_list[4].integer_reference;
9399          channel_mask=SetImageChannelMask(image,channel);
9400          (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9401          (void) SetImageChannelMask(image,channel_mask);
9402          break;
9403        }
9404        case 48:  /* Quantize */
9405        {
9406          QuantizeInfo
9407            *quantize_info;
9408
9409          quantize_info=AcquireQuantizeInfo(info->image_info);
9410          if (attribute_flag[0] != 0)
9411            quantize_info->number_colors=(size_t)
9412              argument_list[0].integer_reference;
9413          if (attribute_flag[1] != 0)
9414            quantize_info->tree_depth=(size_t)
9415              argument_list[1].integer_reference;
9416          if (attribute_flag[2] != 0)
9417            quantize_info->colorspace=(ColorspaceType)
9418              argument_list[2].integer_reference;
9419          if (attribute_flag[3] != 0)
9420            quantize_info->dither_method=(DitherMethod)
9421              argument_list[3].integer_reference;
9422          if (attribute_flag[4] != 0)
9423            quantize_info->measure_error=
9424              argument_list[4].integer_reference != 0 ? MagickTrue :
9425              MagickFalse;
9426          if (attribute_flag[6] != 0)
9427            (void) QueryColorCompliance(argument_list[6].string_reference,
9428              AllCompliance,&image->transparent_color,exception);
9429          if (attribute_flag[7] != 0)
9430            quantize_info->dither_method=(DitherMethod)
9431              argument_list[7].integer_reference;
9432          if (attribute_flag[5] && argument_list[5].integer_reference)
9433            (void) QuantizeImages(quantize_info,image,exception);
9434          else
9435            if ((image->storage_class == DirectClass) ||
9436               (image->colors > quantize_info->number_colors) ||
9437               (quantize_info->colorspace == GRAYColorspace))
9438             (void) QuantizeImage(quantize_info,image,exception);
9439           else
9440             CompressImageColormap(image,exception);
9441          quantize_info=DestroyQuantizeInfo(quantize_info);
9442          break;
9443        }
9444        case 49:  /* Raise */
9445        {
9446          if (attribute_flag[0] != 0)
9447            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9448              &geometry,exception);
9449          if (attribute_flag[1] != 0)
9450            geometry.width=argument_list[1].integer_reference;
9451          if (attribute_flag[2] != 0)
9452            geometry.height=argument_list[2].integer_reference;
9453          if (attribute_flag[3] == 0)
9454            argument_list[3].integer_reference=1;
9455          (void) RaiseImage(image,&geometry,
9456            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9457            exception);
9458          break;
9459        }
9460        case 50:  /* Segment */
9461        {
9462          ColorspaceType
9463            colorspace;
9464
9465          double
9466            cluster_threshold,
9467            smoothing_threshold;
9468
9469          MagickBooleanType
9470            verbose;
9471
9472          cluster_threshold=1.0;
9473          smoothing_threshold=1.5;
9474          colorspace=sRGBColorspace;
9475          verbose=MagickFalse;
9476          if (attribute_flag[0] != 0)
9477            {
9478              flags=ParseGeometry(argument_list[0].string_reference,
9479                &geometry_info);
9480              cluster_threshold=geometry_info.rho;
9481              if (flags & SigmaValue)
9482                smoothing_threshold=geometry_info.sigma;
9483            }
9484          if (attribute_flag[1] != 0)
9485            cluster_threshold=argument_list[1].real_reference;
9486          if (attribute_flag[2] != 0)
9487            smoothing_threshold=argument_list[2].real_reference;
9488          if (attribute_flag[3] != 0)
9489            colorspace=(ColorspaceType) argument_list[3].integer_reference;
9490          if (attribute_flag[4] != 0)
9491            verbose=argument_list[4].integer_reference != 0 ? MagickTrue :
9492              MagickFalse;
9493          (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9494            smoothing_threshold,exception);
9495          break;
9496        }
9497        case 51:  /* Signature */
9498        {
9499          (void) SignatureImage(image,exception);
9500          break;
9501        }
9502        case 52:  /* Solarize */
9503        {
9504          geometry_info.rho=QuantumRange/2.0;
9505          if (attribute_flag[0] != 0)
9506            flags=ParseGeometry(argument_list[0].string_reference,
9507              &geometry_info);
9508          if (attribute_flag[1] != 0)
9509            geometry_info.rho=StringToDoubleInterval(
9510              argument_list[1].string_reference,(double) QuantumRange+1.0);
9511          (void) SolarizeImage(image,geometry_info.rho,exception);
9512          break;
9513        }
9514        case 53:  /* Sync */
9515        {
9516          (void) SyncImage(image,exception);
9517          break;
9518        }
9519        case 54:  /* Texture */
9520        {
9521          if (attribute_flag[0] == 0)
9522            break;
9523          TextureImage(image,argument_list[0].image_reference,exception);
9524          break;
9525        }
9526        case 55:  /* Evalute */
9527        {
9528          MagickEvaluateOperator
9529            op;
9530
9531          op=SetEvaluateOperator;
9532          if (attribute_flag[0] == MagickFalse)
9533            argument_list[0].real_reference=0.0;
9534          if (attribute_flag[1] != MagickFalse)
9535            op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9536          if (attribute_flag[2] != MagickFalse)
9537            channel=(ChannelType) argument_list[2].integer_reference;
9538          channel_mask=SetImageChannelMask(image,channel);
9539          (void) EvaluateImage(image,op,argument_list[0].real_reference,
9540            exception);
9541          (void) SetImageChannelMask(image,channel_mask);
9542          break;
9543        }
9544        case 56:  /* Transparent */
9545        {
9546          double
9547            opacity;
9548
9549          MagickBooleanType
9550            invert;
9551
9552          PixelInfo
9553            target;
9554
9555          (void) QueryColorCompliance("none",AllCompliance,&target,
9556            exception);
9557          if (attribute_flag[0] != 0)
9558            (void) QueryColorCompliance(argument_list[0].string_reference,
9559              AllCompliance,&target,exception);
9560          opacity=TransparentAlpha;
9561          if (attribute_flag[1] != 0)
9562            opacity=StringToDoubleInterval(argument_list[1].string_reference,
9563              (double) QuantumRange+1.0);
9564          if (attribute_flag[2] != 0)
9565            image->fuzz=StringToDoubleInterval(
9566              argument_list[2].string_reference,(double) QuantumRange+1.0);
9567          if (attribute_flag[3] == 0)
9568            argument_list[3].integer_reference=0;
9569          invert=MagickFalse;
9570          if (attribute_flag[3] != 0)
9571            invert=(MagickBooleanType) argument_list[3].integer_reference;
9572          (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9573            invert,exception);
9574          break;
9575        }
9576        case 57:  /* Threshold */
9577        {
9578          double
9579            threshold;
9580
9581          if (attribute_flag[0] == 0)
9582            argument_list[0].string_reference="50%";
9583          if (attribute_flag[1] != 0)
9584            channel=(ChannelType) argument_list[1].integer_reference;
9585          threshold=StringToDoubleInterval(argument_list[0].string_reference,
9586            (double) QuantumRange+1.0);
9587          channel_mask=SetImageChannelMask(image,channel);
9588          (void) BilevelImage(image,threshold,exception);
9589          (void) SetImageChannelMask(image,channel_mask);
9590          break;
9591        }
9592        case 58:  /* Charcoal */
9593        {
9594          if (attribute_flag[0] != 0)
9595            {
9596              flags=ParseGeometry(argument_list[0].string_reference,
9597                &geometry_info);
9598              if ((flags & SigmaValue) == 0)
9599                geometry_info.sigma=1.0;
9600            }
9601          if (attribute_flag[1] != 0)
9602            geometry_info.rho=argument_list[1].real_reference;
9603          if (attribute_flag[2] != 0)
9604            geometry_info.sigma=argument_list[2].real_reference;
9605          image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9606            exception);
9607          break;
9608        }
9609        case 59:  /* Trim */
9610        {
9611          if (attribute_flag[0] != 0)
9612            image->fuzz=StringToDoubleInterval(
9613              argument_list[0].string_reference,(double) QuantumRange+1.0);
9614          image=TrimImage(image,exception);
9615          break;
9616        }
9617        case 60:  /* Wave */
9618        {
9619          PixelInterpolateMethod
9620            method;
9621
9622          if (attribute_flag[0] != 0)
9623            {
9624              flags=ParseGeometry(argument_list[0].string_reference,
9625                &geometry_info);
9626              if ((flags & SigmaValue) == 0)
9627                geometry_info.sigma=1.0;
9628            }
9629          if (attribute_flag[1] != 0)
9630            geometry_info.rho=argument_list[1].real_reference;
9631          if (attribute_flag[2] != 0)
9632            geometry_info.sigma=argument_list[2].real_reference;
9633          method=UndefinedInterpolatePixel;
9634          if (attribute_flag[3] != 0)
9635            method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9636          image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9637            method,exception);
9638          break;
9639        }
9640        case 61:  /* Separate */
9641        {
9642          if (attribute_flag[0] != 0)
9643            channel=(ChannelType) argument_list[0].integer_reference;
9644          image=SeparateImage(image,channel,exception);
9645          break;
9646        }
9647        case 63:  /* Stereo */
9648        {
9649          if (attribute_flag[0] == 0)
9650            {
9651              ThrowPerlException(exception,OptionError,"StereoImageRequired",
9652                PackageName);
9653              goto PerlException;
9654            }
9655          if (attribute_flag[1] != 0)
9656            geometry.x=argument_list[1].integer_reference;
9657          if (attribute_flag[2] != 0)
9658            geometry.y=argument_list[2].integer_reference;
9659          image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9660            geometry.x,geometry.y,exception);
9661          break;
9662        }
9663        case 64:  /* Stegano */
9664        {
9665          if (attribute_flag[0] == 0)
9666            {
9667              ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9668                PackageName);
9669              goto PerlException;
9670            }
9671          if (attribute_flag[1] == 0)
9672            argument_list[1].integer_reference=0;
9673          image->offset=argument_list[1].integer_reference;
9674          image=SteganoImage(image,argument_list[0].image_reference,exception);
9675          break;
9676        }
9677        case 65:  /* Deconstruct */
9678        {
9679          image=CompareImagesLayers(image,CompareAnyLayer,exception);
9680          break;
9681        }
9682        case 66:  /* GaussianBlur */
9683        {
9684          if (attribute_flag[0] != 0)
9685            {
9686              flags=ParseGeometry(argument_list[0].string_reference,
9687                &geometry_info);
9688              if ((flags & SigmaValue) == 0)
9689                geometry_info.sigma=1.0;
9690            }
9691          if (attribute_flag[1] != 0)
9692            geometry_info.rho=argument_list[1].real_reference;
9693          if (attribute_flag[2] != 0)
9694            geometry_info.sigma=argument_list[2].real_reference;
9695          if (attribute_flag[3] != 0)
9696            channel=(ChannelType) argument_list[3].integer_reference;
9697          channel_mask=SetImageChannelMask(image,channel);
9698          image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9699            exception);
9700          if (image != (Image *) NULL)
9701            (void) SetImageChannelMask(image,channel_mask);
9702          break;
9703        }
9704        case 67:  /* Convolve */
9705        {
9706          KernelInfo
9707            *kernel;
9708
9709          kernel=(KernelInfo *) NULL;
9710          if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9711            break;
9712          if (attribute_flag[0] != 0)
9713            {
9714              AV
9715                *av;
9716
9717              size_t
9718                order;
9719
9720              kernel=AcquireKernelInfo((const char *) NULL,exception);
9721              if (kernel == (KernelInfo *) NULL)
9722                break;
9723              av=(AV *) argument_list[0].array_reference;
9724              order=(size_t) sqrt(av_len(av)+1);
9725              kernel->width=order;
9726              kernel->height=order;
9727              kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9728                order*sizeof(*kernel->values));
9729              if (kernel->values == (MagickRealType *) NULL)
9730                {
9731                  kernel=DestroyKernelInfo(kernel);
9732                  ThrowPerlException(exception,ResourceLimitFatalError,
9733                    "MemoryAllocationFailed",PackageName);
9734                  goto PerlException;
9735                }
9736              for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9737                kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9738              for ( ; j < (ssize_t) (order*order); j++)
9739                kernel->values[j]=0.0;
9740            }
9741          if (attribute_flag[1] != 0)
9742            channel=(ChannelType) argument_list[1].integer_reference;
9743          if (attribute_flag[2] != 0)
9744            SetImageArtifact(image,"convolve:bias",
9745              argument_list[2].string_reference);
9746          if (attribute_flag[3] != 0)
9747            {
9748              kernel=AcquireKernelInfo(argument_list[3].string_reference,
9749                exception);
9750              if (kernel == (KernelInfo *) NULL)
9751                break;
9752            }
9753          channel_mask=SetImageChannelMask(image,channel);
9754          image=ConvolveImage(image,kernel,exception);
9755          if (image != (Image *) NULL)
9756            (void) SetImageChannelMask(image,channel_mask);
9757          kernel=DestroyKernelInfo(kernel);
9758          break;
9759        }
9760        case 68:  /* Profile */
9761        {
9762          const char
9763            *name;
9764
9765          Image
9766            *profile_image;
9767
9768          ImageInfo
9769            *profile_info;
9770
9771          StringInfo
9772            *profile;
9773
9774          name="*";
9775          if (attribute_flag[0] != 0)
9776            name=argument_list[0].string_reference;
9777          if (attribute_flag[2] != 0)
9778            image->rendering_intent=(RenderingIntent)
9779              argument_list[2].integer_reference;
9780          if (attribute_flag[3] != 0)
9781            image->black_point_compensation=
9782              argument_list[3].integer_reference != 0 ? MagickTrue :
9783              MagickFalse;
9784          if (attribute_flag[1] != 0)
9785            {
9786              if (argument_list[1].length == 0)
9787                {
9788                  /*
9789                    Remove a profile from the image.
9790                  */
9791                  (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9792                    exception);
9793                  break;
9794                }
9795              /*
9796                Associate user supplied profile with the image.
9797              */
9798              profile=AcquireStringInfo(argument_list[1].length);
9799              SetStringInfoDatum(profile,(const unsigned char *)
9800                argument_list[1].string_reference);
9801              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9802                (size_t) GetStringInfoLength(profile),exception);
9803              profile=DestroyStringInfo(profile);
9804              break;
9805            }
9806          /*
9807            Associate a profile with the image.
9808          */
9809          profile_info=CloneImageInfo(info ? info->image_info : (ImageInfo *)
9810            NULL);
9811          profile_image=ReadImages(profile_info,name,exception);
9812          if (profile_image == (Image *) NULL)
9813            break;
9814          ResetImageProfileIterator(profile_image);
9815          name=GetNextImageProfile(profile_image);
9816          while (name != (const char *) NULL)
9817          {
9818            const StringInfo
9819              *profile;
9820
9821            profile=GetImageProfile(profile_image,name);
9822            if (profile != (const StringInfo *) NULL)
9823              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9824                (size_t) GetStringInfoLength(profile),exception);
9825            name=GetNextImageProfile(profile_image);
9826          }
9827          profile_image=DestroyImage(profile_image);
9828          profile_info=DestroyImageInfo(profile_info);
9829          break;
9830        }
9831        case 69:  /* UnsharpMask */
9832        {
9833          if (attribute_flag[0] != 0)
9834            {
9835              flags=ParseGeometry(argument_list[0].string_reference,
9836                &geometry_info);
9837              if ((flags & SigmaValue) == 0)
9838                geometry_info.sigma=1.0;
9839              if ((flags & XiValue) == 0)
9840                geometry_info.xi=1.0;
9841              if ((flags & PsiValue) == 0)
9842                geometry_info.psi=0.5;
9843            }
9844          if (attribute_flag[1] != 0)
9845            geometry_info.rho=argument_list[1].real_reference;
9846          if (attribute_flag[2] != 0)
9847            geometry_info.sigma=argument_list[2].real_reference;
9848          if (attribute_flag[3] != 0)
9849            geometry_info.xi=argument_list[3].real_reference;
9850          if (attribute_flag[4] != 0)
9851            geometry_info.psi=argument_list[4].real_reference;
9852          if (attribute_flag[5] != 0)
9853            channel=(ChannelType) argument_list[5].integer_reference;
9854          channel_mask=SetImageChannelMask(image,channel);
9855          image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9856            geometry_info.xi,geometry_info.psi,exception);
9857          if (image != (Image *) NULL)
9858            (void) SetImageChannelMask(image,channel_mask);
9859          break;
9860        }
9861        case 70:  /* MotionBlur */
9862        {
9863          if (attribute_flag[0] != 0)
9864            {
9865              flags=ParseGeometry(argument_list[0].string_reference,
9866                &geometry_info);
9867              if ((flags & SigmaValue) == 0)
9868                geometry_info.sigma=1.0;
9869              if ((flags & XiValue) == 0)
9870                geometry_info.xi=1.0;
9871            }
9872          if (attribute_flag[1] != 0)
9873            geometry_info.rho=argument_list[1].real_reference;
9874          if (attribute_flag[2] != 0)
9875            geometry_info.sigma=argument_list[2].real_reference;
9876          if (attribute_flag[3] != 0)
9877            geometry_info.xi=argument_list[3].real_reference;
9878          if (attribute_flag[4] != 0)
9879            channel=(ChannelType) argument_list[4].integer_reference;
9880          channel_mask=SetImageChannelMask(image,channel);
9881          image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9882            geometry_info.xi,exception);
9883          if (image != (Image *) NULL)
9884            (void) SetImageChannelMask(image,channel_mask);
9885          break;
9886        }
9887        case 71:  /* OrderedDither */
9888        {
9889          if (attribute_flag[0] == 0)
9890            argument_list[0].string_reference="o8x8";
9891          if (attribute_flag[1] != 0)
9892            channel=(ChannelType) argument_list[1].integer_reference;
9893          channel_mask=SetImageChannelMask(image,channel);
9894          (void) OrderedDitherImage(image,argument_list[0].string_reference,
9895            exception);
9896          (void) SetImageChannelMask(image,channel_mask);
9897          break;
9898        }
9899        case 72:  /* Shave */
9900        {
9901          if (attribute_flag[0] != 0)
9902            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9903              &geometry,exception);
9904          if (attribute_flag[1] != 0)
9905            geometry.width=argument_list[1].integer_reference;
9906          if (attribute_flag[2] != 0)
9907            geometry.height=argument_list[2].integer_reference;
9908          image=ShaveImage(image,&geometry,exception);
9909          break;
9910        }
9911        case 73:  /* Level */
9912        {
9913          double
9914            black_point,
9915            gamma,
9916            white_point;
9917
9918          black_point=0.0;
9919          white_point=(double) image->columns*image->rows;
9920          gamma=1.0;
9921          if (attribute_flag[0] != 0)
9922            {
9923              flags=ParseGeometry(argument_list[0].string_reference,
9924                &geometry_info);
9925              black_point=geometry_info.rho;
9926              if ((flags & SigmaValue) != 0)
9927                white_point=geometry_info.sigma;
9928              if ((flags & XiValue) != 0)
9929                gamma=geometry_info.xi;
9930              if ((flags & PercentValue) != 0)
9931                {
9932                  black_point*=(double) (QuantumRange/100.0);
9933                  white_point*=(double) (QuantumRange/100.0);
9934                }
9935              if ((flags & SigmaValue) == 0)
9936                white_point=(double) QuantumRange-black_point;
9937            }
9938          if (attribute_flag[1] != 0)
9939            black_point=argument_list[1].real_reference;
9940          if (attribute_flag[2] != 0)
9941            white_point=argument_list[2].real_reference;
9942          if (attribute_flag[3] != 0)
9943            gamma=argument_list[3].real_reference;
9944          if (attribute_flag[4] != 0)
9945            channel=(ChannelType) argument_list[4].integer_reference;
9946          if (attribute_flag[5] != 0)
9947            {
9948              argument_list[0].real_reference=argument_list[5].real_reference;
9949              attribute_flag[0]=attribute_flag[5];
9950            }
9951          channel_mask=SetImageChannelMask(image,channel);
9952          (void) LevelImage(image,black_point,white_point,gamma,exception);
9953          (void) SetImageChannelMask(image,channel_mask);
9954          break;
9955        }
9956        case 74:  /* Clip */
9957        {
9958          if (attribute_flag[0] == 0)
9959            argument_list[0].string_reference="#1";
9960          if (attribute_flag[1] == 0)
9961            argument_list[1].integer_reference=MagickTrue;
9962          (void) ClipImagePath(image,argument_list[0].string_reference,
9963            argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9964            exception);
9965          break;
9966        }
9967        case 75:  /* AffineTransform */
9968        {
9969          DrawInfo
9970            *draw_info;
9971
9972          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9973            (DrawInfo *) NULL);
9974          if (attribute_flag[0] != 0)
9975            {
9976              AV
9977                *av;
9978
9979              av=(AV *) argument_list[0].array_reference;
9980              if ((av_len(av) != 3) && (av_len(av) != 5))
9981                {
9982                  ThrowPerlException(exception,OptionError,
9983                    "affine matrix must have 4 or 6 elements",PackageName);
9984                  goto PerlException;
9985                }
9986              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9987              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9988              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9989              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9990              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9991                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9992                {
9993                  ThrowPerlException(exception,OptionError,
9994                    "affine matrix is singular",PackageName);
9995                   goto PerlException;
9996                }
9997              if (av_len(av) == 5)
9998                {
9999                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
10000                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
10001                }
10002            }
10003          for (j=1; j < 6; j++)
10004          {
10005            if (attribute_flag[j] == 0)
10006              continue;
10007            value=argument_list[j].string_reference;
10008            angle=argument_list[j].real_reference;
10009            current=draw_info->affine;
10010            GetAffineMatrix(&affine);
10011            switch (j)
10012            {
10013              case 1:
10014              {
10015                /*
10016                  Translate.
10017                */
10018                flags=ParseGeometry(value,&geometry_info);
10019                affine.tx=geometry_info.xi;
10020                affine.ty=geometry_info.psi;
10021                if ((flags & PsiValue) == 0)
10022                  affine.ty=affine.tx;
10023                break;
10024              }
10025              case 2:
10026              {
10027                /*
10028                  Scale.
10029                */
10030                flags=ParseGeometry(value,&geometry_info);
10031                affine.sx=geometry_info.rho;
10032                affine.sy=geometry_info.sigma;
10033                if ((flags & SigmaValue) == 0)
10034                  affine.sy=affine.sx;
10035                break;
10036              }
10037              case 3:
10038              {
10039                /*
10040                  Rotate.
10041                */
10042                if (angle == 0.0)
10043                  break;
10044                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
10045                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
10046                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
10047                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
10048                break;
10049              }
10050              case 4:
10051              {
10052                /*
10053                  SkewX.
10054                */
10055                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
10056                break;
10057              }
10058              case 5:
10059              {
10060                /*
10061                  SkewY.
10062                */
10063                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10064                break;
10065              }
10066            }
10067            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10068            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10069            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10070            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10071            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
10072              current.tx;
10073            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
10074              current.ty;
10075          }
10076          if (attribute_flag[6] != 0)
10077            image->interpolate=(PixelInterpolateMethod)
10078              argument_list[6].integer_reference;
10079          if (attribute_flag[7] != 0)
10080            QueryColorCompliance(argument_list[7].string_reference,
10081              AllCompliance,&image->background_color,exception);
10082          image=AffineTransformImage(image,&draw_info->affine,exception);
10083          draw_info=DestroyDrawInfo(draw_info);
10084          break;
10085        }
10086        case 76:  /* Difference */
10087        {
10088          if (attribute_flag[0] == 0)
10089            {
10090              ThrowPerlException(exception,OptionError,
10091                "ReferenceImageRequired",PackageName);
10092              goto PerlException;
10093            }
10094          if (attribute_flag[1] != 0)
10095            image->fuzz=StringToDoubleInterval(
10096              argument_list[1].string_reference,(double) QuantumRange+1.0);
10097          (void) SetImageColorMetric(image,argument_list[0].image_reference,
10098            exception);
10099          break;
10100        }
10101        case 77:  /* AdaptiveThreshold */
10102        {
10103          if (attribute_flag[0] != 0)
10104            {
10105              flags=ParseGeometry(argument_list[0].string_reference,
10106                &geometry_info);
10107              if ((flags & PercentValue) != 0)
10108                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10109            }
10110          if (attribute_flag[1] != 0)
10111            geometry_info.rho=argument_list[1].integer_reference;
10112          if (attribute_flag[2] != 0)
10113            geometry_info.sigma=argument_list[2].integer_reference;
10114          if (attribute_flag[3] != 0)
10115            geometry_info.xi=argument_list[3].integer_reference;;
10116          image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10117            (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10118          break;
10119        }
10120        case 78:  /* Resample */
10121        {
10122          size_t
10123            height,
10124            width;
10125
10126          if (attribute_flag[0] != 0)
10127            {
10128              flags=ParseGeometry(argument_list[0].string_reference,
10129                &geometry_info);
10130              if ((flags & SigmaValue) == 0)
10131                geometry_info.sigma=geometry_info.rho;
10132            }
10133          if (attribute_flag[1] != 0)
10134            geometry_info.rho=argument_list[1].real_reference;
10135          if (attribute_flag[2] != 0)
10136            geometry_info.sigma=argument_list[2].real_reference;
10137          if (attribute_flag[3] == 0)
10138            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10139          if (attribute_flag[4] == 0)
10140            SetImageArtifact(image,"filter:support",
10141              argument_list[4].string_reference);
10142          width=(size_t) (geometry_info.rho*image->columns/
10143            (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10144          height=(size_t) (geometry_info.sigma*image->rows/
10145            (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10146          image=ResizeImage(image,width,height,(FilterType)
10147            argument_list[3].integer_reference,exception);
10148          if (image != (Image *) NULL)
10149            {
10150              image->resolution.x=geometry_info.rho;
10151              image->resolution.y=geometry_info.sigma;
10152            }
10153          break;
10154        }
10155        case 79:  /* Describe */
10156        {
10157          if (attribute_flag[0] == 0)
10158            argument_list[0].file_reference=(FILE *) NULL;
10159          (void) IdentifyImage(image,argument_list[0].file_reference,
10160            MagickTrue,exception);
10161          break;
10162        }
10163        case 80:  /* BlackThreshold */
10164        {
10165          if (attribute_flag[0] == 0)
10166            argument_list[0].string_reference="50%";
10167          if (attribute_flag[2] != 0)
10168            channel=(ChannelType) argument_list[2].integer_reference;
10169          channel_mask=SetImageChannelMask(image,channel);
10170          (void) BlackThresholdImage(image,argument_list[0].string_reference,
10171            exception);
10172          (void) SetImageChannelMask(image,channel_mask);
10173          break;
10174        }
10175        case 81:  /* WhiteThreshold */
10176        {
10177          if (attribute_flag[0] == 0)
10178            argument_list[0].string_reference="50%";
10179          if (attribute_flag[2] != 0)
10180            channel=(ChannelType) argument_list[2].integer_reference;
10181          channel_mask=SetImageChannelMask(image,channel);
10182          WhiteThresholdImage(image,argument_list[0].string_reference,
10183            exception);
10184          (void) SetImageChannelMask(image,channel_mask);
10185          break;
10186        }
10187        case 82:  /* RotationalBlur */
10188        {
10189          if (attribute_flag[0] != 0)
10190            flags=ParseGeometry(argument_list[0].string_reference,
10191              &geometry_info);
10192          if (attribute_flag[1] != 0)
10193            geometry_info.rho=argument_list[1].real_reference;
10194          if (attribute_flag[2] != 0)
10195            channel=(ChannelType) argument_list[2].integer_reference;
10196          channel_mask=SetImageChannelMask(image,channel);
10197          image=RotationalBlurImage(image,geometry_info.rho,exception);
10198          if (image != (Image *) NULL)
10199            (void) SetImageChannelMask(image,channel_mask);
10200          break;
10201        }
10202        case 83:  /* Thumbnail */
10203        {
10204          if (attribute_flag[0] != 0)
10205            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10206              &geometry,exception);
10207          if (attribute_flag[1] != 0)
10208            geometry.width=argument_list[1].integer_reference;
10209          if (attribute_flag[2] != 0)
10210            geometry.height=argument_list[2].integer_reference;
10211          image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10212          break;
10213        }
10214        case 84:  /* Strip */
10215        {
10216          (void) StripImage(image,exception);
10217          break;
10218        }
10219        case 85:  /* Tint */
10220        {
10221          PixelInfo
10222            tint;
10223
10224          GetPixelInfo(image,&tint);
10225          if (attribute_flag[0] != 0)
10226            (void) QueryColorCompliance(argument_list[0].string_reference,
10227              AllCompliance,&tint,exception);
10228          if (attribute_flag[1] == 0)
10229            argument_list[1].string_reference="100";
10230          image=TintImage(image,argument_list[1].string_reference,&tint,
10231            exception);
10232          break;
10233        }
10234        case 86:  /* Channel */
10235        {
10236          if (attribute_flag[0] != 0)
10237            channel=(ChannelType) argument_list[0].integer_reference;
10238          image=SeparateImage(image,channel,exception);
10239          break;
10240        }
10241        case 87:  /* Splice */
10242        {
10243          if (attribute_flag[7] != 0)
10244            image->gravity=(GravityType) argument_list[7].integer_reference;
10245          if (attribute_flag[0] != 0)
10246            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10247              &geometry,exception);
10248          if (attribute_flag[1] != 0)
10249            geometry.width=argument_list[1].integer_reference;
10250          if (attribute_flag[2] != 0)
10251            geometry.height=argument_list[2].integer_reference;
10252          if (attribute_flag[3] != 0)
10253            geometry.x=argument_list[3].integer_reference;
10254          if (attribute_flag[4] != 0)
10255            geometry.y=argument_list[4].integer_reference;
10256          if (attribute_flag[5] != 0)
10257            image->fuzz=StringToDoubleInterval(
10258              argument_list[5].string_reference,(double) QuantumRange+1.0);
10259          if (attribute_flag[6] != 0)
10260            (void) QueryColorCompliance(argument_list[6].string_reference,
10261              AllCompliance,&image->background_color,exception);
10262          image=SpliceImage(image,&geometry,exception);
10263          break;
10264        }
10265        case 88:  /* Posterize */
10266        {
10267          if (attribute_flag[0] == 0)
10268            argument_list[0].integer_reference=3;
10269          if (attribute_flag[1] == 0)
10270            argument_list[1].integer_reference=0;
10271          (void) PosterizeImage(image,argument_list[0].integer_reference,
10272            argument_list[1].integer_reference ? RiemersmaDitherMethod :
10273            NoDitherMethod,exception);
10274          break;
10275        }
10276        case 89:  /* Shadow */
10277        {
10278          if (attribute_flag[0] != 0)
10279            {
10280              flags=ParseGeometry(argument_list[0].string_reference,
10281                &geometry_info);
10282              if ((flags & SigmaValue) == 0)
10283                geometry_info.sigma=1.0;
10284              if ((flags & XiValue) == 0)
10285                geometry_info.xi=4.0;
10286              if ((flags & PsiValue) == 0)
10287                geometry_info.psi=4.0;
10288            }
10289          if (attribute_flag[1] != 0)
10290            geometry_info.rho=argument_list[1].real_reference;
10291          if (attribute_flag[2] != 0)
10292            geometry_info.sigma=argument_list[2].real_reference;
10293          if (attribute_flag[3] != 0)
10294            geometry_info.xi=argument_list[3].integer_reference;
10295          if (attribute_flag[4] != 0)
10296            geometry_info.psi=argument_list[4].integer_reference;
10297          image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10298            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10299            ceil(geometry_info.psi-0.5),exception);
10300          break;
10301        }
10302        case 90:  /* Identify */
10303        {
10304          if (attribute_flag[0] == 0)
10305            argument_list[0].file_reference=(FILE *) NULL;
10306          if (attribute_flag[1] != 0)
10307            (void) SetImageArtifact(image,"identify:features",
10308              argument_list[1].string_reference);
10309          if ((attribute_flag[2] != 0) &&
10310              (argument_list[2].integer_reference != 0))
10311            (void) SetImageArtifact(image,"identify:moments","true");
10312          if ((attribute_flag[3] != 0) &&
10313              (argument_list[3].integer_reference != 0))
10314            (void) SetImageArtifact(image,"identify:unique","true");
10315          (void) IdentifyImage(image,argument_list[0].file_reference,
10316            MagickTrue,exception);
10317          break;
10318        }
10319        case 91:  /* SepiaTone */
10320        {
10321          if (attribute_flag[0] == 0)
10322            argument_list[0].real_reference=80.0*QuantumRange/100.0;
10323          image=SepiaToneImage(image,argument_list[0].real_reference,exception);
10324          break;
10325        }
10326        case 92:  /* SigmoidalContrast */
10327        {
10328          MagickBooleanType
10329            sharpen;
10330
10331          if (attribute_flag[0] != 0)
10332            {
10333              flags=ParseGeometry(argument_list[0].string_reference,
10334                &geometry_info);
10335              if ((flags & SigmaValue) == 0)
10336                geometry_info.sigma=QuantumRange/2.0;
10337              if ((flags & PercentValue) != 0)
10338                geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10339            }
10340          if (attribute_flag[1] != 0)
10341            geometry_info.rho=argument_list[1].real_reference;
10342          if (attribute_flag[2] != 0)
10343            geometry_info.sigma=argument_list[2].real_reference;
10344          if (attribute_flag[3] != 0)
10345            channel=(ChannelType) argument_list[3].integer_reference;
10346          sharpen=MagickTrue;
10347          if (attribute_flag[4] != 0)
10348            sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10349              MagickFalse;
10350          channel_mask=SetImageChannelMask(image,channel);
10351          (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10352            geometry_info.sigma,exception);
10353          (void) SetImageChannelMask(image,channel_mask);
10354          break;
10355        }
10356        case 93:  /* Extent */
10357        {
10358          if (attribute_flag[7] != 0)
10359            image->gravity=(GravityType) argument_list[7].integer_reference;
10360          if (attribute_flag[0] != 0)
10361            {
10362              int
10363                flags;
10364
10365              flags=ParseGravityGeometry(image,
10366                argument_list[0].string_reference,&geometry,exception);
10367              (void) flags;
10368              if (geometry.width == 0)
10369                geometry.width=image->columns;
10370              if (geometry.height == 0)
10371                geometry.height=image->rows;
10372            }
10373          if (attribute_flag[1] != 0)
10374            geometry.width=argument_list[1].integer_reference;
10375          if (attribute_flag[2] != 0)
10376            geometry.height=argument_list[2].integer_reference;
10377          if (attribute_flag[3] != 0)
10378            geometry.x=argument_list[3].integer_reference;
10379          if (attribute_flag[4] != 0)
10380            geometry.y=argument_list[4].integer_reference;
10381          if (attribute_flag[5] != 0)
10382            image->fuzz=StringToDoubleInterval(
10383              argument_list[5].string_reference,(double) QuantumRange+1.0);
10384          if (attribute_flag[6] != 0)
10385            (void) QueryColorCompliance(argument_list[6].string_reference,
10386              AllCompliance,&image->background_color,exception);
10387          image=ExtentImage(image,&geometry,exception);
10388          break;
10389        }
10390        case 94:  /* Vignette */
10391        {
10392          if (attribute_flag[0] != 0)
10393            {
10394              flags=ParseGeometry(argument_list[0].string_reference,
10395                &geometry_info);
10396              if ((flags & SigmaValue) == 0)
10397                geometry_info.sigma=1.0;
10398              if ((flags & XiValue) == 0)
10399                geometry_info.xi=0.1*image->columns;
10400              if ((flags & PsiValue) == 0)
10401                geometry_info.psi=0.1*image->rows;
10402            }
10403          if (attribute_flag[1] != 0)
10404            geometry_info.rho=argument_list[1].real_reference;
10405          if (attribute_flag[2] != 0)
10406            geometry_info.sigma=argument_list[2].real_reference;
10407          if (attribute_flag[3] != 0)
10408            geometry_info.xi=argument_list[3].integer_reference;
10409          if (attribute_flag[4] != 0)
10410            geometry_info.psi=argument_list[4].integer_reference;
10411          if (attribute_flag[5] != 0)
10412            (void) QueryColorCompliance(argument_list[5].string_reference,
10413              AllCompliance,&image->background_color,exception);
10414          image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10415            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10416            ceil(geometry_info.psi-0.5),exception);
10417          break;
10418        }
10419        case 95:  /* ContrastStretch */
10420        {
10421          double
10422            black_point,
10423            white_point;
10424
10425          black_point=0.0;
10426          white_point=(double) image->columns*image->rows;
10427          if (attribute_flag[0] != 0)
10428            {
10429              flags=ParseGeometry(argument_list[0].string_reference,
10430                &geometry_info);
10431              black_point=geometry_info.rho;
10432              white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10433                black_point;
10434              if ((flags & PercentValue) != 0)
10435                {
10436                  black_point*=(double) image->columns*image->rows/100.0;
10437                  white_point*=(double) image->columns*image->rows/100.0;
10438                }
10439              white_point=(double) image->columns*image->rows-white_point;
10440            }
10441          if (attribute_flag[1] != 0)
10442            black_point=argument_list[1].real_reference;
10443          if (attribute_flag[2] != 0)
10444            white_point=argument_list[2].real_reference;
10445          if (attribute_flag[4] != 0)
10446            channel=(ChannelType) argument_list[4].integer_reference;
10447          channel_mask=SetImageChannelMask(image,channel);
10448          (void) ContrastStretchImage(image,black_point,white_point,exception);
10449          (void) SetImageChannelMask(image,channel_mask);
10450          break;
10451        }
10452        case 96:  /* Sans0 */
10453        {
10454          break;
10455        }
10456        case 97:  /* Sans1 */
10457        {
10458          break;
10459        }
10460        case 98:  /* AdaptiveSharpen */
10461        {
10462          if (attribute_flag[0] != 0)
10463            {
10464              flags=ParseGeometry(argument_list[0].string_reference,
10465                &geometry_info);
10466              if ((flags & SigmaValue) == 0)
10467                geometry_info.sigma=1.0;
10468              if ((flags & XiValue) == 0)
10469                geometry_info.xi=0.0;
10470            }
10471          if (attribute_flag[1] != 0)
10472            geometry_info.rho=argument_list[1].real_reference;
10473          if (attribute_flag[2] != 0)
10474            geometry_info.sigma=argument_list[2].real_reference;
10475          if (attribute_flag[3] != 0)
10476            geometry_info.xi=argument_list[3].real_reference;
10477          if (attribute_flag[4] != 0)
10478            channel=(ChannelType) argument_list[4].integer_reference;
10479          channel_mask=SetImageChannelMask(image,channel);
10480          image=AdaptiveSharpenImage(image,geometry_info.rho,
10481            geometry_info.sigma,exception);
10482          if (image != (Image *) NULL)
10483            (void) SetImageChannelMask(image,channel_mask);
10484          break;
10485        }
10486        case 99:  /* Transpose */
10487        {
10488          image=TransposeImage(image,exception);
10489          break;
10490        }
10491        case 100:  /* Tranverse */
10492        {
10493          image=TransverseImage(image,exception);
10494          break;
10495        }
10496        case 101:  /* AutoOrient */
10497        {
10498          image=AutoOrientImage(image,image->orientation,exception);
10499          break;
10500        }
10501        case 102:  /* AdaptiveBlur */
10502        {
10503          if (attribute_flag[0] != 0)
10504            {
10505              flags=ParseGeometry(argument_list[0].string_reference,
10506                &geometry_info);
10507              if ((flags & SigmaValue) == 0)
10508                geometry_info.sigma=1.0;
10509              if ((flags & XiValue) == 0)
10510                geometry_info.xi=0.0;
10511            }
10512          if (attribute_flag[1] != 0)
10513            geometry_info.rho=argument_list[1].real_reference;
10514          if (attribute_flag[2] != 0)
10515            geometry_info.sigma=argument_list[2].real_reference;
10516          if (attribute_flag[3] != 0)
10517            channel=(ChannelType) argument_list[3].integer_reference;
10518          channel_mask=SetImageChannelMask(image,channel);
10519          image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10520            exception);
10521          if (image != (Image *) NULL)
10522            (void) SetImageChannelMask(image,channel_mask);
10523          break;
10524        }
10525        case 103:  /* Sketch */
10526        {
10527          if (attribute_flag[0] != 0)
10528            {
10529              flags=ParseGeometry(argument_list[0].string_reference,
10530                &geometry_info);
10531              if ((flags & SigmaValue) == 0)
10532                geometry_info.sigma=1.0;
10533              if ((flags & XiValue) == 0)
10534                geometry_info.xi=1.0;
10535            }
10536          if (attribute_flag[1] != 0)
10537            geometry_info.rho=argument_list[1].real_reference;
10538          if (attribute_flag[2] != 0)
10539            geometry_info.sigma=argument_list[2].real_reference;
10540          if (attribute_flag[3] != 0)
10541            geometry_info.xi=argument_list[3].real_reference;
10542          image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10543            geometry_info.xi,exception);
10544          break;
10545        }
10546        case 104:  /* UniqueColors */
10547        {
10548          image=UniqueImageColors(image,exception);
10549          break;
10550        }
10551        case 105:  /* AdaptiveResize */
10552        {
10553          if (attribute_flag[0] != 0)
10554            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10555              &geometry,exception);
10556          if (attribute_flag[1] != 0)
10557            geometry.width=argument_list[1].integer_reference;
10558          if (attribute_flag[2] != 0)
10559            geometry.height=argument_list[2].integer_reference;
10560          if (attribute_flag[3] != 0)
10561            image->filter=(FilterType) argument_list[4].integer_reference;
10562          if (attribute_flag[4] != 0)
10563            SetImageArtifact(image,"filter:support",
10564              argument_list[4].string_reference);
10565          image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10566            exception);
10567          break;
10568        }
10569        case 106:  /* ClipMask */
10570        {
10571          Image
10572            *mask_image;
10573
10574          if (attribute_flag[0] == 0)
10575            {
10576              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10577                PackageName);
10578              goto PerlException;
10579            }
10580          mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10581            exception);
10582          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10583          mask_image=DestroyImage(mask_image);
10584          break;
10585        }
10586        case 107:  /* LinearStretch */
10587        {
10588           double
10589             black_point,
10590             white_point;
10591
10592           black_point=0.0;
10593           white_point=(double) image->columns*image->rows;
10594           if (attribute_flag[0] != 0)
10595             {
10596               flags=ParseGeometry(argument_list[0].string_reference,
10597                 &geometry_info);
10598               if ((flags & SigmaValue) != 0)
10599                  white_point=geometry_info.sigma;
10600               if ((flags & PercentValue) != 0)
10601                 {
10602                   black_point*=(double) image->columns*image->rows/100.0;
10603                   white_point*=(double) image->columns*image->rows/100.0;
10604                 }
10605               if ((flags & SigmaValue) == 0)
10606                 white_point=(double) image->columns*image->rows-black_point;
10607             }
10608          if (attribute_flag[1] != 0)
10609            black_point=argument_list[1].real_reference;
10610          if (attribute_flag[2] != 0)
10611            white_point=argument_list[2].real_reference;
10612          (void) LinearStretchImage(image,black_point,white_point,exception);
10613          break;
10614        }
10615        case 108:  /* ColorMatrix */
10616        {
10617          AV
10618            *av;
10619
10620          double
10621            *color_matrix;
10622
10623          KernelInfo
10624            *kernel_info;
10625
10626          size_t
10627            order;
10628
10629          if (attribute_flag[0] == 0)
10630            break;
10631          av=(AV *) argument_list[0].array_reference;
10632          order=(size_t) sqrt(av_len(av)+1);
10633          color_matrix=(double *) AcquireQuantumMemory(order,order*
10634            sizeof(*color_matrix));
10635          if (color_matrix == (double *) NULL)
10636            {
10637              ThrowPerlException(exception,ResourceLimitFatalError,
10638                "MemoryAllocationFailed",PackageName);
10639              goto PerlException;
10640           }
10641          for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10642            color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10643          for ( ; j < (ssize_t) (order*order); j++)
10644            color_matrix[j]=0.0;
10645          kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10646          if (kernel_info == (KernelInfo *) NULL)
10647            break;
10648          kernel_info->width=order;
10649          kernel_info->height=order;
10650          kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10651            order*sizeof(*kernel_info->values));
10652          if (kernel_info->values != (MagickRealType *) NULL)
10653            {
10654              for (i=0; i < (ssize_t) (order*order); i++)
10655                kernel_info->values[i]=(MagickRealType) color_matrix[i];
10656              image=ColorMatrixImage(image,kernel_info,exception);
10657            }
10658          kernel_info=DestroyKernelInfo(kernel_info);
10659          color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10660          break;
10661        }
10662        case 109:  /* Mask */
10663        {
10664          Image
10665            *mask_image;
10666
10667          if (attribute_flag[0] == 0)
10668            {
10669              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10670                PackageName);
10671              goto PerlException;
10672            }
10673          mask_image=CloneImage(argument_list[0].image_reference,0,0,
10674            MagickTrue,exception);
10675          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10676          mask_image=DestroyImage(mask_image);
10677          break;
10678        }
10679        case 110:  /* Polaroid */
10680        {
10681          char
10682            *caption;
10683
10684          double
10685            angle;
10686
10687          DrawInfo
10688            *draw_info;
10689
10690          PixelInterpolateMethod
10691            method;
10692
10693          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10694            (DrawInfo *) NULL);
10695          caption=(char *) NULL;
10696          if (attribute_flag[0] != 0)
10697            caption=InterpretImageProperties(info ? info->image_info :
10698              (ImageInfo *) NULL,image,argument_list[0].string_reference,
10699              exception);
10700          angle=0.0;
10701          if (attribute_flag[1] != 0)
10702            angle=argument_list[1].real_reference;
10703          if (attribute_flag[2] != 0)
10704            (void) CloneString(&draw_info->font,
10705              argument_list[2].string_reference);
10706          if (attribute_flag[3] != 0)
10707            (void) QueryColorCompliance(argument_list[3].string_reference,
10708              AllCompliance,&draw_info->stroke,exception);
10709          if (attribute_flag[4] != 0)
10710            (void) QueryColorCompliance(argument_list[4].string_reference,
10711              AllCompliance,&draw_info->fill,exception);
10712          if (attribute_flag[5] != 0)
10713            draw_info->stroke_width=argument_list[5].real_reference;
10714          if (attribute_flag[6] != 0)
10715            draw_info->pointsize=argument_list[6].real_reference;
10716          if (attribute_flag[7] != 0)
10717            draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10718          if (attribute_flag[8] != 0)
10719            (void) QueryColorCompliance(argument_list[8].string_reference,
10720              AllCompliance,&image->background_color,exception);
10721          method=UndefinedInterpolatePixel;
10722          if (attribute_flag[9] != 0)
10723            method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10724          image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10725          draw_info=DestroyDrawInfo(draw_info);
10726          if (caption != (char *) NULL)
10727            caption=DestroyString(caption);
10728          break;
10729        }
10730        case 111:  /* FloodfillPaint */
10731        {
10732          DrawInfo
10733            *draw_info;
10734
10735          MagickBooleanType
10736            invert;
10737
10738          PixelInfo
10739            target;
10740
10741          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10742            (DrawInfo *) NULL);
10743          if (attribute_flag[0] != 0)
10744            flags=ParsePageGeometry(image,argument_list[0].string_reference,
10745              &geometry,exception);
10746          if (attribute_flag[1] != 0)
10747            geometry.x=argument_list[1].integer_reference;
10748          if (attribute_flag[2] != 0)
10749            geometry.y=argument_list[2].integer_reference;
10750          if (attribute_flag[3] != 0)
10751            (void) QueryColorCompliance(argument_list[3].string_reference,
10752              AllCompliance,&draw_info->fill,exception);
10753          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10754            geometry.x,geometry.y,&target,exception);
10755          if (attribute_flag[4] != 0)
10756            QueryColorCompliance(argument_list[4].string_reference,
10757              AllCompliance,&target,exception);
10758          if (attribute_flag[5] != 0)
10759            image->fuzz=StringToDoubleInterval(
10760              argument_list[5].string_reference,(double) QuantumRange+1.0);
10761          if (attribute_flag[6] != 0)
10762            channel=(ChannelType) argument_list[6].integer_reference;
10763          invert=MagickFalse;
10764          if (attribute_flag[7] != 0)
10765            invert=(MagickBooleanType) argument_list[7].integer_reference;
10766          channel_mask=SetImageChannelMask(image,channel);
10767          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10768            geometry.y,invert,exception);
10769          (void) SetImageChannelMask(image,channel_mask);
10770          draw_info=DestroyDrawInfo(draw_info);
10771          break;
10772        }
10773        case 112:  /* Distort */
10774        {
10775          AV
10776            *av;
10777
10778          DistortMethod
10779            method;
10780
10781          double
10782            *coordinates;
10783
10784          size_t
10785            number_coordinates;
10786
10787          VirtualPixelMethod
10788            virtual_pixel;
10789
10790          if (attribute_flag[0] == 0)
10791            break;
10792          method=UndefinedDistortion;
10793          if (attribute_flag[1] != 0)
10794            method=(DistortMethod) argument_list[1].integer_reference;
10795          av=(AV *) argument_list[0].array_reference;
10796          number_coordinates=(size_t) av_len(av)+1;
10797          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10798            sizeof(*coordinates));
10799          if (coordinates == (double *) NULL)
10800            {
10801              ThrowPerlException(exception,ResourceLimitFatalError,
10802                "MemoryAllocationFailed",PackageName);
10803              goto PerlException;
10804            }
10805          for (j=0; j < (ssize_t) number_coordinates; j++)
10806            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10807          virtual_pixel=UndefinedVirtualPixelMethod;
10808          if (attribute_flag[2] != 0)
10809            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10810              argument_list[2].integer_reference,exception);
10811          image=DistortImage(image,method,number_coordinates,coordinates,
10812            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10813            exception);
10814          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10815            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10816              exception);
10817          coordinates=(double *) RelinquishMagickMemory(coordinates);
10818          break;
10819        }
10820        case 113:  /* Clut */
10821        {
10822          PixelInterpolateMethod
10823            method;
10824
10825          if (attribute_flag[0] == 0)
10826            {
10827              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10828                PackageName);
10829              goto PerlException;
10830            }
10831          method=UndefinedInterpolatePixel;
10832          if (attribute_flag[1] != 0)
10833            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10834          if (attribute_flag[2] != 0)
10835            channel=(ChannelType) argument_list[2].integer_reference;
10836          channel_mask=SetImageChannelMask(image,channel);
10837          (void) ClutImage(image,argument_list[0].image_reference,method,
10838            exception);
10839          (void) SetImageChannelMask(image,channel_mask);
10840          break;
10841        }
10842        case 114:  /* LiquidRescale */
10843        {
10844          if (attribute_flag[0] != 0)
10845            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10846              &geometry,exception);
10847          if (attribute_flag[1] != 0)
10848            geometry.width=argument_list[1].integer_reference;
10849          if (attribute_flag[2] != 0)
10850            geometry.height=argument_list[2].integer_reference;
10851          if (attribute_flag[3] == 0)
10852            argument_list[3].real_reference=1.0;
10853          if (attribute_flag[4] == 0)
10854            argument_list[4].real_reference=0.0;
10855          image=LiquidRescaleImage(image,geometry.width,geometry.height,
10856            argument_list[3].real_reference,argument_list[4].real_reference,
10857            exception);
10858          break;
10859        }
10860        case 115:  /* EncipherImage */
10861        {
10862          (void) EncipherImage(image,argument_list[0].string_reference,
10863            exception);
10864          break;
10865        }
10866        case 116:  /* DecipherImage */
10867        {
10868          (void) DecipherImage(image,argument_list[0].string_reference,
10869            exception);
10870          break;
10871        }
10872        case 117:  /* Deskew */
10873        {
10874          geometry_info.rho=QuantumRange/2.0;
10875          if (attribute_flag[0] != 0)
10876            flags=ParseGeometry(argument_list[0].string_reference,
10877              &geometry_info);
10878          if (attribute_flag[1] != 0)
10879            geometry_info.rho=StringToDoubleInterval(
10880              argument_list[1].string_reference,(double) QuantumRange+1.0);
10881          image=DeskewImage(image,geometry_info.rho,exception);
10882          break;
10883        }
10884        case 118:  /* Remap */
10885        {
10886          QuantizeInfo
10887            *quantize_info;
10888
10889          if (attribute_flag[0] == 0)
10890            {
10891              ThrowPerlException(exception,OptionError,"RemapImageRequired",
10892                PackageName);
10893              goto PerlException;
10894            }
10895          quantize_info=AcquireQuantizeInfo(info->image_info);
10896          if (attribute_flag[1] != 0)
10897            quantize_info->dither_method=(DitherMethod)
10898              argument_list[1].integer_reference;
10899          (void) RemapImages(quantize_info,image,
10900            argument_list[0].image_reference,exception);
10901          quantize_info=DestroyQuantizeInfo(quantize_info);
10902          break;
10903        }
10904        case 119:  /* SparseColor */
10905        {
10906          AV
10907            *av;
10908
10909          double
10910            *coordinates;
10911
10912          size_t
10913            number_coordinates;
10914
10915          SparseColorMethod
10916            method;
10917
10918          VirtualPixelMethod
10919            virtual_pixel;
10920
10921          if (attribute_flag[0] == 0)
10922            break;
10923          method=UndefinedColorInterpolate;
10924          if (attribute_flag[1] != 0)
10925            method=(SparseColorMethod) argument_list[1].integer_reference;
10926          av=(AV *) argument_list[0].array_reference;
10927          number_coordinates=(size_t) av_len(av)+1;
10928          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10929            sizeof(*coordinates));
10930          if (coordinates == (double *) NULL)
10931            {
10932              ThrowPerlException(exception,ResourceLimitFatalError,
10933                "MemoryAllocationFailed",PackageName);
10934              goto PerlException;
10935            }
10936          for (j=0; j < (ssize_t) number_coordinates; j++)
10937            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10938          virtual_pixel=UndefinedVirtualPixelMethod;
10939          if (attribute_flag[2] != 0)
10940            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10941              argument_list[2].integer_reference,exception);
10942          if (attribute_flag[3] != 0)
10943            channel=(ChannelType) argument_list[3].integer_reference;
10944          channel_mask=SetImageChannelMask(image,channel);
10945          image=SparseColorImage(image,method,number_coordinates,coordinates,
10946            exception);
10947          if (image != (Image *) NULL)
10948            (void) SetImageChannelMask(image,channel_mask);
10949          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10950            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10951              exception);
10952          coordinates=(double *) RelinquishMagickMemory(coordinates);
10953          break;
10954        }
10955        case 120:  /* Function */
10956        {
10957          AV
10958            *av;
10959
10960          double
10961            *parameters;
10962
10963          MagickFunction
10964            function;
10965
10966          size_t
10967            number_parameters;
10968
10969          VirtualPixelMethod
10970            virtual_pixel;
10971
10972          if (attribute_flag[0] == 0)
10973            break;
10974          function=UndefinedFunction;
10975          if (attribute_flag[1] != 0)
10976            function=(MagickFunction) argument_list[1].integer_reference;
10977          av=(AV *) argument_list[0].array_reference;
10978          number_parameters=(size_t) av_len(av)+1;
10979          parameters=(double *) AcquireQuantumMemory(number_parameters,
10980            sizeof(*parameters));
10981          if (parameters == (double *) NULL)
10982            {
10983              ThrowPerlException(exception,ResourceLimitFatalError,
10984                "MemoryAllocationFailed",PackageName);
10985              goto PerlException;
10986            }
10987          for (j=0; j < (ssize_t) number_parameters; j++)
10988            parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10989          virtual_pixel=UndefinedVirtualPixelMethod;
10990          if (attribute_flag[2] != 0)
10991            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10992              argument_list[2].integer_reference,exception);
10993          (void) FunctionImage(image,function,number_parameters,parameters,
10994            exception);
10995          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10996            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10997              exception);
10998          parameters=(double *) RelinquishMagickMemory(parameters);
10999          break;
11000        }
11001        case 121:  /* SelectiveBlur */
11002        {
11003          if (attribute_flag[0] != 0)
11004            {
11005              flags=ParseGeometry(argument_list[0].string_reference,
11006                &geometry_info);
11007              if ((flags & SigmaValue) == 0)
11008                geometry_info.sigma=1.0;
11009              if ((flags & PercentValue) != 0)
11010                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11011            }
11012          if (attribute_flag[1] != 0)
11013            geometry_info.rho=argument_list[1].real_reference;
11014          if (attribute_flag[2] != 0)
11015            geometry_info.sigma=argument_list[2].real_reference;
11016          if (attribute_flag[3] != 0)
11017            geometry_info.xi=argument_list[3].integer_reference;;
11018          if (attribute_flag[5] != 0)
11019            channel=(ChannelType) argument_list[5].integer_reference;
11020          channel_mask=SetImageChannelMask(image,channel);
11021          image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
11022            geometry_info.xi,exception);
11023          if (image != (Image *) NULL)
11024            (void) SetImageChannelMask(image,channel_mask);
11025          break;
11026        }
11027        case 122:  /* HaldClut */
11028        {
11029          if (attribute_flag[0] == 0)
11030            {
11031              ThrowPerlException(exception,OptionError,"ClutImageRequired",
11032                PackageName);
11033              goto PerlException;
11034            }
11035          if (attribute_flag[1] != 0)
11036            channel=(ChannelType) argument_list[1].integer_reference;
11037          channel_mask=SetImageChannelMask(image,channel);
11038          (void) HaldClutImage(image,argument_list[0].image_reference,
11039            exception);
11040          (void) SetImageChannelMask(image,channel_mask);
11041          break;
11042        }
11043        case 123:  /* BlueShift */
11044        {
11045          if (attribute_flag[0] != 0)
11046            (void) ParseGeometry(argument_list[0].string_reference,
11047              &geometry_info);
11048          image=BlueShiftImage(image,geometry_info.rho,exception);
11049          break;
11050        }
11051        case 124:  /* ForwardFourierTransformImage */
11052        {
11053          image=ForwardFourierTransformImage(image,
11054            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11055            exception);
11056          break;
11057        }
11058        case 125:  /* InverseFourierTransformImage */
11059        {
11060          image=InverseFourierTransformImage(image,image->next,
11061            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11062            exception);
11063          break;
11064        }
11065        case 126:  /* ColorDecisionList */
11066        {
11067          if (attribute_flag[0] == 0)
11068            argument_list[0].string_reference=(char *) NULL;
11069          (void) ColorDecisionListImage(image,
11070            argument_list[0].string_reference,exception);
11071          break;
11072        }
11073        case 127:  /* AutoGamma */
11074        {
11075          if (attribute_flag[0] != 0)
11076            channel=(ChannelType) argument_list[0].integer_reference;
11077          channel_mask=SetImageChannelMask(image,channel);
11078          (void) AutoGammaImage(image,exception);
11079          (void) SetImageChannelMask(image,channel_mask);
11080          break;
11081        }
11082        case 128:  /* AutoLevel */
11083        {
11084          if (attribute_flag[0] != 0)
11085            channel=(ChannelType) argument_list[0].integer_reference;
11086          channel_mask=SetImageChannelMask(image,channel);
11087          (void) AutoLevelImage(image,exception);
11088          (void) SetImageChannelMask(image,channel_mask);
11089          break;
11090        }
11091        case 129:  /* LevelColors */
11092        {
11093          PixelInfo
11094            black_point,
11095            white_point;
11096
11097          (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11098            exception);
11099          (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11100            exception);
11101          if (attribute_flag[1] != 0)
11102             (void) QueryColorCompliance(
11103               argument_list[1].string_reference,AllCompliance,&black_point,
11104               exception);
11105          if (attribute_flag[2] != 0)
11106             (void) QueryColorCompliance(
11107               argument_list[2].string_reference,AllCompliance,&white_point,
11108               exception);
11109          if (attribute_flag[3] != 0)
11110            channel=(ChannelType) argument_list[3].integer_reference;
11111          channel_mask=SetImageChannelMask(image,channel);
11112          (void) LevelImageColors(image,&black_point,&white_point,
11113            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11114            exception);
11115          (void) SetImageChannelMask(image,channel_mask);
11116          break;
11117        }
11118        case 130:  /* Clamp */
11119        {
11120          if (attribute_flag[0] != 0)
11121            channel=(ChannelType) argument_list[0].integer_reference;
11122          channel_mask=SetImageChannelMask(image,channel);
11123          (void) ClampImage(image,exception);
11124          (void) SetImageChannelMask(image,channel_mask);
11125          break;
11126        }
11127        case 131:  /* BrightnessContrast */
11128        {
11129          double
11130            brightness,
11131            contrast;
11132
11133          brightness=0.0;
11134          contrast=0.0;
11135          if (attribute_flag[0] != 0)
11136            {
11137              flags=ParseGeometry(argument_list[0].string_reference,
11138                &geometry_info);
11139              brightness=geometry_info.rho;
11140              if ((flags & SigmaValue) == 0)
11141                contrast=geometry_info.sigma;
11142            }
11143          if (attribute_flag[1] != 0)
11144            brightness=argument_list[1].real_reference;
11145          if (attribute_flag[2] != 0)
11146            contrast=argument_list[2].real_reference;
11147          if (attribute_flag[4] != 0)
11148            channel=(ChannelType) argument_list[4].integer_reference;
11149          channel_mask=SetImageChannelMask(image,channel);
11150          (void) BrightnessContrastImage(image,brightness,contrast,exception);
11151          (void) SetImageChannelMask(image,channel_mask);
11152          break;
11153        }
11154        case 132:  /* Morphology */
11155        {
11156          KernelInfo
11157            *kernel;
11158
11159          MorphologyMethod
11160            method;
11161
11162          ssize_t
11163            iterations;
11164
11165          if (attribute_flag[0] == 0)
11166            break;
11167          kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11168          if (kernel == (KernelInfo *) NULL)
11169            break;
11170          if (attribute_flag[1] != 0)
11171            channel=(ChannelType) argument_list[1].integer_reference;
11172          method=UndefinedMorphology;
11173          if (attribute_flag[2] != 0)
11174            method=argument_list[2].integer_reference;
11175          iterations=1;
11176          if (attribute_flag[3] != 0)
11177            iterations=argument_list[3].integer_reference;
11178          channel_mask=SetImageChannelMask(image,channel);
11179          image=MorphologyImage(image,method,iterations,kernel,exception);
11180          if (image != (Image *) NULL)
11181            (void) SetImageChannelMask(image,channel_mask);
11182          kernel=DestroyKernelInfo(kernel);
11183          break;
11184        }
11185        case 133:  /* Mode */
11186        {
11187          if (attribute_flag[0] != 0)
11188            {
11189              flags=ParseGeometry(argument_list[0].string_reference,
11190                &geometry_info);
11191              if ((flags & SigmaValue) == 0)
11192                geometry_info.sigma=1.0;
11193            }
11194          if (attribute_flag[1] != 0)
11195            geometry_info.rho=argument_list[1].real_reference;
11196          if (attribute_flag[2] != 0)
11197            geometry_info.sigma=argument_list[2].real_reference;
11198          if (attribute_flag[3] != 0)
11199            channel=(ChannelType) argument_list[3].integer_reference;
11200          channel_mask=SetImageChannelMask(image,channel);
11201          image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11202            (size_t) geometry_info.sigma,exception);
11203          if (image != (Image *) NULL)
11204            (void) SetImageChannelMask(image,channel_mask);
11205          break;
11206        }
11207        case 134:  /* Statistic */
11208        {
11209          StatisticType
11210            statistic;
11211
11212          statistic=UndefinedStatistic;
11213          if (attribute_flag[0] != 0)
11214            {
11215              flags=ParseGeometry(argument_list[0].string_reference,
11216                &geometry_info);
11217              if ((flags & SigmaValue) == 0)
11218                geometry_info.sigma=1.0;
11219            }
11220          if (attribute_flag[1] != 0)
11221            geometry_info.rho=argument_list[1].real_reference;
11222          if (attribute_flag[2] != 0)
11223            geometry_info.sigma=argument_list[2].real_reference;
11224          if (attribute_flag[3] != 0)
11225            channel=(ChannelType) argument_list[3].integer_reference;
11226          if (attribute_flag[4] != 0)
11227            statistic=(StatisticType) argument_list[4].integer_reference;
11228          channel_mask=SetImageChannelMask(image,channel);
11229          image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11230            (size_t) geometry_info.sigma,exception);
11231          if (image != (Image *) NULL)
11232            (void) SetImageChannelMask(image,channel_mask);
11233          break;
11234        }
11235        case 135:  /* Perceptible */
11236        {
11237          double
11238            epsilon;
11239
11240          epsilon=MagickEpsilon;
11241          if (attribute_flag[0] != 0)
11242            epsilon=argument_list[0].real_reference;
11243          if (attribute_flag[1] != 0)
11244            channel=(ChannelType) argument_list[1].integer_reference;
11245          channel_mask=SetImageChannelMask(image,channel);
11246          (void) PerceptibleImage(image,epsilon,exception);
11247          (void) SetImageChannelMask(image,channel_mask);
11248          break;
11249        }
11250        case 136:  /* Poly */
11251        {
11252          AV
11253            *av;
11254
11255          double
11256            *terms;
11257
11258          size_t
11259            number_terms;
11260
11261          if (attribute_flag[0] == 0)
11262            break;
11263          if (attribute_flag[1] != 0)
11264            channel=(ChannelType) argument_list[1].integer_reference;
11265          av=(AV *) argument_list[0].array_reference;
11266          number_terms=(size_t) av_len(av);
11267          terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11268          if (terms == (double *) NULL)
11269            {
11270              ThrowPerlException(exception,ResourceLimitFatalError,
11271                "MemoryAllocationFailed",PackageName);
11272              goto PerlException;
11273            }
11274          for (j=0; j < av_len(av); j++)
11275            terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11276          image=PolynomialImage(image,number_terms >> 1,terms,exception);
11277          terms=(double *) RelinquishMagickMemory(terms);
11278          break;
11279        }
11280        case 137:  /* Grayscale */
11281        {
11282          PixelIntensityMethod
11283            method;
11284
11285          method=UndefinedPixelIntensityMethod;
11286          if (attribute_flag[0] != 0)
11287            method=(PixelIntensityMethod) argument_list[0].integer_reference;
11288          (void) GrayscaleImage(image,method,exception);
11289          break;
11290        }
11291        case 138:  /* Canny */
11292        {
11293          if (attribute_flag[0] != 0)
11294            {
11295              flags=ParseGeometry(argument_list[0].string_reference,
11296                &geometry_info);
11297              if ((flags & SigmaValue) == 0)
11298                geometry_info.sigma=1.0;
11299              if ((flags & XiValue) == 0)
11300                geometry_info.xi=0.10;
11301              if ((flags & PsiValue) == 0)
11302                geometry_info.psi=0.30;
11303              if ((flags & PercentValue) != 0)
11304                {
11305                  geometry_info.xi/=100.0;
11306                  geometry_info.psi/=100.0;
11307                }
11308            }
11309          if (attribute_flag[1] != 0)
11310            geometry_info.rho=argument_list[1].real_reference;
11311          if (attribute_flag[2] != 0)
11312            geometry_info.sigma=argument_list[2].real_reference;
11313          if (attribute_flag[3] != 0)
11314            geometry_info.xi=argument_list[3].real_reference;
11315          if (attribute_flag[4] != 0)
11316            geometry_info.psi=argument_list[4].real_reference;
11317          if (attribute_flag[5] != 0)
11318            channel=(ChannelType) argument_list[5].integer_reference;
11319          channel_mask=SetImageChannelMask(image,channel);
11320          image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11321            geometry_info.xi,geometry_info.psi,exception);
11322          if (image != (Image *) NULL)
11323            (void) SetImageChannelMask(image,channel_mask);
11324          break;
11325        }
11326        case 139:  /* HoughLine */
11327        {
11328          if (attribute_flag[0] != 0)
11329            {
11330              flags=ParseGeometry(argument_list[0].string_reference,
11331                &geometry_info);
11332              if ((flags & SigmaValue) == 0)
11333                geometry_info.sigma=geometry_info.rho;
11334              if ((flags & XiValue) == 0)
11335                geometry_info.xi=40;
11336            }
11337          if (attribute_flag[1] != 0)
11338            geometry_info.rho=(double) argument_list[1].integer_reference;
11339          if (attribute_flag[2] != 0)
11340            geometry_info.sigma=(double) argument_list[2].integer_reference;
11341          if (attribute_flag[3] != 0)
11342            geometry_info.xi=(double) argument_list[3].integer_reference;
11343          image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11344            geometry_info.sigma,(size_t) geometry_info.xi,exception);
11345          break;
11346        }
11347        case 140:  /* MeanShift */
11348        {
11349          if (attribute_flag[0] != 0)
11350            {
11351              flags=ParseGeometry(argument_list[0].string_reference,
11352                &geometry_info);
11353              if ((flags & SigmaValue) == 0)
11354                geometry_info.sigma=geometry_info.rho;
11355              if ((flags & XiValue) == 0)
11356                geometry_info.xi=0.10*QuantumRange;
11357              if ((flags & PercentValue) != 0)
11358                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11359            }
11360          if (attribute_flag[1] != 0)
11361            geometry_info.rho=(double) argument_list[1].integer_reference;
11362          if (attribute_flag[2] != 0)
11363            geometry_info.sigma=(double) argument_list[2].integer_reference;
11364          if (attribute_flag[3] != 0)
11365            geometry_info.xi=(double) argument_list[3].integer_reference;
11366          image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11367            geometry_info.sigma,geometry_info.xi,exception);
11368          break;
11369        }
11370        case 141:  /* Kuwahara */
11371        {
11372          if (attribute_flag[0] != 0)
11373            {
11374              flags=ParseGeometry(argument_list[0].string_reference,
11375                &geometry_info);
11376              if ((flags & SigmaValue) == 0)
11377                geometry_info.sigma=geometry_info.rho-0.5;
11378            }
11379          if (attribute_flag[1] != 0)
11380            geometry_info.rho=argument_list[1].real_reference;
11381          if (attribute_flag[2] != 0)
11382            geometry_info.sigma=argument_list[2].real_reference;
11383          if (attribute_flag[3] != 0)
11384            channel=(ChannelType) argument_list[3].integer_reference;
11385          channel_mask=SetImageChannelMask(image,channel);
11386          image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11387            exception);
11388          if (image != (Image *) NULL)
11389            (void) SetImageChannelMask(image,channel_mask);
11390          break;
11391        }
11392        case 142:  /* ConnectedComponents */
11393        {
11394          size_t
11395            connectivity;
11396
11397          connectivity=4;
11398          if (attribute_flag[0] != 0)
11399            connectivity=argument_list[0].integer_reference;
11400          image=ConnectedComponentsImage(image,connectivity,
11401            (CCObjectInfo **) NULL,exception);
11402          break;
11403        }
11404        case 143:  /* Copy */
11405        {
11406          Image
11407            *source_image;
11408
11409          OffsetInfo
11410            offset;
11411
11412          RectangleInfo
11413            offset_geometry;
11414
11415          source_image=image;
11416          if (attribute_flag[0] != 0)
11417            source_image=argument_list[0].image_reference;
11418          SetGeometry(source_image,&geometry);
11419          if (attribute_flag[1] != 0)
11420            flags=ParseGravityGeometry(source_image,
11421              argument_list[1].string_reference,&geometry,exception);
11422          if (attribute_flag[2] != 0)
11423            geometry.width=argument_list[2].integer_reference;
11424          if (attribute_flag[3] != 0)
11425            geometry.height=argument_list[3].integer_reference;
11426          if (attribute_flag[4] != 0)
11427            geometry.x=argument_list[4].integer_reference;
11428          if (attribute_flag[5] != 0)
11429            geometry.y=argument_list[5].integer_reference;
11430          if (attribute_flag[6] != 0)
11431            image->gravity=(GravityType) argument_list[6].integer_reference;
11432          SetGeometry(image,&offset_geometry);
11433          if (attribute_flag[7] != 0)
11434            flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11435              &offset_geometry,exception);
11436          offset.x=offset_geometry.x;
11437          offset.y=offset_geometry.y;
11438          if (attribute_flag[8] != 0)
11439            offset.x=argument_list[8].integer_reference;
11440          if (attribute_flag[9] != 0)
11441            offset.y=argument_list[9].integer_reference;
11442          (void) CopyImagePixels(image,source_image,&geometry,&offset,
11443            exception);
11444          break;
11445        }
11446        case 144:  /* Color */
11447        {
11448          PixelInfo
11449            color;
11450
11451          (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11452          if (attribute_flag[0] != 0)
11453            (void) QueryColorCompliance(argument_list[0].string_reference,
11454              AllCompliance,&color,exception);
11455          (void) SetImageColor(image,&color,exception);
11456          break;
11457        }
11458        case 145:  /* WaveletDenoise */
11459        {
11460          if (attribute_flag[0] != 0)
11461            {
11462              flags=ParseGeometry(argument_list[0].string_reference,
11463                &geometry_info);
11464              if ((flags & PercentValue) != 0)
11465                {
11466                  geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11467                  geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11468                }
11469              if ((flags & SigmaValue) == 0)
11470                geometry_info.sigma=0.0;
11471            }
11472          if (attribute_flag[1] != 0)
11473            geometry_info.rho=argument_list[1].real_reference;
11474          if (attribute_flag[2] != 0)
11475            geometry_info.sigma=argument_list[2].real_reference;
11476          if (attribute_flag[3] != 0)
11477            channel=(ChannelType) argument_list[3].integer_reference;
11478          channel_mask=SetImageChannelMask(image,channel);
11479          image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11480            exception);
11481          if (image != (Image *) NULL)
11482            (void) SetImageChannelMask(image,channel_mask);
11483          break;
11484        }
11485        case 146:  /* Colorspace */
11486        {
11487          ColorspaceType
11488            colorspace;
11489
11490          colorspace=sRGBColorspace;
11491          if (attribute_flag[0] != 0)
11492            colorspace=(ColorspaceType) argument_list[0].integer_reference;
11493          (void) TransformImageColorspace(image,colorspace,exception);
11494          break;
11495        }
11496        case 147:  /* AutoThreshold */
11497        {
11498          AutoThresholdMethod
11499            method;
11500
11501          method=UndefinedThresholdMethod;
11502          if (attribute_flag[0] != 0)
11503            method=(AutoThresholdMethod) argument_list[0].integer_reference;
11504          (void) AutoThresholdImage(image,method,exception);
11505          break;
11506        }
11507        case 148:  /* RangeThreshold */
11508        {
11509          if (attribute_flag[0] != 0)
11510            {
11511              flags=ParseGeometry(argument_list[0].string_reference,
11512                &geometry_info);
11513              if ((flags & SigmaValue) == 0)
11514                geometry_info.sigma=geometry_info.rho;
11515              if ((flags & XiValue) == 0)
11516                geometry_info.xi=geometry_info.sigma;
11517              if ((flags & PsiValue) == 0)
11518                geometry_info.psi=geometry_info.xi;
11519            }
11520          if (attribute_flag[1] != 0)
11521            geometry_info.rho=argument_list[1].real_reference;
11522          if (attribute_flag[2] != 0)
11523            geometry_info.sigma=argument_list[2].real_reference;
11524          if (attribute_flag[3] != 0)
11525            geometry_info.xi=argument_list[3].real_reference;
11526          if (attribute_flag[4] != 0)
11527            geometry_info.psi=argument_list[4].real_reference;
11528          if (attribute_flag[5] != 0)
11529            channel=(ChannelType) argument_list[5].integer_reference;
11530          channel_mask=SetImageChannelMask(image,channel);
11531          (void) RangeThresholdImage(image,geometry_info.rho,
11532            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
11533          if (image != (Image *) NULL)
11534            (void) SetImageChannelMask(image,channel_mask);
11535          break;
11536        }
11537        case 149:  /* CLAHE */
11538        {
11539          if (attribute_flag[0] != 0)
11540            {
11541              flags=ParseGeometry(argument_list[0].string_reference,
11542                &geometry_info);
11543              flags=ParseRegionGeometry(image,argument_list[0].string_reference,
11544                &geometry,exception);
11545            }
11546          if (attribute_flag[1] != 0)
11547            geometry.width=argument_list[1].integer_reference;
11548          if (attribute_flag[2] != 0)
11549            geometry.height=argument_list[2].integer_reference;
11550          if (attribute_flag[3] != 0)
11551            geometry.x=argument_list[3].integer_reference;
11552          if (attribute_flag[4] != 0)
11553            geometry_info.psi=argument_list[4].real_reference;
11554          (void) CLAHEImage(image,geometry.width,geometry.height,geometry.x,
11555            geometry_info.psi,exception);
11556          break;
11557        }
11558        case 150:  /* Kmeans */
11559        {
11560          if (attribute_flag[0] != 0)
11561            {
11562              flags=ParseGeometry(argument_list[0].string_reference,
11563                &geometry_info);
11564              if ((flags & SigmaValue) == 0)
11565                geometry_info.sigma=100.0;
11566              if ((flags & XiValue) == 0)
11567                geometry_info.xi=0.01;
11568            }
11569          if (attribute_flag[1] != 0)
11570            geometry_info.rho=argument_list[1].integer_reference;
11571          if (attribute_flag[2] != 0)
11572            geometry_info.sigma=argument_list[2].integer_reference;
11573          if (attribute_flag[3] != 0)
11574            geometry_info.xi=(ChannelType) argument_list[3].real_reference;
11575          (void) KmeansImage(image,geometry_info.rho,geometry_info.sigma,
11576            geometry_info.xi,exception);
11577          break;
11578        }
11579        case 151:  /* ColorThreshold */
11580        {
11581          PixelInfo
11582            start_color,
11583            stop_color;
11584
11585          (void) QueryColorCompliance("black",AllCompliance,&start_color,
11586            exception);
11587          (void) QueryColorCompliance("white",AllCompliance,&stop_color,
11588            exception);
11589          if (attribute_flag[0] != 0)
11590            (void) QueryColorCompliance(argument_list[0].string_reference,
11591              AllCompliance,&start_color,exception);
11592          if (attribute_flag[1] != 0)
11593            (void) QueryColorCompliance(argument_list[1].string_reference,
11594              AllCompliance,&stop_color,exception);
11595          channel_mask=SetImageChannelMask(image,channel);
11596          (void) ColorThresholdImage(image,&start_color,&stop_color,exception);
11597          (void) SetImageChannelMask(image,channel_mask);
11598          break;
11599        }
11600        case 152:  /* WhiteBalance */
11601        {
11602          (void) WhiteBalanceImage(image,exception);
11603          break;
11604        }
11605        case 153:  /* BilateralBlur */
11606        {
11607          if (attribute_flag[0] != 0)
11608            {
11609              flags=ParseGeometry(argument_list[0].string_reference,
11610                &geometry_info);
11611              if ((flags & SigmaValue) == 0)
11612                geometry_info.sigma=geometry_info.rho;
11613              if ((flags & XiValue) == 0)
11614                geometry_info.xi=1.0*sqrt(geometry_info.rho*geometry_info.rho+
11615                  geometry_info.sigma*geometry_info.sigma);
11616              if ((flags & PsiValue) == 0)
11617                geometry_info.xi=0.25*sqrt(geometry_info.rho*geometry_info.rho+
11618                  geometry_info.sigma*geometry_info.sigma);
11619            }
11620          if (attribute_flag[1] != 0)
11621            geometry_info.rho=(double) argument_list[1].integer_reference;
11622          if (attribute_flag[2] != 0)
11623            geometry_info.sigma=(double) argument_list[2].integer_reference;
11624          if (attribute_flag[3] != 0)
11625            geometry_info.xi=argument_list[3].real_reference;
11626          if (attribute_flag[4] != 0)
11627            geometry_info.psi=argument_list[4].real_reference;
11628          if (attribute_flag[5] != 0)
11629            channel=(ChannelType) argument_list[5].integer_reference;
11630          channel_mask=SetImageChannelMask(image,channel);
11631          image=BilateralBlurImage(image,(size_t) geometry_info.rho,(size_t)
11632            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
11633          if (image != (Image *) NULL)
11634            (void) SetImageChannelMask(image,channel_mask);
11635          break;
11636        }
11637        case 154:  /* SortPixels */
11638        {
11639          (void) SortImagePixels(image,exception);
11640          break;
11641        }
11642      }
11643      if (next != (Image *) NULL)
11644        (void) CatchImageException(next);
11645      if ((region_info.width*region_info.height) != 0)
11646        (void) SetImageRegionMask(image,WritePixelMask,(const RectangleInfo *)
11647          NULL,exception);
11648      if (image != (Image *) NULL)
11649        {
11650          number_images++;
11651          if (next && (next != image))
11652            {
11653              image->next=next->next;
11654              if (image->next != (Image *) NULL)
11655                image->next->previous=image;
11656              DeleteImageFromRegistry(*pv,next);
11657            }
11658          sv_setiv(*pv,PTR2IV(image));
11659          next=image;
11660        }
11661      if (*pv)
11662        pv++;
11663    }
11664
11665  PerlException:
11666    if (reference_vector)
11667      reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11668    InheritPerlException(exception,perl_exception);
11669    exception=DestroyExceptionInfo(exception);
11670    sv_setiv(perl_exception,(IV) number_images);
11671    SvPOK_on(perl_exception);
11672    ST(0)=sv_2mortal(perl_exception);
11673    XSRETURN(1);
11674  }
11675
11676#
11677###############################################################################
11678#                                                                             #
11679#                                                                             #
11680#                                                                             #
11681#   M o n t a g e                                                             #
11682#                                                                             #
11683#                                                                             #
11684#                                                                             #
11685###############################################################################
11686#
11687#
11688void
11689Montage(ref,...)
11690  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11691  ALIAS:
11692    MontageImage  = 1
11693    montage       = 2
11694    montageimage  = 3
11695  PPCODE:
11696  {
11697    AV
11698      *av;
11699
11700    char
11701      *attribute;
11702
11703    ExceptionInfo
11704      *exception;
11705
11706    HV
11707      *hv;
11708
11709    Image
11710      *image,
11711      *next;
11712
11713    MontageInfo
11714      *montage_info;
11715
11716    PixelInfo
11717      transparent_color;
11718
11719    ssize_t
11720      i;
11721
11722    ssize_t
11723      sp;
11724
11725    struct PackageInfo
11726      *info;
11727
11728    SV
11729      *av_reference,
11730      *perl_exception,
11731      *reference,
11732      *rv,
11733      *sv;
11734
11735    PERL_UNUSED_VAR(ref);
11736    PERL_UNUSED_VAR(ix);
11737    exception=AcquireExceptionInfo();
11738    perl_exception=newSVpv("",0);
11739    sv=NULL;
11740    attribute=NULL;
11741    if (sv_isobject(ST(0)) == 0)
11742      {
11743        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11744          PackageName);
11745        goto PerlException;
11746      }
11747    reference=SvRV(ST(0));
11748    hv=SvSTASH(reference);
11749    av=newAV();
11750    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11751    SvREFCNT_dec(av);
11752    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11753    if (image == (Image *) NULL)
11754      {
11755        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11756          PackageName);
11757        goto PerlException;
11758      }
11759    /*
11760      Get options.
11761    */
11762    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11763    montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11764    (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11765      exception);
11766    for (i=2; i < items; i+=2)
11767    {
11768      attribute=(char *) SvPV(ST(i-1),na);
11769      switch (*attribute)
11770      {
11771        case 'B':
11772        case 'b':
11773        {
11774          if (LocaleCompare(attribute,"background") == 0)
11775            {
11776              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11777                &montage_info->background_color,exception);
11778              for (next=image; next; next=next->next)
11779                next->background_color=montage_info->background_color;
11780              break;
11781            }
11782          if (LocaleCompare(attribute,"border") == 0)
11783            {
11784              montage_info->border_width=SvIV(ST(i));
11785              break;
11786            }
11787          if (LocaleCompare(attribute,"bordercolor") == 0)
11788            {
11789              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11790                &montage_info->border_color,exception);
11791              for (next=image; next; next=next->next)
11792                next->border_color=montage_info->border_color;
11793              break;
11794            }
11795          if (LocaleCompare(attribute,"borderwidth") == 0)
11796            {
11797              montage_info->border_width=SvIV(ST(i));
11798              break;
11799            }
11800          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11801            attribute);
11802          break;
11803        }
11804        case 'C':
11805        case 'c':
11806        {
11807          if (LocaleCompare(attribute,"compose") == 0)
11808            {
11809              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11810                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11811              if (sp < 0)
11812                {
11813                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11814                    SvPV(ST(i),na));
11815                  break;
11816                }
11817              for (next=image; next; next=next->next)
11818                next->compose=(CompositeOperator) sp;
11819              break;
11820            }
11821          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11822            attribute);
11823          break;
11824        }
11825        case 'F':
11826        case 'f':
11827        {
11828          if (LocaleCompare(attribute,"fill") == 0)
11829            {
11830              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11831                &montage_info->fill,exception);
11832              break;
11833            }
11834          if (LocaleCompare(attribute,"font") == 0)
11835            {
11836              (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11837              break;
11838            }
11839          if (LocaleCompare(attribute,"frame") == 0)
11840            {
11841              char
11842                *p;
11843
11844              p=SvPV(ST(i),na);
11845              if (IsGeometry(p) == MagickFalse)
11846                {
11847                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11848                    p);
11849                  break;
11850                }
11851              (void) CloneString(&montage_info->frame,p);
11852              if (*p == '\0')
11853                montage_info->frame=(char *) NULL;
11854              break;
11855            }
11856          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11857            attribute);
11858          break;
11859        }
11860        case 'G':
11861        case 'g':
11862        {
11863          if (LocaleCompare(attribute,"geometry") == 0)
11864            {
11865              char
11866                *p;
11867
11868              p=SvPV(ST(i),na);
11869              if (IsGeometry(p) == MagickFalse)
11870                {
11871                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11872                    p);
11873                  break;
11874                }
11875             (void) CloneString(&montage_info->geometry,p);
11876             if (*p == '\0')
11877               montage_info->geometry=(char *) NULL;
11878             break;
11879           }
11880         if (LocaleCompare(attribute,"gravity") == 0)
11881           {
11882             ssize_t
11883               in;
11884
11885             in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11886               MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11887             if (in < 0)
11888               {
11889                 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11890                   SvPV(ST(i),na));
11891                 return;
11892               }
11893             montage_info->gravity=(GravityType) in;
11894             for (next=image; next; next=next->next)
11895               next->gravity=(GravityType) in;
11896             break;
11897           }
11898          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11899            attribute);
11900          break;
11901        }
11902        case 'L':
11903        case 'l':
11904        {
11905          if (LocaleCompare(attribute,"label") == 0)
11906            {
11907              for (next=image; next; next=next->next)
11908                (void) SetImageProperty(next,"label",InterpretImageProperties(
11909                  info ? info->image_info : (ImageInfo *) NULL,next,
11910                  SvPV(ST(i),na),exception),exception);
11911              break;
11912            }
11913          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11914            attribute);
11915          break;
11916        }
11917        case 'M':
11918        case 'm':
11919        {
11920          if (LocaleCompare(attribute,"mattecolor") == 0)
11921            {
11922              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11923                &montage_info->alpha_color,exception);
11924              for (next=image; next; next=next->next)
11925                next->alpha_color=montage_info->alpha_color;
11926              break;
11927            }
11928          if (LocaleCompare(attribute,"mode") == 0)
11929            {
11930              ssize_t
11931                in;
11932
11933              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11934                MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11935              switch (in)
11936              {
11937                default:
11938                {
11939                  ThrowPerlException(exception,OptionError,
11940                    "UnrecognizedModeType",SvPV(ST(i),na));
11941                  break;
11942                }
11943                case FrameMode:
11944                {
11945                  (void) CloneString(&montage_info->frame,"15x15+3+3");
11946                  montage_info->shadow=MagickTrue;
11947                  break;
11948                }
11949                case UnframeMode:
11950                {
11951                  montage_info->frame=(char *) NULL;
11952                  montage_info->shadow=MagickFalse;
11953                  montage_info->border_width=0;
11954                  break;
11955                }
11956                case ConcatenateMode:
11957                {
11958                  montage_info->frame=(char *) NULL;
11959                  montage_info->shadow=MagickFalse;
11960                  (void) CloneString(&montage_info->geometry,"+0+0");
11961                  montage_info->border_width=0;
11962                }
11963              }
11964              break;
11965            }
11966          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11967            attribute);
11968          break;
11969        }
11970        case 'P':
11971        case 'p':
11972        {
11973          if (LocaleCompare(attribute,"pointsize") == 0)
11974            {
11975              montage_info->pointsize=SvIV(ST(i));
11976              break;
11977            }
11978          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11979            attribute);
11980          break;
11981        }
11982        case 'S':
11983        case 's':
11984        {
11985          if (LocaleCompare(attribute,"shadow") == 0)
11986            {
11987              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11988                MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11989              if (sp < 0)
11990                {
11991                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11992                    SvPV(ST(i),na));
11993                  break;
11994                }
11995             montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11996             break;
11997            }
11998          if (LocaleCompare(attribute,"stroke") == 0)
11999            {
12000              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12001                &montage_info->stroke,exception);
12002              break;
12003            }
12004          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12005            attribute);
12006          break;
12007        }
12008        case 'T':
12009        case 't':
12010        {
12011          if (LocaleCompare(attribute,"texture") == 0)
12012            {
12013              (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
12014              break;
12015            }
12016          if (LocaleCompare(attribute,"tile") == 0)
12017            {
12018              char *p=SvPV(ST(i),na);
12019              if (IsGeometry(p) == MagickFalse)
12020                {
12021                  ThrowPerlException(exception,OptionError,"MissingGeometry",
12022                    p);
12023                  break;
12024                }
12025              (void) CloneString(&montage_info->tile,p);
12026              if (*p == '\0')
12027                montage_info->tile=(char *) NULL;
12028              break;
12029            }
12030          if (LocaleCompare(attribute,"title") == 0)
12031            {
12032              (void) CloneString(&montage_info->title,SvPV(ST(i),na));
12033              break;
12034            }
12035          if (LocaleCompare(attribute,"transparent") == 0)
12036            {
12037              PixelInfo
12038                transparent_color;
12039
12040              QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12041                &transparent_color,exception);
12042              for (next=image; next; next=next->next)
12043                (void) TransparentPaintImage(next,&transparent_color,
12044                  TransparentAlpha,MagickFalse,exception);
12045              break;
12046            }
12047          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12048            attribute);
12049          break;
12050        }
12051        default:
12052        {
12053          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12054            attribute);
12055          break;
12056        }
12057      }
12058    }
12059    image=MontageImageList(info->image_info,montage_info,image,exception);
12060    montage_info=DestroyMontageInfo(montage_info);
12061    if (image == (Image *) NULL)
12062      goto PerlException;
12063    if (transparent_color.alpha != TransparentAlpha)
12064      for (next=image; next; next=next->next)
12065        (void) TransparentPaintImage(next,&transparent_color,
12066          TransparentAlpha,MagickFalse,exception);
12067    for (  ; image; image=image->next)
12068    {
12069      AddImageToRegistry(sv,image);
12070      rv=newRV(sv);
12071      av_push(av,sv_bless(rv,hv));
12072      SvREFCNT_dec(sv);
12073    }
12074    exception=DestroyExceptionInfo(exception);
12075    ST(0)=av_reference;
12076    SvREFCNT_dec(perl_exception);
12077    XSRETURN(1);
12078
12079  PerlException:
12080    InheritPerlException(exception,perl_exception);
12081    exception=DestroyExceptionInfo(exception);
12082    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12083    SvPOK_on(perl_exception);
12084    ST(0)=sv_2mortal(perl_exception);
12085    XSRETURN(1);
12086  }
12087
12088#
12089###############################################################################
12090#                                                                             #
12091#                                                                             #
12092#                                                                             #
12093#   M o r p h                                                                 #
12094#                                                                             #
12095#                                                                             #
12096#                                                                             #
12097###############################################################################
12098#
12099#
12100void
12101Morph(ref,...)
12102  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12103  ALIAS:
12104    MorphImage  = 1
12105    morph       = 2
12106    morphimage  = 3
12107  PPCODE:
12108  {
12109    AV
12110      *av;
12111
12112    char
12113      *attribute;
12114
12115    ExceptionInfo
12116      *exception;
12117
12118    HV
12119      *hv;
12120
12121    Image
12122      *image;
12123
12124    ssize_t
12125      i;
12126
12127    ssize_t
12128      number_frames;
12129
12130    struct PackageInfo
12131      *info;
12132
12133    SV
12134      *av_reference,
12135      *perl_exception,
12136      *reference,
12137      *rv,
12138      *sv;
12139
12140    PERL_UNUSED_VAR(ref);
12141    PERL_UNUSED_VAR(ix);
12142    exception=AcquireExceptionInfo();
12143    perl_exception=newSVpv("",0);
12144    sv=NULL;
12145    av=NULL;
12146    attribute=NULL;
12147    if (sv_isobject(ST(0)) == 0)
12148      {
12149        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12150          PackageName);
12151        goto PerlException;
12152      }
12153    reference=SvRV(ST(0));
12154    hv=SvSTASH(reference);
12155    av=newAV();
12156    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12157    SvREFCNT_dec(av);
12158    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12159    if (image == (Image *) NULL)
12160      {
12161        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12162          PackageName);
12163        goto PerlException;
12164      }
12165    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12166    /*
12167      Get attribute.
12168    */
12169    number_frames=30;
12170    for (i=2; i < items; i+=2)
12171    {
12172      attribute=(char *) SvPV(ST(i-1),na);
12173      switch (*attribute)
12174      {
12175        case 'F':
12176        case 'f':
12177        {
12178          if (LocaleCompare(attribute,"frames") == 0)
12179            {
12180              number_frames=SvIV(ST(i));
12181              break;
12182            }
12183          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12184            attribute);
12185          break;
12186        }
12187        default:
12188        {
12189          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12190            attribute);
12191          break;
12192        }
12193      }
12194    }
12195    image=MorphImages(image,number_frames,exception);
12196    if (image == (Image *) NULL)
12197      goto PerlException;
12198    for ( ; image; image=image->next)
12199    {
12200      AddImageToRegistry(sv,image);
12201      rv=newRV(sv);
12202      av_push(av,sv_bless(rv,hv));
12203      SvREFCNT_dec(sv);
12204    }
12205    exception=DestroyExceptionInfo(exception);
12206    ST(0)=av_reference;
12207    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12208    XSRETURN(1);
12209
12210  PerlException:
12211    InheritPerlException(exception,perl_exception);
12212    exception=DestroyExceptionInfo(exception);
12213    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12214    SvPOK_on(perl_exception);
12215    ST(0)=sv_2mortal(perl_exception);
12216    XSRETURN(1);
12217  }
12218
12219#
12220###############################################################################
12221#                                                                             #
12222#                                                                             #
12223#                                                                             #
12224#   M o s a i c                                                               #
12225#                                                                             #
12226#                                                                             #
12227#                                                                             #
12228###############################################################################
12229#
12230#
12231void
12232Mosaic(ref)
12233  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12234  ALIAS:
12235    MosaicImage   = 1
12236    mosaic        = 2
12237    mosaicimage   = 3
12238  PPCODE:
12239  {
12240    AV
12241      *av;
12242
12243    ExceptionInfo
12244      *exception;
12245
12246    HV
12247      *hv;
12248
12249    Image
12250      *image;
12251
12252    struct PackageInfo
12253      *info;
12254
12255    SV
12256      *perl_exception,
12257      *reference,
12258      *rv,
12259      *sv;
12260
12261    PERL_UNUSED_VAR(ref);
12262    PERL_UNUSED_VAR(ix);
12263    exception=AcquireExceptionInfo();
12264    perl_exception=newSVpv("",0);
12265    sv=NULL;
12266    if (sv_isobject(ST(0)) == 0)
12267      {
12268        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12269          PackageName);
12270        goto PerlException;
12271      }
12272    reference=SvRV(ST(0));
12273    hv=SvSTASH(reference);
12274    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12275    if (image == (Image *) NULL)
12276      {
12277        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12278          PackageName);
12279        goto PerlException;
12280      }
12281    image=MergeImageLayers(image,MosaicLayer,exception);
12282    /*
12283      Create blessed Perl array for the returned image.
12284    */
12285    av=newAV();
12286    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12287    SvREFCNT_dec(av);
12288    AddImageToRegistry(sv,image);
12289    rv=newRV(sv);
12290    av_push(av,sv_bless(rv,hv));
12291    SvREFCNT_dec(sv);
12292    (void) CopyMagickString(info->image_info->filename,image->filename,
12293      MagickPathExtent);
12294    SetImageInfo(info->image_info,0,exception);
12295    exception=DestroyExceptionInfo(exception);
12296    SvREFCNT_dec(perl_exception);
12297    XSRETURN(1);
12298
12299  PerlException:
12300    InheritPerlException(exception,perl_exception);
12301    exception=DestroyExceptionInfo(exception);
12302    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12303    SvPOK_on(perl_exception);  /* return messages in string context */
12304    ST(0)=sv_2mortal(perl_exception);
12305    XSRETURN(1);
12306  }
12307
12308#
12309###############################################################################
12310#                                                                             #
12311#                                                                             #
12312#                                                                             #
12313#   P e r c e p t u a l H a s h                                               #
12314#                                                                             #
12315#                                                                             #
12316#                                                                             #
12317###############################################################################
12318#
12319#
12320void
12321PerceptualHash(ref)
12322  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12323  ALIAS:
12324    PerceptualHashImage = 1
12325    perceptualhash      = 2
12326    perceptualhashimage = 3
12327  PPCODE:
12328  {
12329    AV
12330      *av;
12331
12332    ChannelPerceptualHash
12333      *channel_phash;
12334
12335    char
12336      message[MagickPathExtent];
12337
12338    ExceptionInfo
12339      *exception;
12340
12341    Image
12342      *image;
12343
12344    ssize_t
12345      count;
12346
12347    struct PackageInfo
12348      *info;
12349
12350    SV
12351      *perl_exception,
12352      *reference;
12353
12354    PERL_UNUSED_VAR(ref);
12355    PERL_UNUSED_VAR(ix);
12356    exception=AcquireExceptionInfo();
12357    perl_exception=newSVpv("",0);
12358    av=NULL;
12359    if (sv_isobject(ST(0)) == 0)
12360      {
12361        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12362          PackageName);
12363        goto PerlException;
12364      }
12365    reference=SvRV(ST(0));
12366    av=newAV();
12367    SvREFCNT_dec(av);
12368    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12369    if (image == (Image *) NULL)
12370      {
12371        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12372          PackageName);
12373        goto PerlException;
12374      }
12375    count=0;
12376    for ( ; image; image=image->next)
12377    {
12378      size_t
12379        i;
12380
12381      channel_phash=GetImagePerceptualHash(image,exception);
12382      if (channel_phash == (ChannelPerceptualHash *) NULL)
12383        continue;
12384      count++;
12385      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
12386      {
12387        ssize_t
12388          j;
12389
12390        PixelChannel channel=GetPixelChannelChannel(image,i);
12391        PixelTrait traits=GetPixelChannelTraits(image,channel);
12392        if (traits == UndefinedPixelTrait)
12393          continue;
12394        EXTEND(sp,GetPixelChannels(image)*MaximumNumberOfPerceptualHashes*
12395          channel_phash[0].number_colorspaces*(i+1)*count);
12396        for (j=0; j < MaximumNumberOfPerceptualHashes; j++)
12397        {
12398          ssize_t
12399            k;
12400
12401          for (k=0; k < (ssize_t) channel_phash[0].number_colorspaces; k++)
12402          {
12403            (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
12404              channel_phash[channel].phash[k][j]);
12405            PUSHs(sv_2mortal(newSVpv(message,0)));
12406          }
12407        }
12408      }
12409      channel_phash=(ChannelPerceptualHash *)
12410        RelinquishMagickMemory(channel_phash);
12411    }
12412
12413  PerlException:
12414    InheritPerlException(exception,perl_exception);
12415    exception=DestroyExceptionInfo(exception);
12416    SvREFCNT_dec(perl_exception);
12417  }
12418
12419#
12420###############################################################################
12421#                                                                             #
12422#                                                                             #
12423#                                                                             #
12424#   P i n g                                                                   #
12425#                                                                             #
12426#                                                                             #
12427#                                                                             #
12428###############################################################################
12429#
12430#
12431void
12432Ping(ref,...)
12433  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12434  ALIAS:
12435    PingImage  = 1
12436    ping       = 2
12437    pingimage  = 3
12438  PPCODE:
12439  {
12440    AV
12441      *av;
12442
12443    char
12444      **keep,
12445      **list;
12446
12447    ExceptionInfo
12448      *exception;
12449
12450    Image
12451      *image,
12452      *next;
12453
12454    int
12455      n;
12456
12457    MagickBooleanType
12458      status;
12459
12460    char
12461      **p;
12462
12463    ssize_t
12464      i;
12465
12466    ssize_t
12467      ac;
12468
12469    STRLEN
12470      *length;
12471
12472    struct PackageInfo
12473      *info,
12474      *package_info;
12475
12476    SV
12477      *perl_exception,
12478      *reference;
12479
12480    size_t
12481      count;
12482
12483    PERL_UNUSED_VAR(ref);
12484    PERL_UNUSED_VAR(ix);
12485    exception=AcquireExceptionInfo();
12486    perl_exception=newSVpv("",0);
12487    package_info=(struct PackageInfo *) NULL;
12488    ac=(items < 2) ? 1 : items-1;
12489    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12490    keep=list;
12491    length=(STRLEN *) NULL;
12492    if (list == (char **) NULL)
12493      {
12494        ThrowPerlException(exception,ResourceLimitError,
12495          "MemoryAllocationFailed",PackageName);
12496        goto PerlException;
12497      }
12498    keep=list;
12499    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12500    if (length == (STRLEN *) NULL)
12501      {
12502        ThrowPerlException(exception,ResourceLimitError,
12503          "MemoryAllocationFailed",PackageName);
12504        goto PerlException;
12505      }
12506    if (sv_isobject(ST(0)) == 0)
12507      {
12508        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12509          PackageName);
12510        goto PerlException;
12511      }
12512    reference=SvRV(ST(0));
12513    if (SvTYPE(reference) != SVt_PVAV)
12514      {
12515        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12516          PackageName);
12517        goto PerlException;
12518      }
12519    av=(AV *) reference;
12520    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12521      exception);
12522    package_info=ClonePackageInfo(info,exception);
12523    n=1;
12524    if (items <= 1)
12525      *list=(char *) (*package_info->image_info->filename ?
12526        package_info->image_info->filename : "XC:black");
12527    else
12528      for (n=0, i=0; i < ac; i++)
12529      {
12530        list[n]=(char *) SvPV(ST(i+1),length[n]);
12531        if ((items >= 3) && strEQcase(list[n],"blob"))
12532          {
12533            void
12534              *blob;
12535
12536            i++;
12537            blob=(void *) (SvPV(ST(i+1),length[n]));
12538            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12539          }
12540        if ((items >= 3) && strEQcase(list[n],"filename"))
12541          continue;
12542        if ((items >= 3) && strEQcase(list[n],"file"))
12543          {
12544            FILE
12545              *file;
12546
12547            PerlIO
12548              *io_info;
12549
12550            i++;
12551            io_info=IoIFP(sv_2io(ST(i+1)));
12552            if (io_info == (PerlIO *) NULL)
12553              {
12554                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12555                  PackageName);
12556                continue;
12557              }
12558            file=PerlIO_findFILE(io_info);
12559            if (file == (FILE *) NULL)
12560              {
12561                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12562                  PackageName);
12563                continue;
12564              }
12565            SetImageInfoFile(package_info->image_info,file);
12566          }
12567        if ((items >= 3) && strEQcase(list[n],"magick"))
12568          continue;
12569        n++;
12570      }
12571    list[n]=(char *) NULL;
12572    keep=list;
12573    status=ExpandFilenames(&n,&list);
12574    if (status == MagickFalse)
12575      {
12576        ThrowPerlException(exception,ResourceLimitError,
12577          "MemoryAllocationFailed",PackageName);
12578        goto PerlException;
12579      }
12580    count=0;
12581    for (i=0; i < n; i++)
12582    {
12583      (void) CopyMagickString(package_info->image_info->filename,list[i],
12584        MagickPathExtent);
12585      image=PingImage(package_info->image_info,exception);
12586      if (image == (Image *) NULL)
12587        break;
12588      if ((package_info->image_info->file != (FILE *) NULL) ||
12589          (package_info->image_info->blob != (void *) NULL))
12590        DisassociateImageStream(image);
12591      count+=GetImageListLength(image);
12592      EXTEND(sp,4*count);
12593      for (next=image; next; next=next->next)
12594      {
12595        PUSHs(sv_2mortal(newSViv(next->columns)));
12596        PUSHs(sv_2mortal(newSViv(next->rows)));
12597        PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12598        PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12599      }
12600      image=DestroyImageList(image);
12601    }
12602    /*
12603      Free resources.
12604    */
12605    for (i=0; i < n; i++)
12606      if (list[i] != (char *) NULL)
12607        for (p=keep; list[i] != *p++; )
12608          if (*p == NULL)
12609            {
12610              list[i]=(char *) RelinquishMagickMemory(list[i]);
12611              break;
12612            }
12613
12614  PerlException:
12615    if (package_info != (struct PackageInfo *) NULL)
12616      DestroyPackageInfo(package_info);
12617    if (list && (list != keep))
12618      list=(char **) RelinquishMagickMemory(list);
12619    if (keep)
12620      keep=(char **) RelinquishMagickMemory(keep);
12621    if (length)
12622      length=(STRLEN *) RelinquishMagickMemory(length);
12623    InheritPerlException(exception,perl_exception);
12624    exception=DestroyExceptionInfo(exception);
12625    SvREFCNT_dec(perl_exception);  /* throw away all errors */
12626  }
12627
12628#
12629###############################################################################
12630#                                                                             #
12631#                                                                             #
12632#                                                                             #
12633#   P r e v i e w                                                             #
12634#                                                                             #
12635#                                                                             #
12636#                                                                             #
12637###############################################################################
12638#
12639#
12640void
12641Preview(ref,...)
12642  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12643  ALIAS:
12644    PreviewImage = 1
12645    preview      = 2
12646    previewimage = 3
12647  PPCODE:
12648  {
12649    AV
12650      *av;
12651
12652    ExceptionInfo
12653      *exception;
12654
12655    HV
12656      *hv;
12657
12658    Image
12659      *image,
12660      *preview_image;
12661
12662    PreviewType
12663      preview_type;
12664
12665    struct PackageInfo
12666      *info;
12667
12668    SV
12669      *av_reference,
12670      *perl_exception,
12671      *reference,
12672      *rv,
12673      *sv;
12674
12675    PERL_UNUSED_VAR(ref);
12676    PERL_UNUSED_VAR(ix);
12677    exception=AcquireExceptionInfo();
12678    perl_exception=newSVpv("",0);
12679    sv=NULL;
12680    av=NULL;
12681    if (sv_isobject(ST(0)) == 0)
12682      {
12683        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12684          PackageName);
12685        goto PerlException;
12686      }
12687    reference=SvRV(ST(0));
12688    hv=SvSTASH(reference);
12689    av=newAV();
12690    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12691    SvREFCNT_dec(av);
12692    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12693    if (image == (Image *) NULL)
12694      {
12695        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12696          PackageName);
12697        goto PerlException;
12698      }
12699    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12700    preview_type=GammaPreview;
12701    if (items > 1)
12702      preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
12703        MagickFalse,SvPV(ST(1),na));
12704    for ( ; image; image=image->next)
12705    {
12706      preview_image=PreviewImage(image,preview_type,exception);
12707      if (preview_image == (Image *) NULL)
12708        goto PerlException;
12709      AddImageToRegistry(sv,preview_image);
12710      rv=newRV(sv);
12711      av_push(av,sv_bless(rv,hv));
12712      SvREFCNT_dec(sv);
12713    }
12714    exception=DestroyExceptionInfo(exception);
12715    ST(0)=av_reference;
12716    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12717    XSRETURN(1);
12718
12719  PerlException:
12720    InheritPerlException(exception,perl_exception);
12721    exception=DestroyExceptionInfo(exception);
12722    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12723    SvPOK_on(perl_exception);
12724    ST(0)=sv_2mortal(perl_exception);
12725    XSRETURN(1);
12726  }
12727
12728#
12729###############################################################################
12730#                                                                             #
12731#                                                                             #
12732#                                                                             #
12733#   Q u e r y C o l o r                                                       #
12734#                                                                             #
12735#                                                                             #
12736#                                                                             #
12737###############################################################################
12738#
12739#
12740void
12741QueryColor(ref,...)
12742  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12743  ALIAS:
12744    querycolor = 1
12745  PPCODE:
12746  {
12747    char
12748      *name;
12749
12750    ExceptionInfo
12751      *exception;
12752
12753    PixelInfo
12754      color;
12755
12756    ssize_t
12757      i;
12758
12759    SV
12760      *perl_exception;
12761
12762    PERL_UNUSED_VAR(ref);
12763    PERL_UNUSED_VAR(ix);
12764    exception=AcquireExceptionInfo();
12765    perl_exception=newSVpv("",0);
12766    if (items == 1)
12767      {
12768        const ColorInfo
12769          **colorlist;
12770
12771        size_t
12772          colors;
12773
12774        colorlist=GetColorInfoList("*",&colors,exception);
12775        EXTEND(sp,colors);
12776        for (i=0; i < (ssize_t) colors; i++)
12777        {
12778          PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12779        }
12780        colorlist=(const ColorInfo **)
12781          RelinquishMagickMemory((ColorInfo **) colorlist);
12782        goto PerlException;
12783      }
12784    EXTEND(sp,5*items);
12785    for (i=1; i < items; i++)
12786    {
12787      name=(char *) SvPV(ST(i),na);
12788      if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12789        {
12790          PUSHs(&sv_undef);
12791          continue;
12792        }
12793      PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12794      PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12795      PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12796      if (color.colorspace == CMYKColorspace)
12797        PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12798      if (color.alpha_trait != UndefinedPixelTrait)
12799        PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12800    }
12801
12802  PerlException:
12803    InheritPerlException(exception,perl_exception);
12804    exception=DestroyExceptionInfo(exception);
12805    SvREFCNT_dec(perl_exception);
12806  }
12807
12808#
12809###############################################################################
12810#                                                                             #
12811#                                                                             #
12812#                                                                             #
12813#   Q u e r y C o l o r N a m e                                               #
12814#                                                                             #
12815#                                                                             #
12816#                                                                             #
12817###############################################################################
12818#
12819#
12820void
12821QueryColorname(ref,...)
12822  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12823  ALIAS:
12824    querycolorname = 1
12825  PPCODE:
12826  {
12827    AV
12828      *av;
12829
12830    char
12831      message[MagickPathExtent];
12832
12833    ExceptionInfo
12834      *exception;
12835
12836    Image
12837      *image;
12838
12839    PixelInfo
12840      target_color;
12841
12842    ssize_t
12843      i;
12844
12845    struct PackageInfo
12846      *info;
12847
12848    SV
12849      *perl_exception,
12850      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12851
12852    PERL_UNUSED_VAR(ref);
12853    PERL_UNUSED_VAR(ix);
12854    exception=AcquireExceptionInfo();
12855    perl_exception=newSVpv("",0);
12856    reference=SvRV(ST(0));
12857    av=(AV *) reference;
12858    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12859      exception);
12860    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12861    if (image == (Image *) NULL)
12862      {
12863        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12864          PackageName);
12865        goto PerlException;
12866      }
12867    EXTEND(sp,items);
12868    for (i=1; i < items; i++)
12869    {
12870      (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12871        exception);
12872      (void) QueryColorname(image,&target_color,SVGCompliance,message,
12873        exception);
12874      PUSHs(sv_2mortal(newSVpv(message,0)));
12875    }
12876
12877  PerlException:
12878    InheritPerlException(exception,perl_exception);
12879    exception=DestroyExceptionInfo(exception);
12880    SvREFCNT_dec(perl_exception);
12881  }
12882
12883#
12884###############################################################################
12885#                                                                             #
12886#                                                                             #
12887#                                                                             #
12888#   Q u e r y F o n t                                                         #
12889#                                                                             #
12890#                                                                             #
12891#                                                                             #
12892###############################################################################
12893#
12894#
12895void
12896QueryFont(ref,...)
12897  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12898  ALIAS:
12899    queryfont = 1
12900  PPCODE:
12901  {
12902    char
12903      *name,
12904      message[MagickPathExtent];
12905
12906    ExceptionInfo
12907      *exception;
12908
12909    ssize_t
12910      i;
12911
12912    SV
12913      *perl_exception;
12914
12915    volatile const TypeInfo
12916      *type_info;
12917
12918    PERL_UNUSED_VAR(ref);
12919    PERL_UNUSED_VAR(ix);
12920    exception=AcquireExceptionInfo();
12921    perl_exception=newSVpv("",0);
12922    if (items == 1)
12923      {
12924        const TypeInfo
12925          **typelist;
12926
12927        size_t
12928          types;
12929
12930        typelist=GetTypeInfoList("*",&types,exception);
12931        EXTEND(sp,types);
12932        for (i=0; i < (ssize_t) types; i++)
12933        {
12934          PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12935        }
12936        typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12937          typelist);
12938        goto PerlException;
12939      }
12940    EXTEND(sp,10*items);
12941    for (i=1; i < items; i++)
12942    {
12943      name=(char *) SvPV(ST(i),na);
12944      type_info=GetTypeInfo(name,exception);
12945      if (type_info == (TypeInfo *) NULL)
12946        {
12947          PUSHs(&sv_undef);
12948          continue;
12949        }
12950      if (type_info->name == (char *) NULL)
12951        PUSHs(&sv_undef);
12952      else
12953        PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12954      if (type_info->description == (char *) NULL)
12955        PUSHs(&sv_undef);
12956      else
12957        PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12958      if (type_info->family == (char *) NULL)
12959        PUSHs(&sv_undef);
12960      else
12961        PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12962      if (type_info->style == UndefinedStyle)
12963        PUSHs(&sv_undef);
12964      else
12965        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12966          type_info->style),0)));
12967      if (type_info->stretch == UndefinedStretch)
12968        PUSHs(&sv_undef);
12969      else
12970        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12971          type_info->stretch),0)));
12972      (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12973        type_info->weight);
12974      PUSHs(sv_2mortal(newSVpv(message,0)));
12975      if (type_info->encoding == (char *) NULL)
12976        PUSHs(&sv_undef);
12977      else
12978        PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12979      if (type_info->foundry == (char *) NULL)
12980        PUSHs(&sv_undef);
12981      else
12982        PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12983      if (type_info->format == (char *) NULL)
12984        PUSHs(&sv_undef);
12985      else
12986        PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12987      if (type_info->metrics == (char *) NULL)
12988        PUSHs(&sv_undef);
12989      else
12990        PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12991      if (type_info->glyphs == (char *) NULL)
12992        PUSHs(&sv_undef);
12993      else
12994        PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12995    }
12996
12997  PerlException:
12998    InheritPerlException(exception,perl_exception);
12999    exception=DestroyExceptionInfo(exception);
13000    SvREFCNT_dec(perl_exception);
13001  }
13002
13003#
13004###############################################################################
13005#                                                                             #
13006#                                                                             #
13007#                                                                             #
13008#   Q u e r y F o n t M e t r i c s                                           #
13009#                                                                             #
13010#                                                                             #
13011#                                                                             #
13012###############################################################################
13013#
13014#
13015void
13016QueryFontMetrics(ref,...)
13017  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13018  ALIAS:
13019    queryfontmetrics = 1
13020  PPCODE:
13021  {
13022    AffineMatrix
13023      affine,
13024      current;
13025
13026    AV
13027      *av;
13028
13029    char
13030      *attribute;
13031
13032    double
13033      x,
13034      y;
13035
13036    DrawInfo
13037      *draw_info;
13038
13039    ExceptionInfo
13040      *exception;
13041
13042    GeometryInfo
13043      geometry_info;
13044
13045    Image
13046      *image;
13047
13048    MagickBooleanType
13049      status;
13050
13051    MagickStatusType
13052      flags;
13053
13054    ssize_t
13055      i;
13056
13057    ssize_t
13058      type;
13059
13060    struct PackageInfo
13061      *info,
13062      *package_info;
13063
13064    SV
13065      *perl_exception,
13066      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13067
13068    TypeMetric
13069      metrics;
13070
13071    PERL_UNUSED_VAR(ref);
13072    PERL_UNUSED_VAR(ix);
13073    exception=AcquireExceptionInfo();
13074    package_info=(struct PackageInfo *) NULL;
13075    perl_exception=newSVpv("",0);
13076    reference=SvRV(ST(0));
13077    av=(AV *) reference;
13078    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13079      exception);
13080    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13081    if (image == (Image *) NULL)
13082      {
13083        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13084          PackageName);
13085        goto PerlException;
13086      }
13087    package_info=ClonePackageInfo(info,exception);
13088    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13089    CloneString(&draw_info->text,"");
13090    current=draw_info->affine;
13091    GetAffineMatrix(&affine);
13092    x=0.0;
13093    y=0.0;
13094    EXTEND(sp,7*items);
13095    for (i=2; i < items; i+=2)
13096    {
13097      attribute=(char *) SvPV(ST(i-1),na);
13098      switch (*attribute)
13099      {
13100        case 'A':
13101        case 'a':
13102        {
13103          if (LocaleCompare(attribute,"antialias") == 0)
13104            {
13105              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13106                SvPV(ST(i),na));
13107              if (type < 0)
13108                {
13109                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13110                    SvPV(ST(i),na));
13111                  break;
13112                }
13113              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13114              break;
13115            }
13116          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13117            attribute);
13118          break;
13119        }
13120        case 'd':
13121        case 'D':
13122        {
13123          if (LocaleCompare(attribute,"density") == 0)
13124            {
13125              CloneString(&draw_info->density,SvPV(ST(i),na));
13126              break;
13127            }
13128          if (LocaleCompare(attribute,"direction") == 0)
13129            {
13130              draw_info->direction=(DirectionType) ParseCommandOption(
13131                MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
13132              break;
13133            }
13134          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13135            attribute);
13136          break;
13137        }
13138        case 'e':
13139        case 'E':
13140        {
13141          if (LocaleCompare(attribute,"encoding") == 0)
13142            {
13143              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13144              break;
13145            }
13146          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13147            attribute);
13148          break;
13149        }
13150        case 'f':
13151        case 'F':
13152        {
13153          if (LocaleCompare(attribute,"family") == 0)
13154            {
13155              CloneString(&draw_info->family,SvPV(ST(i),na));
13156              break;
13157            }
13158          if (LocaleCompare(attribute,"fill") == 0)
13159            {
13160              if (info)
13161                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13162                  &draw_info->fill,exception);
13163              break;
13164            }
13165          if (LocaleCompare(attribute,"font") == 0)
13166            {
13167              CloneString(&draw_info->font,SvPV(ST(i),na));
13168              break;
13169            }
13170          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13171            attribute);
13172          break;
13173        }
13174        case 'g':
13175        case 'G':
13176        {
13177          if (LocaleCompare(attribute,"geometry") == 0)
13178            {
13179              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13180              break;
13181            }
13182          if (LocaleCompare(attribute,"gravity") == 0)
13183            {
13184              draw_info->gravity=(GravityType) ParseCommandOption(
13185                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13186              break;
13187            }
13188          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13189            attribute);
13190          break;
13191        }
13192        case 'i':
13193        case 'I':
13194        {
13195          if (LocaleCompare(attribute,"interline-spacing") == 0)
13196            {
13197              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13198              draw_info->interline_spacing=geometry_info.rho;
13199              break;
13200            }
13201          if (LocaleCompare(attribute,"interword-spacing") == 0)
13202            {
13203              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13204              draw_info->interword_spacing=geometry_info.rho;
13205              break;
13206            }
13207          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13208            attribute);
13209          break;
13210        }
13211        case 'k':
13212        case 'K':
13213        {
13214          if (LocaleCompare(attribute,"kerning") == 0)
13215            {
13216              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13217              draw_info->kerning=geometry_info.rho;
13218              break;
13219            }
13220          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13221            attribute);
13222          break;
13223        }
13224        case 'p':
13225        case 'P':
13226        {
13227          if (LocaleCompare(attribute,"pointsize") == 0)
13228            {
13229              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13230              draw_info->pointsize=geometry_info.rho;
13231              break;
13232            }
13233          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13234            attribute);
13235          break;
13236        }
13237        case 'r':
13238        case 'R':
13239        {
13240          if (LocaleCompare(attribute,"rotate") == 0)
13241            {
13242              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13243              affine.rx=geometry_info.rho;
13244              affine.ry=geometry_info.sigma;
13245              if ((flags & SigmaValue) == 0)
13246                affine.ry=affine.rx;
13247              break;
13248            }
13249          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13250            attribute);
13251          break;
13252        }
13253        case 's':
13254        case 'S':
13255        {
13256          if (LocaleCompare(attribute,"scale") == 0)
13257            {
13258              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13259              affine.sx=geometry_info.rho;
13260              affine.sy=geometry_info.sigma;
13261              if ((flags & SigmaValue) == 0)
13262                affine.sy=affine.sx;
13263              break;
13264            }
13265          if (LocaleCompare(attribute,"skew") == 0)
13266            {
13267              double
13268                x_angle,
13269                y_angle;
13270
13271              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13272              x_angle=geometry_info.rho;
13273              y_angle=geometry_info.sigma;
13274              if ((flags & SigmaValue) == 0)
13275                y_angle=x_angle;
13276              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13277              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13278              break;
13279            }
13280          if (LocaleCompare(attribute,"stroke") == 0)
13281            {
13282              if (info)
13283                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13284                  &draw_info->stroke,exception);
13285              break;
13286            }
13287          if (LocaleCompare(attribute,"style") == 0)
13288            {
13289              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13290                SvPV(ST(i),na));
13291              if (type < 0)
13292                {
13293                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13294                    SvPV(ST(i),na));
13295                  break;
13296                }
13297              draw_info->style=(StyleType) type;
13298              break;
13299            }
13300          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13301            attribute);
13302          break;
13303        }
13304        case 't':
13305        case 'T':
13306        {
13307          if (LocaleCompare(attribute,"text") == 0)
13308            {
13309              CloneString(&draw_info->text,SvPV(ST(i),na));
13310              break;
13311            }
13312          if (LocaleCompare(attribute,"translate") == 0)
13313            {
13314              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13315              affine.tx=geometry_info.rho;
13316              affine.ty=geometry_info.sigma;
13317              if ((flags & SigmaValue) == 0)
13318                affine.ty=affine.tx;
13319              break;
13320            }
13321          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13322            attribute);
13323          break;
13324        }
13325        case 'w':
13326        case 'W':
13327        {
13328          if (LocaleCompare(attribute,"weight") == 0)
13329            {
13330              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13331              draw_info->weight=(size_t) geometry_info.rho;
13332              break;
13333            }
13334          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13335            attribute);
13336          break;
13337        }
13338        case 'x':
13339        case 'X':
13340        {
13341          if (LocaleCompare(attribute,"x") == 0)
13342            {
13343              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13344              x=geometry_info.rho;
13345              break;
13346            }
13347          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13348            attribute);
13349          break;
13350        }
13351        case 'y':
13352        case 'Y':
13353        {
13354          if (LocaleCompare(attribute,"y") == 0)
13355            {
13356              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13357              y=geometry_info.rho;
13358              break;
13359            }
13360          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13361            attribute);
13362          break;
13363        }
13364        default:
13365        {
13366          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13367            attribute);
13368          break;
13369        }
13370      }
13371    }
13372    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13373    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13374    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13375    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13376    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13377    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13378    if (draw_info->geometry == (char *) NULL)
13379      {
13380        draw_info->geometry=AcquireString((char *) NULL);
13381        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13382          "%.20g,%.20g",x,y);
13383      }
13384    status=GetTypeMetrics(image,draw_info,&metrics,exception);
13385    (void) CatchImageException(image);
13386    if (status == MagickFalse)
13387      PUSHs(&sv_undef);
13388    else
13389      {
13390        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13391        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13392        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13393        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13394        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13395        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13396        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13397        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13398        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13399        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13400        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13401        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13402        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13403      }
13404    draw_info=DestroyDrawInfo(draw_info);
13405
13406  PerlException:
13407    if (package_info != (struct PackageInfo *) NULL)
13408      DestroyPackageInfo(package_info);
13409    InheritPerlException(exception,perl_exception);
13410    exception=DestroyExceptionInfo(exception);
13411    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13412  }
13413
13414#
13415###############################################################################
13416#                                                                             #
13417#                                                                             #
13418#                                                                             #
13419#   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                         #
13420#                                                                             #
13421#                                                                             #
13422#                                                                             #
13423###############################################################################
13424#
13425#
13426void
13427QueryMultilineFontMetrics(ref,...)
13428  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13429  ALIAS:
13430    querymultilinefontmetrics = 1
13431  PPCODE:
13432  {
13433    AffineMatrix
13434      affine,
13435      current;
13436
13437    AV
13438      *av;
13439
13440    char
13441      *attribute;
13442
13443    double
13444      x,
13445      y;
13446
13447    DrawInfo
13448      *draw_info;
13449
13450    ExceptionInfo
13451      *exception;
13452
13453    GeometryInfo
13454      geometry_info;
13455
13456    Image
13457      *image;
13458
13459    MagickBooleanType
13460      status;
13461
13462    MagickStatusType
13463      flags;
13464
13465    ssize_t
13466      i;
13467
13468    ssize_t
13469      type;
13470
13471    struct PackageInfo
13472      *info,
13473      *package_info;
13474
13475    SV
13476      *perl_exception,
13477      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13478
13479    TypeMetric
13480      metrics;
13481
13482    PERL_UNUSED_VAR(ref);
13483    PERL_UNUSED_VAR(ix);
13484    exception=AcquireExceptionInfo();
13485    package_info=(struct PackageInfo *) NULL;
13486    perl_exception=newSVpv("",0);
13487    reference=SvRV(ST(0));
13488    av=(AV *) reference;
13489    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13490      exception);
13491    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13492    if (image == (Image *) NULL)
13493      {
13494        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13495          PackageName);
13496        goto PerlException;
13497      }
13498    package_info=ClonePackageInfo(info,exception);
13499    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13500    CloneString(&draw_info->text,"");
13501    current=draw_info->affine;
13502    GetAffineMatrix(&affine);
13503    x=0.0;
13504    y=0.0;
13505    EXTEND(sp,7*items);
13506    for (i=2; i < items; i+=2)
13507    {
13508      attribute=(char *) SvPV(ST(i-1),na);
13509      switch (*attribute)
13510      {
13511        case 'A':
13512        case 'a':
13513        {
13514          if (LocaleCompare(attribute,"antialias") == 0)
13515            {
13516              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13517                SvPV(ST(i),na));
13518              if (type < 0)
13519                {
13520                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13521                    SvPV(ST(i),na));
13522                  break;
13523                }
13524              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13525              break;
13526            }
13527          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13528            attribute);
13529          break;
13530        }
13531        case 'd':
13532        case 'D':
13533        {
13534          if (LocaleCompare(attribute,"density") == 0)
13535            {
13536              CloneString(&draw_info->density,SvPV(ST(i),na));
13537              break;
13538            }
13539          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13540            attribute);
13541          break;
13542        }
13543        case 'e':
13544        case 'E':
13545        {
13546          if (LocaleCompare(attribute,"encoding") == 0)
13547            {
13548              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13549              break;
13550            }
13551          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13552            attribute);
13553          break;
13554        }
13555        case 'f':
13556        case 'F':
13557        {
13558          if (LocaleCompare(attribute,"family") == 0)
13559            {
13560              CloneString(&draw_info->family,SvPV(ST(i),na));
13561              break;
13562            }
13563          if (LocaleCompare(attribute,"fill") == 0)
13564            {
13565              if (info)
13566                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13567                  &draw_info->fill,exception);
13568              break;
13569            }
13570          if (LocaleCompare(attribute,"font") == 0)
13571            {
13572              CloneString(&draw_info->font,SvPV(ST(i),na));
13573              break;
13574            }
13575          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13576            attribute);
13577          break;
13578        }
13579        case 'g':
13580        case 'G':
13581        {
13582          if (LocaleCompare(attribute,"geometry") == 0)
13583            {
13584              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13585              break;
13586            }
13587          if (LocaleCompare(attribute,"gravity") == 0)
13588            {
13589              draw_info->gravity=(GravityType) ParseCommandOption(
13590                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13591              break;
13592            }
13593          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13594            attribute);
13595          break;
13596        }
13597        case 'p':
13598        case 'P':
13599        {
13600          if (LocaleCompare(attribute,"pointsize") == 0)
13601            {
13602              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13603              draw_info->pointsize=geometry_info.rho;
13604              break;
13605            }
13606          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13607            attribute);
13608          break;
13609        }
13610        case 'r':
13611        case 'R':
13612        {
13613          if (LocaleCompare(attribute,"rotate") == 0)
13614            {
13615              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13616              affine.rx=geometry_info.rho;
13617              affine.ry=geometry_info.sigma;
13618              if ((flags & SigmaValue) == 0)
13619                affine.ry=affine.rx;
13620              break;
13621            }
13622          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13623            attribute);
13624          break;
13625        }
13626        case 's':
13627        case 'S':
13628        {
13629          if (LocaleCompare(attribute,"scale") == 0)
13630            {
13631              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13632              affine.sx=geometry_info.rho;
13633              affine.sy=geometry_info.sigma;
13634              if ((flags & SigmaValue) == 0)
13635                affine.sy=affine.sx;
13636              break;
13637            }
13638          if (LocaleCompare(attribute,"skew") == 0)
13639            {
13640              double
13641                x_angle,
13642                y_angle;
13643
13644              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13645              x_angle=geometry_info.rho;
13646              y_angle=geometry_info.sigma;
13647              if ((flags & SigmaValue) == 0)
13648                y_angle=x_angle;
13649              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13650              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13651              break;
13652            }
13653          if (LocaleCompare(attribute,"stroke") == 0)
13654            {
13655              if (info)
13656                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13657                  &draw_info->stroke,exception);
13658              break;
13659            }
13660          if (LocaleCompare(attribute,"style") == 0)
13661            {
13662              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13663                SvPV(ST(i),na));
13664              if (type < 0)
13665                {
13666                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13667                    SvPV(ST(i),na));
13668                  break;
13669                }
13670              draw_info->style=(StyleType) type;
13671              break;
13672            }
13673          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13674            attribute);
13675          break;
13676        }
13677        case 't':
13678        case 'T':
13679        {
13680          if (LocaleCompare(attribute,"text") == 0)
13681            {
13682              CloneString(&draw_info->text,SvPV(ST(i),na));
13683              break;
13684            }
13685          if (LocaleCompare(attribute,"translate") == 0)
13686            {
13687              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13688              affine.tx=geometry_info.rho;
13689              affine.ty=geometry_info.sigma;
13690              if ((flags & SigmaValue) == 0)
13691                affine.ty=affine.tx;
13692              break;
13693            }
13694          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13695            attribute);
13696          break;
13697        }
13698        case 'w':
13699        case 'W':
13700        {
13701          if (LocaleCompare(attribute,"weight") == 0)
13702            {
13703              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13704              draw_info->weight=(size_t) geometry_info.rho;
13705              break;
13706            }
13707          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13708            attribute);
13709          break;
13710        }
13711        case 'x':
13712        case 'X':
13713        {
13714          if (LocaleCompare(attribute,"x") == 0)
13715            {
13716              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13717              x=geometry_info.rho;
13718              break;
13719            }
13720          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13721            attribute);
13722          break;
13723        }
13724        case 'y':
13725        case 'Y':
13726        {
13727          if (LocaleCompare(attribute,"y") == 0)
13728            {
13729              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13730              y=geometry_info.rho;
13731              break;
13732            }
13733          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13734            attribute);
13735          break;
13736        }
13737        default:
13738        {
13739          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13740            attribute);
13741          break;
13742        }
13743      }
13744    }
13745    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13746    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13747    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13748    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13749    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13750    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13751    if (draw_info->geometry == (char *) NULL)
13752      {
13753        draw_info->geometry=AcquireString((char *) NULL);
13754        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13755          "%.20g,%.20g",x,y);
13756      }
13757    status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13758    (void) CatchException(exception);
13759    if (status == MagickFalse)
13760      PUSHs(&sv_undef);
13761    else
13762      {
13763        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13764        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13765        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13766        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13767        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13768        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13769        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13770        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13771        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13772        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13773        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13774        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13775        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13776      }
13777    draw_info=DestroyDrawInfo(draw_info);
13778
13779  PerlException:
13780    if (package_info != (struct PackageInfo *) NULL)
13781      DestroyPackageInfo(package_info);
13782    InheritPerlException(exception,perl_exception);
13783    exception=DestroyExceptionInfo(exception);
13784    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13785  }
13786
13787#
13788###############################################################################
13789#                                                                             #
13790#                                                                             #
13791#                                                                             #
13792#   Q u e r y F o r m a t                                                     #
13793#                                                                             #
13794#                                                                             #
13795#                                                                             #
13796###############################################################################
13797#
13798#
13799void
13800QueryFormat(ref,...)
13801  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13802  ALIAS:
13803    queryformat = 1
13804  PPCODE:
13805  {
13806    char
13807      *name;
13808
13809    ExceptionInfo
13810      *exception;
13811
13812    ssize_t
13813      i;
13814
13815    SV
13816      *perl_exception;
13817
13818    volatile const MagickInfo
13819      *magick_info;
13820
13821    PERL_UNUSED_VAR(ref);
13822    PERL_UNUSED_VAR(ix);
13823    exception=AcquireExceptionInfo();
13824    perl_exception=newSVpv("",0);
13825    if (items == 1)
13826      {
13827        char
13828          format[MagickPathExtent];
13829
13830        const MagickInfo
13831          **format_list;
13832
13833        size_t
13834          types;
13835
13836        format_list=GetMagickInfoList("*",&types,exception);
13837        EXTEND(sp,types);
13838        for (i=0; i < (ssize_t) types; i++)
13839        {
13840          (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13841          LocaleLower(format);
13842          PUSHs(sv_2mortal(newSVpv(format,0)));
13843        }
13844        format_list=(const MagickInfo **)
13845          RelinquishMagickMemory((MagickInfo *) format_list);
13846        goto PerlException;
13847      }
13848    EXTEND(sp,8*items);
13849    for (i=1; i < items; i++)
13850    {
13851      name=(char *) SvPV(ST(i),na);
13852      magick_info=GetMagickInfo(name,exception);
13853      if (magick_info == (const MagickInfo *) NULL)
13854        {
13855          PUSHs(&sv_undef);
13856          continue;
13857        }
13858      if (magick_info->description == (char *) NULL)
13859        PUSHs(&sv_undef);
13860      else
13861        PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13862      if (magick_info->magick_module == (char *) NULL)
13863        PUSHs(&sv_undef);
13864      else
13865        PUSHs(sv_2mortal(newSVpv(magick_info->magick_module,0)));
13866    }
13867
13868  PerlException:
13869    InheritPerlException(exception,perl_exception);
13870    exception=DestroyExceptionInfo(exception);
13871    SvREFCNT_dec(perl_exception);
13872  }
13873
13874#
13875###############################################################################
13876#                                                                             #
13877#                                                                             #
13878#                                                                             #
13879#   Q u e r y O p t i o n                                                     #
13880#                                                                             #
13881#                                                                             #
13882#                                                                             #
13883###############################################################################
13884#
13885#
13886void
13887QueryOption(ref,...)
13888  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13889  ALIAS:
13890    queryoption = 1
13891  PPCODE:
13892  {
13893    char
13894      **options;
13895
13896    ExceptionInfo
13897      *exception;
13898
13899    ssize_t
13900      i;
13901
13902    ssize_t
13903      j,
13904      option;
13905
13906    SV
13907      *perl_exception;
13908
13909    PERL_UNUSED_VAR(ref);
13910    PERL_UNUSED_VAR(ix);
13911    exception=AcquireExceptionInfo();
13912    perl_exception=newSVpv("",0);
13913    EXTEND(sp,8*items);
13914    for (i=1; i < items; i++)
13915    {
13916      option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13917        SvPV(ST(i),na));
13918      options=GetCommandOptions((CommandOption) option);
13919      if (options == (char **) NULL)
13920        PUSHs(&sv_undef);
13921      else
13922        {
13923          for (j=0; options[j] != (char *) NULL; j++)
13924            PUSHs(sv_2mortal(newSVpv(options[j],0)));
13925          options=DestroyStringList(options);
13926        }
13927    }
13928
13929    InheritPerlException(exception,perl_exception);
13930    exception=DestroyExceptionInfo(exception);
13931    SvREFCNT_dec(perl_exception);
13932  }
13933
13934#
13935###############################################################################
13936#                                                                             #
13937#                                                                             #
13938#                                                                             #
13939#   R e a d                                                                   #
13940#                                                                             #
13941#                                                                             #
13942#                                                                             #
13943###############################################################################
13944#
13945#
13946void
13947Read(ref,...)
13948  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13949  ALIAS:
13950    ReadImage  = 1
13951    read       = 2
13952    readimage  = 3
13953  PPCODE:
13954  {
13955    AV
13956      *av;
13957
13958    char
13959      **keep,
13960      **list;
13961
13962    ExceptionInfo
13963      *exception;
13964
13965    HV
13966      *hv;
13967
13968    Image
13969      *image;
13970
13971    int
13972      n;
13973
13974    MagickBooleanType
13975      status;
13976
13977    char
13978      **p;
13979
13980    ssize_t
13981      i;
13982
13983    ssize_t
13984      ac,
13985      number_images;
13986
13987    STRLEN
13988      *length;
13989
13990    struct PackageInfo
13991      *info,
13992      *package_info;
13993
13994    SV
13995      *perl_exception,  /* Perl variable for storing messages */
13996      *reference,
13997      *rv,
13998      *sv;
13999
14000    PERL_UNUSED_VAR(ref);
14001    PERL_UNUSED_VAR(ix);
14002    exception=AcquireExceptionInfo();
14003    perl_exception=newSVpv("",0);
14004    sv=NULL;
14005    package_info=(struct PackageInfo *) NULL;
14006    number_images=0;
14007    ac=(items < 2) ? 1 : items-1;
14008    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
14009    keep=list;
14010    length=(STRLEN *) NULL;
14011    if (list == (char **) NULL)
14012      {
14013        ThrowPerlException(exception,ResourceLimitError,
14014          "MemoryAllocationFailed",PackageName);
14015        goto PerlException;
14016      }
14017    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
14018    if (length == (STRLEN *) NULL)
14019      {
14020        ThrowPerlException(exception,ResourceLimitError,
14021          "MemoryAllocationFailed",PackageName);
14022        goto PerlException;
14023      }
14024    if (sv_isobject(ST(0)) == 0)
14025      {
14026        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14027          PackageName);
14028        goto PerlException;
14029      }
14030    reference=SvRV(ST(0));
14031    hv=SvSTASH(reference);
14032    if (SvTYPE(reference) != SVt_PVAV)
14033      {
14034        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14035          PackageName);
14036        goto PerlException;
14037      }
14038    av=(AV *) reference;
14039    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14040      exception);
14041    package_info=ClonePackageInfo(info,exception);
14042    n=1;
14043    if (items <= 1)
14044      *list=(char *) (*package_info->image_info->filename ?
14045        package_info->image_info->filename : "XC:black");
14046    else
14047      for (n=0, i=0; i < ac; i++)
14048      {
14049        list[n]=(char *) SvPV(ST(i+1),length[n]);
14050        if ((items >= 3) && strEQcase(list[n],"blob"))
14051          {
14052            void
14053              *blob;
14054
14055            i++;
14056            blob=(void *) (SvPV(ST(i+1),length[n]));
14057            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
14058          }
14059        if ((items >= 3) && strEQcase(list[n],"filename"))
14060          continue;
14061        if ((items >= 3) && strEQcase(list[n],"file"))
14062          {
14063            FILE
14064              *file;
14065
14066            PerlIO
14067              *io_info;
14068
14069            i++;
14070            io_info=IoIFP(sv_2io(ST(i+1)));
14071            if (io_info == (PerlIO *) NULL)
14072              {
14073                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
14074                  PackageName);
14075                continue;
14076              }
14077            file=PerlIO_findFILE(io_info);
14078            if (file == (FILE *) NULL)
14079              {
14080                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
14081                  PackageName);
14082                continue;
14083              }
14084            SetImageInfoFile(package_info->image_info,file);
14085          }
14086        if ((items >= 3) && strEQcase(list[n],"magick"))
14087          continue;
14088        n++;
14089      }
14090    list[n]=(char *) NULL;
14091    keep=list;
14092    status=ExpandFilenames(&n,&list);
14093    if (status == MagickFalse)
14094      {
14095        ThrowPerlException(exception,ResourceLimitError,
14096          "MemoryAllocationFailed",PackageName);
14097        goto PerlException;
14098      }
14099    number_images=0;
14100    for (i=0; i < n; i++)
14101    {
14102      if ((package_info->image_info->file == (FILE *) NULL) &&
14103          (package_info->image_info->blob == (void *) NULL))
14104        image=ReadImages(package_info->image_info,list[i],exception);
14105      else
14106        {
14107          image=ReadImages(package_info->image_info,
14108            package_info->image_info->filename,exception);
14109          if (image != (Image *) NULL)
14110            DisassociateImageStream(image);
14111        }
14112      if (image == (Image *) NULL)
14113        break;
14114      for ( ; image; image=image->next)
14115      {
14116        AddImageToRegistry(sv,image);
14117        rv=newRV(sv);
14118        av_push(av,sv_bless(rv,hv));
14119        SvREFCNT_dec(sv);
14120        number_images++;
14121      }
14122    }
14123    /*
14124      Free resources.
14125    */
14126    for (i=0; i < n; i++)
14127      if (list[i] != (char *) NULL)
14128        for (p=keep; list[i] != *p++; )
14129          if (*p == (char *) NULL)
14130            {
14131              list[i]=(char *) RelinquishMagickMemory(list[i]);
14132              break;
14133            }
14134
14135  PerlException:
14136    if (package_info != (struct PackageInfo *) NULL)
14137      DestroyPackageInfo(package_info);
14138    if (list && (list != keep))
14139      list=(char **) RelinquishMagickMemory(list);
14140    if (keep)
14141      keep=(char **) RelinquishMagickMemory(keep);
14142    if (length)
14143      length=(STRLEN *) RelinquishMagickMemory(length);
14144    InheritPerlException(exception,perl_exception);
14145    exception=DestroyExceptionInfo(exception);
14146    sv_setiv(perl_exception,(IV) number_images);
14147    SvPOK_on(perl_exception);
14148    ST(0)=sv_2mortal(perl_exception);
14149    XSRETURN(1);
14150  }
14151
14152#
14153###############################################################################
14154#                                                                             #
14155#                                                                             #
14156#                                                                             #
14157#   R e m o t e                                                               #
14158#                                                                             #
14159#                                                                             #
14160#                                                                             #
14161###############################################################################
14162#
14163#
14164void
14165Remote(ref,...)
14166  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14167  ALIAS:
14168    RemoteCommand  = 1
14169    remote         = 2
14170    remoteCommand  = 3
14171  PPCODE:
14172  {
14173    AV
14174      *av;
14175
14176    ExceptionInfo
14177      *exception;
14178
14179    ssize_t
14180      i;
14181
14182    SV
14183      *perl_exception,
14184      *reference;
14185
14186    struct PackageInfo
14187      *info;
14188
14189    PERL_UNUSED_VAR(ref);
14190    PERL_UNUSED_VAR(ix);
14191    exception=AcquireExceptionInfo();
14192    perl_exception=newSVpv("",0);
14193    reference=SvRV(ST(0));
14194    av=(AV *) reference;
14195    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14196      exception);
14197    for (i=1; i < items; i++)
14198      (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
14199        SvPV(ST(i),na),exception);
14200    InheritPerlException(exception,perl_exception);
14201    exception=DestroyExceptionInfo(exception);
14202    SvREFCNT_dec(perl_exception);    /* throw away all errors */
14203  }
14204
14205#
14206###############################################################################
14207#                                                                             #
14208#                                                                             #
14209#                                                                             #
14210#   S e t                                                                     #
14211#                                                                             #
14212#                                                                             #
14213#                                                                             #
14214###############################################################################
14215#
14216#
14217void
14218Set(ref,...)
14219  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14220  ALIAS:
14221    SetAttributes  = 1
14222    SetAttribute   = 2
14223    set            = 3
14224    setattributes  = 4
14225    setattribute   = 5
14226  PPCODE:
14227  {
14228    ExceptionInfo
14229      *exception;
14230
14231    Image
14232      *image;
14233
14234    ssize_t
14235      i;
14236
14237    struct PackageInfo
14238      *info;
14239
14240    SV
14241      *perl_exception,
14242      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14243
14244    PERL_UNUSED_VAR(ref);
14245    PERL_UNUSED_VAR(ix);
14246    exception=AcquireExceptionInfo();
14247    perl_exception=newSVpv("",0);
14248    if (sv_isobject(ST(0)) == 0)
14249      {
14250        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14251          PackageName);
14252        goto PerlException;
14253      }
14254    reference=SvRV(ST(0));
14255    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14256    if (items == 2)
14257      SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14258    else
14259      for (i=2; i < items; i+=2)
14260        SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14261
14262  PerlException:
14263    InheritPerlException(exception,perl_exception);
14264    exception=DestroyExceptionInfo(exception);
14265    sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14266    SvPOK_on(perl_exception);
14267    ST(0)=sv_2mortal(perl_exception);
14268    XSRETURN(1);
14269  }
14270
14271#
14272###############################################################################
14273#                                                                             #
14274#                                                                             #
14275#                                                                             #
14276#   S e t P i x e l                                                           #
14277#                                                                             #
14278#                                                                             #
14279#                                                                             #
14280###############################################################################
14281#
14282#
14283void
14284SetPixel(ref,...)
14285  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14286  ALIAS:
14287    setpixel = 1
14288    setPixel = 2
14289  PPCODE:
14290  {
14291    AV
14292      *av;
14293
14294    char
14295      *attribute;
14296
14297    ChannelType
14298      channel,
14299      channel_mask;
14300
14301    ExceptionInfo
14302      *exception;
14303
14304    Image
14305      *image;
14306
14307    MagickBooleanType
14308      normalize;
14309
14310    RectangleInfo
14311      region;
14312
14313    ssize_t
14314      i;
14315
14316    Quantum
14317      *q;
14318
14319    ssize_t
14320      option;
14321
14322    struct PackageInfo
14323      *info;
14324
14325    SV
14326      *perl_exception,
14327      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14328
14329    PERL_UNUSED_VAR(ref);
14330    PERL_UNUSED_VAR(ix);
14331    exception=AcquireExceptionInfo();
14332    perl_exception=newSVpv("",0);
14333    reference=SvRV(ST(0));
14334    av=(AV *) reference;
14335    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14336      exception);
14337    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14338    if (image == (Image *) NULL)
14339      {
14340        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14341          PackageName);
14342        goto PerlException;
14343      }
14344    av=(AV *) NULL;
14345    normalize=MagickTrue;
14346    region.x=0;
14347    region.y=0;
14348    region.width=image->columns;
14349    region.height=1;
14350    if (items == 1)
14351      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14352    channel=DefaultChannels;
14353    for (i=2; i < items; i+=2)
14354    {
14355      attribute=(char *) SvPV(ST(i-1),na);
14356      switch (*attribute)
14357      {
14358        case 'C':
14359        case 'c':
14360        {
14361          if (LocaleCompare(attribute,"channel") == 0)
14362            {
14363              ssize_t
14364                option;
14365
14366              option=ParseChannelOption(SvPV(ST(i),na));
14367              if (option < 0)
14368                {
14369                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14370                    SvPV(ST(i),na));
14371                  return;
14372                }
14373              channel=(ChannelType) option;
14374              break;
14375            }
14376          if (LocaleCompare(attribute,"color") == 0)
14377            {
14378              if (SvTYPE(ST(i)) != SVt_RV)
14379                {
14380                  char
14381                    message[MagickPathExtent];
14382
14383                  (void) FormatLocaleString(message,MagickPathExtent,
14384                    "invalid %.60s value",attribute);
14385                  ThrowPerlException(exception,OptionError,message,
14386                    SvPV(ST(i),na));
14387                }
14388              av=(AV *) SvRV(ST(i));
14389              break;
14390            }
14391          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14392            attribute);
14393          break;
14394        }
14395        case 'g':
14396        case 'G':
14397        {
14398          if (LocaleCompare(attribute,"geometry") == 0)
14399            {
14400              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14401              break;
14402            }
14403          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14404            attribute);
14405          break;
14406        }
14407        case 'N':
14408        case 'n':
14409        {
14410          if (LocaleCompare(attribute,"normalize") == 0)
14411            {
14412              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14413                SvPV(ST(i),na));
14414              if (option < 0)
14415                {
14416                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14417                    SvPV(ST(i),na));
14418                  break;
14419                }
14420             normalize=option != 0 ? MagickTrue : MagickFalse;
14421             break;
14422            }
14423          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14424            attribute);
14425          break;
14426        }
14427        case 'x':
14428        case 'X':
14429        {
14430          if (LocaleCompare(attribute,"x") == 0)
14431            {
14432              region.x=SvIV(ST(i));
14433              break;
14434            }
14435          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14436            attribute);
14437          break;
14438        }
14439        case 'y':
14440        case 'Y':
14441        {
14442          if (LocaleCompare(attribute,"y") == 0)
14443            {
14444              region.y=SvIV(ST(i));
14445              break;
14446            }
14447          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14448            attribute);
14449          break;
14450        }
14451        default:
14452        {
14453          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14454            attribute);
14455          break;
14456        }
14457      }
14458    }
14459    (void) SetImageStorageClass(image,DirectClass,exception);
14460    channel_mask=SetImageChannelMask(image,channel);
14461    q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14462    if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14463        (SvTYPE(av) != SVt_PVAV))
14464      PUSHs(&sv_undef);
14465    else
14466      {
14467        double
14468          scale;
14469
14470        ssize_t
14471          i;
14472
14473        i=0;
14474        scale=1.0;
14475        if (normalize != MagickFalse)
14476          scale=QuantumRange;
14477        if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14478            (i <= av_len(av)))
14479          {
14480            SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14481              av_fetch(av,i,0)))),q);
14482            i++;
14483          }
14484        if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14485            (i <= av_len(av)))
14486          {
14487            SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14488              av_fetch(av,i,0)))),q);
14489            i++;
14490          }
14491        if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14492            (i <= av_len(av)))
14493          {
14494            SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14495              av_fetch(av,i,0)))),q);
14496            i++;
14497          }
14498        if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14499            (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14500          {
14501            SetPixelBlack(image,ClampToQuantum(scale*
14502              SvNV(*(av_fetch(av,i,0)))),q);
14503            i++;
14504          }
14505        if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14506            (i <= av_len(av)))
14507          {
14508            SetPixelAlpha(image,ClampToQuantum(scale*
14509              SvNV(*(av_fetch(av,i,0)))),q);
14510            i++;
14511          }
14512        (void) SyncAuthenticPixels(image,exception);
14513      }
14514    (void) SetImageChannelMask(image,channel_mask);
14515
14516  PerlException:
14517    InheritPerlException(exception,perl_exception);
14518    exception=DestroyExceptionInfo(exception);
14519    SvREFCNT_dec(perl_exception);
14520  }
14521
14522#
14523###############################################################################
14524#                                                                             #
14525#                                                                             #
14526#                                                                             #
14527#   S e t P i x e l s                                                         #
14528#                                                                             #
14529#                                                                             #
14530#                                                                             #
14531###############################################################################
14532#
14533#
14534void
14535SetPixels(ref,...)
14536  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14537  ALIAS:
14538    setpixels = 1
14539    setPixels = 2
14540  PPCODE:
14541  {
14542    AV
14543      *av;
14544
14545    char
14546      *attribute;
14547
14548    ChannelType
14549      channel,
14550      channel_mask;
14551
14552    ExceptionInfo
14553      *exception;
14554
14555    Image
14556      *image;
14557
14558    RectangleInfo
14559      region;
14560
14561    ssize_t
14562      i;
14563
14564    Quantum
14565      *q;
14566
14567    struct PackageInfo
14568      *info;
14569
14570    SV
14571      *perl_exception,
14572      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14573
14574    PERL_UNUSED_VAR(ref);
14575    PERL_UNUSED_VAR(ix);
14576    exception=AcquireExceptionInfo();
14577    perl_exception=newSVpv("",0);
14578    reference=SvRV(ST(0));
14579    av=(AV *) reference;
14580    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14581      exception);
14582    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14583    if (image == (Image *) NULL)
14584      {
14585        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14586          PackageName);
14587        goto PerlException;
14588      }
14589    av=(AV *) NULL;
14590    region.x=0;
14591    region.y=0;
14592    region.width=image->columns;
14593    region.height=1;
14594    if (items == 1)
14595      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14596    channel=DefaultChannels;
14597    for (i=2; i < items; i+=2)
14598    {
14599      attribute=(char *) SvPV(ST(i-1),na);
14600      switch (*attribute)
14601      {
14602        case 'C':
14603        case 'c':
14604        {
14605          if (LocaleCompare(attribute,"channel") == 0)
14606            {
14607              ssize_t
14608                option;
14609
14610              option=ParseChannelOption(SvPV(ST(i),na));
14611              if (option < 0)
14612                {
14613                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14614                    SvPV(ST(i),na));
14615                  return;
14616                }
14617              channel=(ChannelType) option;
14618              break;
14619            }
14620          if (LocaleCompare(attribute,"color") == 0)
14621            {
14622              if (SvTYPE(ST(i)) != SVt_RV)
14623                {
14624                  char
14625                    message[MagickPathExtent];
14626
14627                  (void) FormatLocaleString(message,MagickPathExtent,
14628                    "invalid %.60s value",attribute);
14629                  ThrowPerlException(exception,OptionError,message,
14630                    SvPV(ST(i),na));
14631                }
14632              av=(AV *) SvRV(ST(i));
14633              break;
14634            }
14635          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14636            attribute);
14637          break;
14638        }
14639        case 'g':
14640        case 'G':
14641        {
14642          if (LocaleCompare(attribute,"geometry") == 0)
14643            {
14644              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14645              break;
14646            }
14647          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14648            attribute);
14649          break;
14650        }
14651        case 'h':
14652        case 'H':
14653        {
14654          if (LocaleCompare(attribute,"height") == 0)
14655            {
14656              region.height=SvIV(ST(i));
14657              break;
14658            }
14659          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14660            attribute);
14661          break;
14662        }
14663        case 'w':
14664        case 'W':
14665        {
14666          if (LocaleCompare(attribute,"width") == 0)
14667            {
14668              region.width=SvIV(ST(i));
14669              break;
14670            }
14671          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14672            attribute);
14673          break;
14674        }
14675        case 'x':
14676        case 'X':
14677        {
14678          if (LocaleCompare(attribute,"x") == 0)
14679            {
14680              region.x=SvIV(ST(i));
14681              break;
14682            }
14683          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14684            attribute);
14685          break;
14686        }
14687        case 'y':
14688        case 'Y':
14689        {
14690          if (LocaleCompare(attribute,"y") == 0)
14691            {
14692              region.y=SvIV(ST(i));
14693              break;
14694            }
14695          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14696            attribute);
14697          break;
14698        }
14699        default:
14700        {
14701          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14702            attribute);
14703          break;
14704        }
14705      }
14706    }
14707    (void) SetImageStorageClass(image,DirectClass,exception);
14708    channel_mask=SetImageChannelMask(image,channel);
14709    q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14710      exception);
14711    if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14712        (SvTYPE(av) != SVt_PVAV))
14713      PUSHs(&sv_undef);
14714    else
14715      {
14716        double
14717          scale;
14718
14719        ssize_t
14720          i,
14721          n,
14722          number_pixels;
14723
14724        i=0;
14725        n=0;
14726        scale=(double) QuantumRange;
14727        number_pixels=region.width*region.height;
14728        while ((n < number_pixels) && (i < av_len(av)))
14729        {
14730          if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14731              (i <= av_len(av)))
14732            {
14733              SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14734                av_fetch(av,i,0)))),q);
14735              i++;
14736            }
14737          if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14738              (i <= av_len(av)))
14739            {
14740              SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14741                av_fetch(av,i,0)))),q);
14742              i++;
14743            }
14744          if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14745              (i <= av_len(av)))
14746            {
14747              SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14748                av_fetch(av,i,0)))),q);
14749              i++;
14750            }
14751          if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14752              (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14753            {
14754             SetPixelBlack(image,ClampToQuantum(scale*
14755                SvNV(*(av_fetch(av,i,0)))),q);
14756              i++;
14757            }
14758          if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14759              (i <= av_len(av)))
14760            {
14761              SetPixelAlpha(image,ClampToQuantum(scale*
14762                SvNV(*(av_fetch(av,i,0)))),q);
14763              i++;
14764            }
14765         	n++;
14766         	q+=image->number_channels;
14767        }
14768        (void) SyncAuthenticPixels(image,exception);
14769      }
14770    (void) SetImageChannelMask(image,channel_mask);
14771
14772  PerlException:
14773    InheritPerlException(exception,perl_exception);
14774    exception=DestroyExceptionInfo(exception);
14775    SvREFCNT_dec(perl_exception);
14776  }
14777
14778#
14779###############################################################################
14780#                                                                             #
14781#                                                                             #
14782#                                                                             #
14783#   S m u s h                                                                 #
14784#                                                                             #
14785#                                                                             #
14786#                                                                             #
14787###############################################################################
14788#
14789#
14790void
14791Smush(ref,...)
14792  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14793  ALIAS:
14794    SmushImage  = 1
14795    smush       = 2
14796    smushimage  = 3
14797  PPCODE:
14798  {
14799    AV
14800      *av;
14801
14802    char
14803      *attribute;
14804
14805    ExceptionInfo
14806      *exception;
14807
14808    HV
14809      *hv;
14810
14811    Image
14812      *image;
14813
14814    ssize_t
14815      i;
14816
14817    ssize_t
14818      offset,
14819      stack;
14820
14821    struct PackageInfo
14822      *info;
14823
14824    SV
14825      *av_reference,
14826      *perl_exception,
14827      *reference,
14828      *rv,
14829      *sv;
14830
14831    PERL_UNUSED_VAR(ref);
14832    PERL_UNUSED_VAR(ix);
14833    exception=AcquireExceptionInfo();
14834    perl_exception=newSVpv("",0);
14835    sv=NULL;
14836    attribute=NULL;
14837    av=NULL;
14838    if (sv_isobject(ST(0)) == 0)
14839      {
14840        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14841          PackageName);
14842        goto PerlException;
14843      }
14844    reference=SvRV(ST(0));
14845    hv=SvSTASH(reference);
14846    av=newAV();
14847    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14848    SvREFCNT_dec(av);
14849    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14850    if (image == (Image *) NULL)
14851      {
14852        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14853          PackageName);
14854        goto PerlException;
14855      }
14856    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14857    /*
14858      Get options.
14859    */
14860    offset=0;
14861    stack=MagickTrue;
14862    for (i=2; i < items; i+=2)
14863    {
14864      attribute=(char *) SvPV(ST(i-1),na);
14865      switch (*attribute)
14866      {
14867        case 'O':
14868        case 'o':
14869        {
14870          if (LocaleCompare(attribute,"offset") == 0)
14871            {
14872              offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14873              break;
14874            }
14875          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14876            attribute);
14877          break;
14878        }
14879        case 'S':
14880        case 's':
14881        {
14882          if (LocaleCompare(attribute,"stack") == 0)
14883            {
14884              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14885                SvPV(ST(i),na));
14886              if (stack < 0)
14887                {
14888                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14889                    SvPV(ST(i),na));
14890                  return;
14891                }
14892              break;
14893            }
14894          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14895            attribute);
14896          break;
14897        }
14898        default:
14899        {
14900          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14901            attribute);
14902          break;
14903        }
14904      }
14905    }
14906    image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14907      exception);
14908    if (image == (Image *) NULL)
14909      goto PerlException;
14910    for ( ; image; image=image->next)
14911    {
14912      AddImageToRegistry(sv,image);
14913      rv=newRV(sv);
14914      av_push(av,sv_bless(rv,hv));
14915      SvREFCNT_dec(sv);
14916    }
14917    exception=DestroyExceptionInfo(exception);
14918    ST(0)=av_reference;
14919    SvREFCNT_dec(perl_exception);
14920    XSRETURN(1);
14921
14922  PerlException:
14923    InheritPerlException(exception,perl_exception);
14924    exception=DestroyExceptionInfo(exception);
14925    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14926    SvPOK_on(perl_exception);
14927    ST(0)=sv_2mortal(perl_exception);
14928    XSRETURN(1);
14929  }
14930
14931#
14932###############################################################################
14933#                                                                             #
14934#                                                                             #
14935#                                                                             #
14936#   S t a t i s t i c s                                                       #
14937#                                                                             #
14938#                                                                             #
14939#                                                                             #
14940###############################################################################
14941#
14942#
14943void
14944Statistics(ref)
14945  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14946  ALIAS:
14947    StatisticsImage = 1
14948    statistics      = 2
14949    statisticsimage = 3
14950  PPCODE:
14951  {
14952#define ChannelStatistics(channel) \
14953{ \
14954  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14955    (double) channel_statistics[channel].depth); \
14956  PUSHs(sv_2mortal(newSVpv(message,0))); \
14957  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14958    channel_statistics[channel].minima/QuantumRange); \
14959  PUSHs(sv_2mortal(newSVpv(message,0))); \
14960  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14961    channel_statistics[channel].maxima/QuantumRange); \
14962  PUSHs(sv_2mortal(newSVpv(message,0))); \
14963  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14964    channel_statistics[channel].mean/QuantumRange); \
14965  PUSHs(sv_2mortal(newSVpv(message,0))); \
14966  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14967    channel_statistics[channel].standard_deviation/QuantumRange); \
14968  PUSHs(sv_2mortal(newSVpv(message,0))); \
14969  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14970    channel_statistics[channel].kurtosis); \
14971  PUSHs(sv_2mortal(newSVpv(message,0))); \
14972  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14973    channel_statistics[channel].skewness); \
14974  PUSHs(sv_2mortal(newSVpv(message,0))); \
14975  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14976    channel_statistics[channel].entropy); \
14977  PUSHs(sv_2mortal(newSVpv(message,0))); \
14978}
14979
14980    AV
14981      *av;
14982
14983    char
14984      message[MagickPathExtent];
14985
14986    ChannelStatistics
14987      *channel_statistics;
14988
14989    ExceptionInfo
14990      *exception;
14991
14992    Image
14993      *image;
14994
14995    ssize_t
14996      count;
14997
14998    struct PackageInfo
14999      *info;
15000
15001    SV
15002      *perl_exception,
15003      *reference;
15004
15005    PERL_UNUSED_VAR(ref);
15006    PERL_UNUSED_VAR(ix);
15007    exception=AcquireExceptionInfo();
15008    perl_exception=newSVpv("",0);
15009    av=NULL;
15010    if (sv_isobject(ST(0)) == 0)
15011      {
15012        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
15013          PackageName);
15014        goto PerlException;
15015      }
15016    reference=SvRV(ST(0));
15017    av=newAV();
15018    SvREFCNT_dec(av);
15019    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
15020    if (image == (Image *) NULL)
15021      {
15022        ThrowPerlException(exception,OptionError,"NoImagesDefined",
15023          PackageName);
15024        goto PerlException;
15025      }
15026    count=0;
15027    for ( ; image; image=image->next)
15028    {
15029      size_t
15030        i;
15031
15032      channel_statistics=GetImageStatistics(image,exception);
15033      if (channel_statistics == (ChannelStatistics *) NULL)
15034        continue;
15035      count++;
15036      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
15037      {
15038        PixelChannel channel=GetPixelChannelChannel(image,i);
15039        PixelTrait traits=GetPixelChannelTraits(image,channel);
15040        if (traits == UndefinedPixelTrait)
15041          continue;
15042        EXTEND(sp,8*(i+1)*count);
15043        ChannelStatistics(channel);
15044      }
15045      EXTEND(sp,8*(i+1)*count);
15046      ChannelStatistics(CompositePixelChannel);
15047      channel_statistics=(ChannelStatistics *)
15048        RelinquishMagickMemory(channel_statistics);
15049    }
15050
15051  PerlException:
15052    InheritPerlException(exception,perl_exception);
15053    exception=DestroyExceptionInfo(exception);
15054    SvREFCNT_dec(perl_exception);
15055  }
15056
15057#
15058###############################################################################
15059#                                                                             #
15060#                                                                             #
15061#                                                                             #
15062#   S y n c A u t h e n t i c P i x e l s                                     #
15063#                                                                             #
15064#                                                                             #
15065#                                                                             #
15066###############################################################################
15067#
15068#
15069void
15070SyncAuthenticPixels(ref,...)
15071  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
15072  ALIAS:
15073    Syncauthenticpixels = 1
15074    SyncImagePixels = 2
15075    syncimagepixels = 3
15076  CODE:
15077  {
15078    ExceptionInfo
15079      *exception;
15080
15081    Image
15082      *image;
15083
15084    MagickBooleanType
15085      status;
15086
15087    struct PackageInfo
15088      *info;
15089
15090    SV
15091      *perl_exception,
15092      *reference;
15093
15094    PERL_UNUSED_VAR(ref);
15095    PERL_UNUSED_VAR(ix);
15096    exception=AcquireExceptionInfo();
15097    perl_exception=newSVpv("",0);
15098    if (sv_isobject(ST(0)) == 0)
15099      {
15100        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
15101          PackageName);
15102        goto PerlException;
15103      }
15104
15105    reference=SvRV(ST(0));
15106    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
15107    if (image == (Image *) NULL)
15108      {
15109        ThrowPerlException(exception,OptionError,"NoImagesDefined",
15110          PackageName);
15111        goto PerlException;
15112      }
15113
15114    status=SyncAuthenticPixels(image,exception);
15115    if (status != MagickFalse)
15116      return;
15117
15118  PerlException:
15119    InheritPerlException(exception,perl_exception);
15120    exception=DestroyExceptionInfo(exception);
15121    SvREFCNT_dec(perl_exception);  /* throw away all errors */
15122  }
15123
15124
15125#
15126###############################################################################
15127#                                                                             #
15128#                                                                             #
15129#                                                                             #
15130#   W r i t e                                                                 #
15131#                                                                             #
15132#                                                                             #
15133#                                                                             #
15134###############################################################################
15135#
15136#
15137void
15138Write(ref,...)
15139  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
15140  ALIAS:
15141    WriteImage    = 1
15142    write         = 2
15143    writeimage    = 3
15144  PPCODE:
15145  {
15146    char
15147      filename[MagickPathExtent];
15148
15149    ExceptionInfo
15150      *exception;
15151
15152    Image
15153      *image,
15154      *next;
15155
15156    ssize_t
15157      i;
15158
15159    ssize_t
15160      number_images,
15161      scene;
15162
15163    struct PackageInfo
15164      *info,
15165      *package_info;
15166
15167    SV
15168      *perl_exception,
15169      *reference;
15170
15171    PERL_UNUSED_VAR(ref);
15172    PERL_UNUSED_VAR(ix);
15173    exception=AcquireExceptionInfo();
15174    perl_exception=newSVpv("",0);
15175    number_images=0;
15176    package_info=(struct PackageInfo *) NULL;
15177    if (sv_isobject(ST(0)) == 0)
15178      {
15179        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
15180          PackageName);
15181        goto PerlException;
15182      }
15183    reference=SvRV(ST(0));
15184    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
15185    if (image == (Image *) NULL)
15186      {
15187        ThrowPerlException(exception,OptionError,"NoImagesDefined",
15188          PackageName);
15189        goto PerlException;
15190      }
15191    scene=0;
15192    for (next=image; next; next=next->next)
15193      next->scene=scene++;
15194    package_info=ClonePackageInfo(info,exception);
15195    if (items == 2)
15196      SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
15197    else
15198      if (items > 2)
15199        for (i=2; i < items; i+=2)
15200          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
15201            exception);
15202    (void) CopyMagickString(filename,package_info->image_info->filename,
15203      MagickPathExtent);
15204    for (next=image; next; next=next->next)
15205      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
15206    *package_info->image_info->magick='\0';
15207    SetImageInfo(package_info->image_info,(unsigned int)
15208      GetImageListLength(image),exception);
15209    for (next=image; next; next=next->next)
15210    {
15211      (void) WriteImage(package_info->image_info,next,exception);
15212      number_images++;
15213      if (package_info->image_info->adjoin)
15214        break;
15215    }
15216
15217  PerlException:
15218    if (package_info != (struct PackageInfo *) NULL)
15219      DestroyPackageInfo(package_info);
15220    InheritPerlException(exception,perl_exception);
15221    exception=DestroyExceptionInfo(exception);
15222    sv_setiv(perl_exception,(IV) number_images);
15223    SvPOK_on(perl_exception);
15224    ST(0)=sv_2mortal(perl_exception);
15225    XSRETURN(1);
15226  }
15227