• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2019 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      {"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  };
579
580static SplayTreeInfo
581  *magick_registry = (SplayTreeInfo *) NULL;
582
583/*
584  Forward declarations.
585*/
586static Image
587  *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
588
589static ssize_t
590  strEQcase(const char *,const char *);
591
592/*
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594%                                                                             %
595%                                                                             %
596%                                                                             %
597%   C l o n e P a c k a g e I n f o                                           %
598%                                                                             %
599%                                                                             %
600%                                                                             %
601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602%
603%  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
604%  a new one.
605%
606%  The format of the ClonePackageInfo routine is:
607%
608%      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
609%        exception)
610%
611%  A description of each parameter follows:
612%
613%    o info: a structure of type info.
614%
615%    o exception: Return any errors or warnings in this structure.
616%
617*/
618static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
619  ExceptionInfo *exception)
620{
621  struct PackageInfo
622    *clone_info;
623
624  clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
625  if (clone_info == (struct PackageInfo *) NULL)
626    {
627      ThrowPerlException(exception,ResourceLimitError,
628        "UnableToClonePackageInfo",PackageName);
629      return((struct PackageInfo *) NULL);
630    }
631  if (info == (struct PackageInfo *) NULL)
632    {
633      clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
634      return(clone_info);
635    }
636  *clone_info=(*info);
637  clone_info->image_info=CloneImageInfo(info->image_info);
638  return(clone_info);
639}
640
641/*
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%                                                                             %
644%                                                                             %
645%                                                                             %
646%   c o n s t a n t                                                           %
647%                                                                             %
648%                                                                             %
649%                                                                             %
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651%
652%  constant() returns a double value for the specified name.
653%
654%  The format of the constant routine is:
655%
656%      double constant(char *name,ssize_t sans)
657%
658%  A description of each parameter follows:
659%
660%    o value: Method constant returns a double value for the specified name.
661%
662%    o name: The name of the constant.
663%
664%    o sans: This integer value is not used.
665%
666*/
667static double constant(char *name,ssize_t sans)
668{
669  (void) sans;
670  errno=0;
671  switch (*name)
672  {
673    case 'B':
674    {
675      if (strEQ(name,"BlobError"))
676        return(BlobError);
677      if (strEQ(name,"BlobWarning"))
678        return(BlobWarning);
679      break;
680    }
681    case 'C':
682    {
683      if (strEQ(name,"CacheError"))
684        return(CacheError);
685      if (strEQ(name,"CacheWarning"))
686        return(CacheWarning);
687      if (strEQ(name,"CoderError"))
688        return(CoderError);
689      if (strEQ(name,"CoderWarning"))
690        return(CoderWarning);
691      if (strEQ(name,"ConfigureError"))
692        return(ConfigureError);
693      if (strEQ(name,"ConfigureWarning"))
694        return(ConfigureWarning);
695      if (strEQ(name,"CorruptImageError"))
696        return(CorruptImageError);
697      if (strEQ(name,"CorruptImageWarning"))
698        return(CorruptImageWarning);
699      break;
700    }
701    case 'D':
702    {
703      if (strEQ(name,"DelegateError"))
704        return(DelegateError);
705      if (strEQ(name,"DelegateWarning"))
706        return(DelegateWarning);
707      if (strEQ(name,"DrawError"))
708        return(DrawError);
709      if (strEQ(name,"DrawWarning"))
710        return(DrawWarning);
711      break;
712    }
713    case 'E':
714    {
715      if (strEQ(name,"ErrorException"))
716        return(ErrorException);
717      if (strEQ(name,"ExceptionError"))
718        return(CoderError);
719      if (strEQ(name,"ExceptionWarning"))
720        return(CoderWarning);
721      break;
722    }
723    case 'F':
724    {
725      if (strEQ(name,"FatalErrorException"))
726        return(FatalErrorException);
727      if (strEQ(name,"FileOpenError"))
728        return(FileOpenError);
729      if (strEQ(name,"FileOpenWarning"))
730        return(FileOpenWarning);
731      break;
732    }
733    case 'I':
734    {
735      if (strEQ(name,"ImageError"))
736        return(ImageError);
737      if (strEQ(name,"ImageWarning"))
738        return(ImageWarning);
739      break;
740    }
741    case 'M':
742    {
743      if (strEQ(name,"MaxRGB"))
744        return(QuantumRange);
745      if (strEQ(name,"MissingDelegateError"))
746        return(MissingDelegateError);
747      if (strEQ(name,"MissingDelegateWarning"))
748        return(MissingDelegateWarning);
749      if (strEQ(name,"ModuleError"))
750        return(ModuleError);
751      if (strEQ(name,"ModuleWarning"))
752        return(ModuleWarning);
753      break;
754    }
755    case 'O':
756    {
757      if (strEQ(name,"Opaque"))
758        return(OpaqueAlpha);
759      if (strEQ(name,"OptionError"))
760        return(OptionError);
761      if (strEQ(name,"OptionWarning"))
762        return(OptionWarning);
763      break;
764    }
765    case 'Q':
766    {
767      if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
768        return(MAGICKCORE_QUANTUM_DEPTH);
769      if (strEQ(name,"QuantumDepth"))
770        return(MAGICKCORE_QUANTUM_DEPTH);
771      if (strEQ(name,"QuantumRange"))
772        return(QuantumRange);
773      break;
774    }
775    case 'R':
776    {
777      if (strEQ(name,"ResourceLimitError"))
778        return(ResourceLimitError);
779      if (strEQ(name,"ResourceLimitWarning"))
780        return(ResourceLimitWarning);
781      if (strEQ(name,"RegistryError"))
782        return(RegistryError);
783      if (strEQ(name,"RegistryWarning"))
784        return(RegistryWarning);
785      break;
786    }
787    case 'S':
788    {
789      if (strEQ(name,"StreamError"))
790        return(StreamError);
791      if (strEQ(name,"StreamWarning"))
792        return(StreamWarning);
793      if (strEQ(name,"Success"))
794        return(0);
795      break;
796    }
797    case 'T':
798    {
799      if (strEQ(name,"Transparent"))
800        return(TransparentAlpha);
801      if (strEQ(name,"TypeError"))
802        return(TypeError);
803      if (strEQ(name,"TypeWarning"))
804        return(TypeWarning);
805      break;
806    }
807    case 'W':
808    {
809      if (strEQ(name,"WarningException"))
810        return(WarningException);
811      break;
812    }
813    case 'X':
814    {
815      if (strEQ(name,"XServerError"))
816        return(XServerError);
817      if (strEQ(name,"XServerWarning"))
818        return(XServerWarning);
819      break;
820    }
821  }
822  errno=EINVAL;
823  return(0);
824}
825
826/*
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828%                                                                             %
829%                                                                             %
830%                                                                             %
831%   D e s t r o y P a c k a g e I n f o                                       %
832%                                                                             %
833%                                                                             %
834%                                                                             %
835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836%
837%  Method DestroyPackageInfo frees a previously created info structure.
838%
839%  The format of the DestroyPackageInfo routine is:
840%
841%      DestroyPackageInfo(struct PackageInfo *info)
842%
843%  A description of each parameter follows:
844%
845%    o info: a structure of type info.
846%
847*/
848static void DestroyPackageInfo(struct PackageInfo *info)
849{
850  info->image_info=DestroyImageInfo(info->image_info);
851  info=(struct PackageInfo *) RelinquishMagickMemory(info);
852}
853
854/*
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%                                                                             %
857%                                                                             %
858%                                                                             %
859%   G e t L i s t                                                             %
860%                                                                             %
861%                                                                             %
862%                                                                             %
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864%
865%  Method GetList is recursively called by SetupList to traverse the
866%  Image__Magick reference.  If building an reference_vector (see SetupList),
867%  *current is the current position in *reference_vector and *last is the final
868%  entry in *reference_vector.
869%
870%  The format of the GetList routine is:
871%
872%      GetList(info)
873%
874%  A description of each parameter follows:
875%
876%    o info: a structure of type info.
877%
878*/
879static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
880  ssize_t *current,ssize_t *last,ExceptionInfo *exception)
881{
882  Image
883    *image;
884
885  if (reference == (SV *) NULL)
886    return(NULL);
887  switch (SvTYPE(reference))
888  {
889    case SVt_PVAV:
890    {
891      AV
892        *av;
893
894      Image
895        *head,
896        *previous;
897
898      register ssize_t
899        i;
900
901      ssize_t
902        n;
903
904      /*
905        Array of images.
906      */
907      previous=(Image *) NULL;
908      head=(Image *) NULL;
909      av=(AV *) reference;
910      n=av_len(av);
911      for (i=0; i <= n; i++)
912      {
913        SV
914          **rv;
915
916        rv=av_fetch(av,i,0);
917        if (rv && *rv && sv_isobject(*rv))
918          {
919            image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
920              exception);
921            if (image == (Image *) NULL)
922              continue;
923            if (image == previous)
924              {
925                image=CloneImage(image,0,0,MagickTrue,exception);
926                if (image == (Image *) NULL)
927                  return(NULL);
928              }
929            image->previous=previous;
930            *(previous ? &previous->next : &head)=image;
931            for (previous=image; previous->next; previous=previous->next) ;
932          }
933      }
934      return(head);
935    }
936    case SVt_PVMG:
937    {
938      /*
939        Blessed scalar, one image.
940      */
941      image=INT2PTR(Image *,SvIV(reference));
942      if (image == (Image *) NULL)
943        return(NULL);
944      image->previous=(Image *) NULL;
945      image->next=(Image *) NULL;
946      if (reference_vector)
947        {
948          if (*current == *last)
949            {
950              *last+=256;
951              if (*reference_vector == (SV **) NULL)
952                *reference_vector=(SV **) AcquireQuantumMemory(*last,
953                  sizeof(*reference_vector));
954              else
955                *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
956                  *last,sizeof(*reference_vector));
957            }
958          if (*reference_vector == (SV **) NULL)
959            {
960              ThrowPerlException(exception,ResourceLimitError,
961                "MemoryAllocationFailed",PackageName);
962              return((Image *) NULL);
963            }
964          (*reference_vector)[*current]=reference;
965          (*reference_vector)[++(*current)]=NULL;
966        }
967      return(image);
968    }
969    default:
970      break;
971  }
972  (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
973    (double) SvTYPE(reference));
974  return((Image *) NULL);
975}
976
977/*
978%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979%                                                                             %
980%                                                                             %
981%                                                                             %
982%   G e t P a c k a g e I n f o                                               %
983%                                                                             %
984%                                                                             %
985%                                                                             %
986%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
987%
988%  Method GetPackageInfo looks up or creates an info structure for the given
989%  Image__Magick reference.  If it does create a new one, the information in
990%  package_info is used to initialize it.
991%
992%  The format of the GetPackageInfo routine is:
993%
994%      struct PackageInfo *GetPackageInfo(void *reference,
995%        struct PackageInfo *package_info,ExceptionInfo *exception)
996%
997%  A description of each parameter follows:
998%
999%    o info: a structure of type info.
1000%
1001%    o exception: Return any errors or warnings in this structure.
1002%
1003*/
1004static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1005  struct PackageInfo *package_info,ExceptionInfo *exception)
1006{
1007  char
1008    message[MagickPathExtent];
1009
1010  struct PackageInfo
1011    *clone_info;
1012
1013  SV
1014    *sv;
1015
1016  (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1017    PackageName,XS_VERSION,reference);
1018  sv=perl_get_sv(message,(TRUE | 0x02));
1019  if (sv == (SV *) NULL)
1020    {
1021      ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1022        message);
1023      return(package_info);
1024    }
1025  if (SvREFCNT(sv) == 0)
1026    (void) SvREFCNT_inc(sv);
1027  if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1028    return(clone_info);
1029  clone_info=ClonePackageInfo(package_info,exception);
1030  sv_setiv(sv,PTR2IV(clone_info));
1031  return(clone_info);
1032}
1033
1034/*
1035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1036%                                                                             %
1037%                                                                             %
1038%                                                                             %
1039%   S e t A t t r i b u t e                                                   %
1040%                                                                             %
1041%                                                                             %
1042%                                                                             %
1043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1044%
1045%  SetAttribute() sets the attribute to the value in sval.  This can change
1046%  either or both of image or info.
1047%
1048%  The format of the SetAttribute routine is:
1049%
1050%      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1051%        SV *sval,ExceptionInfo *exception)
1052%
1053%  A description of each parameter follows:
1054%
1055%    o list: a list of strings.
1056%
1057%    o string: a character string.
1058%
1059*/
1060
1061static double SiPrefixToDoubleInterval(const char *string,const double interval)
1062{
1063  char
1064    *q;
1065
1066  double
1067    value;
1068
1069  value=InterpretSiPrefixValue(string,&q);
1070  if (*q == '%')
1071    value*=interval/100.0;
1072  return(value);
1073}
1074
1075static inline double StringToDouble(const char *string,char **sentinal)
1076{
1077  return(InterpretLocaleValue(string,sentinal));
1078}
1079
1080static double StringToDoubleInterval(const char *string,const double interval)
1081{
1082  char
1083    *q;
1084
1085  double
1086    value;
1087
1088  value=InterpretLocaleValue(string,&q);
1089  if (*q == '%')
1090    value*=interval/100.0;
1091  return(value);
1092}
1093
1094static inline ssize_t StringToLong(const char *value)
1095{
1096  return(strtol(value,(char **) NULL,10));
1097}
1098
1099static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1100  const char *attribute,SV *sval,ExceptionInfo *exception)
1101{
1102  GeometryInfo
1103    geometry_info;
1104
1105  long
1106    x,
1107    y;
1108
1109  PixelInfo
1110    pixel;
1111
1112  MagickStatusType
1113    flags;
1114
1115  PixelInfo
1116    *color,
1117    target_color;
1118
1119  ssize_t
1120    sp;
1121
1122  switch (*attribute)
1123  {
1124    case 'A':
1125    case 'a':
1126    {
1127      if (LocaleCompare(attribute,"adjoin") == 0)
1128        {
1129          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1130            SvPV(sval,na)) : SvIV(sval);
1131          if (sp < 0)
1132            {
1133              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1134                SvPV(sval,na));
1135              break;
1136            }
1137          if (info)
1138            info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1139          break;
1140        }
1141      if (LocaleCompare(attribute,"alpha") == 0)
1142        {
1143          sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1144            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1145          if (sp < 0)
1146            {
1147              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1148                SvPV(sval,na));
1149              break;
1150            }
1151          for ( ; image; image=image->next)
1152            (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1153              exception);
1154          break;
1155        }
1156      if (LocaleCompare(attribute,"antialias") == 0)
1157        {
1158          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1159            SvPV(sval,na)) : SvIV(sval);
1160          if (sp < 0)
1161            {
1162              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1163                SvPV(sval,na));
1164              break;
1165            }
1166          if (info)
1167            info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1168          break;
1169        }
1170      if (LocaleCompare(attribute,"area-limit") == 0)
1171        {
1172          MagickSizeType
1173            limit;
1174
1175          limit=MagickResourceInfinity;
1176          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1177            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1178              100.0);
1179          (void) SetMagickResourceLimit(AreaResource,limit);
1180          break;
1181        }
1182      if (LocaleCompare(attribute,"attenuate") == 0)
1183        {
1184          if (info)
1185            (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1186          break;
1187        }
1188      if (LocaleCompare(attribute,"authenticate") == 0)
1189        {
1190          if (info)
1191            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1192          break;
1193        }
1194      if (info)
1195        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1196      for ( ; image; image=image->next)
1197      {
1198        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1199        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1200      }
1201      break;
1202    }
1203    case 'B':
1204    case 'b':
1205    {
1206      if (LocaleCompare(attribute,"background") == 0)
1207        {
1208          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1209            exception);
1210          if (info)
1211            info->image_info->background_color=target_color;
1212          for ( ; image; image=image->next)
1213            image->background_color=target_color;
1214          break;
1215        }
1216      if (LocaleCompare(attribute,"blue-primary") == 0)
1217        {
1218          for ( ; image; image=image->next)
1219          {
1220            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1221            image->chromaticity.blue_primary.x=geometry_info.rho;
1222            image->chromaticity.blue_primary.y=geometry_info.sigma;
1223            if ((flags & SigmaValue) == 0)
1224              image->chromaticity.blue_primary.y=
1225                image->chromaticity.blue_primary.x;
1226          }
1227          break;
1228        }
1229      if (LocaleCompare(attribute,"bordercolor") == 0)
1230        {
1231          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1232            exception);
1233          if (info)
1234            info->image_info->border_color=target_color;
1235          for ( ; image; image=image->next)
1236            image->border_color=target_color;
1237          break;
1238        }
1239      if (info)
1240        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1241      for ( ; image; image=image->next)
1242      {
1243        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1244        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1245      }
1246      break;
1247    }
1248    case 'C':
1249    case 'c':
1250    {
1251      if (LocaleCompare(attribute,"cache-threshold") == 0)
1252        {
1253          (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1254            SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1255          (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1256            (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1257          break;
1258        }
1259      if (LocaleCompare(attribute,"clip-mask") == 0)
1260        {
1261          Image
1262            *clip_mask;
1263
1264          clip_mask=(Image *) NULL;
1265          if (SvPOK(sval))
1266            clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1267          for ( ; image; image=image->next)
1268            SetImageMask(image,ReadPixelMask,clip_mask,exception);
1269          break;
1270        }
1271      if (LocaleNCompare(attribute,"colormap",8) == 0)
1272        {
1273          for ( ; image; image=image->next)
1274          {
1275            int
1276              items;
1277
1278            long
1279              i;
1280
1281            if (image->storage_class == DirectClass)
1282              continue;
1283            i=0;
1284            items=sscanf(attribute,"%*[^[][%ld",&i);
1285            (void) items;
1286            if (i > (ssize_t) image->colors)
1287              i%=image->colors;
1288            if ((strchr(SvPV(sval,na),',') == 0) ||
1289                (strchr(SvPV(sval,na),')') != 0))
1290              QueryColorCompliance(SvPV(sval,na),AllCompliance,
1291                image->colormap+i,exception);
1292            else
1293              {
1294                color=image->colormap+i;
1295                pixel.red=color->red;
1296                pixel.green=color->green;
1297                pixel.blue=color->blue;
1298                flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1299                pixel.red=geometry_info.rho;
1300                pixel.green=geometry_info.sigma;
1301                pixel.blue=geometry_info.xi;
1302                color->red=ClampToQuantum(pixel.red);
1303                color->green=ClampToQuantum(pixel.green);
1304                color->blue=ClampToQuantum(pixel.blue);
1305              }
1306          }
1307          break;
1308        }
1309      if (LocaleCompare(attribute,"colorspace") == 0)
1310        {
1311          sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1312            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1313          if (sp < 0)
1314            {
1315              ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1316                SvPV(sval,na));
1317              break;
1318            }
1319          for ( ; image; image=image->next)
1320            (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
1321          break;
1322        }
1323      if (LocaleCompare(attribute,"comment") == 0)
1324        {
1325          for ( ; image; image=image->next)
1326            (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1327              info ? info->image_info : (ImageInfo *) NULL,image,
1328              SvPV(sval,na),exception),exception);
1329          break;
1330        }
1331      if (LocaleCompare(attribute,"compression") == 0)
1332        {
1333          sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1334            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1335          if (sp < 0)
1336            {
1337              ThrowPerlException(exception,OptionError,
1338                "UnrecognizedImageCompression",SvPV(sval,na));
1339              break;
1340            }
1341          if (info)
1342            info->image_info->compression=(CompressionType) sp;
1343          for ( ; image; image=image->next)
1344            image->compression=(CompressionType) sp;
1345          break;
1346        }
1347      if (info)
1348        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1349      for ( ; image; image=image->next)
1350      {
1351        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1352        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1353      }
1354      break;
1355    }
1356    case 'D':
1357    case 'd':
1358    {
1359      if (LocaleCompare(attribute,"debug") == 0)
1360        {
1361          SetLogEventMask(SvPV(sval,na));
1362          break;
1363        }
1364      if (LocaleCompare(attribute,"delay") == 0)
1365        {
1366          flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1367          for ( ; image; image=image->next)
1368          {
1369            image->delay=(size_t) floor(geometry_info.rho+0.5);
1370            if ((flags & SigmaValue) != 0)
1371              image->ticks_per_second=(ssize_t)
1372                floor(geometry_info.sigma+0.5);
1373          }
1374          break;
1375        }
1376      if (LocaleCompare(attribute,"disk-limit") == 0)
1377        {
1378          MagickSizeType
1379            limit;
1380
1381          limit=MagickResourceInfinity;
1382          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1383            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1384              100.0);
1385          (void) SetMagickResourceLimit(DiskResource,limit);
1386          break;
1387        }
1388      if (LocaleCompare(attribute,"density") == 0)
1389        {
1390          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1391            {
1392              ThrowPerlException(exception,OptionError,"MissingGeometry",
1393                SvPV(sval,na));
1394              break;
1395            }
1396          if (info)
1397            (void) CloneString(&info->image_info->density,SvPV(sval,na));
1398          for ( ; image; image=image->next)
1399          {
1400            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1401            image->resolution.x=geometry_info.rho;
1402            image->resolution.y=geometry_info.sigma;
1403            if ((flags & SigmaValue) == 0)
1404              image->resolution.y=image->resolution.x;
1405          }
1406          break;
1407        }
1408      if (LocaleCompare(attribute,"depth") == 0)
1409        {
1410          if (info)
1411            info->image_info->depth=SvIV(sval);
1412          for ( ; image; image=image->next)
1413            (void) SetImageDepth(image,SvIV(sval),exception);
1414          break;
1415        }
1416      if (LocaleCompare(attribute,"dispose") == 0)
1417        {
1418          sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1419            SvPV(sval,na)) : SvIV(sval);
1420          if (sp < 0)
1421            {
1422              ThrowPerlException(exception,OptionError,
1423                "UnrecognizedDisposeMethod",SvPV(sval,na));
1424              break;
1425            }
1426          for ( ; image; image=image->next)
1427            image->dispose=(DisposeType) sp;
1428          break;
1429        }
1430      if (LocaleCompare(attribute,"dither") == 0)
1431        {
1432          if (info)
1433            {
1434              sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1435                MagickFalse,SvPV(sval,na)) : SvIV(sval);
1436              if (sp < 0)
1437                {
1438                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
1439                    SvPV(sval,na));
1440                  break;
1441                }
1442              info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1443            }
1444          break;
1445        }
1446      if (LocaleCompare(attribute,"display") == 0)
1447        {
1448          display:
1449          if (info)
1450            (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1451          break;
1452        }
1453      if (info)
1454        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1455      for ( ; image; image=image->next)
1456      {
1457        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1458        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1459      }
1460      break;
1461    }
1462    case 'E':
1463    case 'e':
1464    {
1465      if (LocaleCompare(attribute,"endian") == 0)
1466        {
1467          sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1468            SvPV(sval,na)) : SvIV(sval);
1469          if (sp < 0)
1470            {
1471              ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1472                SvPV(sval,na));
1473              break;
1474            }
1475          if (info)
1476            info->image_info->endian=(EndianType) sp;
1477          for ( ; image; image=image->next)
1478            image->endian=(EndianType) sp;
1479          break;
1480        }
1481      if (LocaleCompare(attribute,"extract") == 0)
1482        {
1483          /*
1484            Set image extract geometry.
1485          */
1486          (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1487          break;
1488        }
1489      if (info)
1490        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1491      for ( ; image; image=image->next)
1492      {
1493        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1494        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1495      }
1496      break;
1497    }
1498    case 'F':
1499    case 'f':
1500    {
1501      if (LocaleCompare(attribute,"filename") == 0)
1502        {
1503          if (info)
1504            (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1505              MagickPathExtent);
1506          for ( ; image; image=image->next)
1507            (void) CopyMagickString(image->filename,SvPV(sval,na),
1508              MagickPathExtent);
1509          break;
1510        }
1511      if (LocaleCompare(attribute,"file") == 0)
1512        {
1513          FILE
1514            *file;
1515
1516          PerlIO
1517            *io_info;
1518
1519          if (info == (struct PackageInfo *) NULL)
1520            break;
1521          io_info=IoIFP(sv_2io(sval));
1522          if (io_info == (PerlIO *) NULL)
1523            {
1524              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1525                PackageName);
1526              break;
1527            }
1528          file=PerlIO_findFILE(io_info);
1529          if (file == (FILE *) NULL)
1530            {
1531              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1532                PackageName);
1533              break;
1534            }
1535          SetImageInfoFile(info->image_info,file);
1536          break;
1537        }
1538      if (LocaleCompare(attribute,"fill") == 0)
1539        {
1540          if (info)
1541            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1542          break;
1543        }
1544      if (LocaleCompare(attribute,"font") == 0)
1545        {
1546          if (info)
1547            (void) CloneString(&info->image_info->font,SvPV(sval,na));
1548          break;
1549        }
1550      if (LocaleCompare(attribute,"foreground") == 0)
1551        break;
1552      if (LocaleCompare(attribute,"fuzz") == 0)
1553        {
1554          if (info)
1555            info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1556              QuantumRange+1.0);
1557          for ( ; image; image=image->next)
1558            image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1559              QuantumRange+1.0);
1560          break;
1561        }
1562      if (info)
1563        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1564      for ( ; image; image=image->next)
1565      {
1566        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1567        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1568      }
1569      break;
1570    }
1571    case 'G':
1572    case 'g':
1573    {
1574      if (LocaleCompare(attribute,"gamma") == 0)
1575        {
1576          for ( ; image; image=image->next)
1577            image->gamma=SvNV(sval);
1578          break;
1579        }
1580      if (LocaleCompare(attribute,"gravity") == 0)
1581        {
1582          sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1583            SvPV(sval,na)) : SvIV(sval);
1584          if (sp < 0)
1585            {
1586              ThrowPerlException(exception,OptionError,
1587                "UnrecognizedGravityType",SvPV(sval,na));
1588              break;
1589            }
1590          if (info)
1591            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1592          for ( ; image; image=image->next)
1593            image->gravity=(GravityType) sp;
1594          break;
1595        }
1596      if (LocaleCompare(attribute,"green-primary") == 0)
1597        {
1598          for ( ; image; image=image->next)
1599          {
1600            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1601            image->chromaticity.green_primary.x=geometry_info.rho;
1602            image->chromaticity.green_primary.y=geometry_info.sigma;
1603            if ((flags & SigmaValue) == 0)
1604              image->chromaticity.green_primary.y=
1605                image->chromaticity.green_primary.x;
1606          }
1607          break;
1608        }
1609      if (info)
1610        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1611      for ( ; image; image=image->next)
1612      {
1613        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1614        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1615      }
1616      break;
1617    }
1618    case 'I':
1619    case 'i':
1620    {
1621      if (LocaleNCompare(attribute,"index",5) == 0)
1622        {
1623          int
1624            items;
1625
1626          long
1627            index;
1628
1629          register Quantum
1630            *q;
1631
1632          CacheView
1633            *image_view;
1634
1635          for ( ; image; image=image->next)
1636          {
1637            if (image->storage_class != PseudoClass)
1638              continue;
1639            x=0;
1640            y=0;
1641            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1642            (void) items;
1643            image_view=AcquireAuthenticCacheView(image,exception);
1644            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1645            if (q != (Quantum *) NULL)
1646              {
1647                items=sscanf(SvPV(sval,na),"%ld",&index);
1648                if ((index >= 0) && (index < (ssize_t) image->colors))
1649                  SetPixelIndex(image,index,q);
1650                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1651              }
1652            image_view=DestroyCacheView(image_view);
1653          }
1654          break;
1655        }
1656      if (LocaleCompare(attribute,"iterations") == 0)
1657        {
1658  iterations:
1659          for ( ; image; image=image->next)
1660            image->iterations=SvIV(sval);
1661          break;
1662        }
1663      if (LocaleCompare(attribute,"interlace") == 0)
1664        {
1665          sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1666            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1667          if (sp < 0)
1668            {
1669              ThrowPerlException(exception,OptionError,
1670                "UnrecognizedInterlaceType",SvPV(sval,na));
1671              break;
1672            }
1673          if (info)
1674            info->image_info->interlace=(InterlaceType) sp;
1675          for ( ; image; image=image->next)
1676            image->interlace=(InterlaceType) sp;
1677          break;
1678        }
1679      if (info)
1680        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1681      for ( ; image; image=image->next)
1682        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1683      break;
1684    }
1685    case 'L':
1686    case 'l':
1687    {
1688      if (LocaleCompare(attribute,"label") == 0)
1689        {
1690          for ( ; image; image=image->next)
1691            (void) SetImageProperty(image,"label",InterpretImageProperties(
1692              info ? info->image_info : (ImageInfo *) NULL,image,
1693              SvPV(sval,na),exception),exception);
1694          break;
1695        }
1696      if (LocaleCompare(attribute,"loop") == 0)
1697        goto iterations;
1698      if (info)
1699        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1700      for ( ; image; image=image->next)
1701      {
1702        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1703        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1704      }
1705      break;
1706    }
1707    case 'M':
1708    case 'm':
1709    {
1710      if (LocaleCompare(attribute,"magick") == 0)
1711        {
1712          if (info)
1713            (void) FormatLocaleString(info->image_info->filename,
1714              MagickPathExtent,"%s:",SvPV(sval,na));
1715          for ( ; image; image=image->next)
1716            (void) CopyMagickString(image->magick,SvPV(sval,na),
1717              MagickPathExtent);
1718          break;
1719        }
1720      if (LocaleCompare(attribute,"map-limit") == 0)
1721        {
1722          MagickSizeType
1723            limit;
1724
1725          limit=MagickResourceInfinity;
1726          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1727            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1728              100.0);
1729          (void) SetMagickResourceLimit(MapResource,limit);
1730          break;
1731        }
1732      if (LocaleCompare(attribute,"mask") == 0)
1733        {
1734          Image
1735            *mask;
1736
1737          mask=(Image *) NULL;
1738          if (SvPOK(sval))
1739            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1740          for ( ; image; image=image->next)
1741            SetImageMask(image,ReadPixelMask,mask,exception);
1742          break;
1743        }
1744      if (LocaleCompare(attribute,"mattecolor") == 0)
1745        {
1746          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1747            exception);
1748          if (info)
1749            info->image_info->alpha_color=target_color;
1750          for ( ; image; image=image->next)
1751            image->alpha_color=target_color;
1752          break;
1753        }
1754      if (LocaleCompare(attribute,"matte") == 0)
1755        {
1756          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1757            SvPV(sval,na)) : SvIV(sval);
1758          if (sp < 0)
1759            {
1760              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1761                SvPV(sval,na));
1762              break;
1763            }
1764          for ( ; image; image=image->next)
1765            image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1766          break;
1767        }
1768      if (LocaleCompare(attribute,"memory-limit") == 0)
1769        {
1770          MagickSizeType
1771            limit;
1772
1773          limit=MagickResourceInfinity;
1774          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1775            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1776              100.0);
1777          (void) SetMagickResourceLimit(MemoryResource,limit);
1778          break;
1779        }
1780      if (LocaleCompare(attribute,"monochrome") == 0)
1781        {
1782          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1783            SvPV(sval,na)) : SvIV(sval);
1784          if (sp < 0)
1785            {
1786              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1787                SvPV(sval,na));
1788              break;
1789            }
1790          if (info)
1791            info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1792          for ( ; image; image=image->next)
1793            (void) SetImageType(image,BilevelType,exception);
1794          break;
1795        }
1796      if (info)
1797        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1798      for ( ; image; image=image->next)
1799      {
1800        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1801        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1802      }
1803      break;
1804    }
1805    case 'O':
1806    case 'o':
1807    {
1808      if (LocaleCompare(attribute,"option") == 0)
1809        {
1810          if (info)
1811            DefineImageOption(info->image_info,SvPV(sval,na));
1812          break;
1813        }
1814      if (LocaleCompare(attribute,"orientation") == 0)
1815        {
1816          sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1817            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1818          if (sp < 0)
1819            {
1820              ThrowPerlException(exception,OptionError,
1821                "UnrecognizedOrientationType",SvPV(sval,na));
1822              break;
1823            }
1824          if (info)
1825            info->image_info->orientation=(OrientationType) sp;
1826          for ( ; image; image=image->next)
1827            image->orientation=(OrientationType) sp;
1828          break;
1829        }
1830      if (info)
1831        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1832      for ( ; image; image=image->next)
1833      {
1834        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1835        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1836      }
1837      break;
1838    }
1839    case 'P':
1840    case 'p':
1841    {
1842      if (LocaleCompare(attribute,"page") == 0)
1843        {
1844          char
1845            *geometry;
1846
1847          geometry=GetPageGeometry(SvPV(sval,na));
1848          if (info)
1849            (void) CloneString(&info->image_info->page,geometry);
1850          for ( ; image; image=image->next)
1851            (void) ParsePageGeometry(image,geometry,&image->page,exception);
1852          geometry=(char *) RelinquishMagickMemory(geometry);
1853          break;
1854        }
1855      if (LocaleNCompare(attribute,"pixel",5) == 0)
1856        {
1857          int
1858            items;
1859
1860          PixelInfo
1861            pixel;
1862
1863          register Quantum
1864            *q;
1865
1866          CacheView
1867            *image_view;
1868
1869          for ( ; image; image=image->next)
1870          {
1871            if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1872              break;
1873            x=0;
1874            y=0;
1875            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1876            (void) items;
1877            image_view=AcquireVirtualCacheView(image,exception);
1878            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1879            if (q != (Quantum *) NULL)
1880              {
1881                if ((strchr(SvPV(sval,na),',') == 0) ||
1882                    (strchr(SvPV(sval,na),')') != 0))
1883                  QueryColorCompliance(SvPV(sval,na),AllCompliance,
1884                    &pixel,exception);
1885                else
1886                  {
1887                    GetPixelInfo(image,&pixel);
1888                    flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1889                    pixel.red=geometry_info.rho;
1890                    if ((flags & SigmaValue) != 0)
1891                      pixel.green=geometry_info.sigma;
1892                    if ((flags & XiValue) != 0)
1893                      pixel.blue=geometry_info.xi;
1894                    if ((flags & PsiValue) != 0)
1895                      pixel.alpha=geometry_info.psi;
1896                    if ((flags & ChiValue) != 0)
1897                      pixel.black=geometry_info.chi;
1898                  }
1899                SetPixelRed(image,ClampToQuantum(pixel.red),q);
1900                SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1901                SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1902                if (image->colorspace == CMYKColorspace)
1903                  SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1904                SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1905                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1906              }
1907            image_view=DestroyCacheView(image_view);
1908          }
1909          break;
1910        }
1911      if (LocaleCompare(attribute,"pointsize") == 0)
1912        {
1913          if (info)
1914            {
1915              (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1916              info->image_info->pointsize=geometry_info.rho;
1917            }
1918          break;
1919        }
1920      if (info)
1921        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1922      for ( ; image; image=image->next)
1923      {
1924        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1925        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1926      }
1927      break;
1928    }
1929    case 'Q':
1930    case 'q':
1931    {
1932      if (LocaleCompare(attribute,"quality") == 0)
1933        {
1934          if (info)
1935            info->image_info->quality=SvIV(sval);
1936          for ( ; image; image=image->next)
1937            image->quality=SvIV(sval);
1938          break;
1939        }
1940      if (info)
1941        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1942      for ( ; image; image=image->next)
1943      {
1944        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1945        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1946      }
1947      break;
1948    }
1949    case 'R':
1950    case 'r':
1951    {
1952      if (LocaleCompare(attribute,"read-mask") == 0)
1953        {
1954          Image
1955            *mask;
1956
1957          mask=(Image *) NULL;
1958          if (SvPOK(sval))
1959            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1960          for ( ; image; image=image->next)
1961            SetImageMask(image,ReadPixelMask,mask,exception);
1962          break;
1963        }
1964      if (LocaleCompare(attribute,"red-primary") == 0)
1965        {
1966          for ( ; image; image=image->next)
1967          {
1968            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1969            image->chromaticity.red_primary.x=geometry_info.rho;
1970            image->chromaticity.red_primary.y=geometry_info.sigma;
1971            if ((flags & SigmaValue) == 0)
1972              image->chromaticity.red_primary.y=
1973                image->chromaticity.red_primary.x;
1974          }
1975          break;
1976        }
1977      if (LocaleCompare(attribute,"render") == 0)
1978        {
1979          sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1980            SvPV(sval,na)) : SvIV(sval);
1981          if (sp < 0)
1982            {
1983              ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1984                SvPV(sval,na));
1985              break;
1986            }
1987         for ( ; image; image=image->next)
1988           image->rendering_intent=(RenderingIntent) sp;
1989         break;
1990       }
1991      if (LocaleCompare(attribute,"repage") == 0)
1992        {
1993          RectangleInfo
1994            geometry;
1995
1996          for ( ; image; image=image->next)
1997          {
1998            flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1999            if ((flags & WidthValue) != 0)
2000              {
2001                if ((flags & HeightValue) == 0)
2002                  geometry.height=geometry.width;
2003                image->page.width=geometry.width;
2004                image->page.height=geometry.height;
2005              }
2006            if ((flags & AspectValue) != 0)
2007              {
2008                if ((flags & XValue) != 0)
2009                  image->page.x+=geometry.x;
2010                if ((flags & YValue) != 0)
2011                  image->page.y+=geometry.y;
2012              }
2013            else
2014              {
2015                if ((flags & XValue) != 0)
2016                  {
2017                    image->page.x=geometry.x;
2018                    if (((flags & WidthValue) != 0) && (geometry.x > 0))
2019                      image->page.width=image->columns+geometry.x;
2020                  }
2021                if ((flags & YValue) != 0)
2022                  {
2023                    image->page.y=geometry.y;
2024                    if (((flags & HeightValue) != 0) && (geometry.y > 0))
2025                      image->page.height=image->rows+geometry.y;
2026                  }
2027              }
2028          }
2029          break;
2030        }
2031      if (info)
2032        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2033      for ( ; image; image=image->next)
2034      {
2035        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2036        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2037      }
2038      break;
2039    }
2040    case 'S':
2041    case 's':
2042    {
2043      if (LocaleCompare(attribute,"sampling-factor") == 0)
2044        {
2045          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2046            {
2047              ThrowPerlException(exception,OptionError,"MissingGeometry",
2048                SvPV(sval,na));
2049              break;
2050            }
2051          if (info)
2052            (void) CloneString(&info->image_info->sampling_factor,
2053              SvPV(sval,na));
2054          break;
2055        }
2056      if (LocaleCompare(attribute,"scene") == 0)
2057        {
2058          for ( ; image; image=image->next)
2059            image->scene=SvIV(sval);
2060          break;
2061        }
2062      if (LocaleCompare(attribute,"server") == 0)
2063        goto display;
2064      if (LocaleCompare(attribute,"size") == 0)
2065        {
2066          if (info)
2067            {
2068              if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2069                {
2070                  ThrowPerlException(exception,OptionError,"MissingGeometry",
2071                    SvPV(sval,na));
2072                  break;
2073                }
2074              (void) CloneString(&info->image_info->size,SvPV(sval,na));
2075            }
2076          break;
2077        }
2078      if (LocaleCompare(attribute,"stroke") == 0)
2079        {
2080          if (info)
2081            (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2082          break;
2083        }
2084      if (info)
2085        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2086      for ( ; image; image=image->next)
2087      {
2088        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2089        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2090      }
2091      break;
2092    }
2093    case 'T':
2094    case 't':
2095    {
2096      if (LocaleCompare(attribute,"texture") == 0)
2097        {
2098          if (info)
2099            (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2100          break;
2101        }
2102      if (LocaleCompare(attribute,"thread-limit") == 0)
2103        {
2104          MagickSizeType
2105            limit;
2106
2107          limit=MagickResourceInfinity;
2108          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2109            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2110              100.0);
2111          (void) SetMagickResourceLimit(ThreadResource,limit);
2112          break;
2113        }
2114      if (LocaleCompare(attribute,"tile-offset") == 0)
2115        {
2116          char
2117            *geometry;
2118
2119          geometry=GetPageGeometry(SvPV(sval,na));
2120          if (info)
2121            (void) CloneString(&info->image_info->page,geometry);
2122          for ( ; image; image=image->next)
2123            (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2124              exception);
2125          geometry=(char *) RelinquishMagickMemory(geometry);
2126          break;
2127        }
2128      if (LocaleCompare(attribute,"time-limit") == 0)
2129        {
2130          MagickSizeType
2131            limit;
2132
2133          limit=MagickResourceInfinity;
2134          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2135            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2136              100.0);
2137          (void) SetMagickResourceLimit(TimeResource,limit);
2138          break;
2139        }
2140      if (LocaleCompare(attribute,"transparent-color") == 0)
2141        {
2142          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2143            exception);
2144          if (info)
2145            info->image_info->transparent_color=target_color;
2146          for ( ; image; image=image->next)
2147            image->transparent_color=target_color;
2148          break;
2149        }
2150      if (LocaleCompare(attribute,"type") == 0)
2151        {
2152          sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2153            SvPV(sval,na)) : SvIV(sval);
2154          if (sp < 0)
2155            {
2156              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2157                SvPV(sval,na));
2158              break;
2159            }
2160          if (info)
2161            info->image_info->type=(ImageType) sp;
2162          for ( ; image; image=image->next)
2163            SetImageType(image,(ImageType) sp,exception);
2164          break;
2165        }
2166      if (info)
2167        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2168      for ( ; image; image=image->next)
2169      {
2170        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2171        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2172      }
2173      break;
2174    }
2175    case 'U':
2176    case 'u':
2177    {
2178      if (LocaleCompare(attribute,"units") == 0)
2179        {
2180          sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2181            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2182          if (sp < 0)
2183            {
2184              ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2185                SvPV(sval,na));
2186              break;
2187            }
2188          if (info)
2189            info->image_info->units=(ResolutionType) sp;
2190          for ( ; image; image=image->next)
2191          {
2192            ResolutionType
2193              units;
2194
2195            units=(ResolutionType) sp;
2196            if (image->units != units)
2197              switch (image->units)
2198              {
2199                case UndefinedResolution:
2200                case PixelsPerInchResolution:
2201                {
2202                  if (units == PixelsPerCentimeterResolution)
2203                    {
2204                      image->resolution.x*=2.54;
2205                      image->resolution.y*=2.54;
2206                    }
2207                  break;
2208                }
2209                case PixelsPerCentimeterResolution:
2210                {
2211                  if (units == PixelsPerInchResolution)
2212                    {
2213                      image->resolution.x/=2.54;
2214                      image->resolution.y/=2.54;
2215                    }
2216                  break;
2217                }
2218              }
2219            image->units=units;
2220          }
2221          break;
2222        }
2223      if (info)
2224        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2225      for ( ; image; image=image->next)
2226      {
2227        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2228        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2229      }
2230      break;
2231    }
2232    case 'V':
2233    case 'v':
2234    {
2235      if (LocaleCompare(attribute,"verbose") == 0)
2236        {
2237          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2238            SvPV(sval,na)) : SvIV(sval);
2239          if (sp < 0)
2240            {
2241              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2242                SvPV(sval,na));
2243              break;
2244            }
2245          if (info)
2246            info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2247          break;
2248        }
2249      if (LocaleCompare(attribute,"virtual-pixel") == 0)
2250        {
2251          sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2252            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2253          if (sp < 0)
2254            {
2255              ThrowPerlException(exception,OptionError,
2256                "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2257              break;
2258            }
2259          for ( ; image; image=image->next)
2260            SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2261          break;
2262        }
2263      if (info)
2264        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2265      for ( ; image; image=image->next)
2266      {
2267        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2268        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2269      }
2270      break;
2271    }
2272    case 'W':
2273    case 'w':
2274    {
2275      if (LocaleCompare(attribute,"white-point") == 0)
2276        {
2277          for ( ; image; image=image->next)
2278          {
2279            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2280            image->chromaticity.white_point.x=geometry_info.rho;
2281            image->chromaticity.white_point.y=geometry_info.sigma;
2282            if ((flags & SigmaValue) == 0)
2283              image->chromaticity.white_point.y=
2284                image->chromaticity.white_point.x;
2285          }
2286          break;
2287        }
2288      if (LocaleCompare(attribute,"write-mask") == 0)
2289        {
2290          Image
2291            *mask;
2292
2293          mask=(Image *) NULL;
2294          if (SvPOK(sval))
2295            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2296          for ( ; image; image=image->next)
2297            SetImageMask(image,WritePixelMask,mask,exception);
2298          break;
2299        }
2300      if (info)
2301        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2302      for ( ; image; image=image->next)
2303      {
2304        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2305        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2306      }
2307      break;
2308    }
2309    default:
2310    {
2311      if (info)
2312        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2313      for ( ; image; image=image->next)
2314      {
2315        (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2316        (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2317      }
2318      break;
2319    }
2320  }
2321}
2322
2323/*
2324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325%                                                                             %
2326%                                                                             %
2327%                                                                             %
2328%   S e t u p L i s t                                                         %
2329%                                                                             %
2330%                                                                             %
2331%                                                                             %
2332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333%
2334%  Method SetupList returns the list of all the images linked by their
2335%  image->next and image->previous link lists for use with ImageMagick.  If
2336%  info is non-NULL, an info structure is returned in *info.  If
2337%  reference_vector is non-NULL,an array of SV* are returned in
2338%  *reference_vector.  Reference_vector is used when the images are going to be
2339%  replaced with new Image*'s.
2340%
2341%  The format of the SetupList routine is:
2342%
2343%      Image *SetupList(SV *reference,struct PackageInfo **info,
2344%        SV ***reference_vector,ExceptionInfo *exception)
2345%
2346%  A description of each parameter follows:
2347%
2348%    o list: a list of strings.
2349%
2350%    o string: a character string.
2351%
2352%    o exception: Return any errors or warnings in this structure.
2353%
2354*/
2355static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2356  SV ***reference_vector,ExceptionInfo *exception)
2357{
2358  Image
2359    *image;
2360
2361  ssize_t
2362    current,
2363    last;
2364
2365  if (reference_vector)
2366    *reference_vector=NULL;
2367  if (info)
2368    *info=NULL;
2369  current=0;
2370  last=0;
2371  image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2372  if (info && (SvTYPE(reference) == SVt_PVAV))
2373    *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2374      exception);
2375  return(image);
2376}
2377
2378/*
2379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2380%                                                                             %
2381%                                                                             %
2382%                                                                             %
2383%   s t r E Q c a s e                                                         %
2384%                                                                             %
2385%                                                                             %
2386%                                                                             %
2387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2388%
2389%  strEQcase() compares two strings and returns 0 if they are the
2390%  same or if the second string runs out first.  The comparison is case
2391%  insensitive.
2392%
2393%  The format of the strEQcase routine is:
2394%
2395%      ssize_t strEQcase(const char *p,const char *q)
2396%
2397%  A description of each parameter follows:
2398%
2399%    o p: a character string.
2400%
2401%    o q: a character string.
2402%
2403%
2404*/
2405static ssize_t strEQcase(const char *p,const char *q)
2406{
2407  char
2408    c;
2409
2410  register ssize_t
2411    i;
2412
2413  for (i=0 ; (c=(*q)) != 0; i++)
2414  {
2415    if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2416        (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2417      return(0);
2418    p++;
2419    q++;
2420  }
2421  return(((*q == 0) && (*p == 0)) ? i : 0);
2422}
2423
2424/*
2425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2426%                                                                             %
2427%                                                                             %
2428%                                                                             %
2429%   I m a g e : : M a g i c k                                                 %
2430%                                                                             %
2431%                                                                             %
2432%                                                                             %
2433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2434%
2435%
2436*/
2437MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2438
2439PROTOTYPES: ENABLE
2440
2441BOOT:
2442  MagickCoreGenesis("PerlMagick",MagickFalse);
2443  SetWarningHandler(NULL);
2444  SetErrorHandler(NULL);
2445  magick_registry=NewSplayTree((int (*)(const void *,const void *))
2446    NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2447
2448void
2449UNLOAD()
2450  PPCODE:
2451  {
2452    if (magick_registry != (SplayTreeInfo *) NULL)
2453      magick_registry=DestroySplayTree(magick_registry);
2454    MagickCoreTerminus();
2455  }
2456
2457double
2458constant(name,argument)
2459  char *name
2460  ssize_t argument
2461
2462#
2463###############################################################################
2464#                                                                             #
2465#                                                                             #
2466#                                                                             #
2467#   A n i m a t e                                                             #
2468#                                                                             #
2469#                                                                             #
2470#                                                                             #
2471###############################################################################
2472#
2473#
2474void
2475Animate(ref,...)
2476  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2477  ALIAS:
2478    AnimateImage  = 1
2479    animate       = 2
2480    animateimage  = 3
2481  PPCODE:
2482  {
2483    ExceptionInfo
2484      *exception;
2485
2486    Image
2487      *image;
2488
2489    register ssize_t
2490      i;
2491
2492    struct PackageInfo
2493      *info,
2494      *package_info;
2495
2496    SV
2497      *perl_exception,
2498      *reference;
2499
2500    PERL_UNUSED_VAR(ref);
2501    PERL_UNUSED_VAR(ix);
2502    exception=AcquireExceptionInfo();
2503    perl_exception=newSVpv("",0);
2504    package_info=(struct PackageInfo *) NULL;
2505    if (sv_isobject(ST(0)) == 0)
2506      {
2507        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2508          PackageName);
2509        goto PerlException;
2510      }
2511    reference=SvRV(ST(0));
2512    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2513    if (image == (Image *) NULL)
2514      {
2515        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2516          PackageName);
2517        goto PerlException;
2518      }
2519    package_info=ClonePackageInfo(info,exception);
2520    if (items == 2)
2521      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2522    else
2523      if (items > 2)
2524        for (i=2; i < items; i+=2)
2525          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2526            exception);
2527    (void) AnimateImages(package_info->image_info,image,exception);
2528    (void) CatchImageException(image);
2529
2530  PerlException:
2531    if (package_info != (struct PackageInfo *) NULL)
2532      DestroyPackageInfo(package_info);
2533    InheritPerlException(exception,perl_exception);
2534    exception=DestroyExceptionInfo(exception);
2535    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2536    SvPOK_on(perl_exception);
2537    ST(0)=sv_2mortal(perl_exception);
2538    XSRETURN(1);
2539  }
2540
2541#
2542###############################################################################
2543#                                                                             #
2544#                                                                             #
2545#                                                                             #
2546#   A p p e n d                                                               #
2547#                                                                             #
2548#                                                                             #
2549#                                                                             #
2550###############################################################################
2551#
2552#
2553void
2554Append(ref,...)
2555  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2556  ALIAS:
2557    AppendImage  = 1
2558    append       = 2
2559    appendimage  = 3
2560  PPCODE:
2561  {
2562    AV
2563      *av;
2564
2565    char
2566      *attribute;
2567
2568    ExceptionInfo
2569      *exception;
2570
2571    HV
2572      *hv;
2573
2574    Image
2575      *image;
2576
2577    register ssize_t
2578      i;
2579
2580    ssize_t
2581      stack;
2582
2583    struct PackageInfo
2584      *info;
2585
2586    SV
2587      *av_reference,
2588      *perl_exception,
2589      *reference,
2590      *rv,
2591      *sv;
2592
2593    PERL_UNUSED_VAR(ref);
2594    PERL_UNUSED_VAR(ix);
2595    exception=AcquireExceptionInfo();
2596    perl_exception=newSVpv("",0);
2597    sv=NULL;
2598    attribute=NULL;
2599    av=NULL;
2600    if (sv_isobject(ST(0)) == 0)
2601      {
2602        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2603          PackageName);
2604        goto PerlException;
2605      }
2606    reference=SvRV(ST(0));
2607    hv=SvSTASH(reference);
2608    av=newAV();
2609    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2610    SvREFCNT_dec(av);
2611    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2612    if (image == (Image *) NULL)
2613      {
2614        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2615          PackageName);
2616        goto PerlException;
2617      }
2618    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2619    /*
2620      Get options.
2621    */
2622    stack=MagickTrue;
2623    for (i=2; i < items; i+=2)
2624    {
2625      attribute=(char *) SvPV(ST(i-1),na);
2626      switch (*attribute)
2627      {
2628        case 'S':
2629        case 's':
2630        {
2631          if (LocaleCompare(attribute,"stack") == 0)
2632            {
2633              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2634                SvPV(ST(i),na));
2635              if (stack < 0)
2636                {
2637                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
2638                    SvPV(ST(i),na));
2639                  return;
2640                }
2641              break;
2642            }
2643          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2644            attribute);
2645          break;
2646        }
2647        default:
2648        {
2649          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2650            attribute);
2651          break;
2652        }
2653      }
2654    }
2655    image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2656    if (image == (Image *) NULL)
2657      goto PerlException;
2658    for ( ; image; image=image->next)
2659    {
2660      AddImageToRegistry(sv,image);
2661      rv=newRV(sv);
2662      av_push(av,sv_bless(rv,hv));
2663      SvREFCNT_dec(sv);
2664    }
2665    exception=DestroyExceptionInfo(exception);
2666    ST(0)=av_reference;
2667    SvREFCNT_dec(perl_exception);
2668    XSRETURN(1);
2669
2670  PerlException:
2671    InheritPerlException(exception,perl_exception);
2672    exception=DestroyExceptionInfo(exception);
2673    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2674    SvPOK_on(perl_exception);
2675    ST(0)=sv_2mortal(perl_exception);
2676    XSRETURN(1);
2677  }
2678
2679#
2680###############################################################################
2681#                                                                             #
2682#                                                                             #
2683#                                                                             #
2684#   A v e r a g e                                                             #
2685#                                                                             #
2686#                                                                             #
2687#                                                                             #
2688###############################################################################
2689#
2690#
2691void
2692Average(ref)
2693  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2694  ALIAS:
2695    AverageImage   = 1
2696    average        = 2
2697    averageimage   = 3
2698  PPCODE:
2699  {
2700    AV
2701      *av;
2702
2703    char
2704      *p;
2705
2706    ExceptionInfo
2707      *exception;
2708
2709    HV
2710      *hv;
2711
2712    Image
2713      *image;
2714
2715    struct PackageInfo
2716      *info;
2717
2718    SV
2719      *perl_exception,
2720      *reference,
2721      *rv,
2722      *sv;
2723
2724    PERL_UNUSED_VAR(ref);
2725    PERL_UNUSED_VAR(ix);
2726    exception=AcquireExceptionInfo();
2727    perl_exception=newSVpv("",0);
2728    sv=NULL;
2729    if (sv_isobject(ST(0)) == 0)
2730      {
2731        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2732          PackageName);
2733        goto PerlException;
2734      }
2735    reference=SvRV(ST(0));
2736    hv=SvSTASH(reference);
2737    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2738    if (image == (Image *) NULL)
2739      {
2740        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2741          PackageName);
2742        goto PerlException;
2743      }
2744    image=EvaluateImages(image,MeanEvaluateOperator,exception);
2745    if (image == (Image *) NULL)
2746      goto PerlException;
2747    /*
2748      Create blessed Perl array for the returned image.
2749    */
2750    av=newAV();
2751    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2752    SvREFCNT_dec(av);
2753    AddImageToRegistry(sv,image);
2754    rv=newRV(sv);
2755    av_push(av,sv_bless(rv,hv));
2756    SvREFCNT_dec(sv);
2757    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2758    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2759      "average-%.*s",(int) (MagickPathExtent-9),
2760      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2761    (void) CopyMagickString(image->filename,info->image_info->filename,
2762      MagickPathExtent);
2763    SetImageInfo(info->image_info,0,exception);
2764    exception=DestroyExceptionInfo(exception);
2765    SvREFCNT_dec(perl_exception);
2766    XSRETURN(1);
2767
2768  PerlException:
2769    InheritPerlException(exception,perl_exception);
2770    exception=DestroyExceptionInfo(exception);
2771    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2772    SvPOK_on(perl_exception);
2773    ST(0)=sv_2mortal(perl_exception);
2774    XSRETURN(1);
2775  }
2776
2777#
2778###############################################################################
2779#                                                                             #
2780#                                                                             #
2781#                                                                             #
2782#   B l o b T o I m a g e                                                     #
2783#                                                                             #
2784#                                                                             #
2785#                                                                             #
2786###############################################################################
2787#
2788#
2789void
2790BlobToImage(ref,...)
2791  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2792  ALIAS:
2793    BlobToImage  = 1
2794    blobtoimage  = 2
2795    blobto       = 3
2796  PPCODE:
2797  {
2798    AV
2799      *av;
2800
2801    char
2802      **keep,
2803      **list;
2804
2805    ExceptionInfo
2806      *exception;
2807
2808    HV
2809      *hv;
2810
2811    Image
2812      *image;
2813
2814    register char
2815      **p;
2816
2817    register ssize_t
2818      i;
2819
2820    ssize_t
2821      ac,
2822      n,
2823      number_images;
2824
2825    STRLEN
2826      *length;
2827
2828    struct PackageInfo
2829      *info;
2830
2831    SV
2832      *perl_exception,
2833      *reference,
2834      *rv,
2835      *sv;
2836
2837    PERL_UNUSED_VAR(ref);
2838    PERL_UNUSED_VAR(ix);
2839    exception=AcquireExceptionInfo();
2840    perl_exception=newSVpv("",0);
2841    sv=NULL;
2842    number_images=0;
2843    ac=(items < 2) ? 1 : items-1;
2844    length=(STRLEN *) NULL;
2845    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2846    if (list == (char **) NULL)
2847      {
2848        ThrowPerlException(exception,ResourceLimitError,
2849          "MemoryAllocationFailed",PackageName);
2850        goto PerlException;
2851      }
2852    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2853    if (length == (STRLEN *) NULL)
2854      {
2855        ThrowPerlException(exception,ResourceLimitError,
2856          "MemoryAllocationFailed",PackageName);
2857        goto PerlException;
2858      }
2859    if (sv_isobject(ST(0)) == 0)
2860      {
2861        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2862          PackageName);
2863        goto PerlException;
2864      }
2865    reference=SvRV(ST(0));
2866    hv=SvSTASH(reference);
2867    if (SvTYPE(reference) != SVt_PVAV)
2868      {
2869        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2870          PackageName);
2871        goto PerlException;
2872      }
2873    av=(AV *) reference;
2874    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2875      exception);
2876    n=1;
2877    if (items <= 1)
2878      {
2879        ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2880        goto PerlException;
2881      }
2882    for (n=0, i=0; i < ac; i++)
2883    {
2884      list[n]=(char *) (SvPV(ST(i+1),length[n]));
2885      if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2886        {
2887          list[n]=(char *) (SvPV(ST(i+2),length[n]));
2888          continue;
2889        }
2890      n++;
2891    }
2892    list[n]=(char *) NULL;
2893    keep=list;
2894    for (i=number_images=0; i < n; i++)
2895    {
2896      image=BlobToImage(info->image_info,list[i],length[i],exception);
2897      if (image == (Image *) NULL)
2898        break;
2899      for ( ; image; image=image->next)
2900      {
2901        AddImageToRegistry(sv,image);
2902        rv=newRV(sv);
2903        av_push(av,sv_bless(rv,hv));
2904        SvREFCNT_dec(sv);
2905        number_images++;
2906      }
2907    }
2908    /*
2909      Free resources.
2910    */
2911    for (i=0; i < n; i++)
2912      if (list[i] != (char *) NULL)
2913        for (p=keep; list[i] != *p++; )
2914          if (*p == (char *) NULL)
2915            {
2916              list[i]=(char *) RelinquishMagickMemory(list[i]);
2917              break;
2918            }
2919
2920  PerlException:
2921    if (list)
2922      list=(char **) RelinquishMagickMemory(list);
2923    if (length)
2924      length=(STRLEN *) RelinquishMagickMemory(length);
2925    InheritPerlException(exception,perl_exception);
2926    exception=DestroyExceptionInfo(exception);
2927    sv_setiv(perl_exception,(IV) number_images);
2928    SvPOK_on(perl_exception);
2929    ST(0)=sv_2mortal(perl_exception);
2930    XSRETURN(1);
2931  }
2932
2933#
2934###############################################################################
2935#                                                                             #
2936#                                                                             #
2937#                                                                             #
2938#   C h a n n e l F x                                                         #
2939#                                                                             #
2940#                                                                             #
2941#                                                                             #
2942###############################################################################
2943#
2944#
2945void
2946ChannelFx(ref,...)
2947  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2948  ALIAS:
2949    ChannelFxImage  = 1
2950    channelfx       = 2
2951    channelfximage  = 3
2952  PPCODE:
2953  {
2954    AV
2955      *av;
2956
2957    char
2958      *attribute,
2959      expression[MagickPathExtent];
2960
2961    ChannelType
2962      channel,
2963      channel_mask;
2964
2965    ExceptionInfo
2966      *exception;
2967
2968    HV
2969      *hv;
2970
2971    Image
2972      *image;
2973
2974    register ssize_t
2975      i;
2976
2977    struct PackageInfo
2978      *info;
2979
2980    SV
2981      *av_reference,
2982      *perl_exception,
2983      *reference,
2984      *rv,
2985      *sv;
2986
2987    PERL_UNUSED_VAR(ref);
2988    PERL_UNUSED_VAR(ix);
2989    exception=AcquireExceptionInfo();
2990    perl_exception=newSVpv("",0);
2991    sv=NULL;
2992    attribute=NULL;
2993    av=NULL;
2994    if (sv_isobject(ST(0)) == 0)
2995      {
2996        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2997          PackageName);
2998        goto PerlException;
2999      }
3000    reference=SvRV(ST(0));
3001    hv=SvSTASH(reference);
3002    av=newAV();
3003    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3004    SvREFCNT_dec(av);
3005    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3006    if (image == (Image *) NULL)
3007      {
3008        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3009          PackageName);
3010        goto PerlException;
3011      }
3012    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3013    /*
3014      Get options.
3015    */
3016    channel=DefaultChannels;
3017    (void) CopyMagickString(expression,"u",MagickPathExtent);
3018    if (items == 2)
3019      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
3020    else
3021      for (i=2; i < items; i+=2)
3022      {
3023        attribute=(char *) SvPV(ST(i-1),na);
3024        switch (*attribute)
3025        {
3026          case 'C':
3027          case 'c':
3028          {
3029            if (LocaleCompare(attribute,"channel") == 0)
3030              {
3031                ssize_t
3032                  option;
3033
3034                option=ParseChannelOption(SvPV(ST(i),na));
3035                if (option < 0)
3036                  {
3037                    ThrowPerlException(exception,OptionError,
3038                      "UnrecognizedType",SvPV(ST(i),na));
3039                    return;
3040                  }
3041                channel=(ChannelType) option;
3042                break;
3043              }
3044            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3045              attribute);
3046            break;
3047          }
3048          case 'E':
3049          case 'e':
3050          {
3051            if (LocaleCompare(attribute,"expression") == 0)
3052              {
3053                (void) CopyMagickString(expression,SvPV(ST(i),na),
3054                  MagickPathExtent);
3055                break;
3056              }
3057            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3058              attribute);
3059            break;
3060          }
3061          default:
3062          {
3063            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3064              attribute);
3065            break;
3066          }
3067        }
3068      }
3069    channel_mask=SetImageChannelMask(image,channel);
3070    image=ChannelFxImage(image,expression,exception);
3071    if (image != (Image *) NULL)
3072      (void) SetImageChannelMask(image,channel_mask);
3073    if (image == (Image *) NULL)
3074      goto PerlException;
3075    for ( ; image; image=image->next)
3076    {
3077      AddImageToRegistry(sv,image);
3078      rv=newRV(sv);
3079      av_push(av,sv_bless(rv,hv));
3080      SvREFCNT_dec(sv);
3081    }
3082    exception=DestroyExceptionInfo(exception);
3083    ST(0)=av_reference;
3084    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3085    XSRETURN(1);
3086
3087  PerlException:
3088    InheritPerlException(exception,perl_exception);
3089    exception=DestroyExceptionInfo(exception);
3090    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3091    SvPOK_on(perl_exception);
3092    ST(0)=sv_2mortal(perl_exception);
3093    XSRETURN(1);
3094  }
3095
3096#
3097###############################################################################
3098#                                                                             #
3099#                                                                             #
3100#                                                                             #
3101#   C l o n e                                                                 #
3102#                                                                             #
3103#                                                                             #
3104#                                                                             #
3105###############################################################################
3106#
3107#
3108void
3109Clone(ref)
3110  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3111  ALIAS:
3112    CopyImage   = 1
3113    copy        = 2
3114    copyimage   = 3
3115    CloneImage  = 4
3116    clone       = 5
3117    cloneimage  = 6
3118    Clone       = 7
3119  PPCODE:
3120  {
3121    AV
3122      *av;
3123
3124    ExceptionInfo
3125      *exception;
3126
3127    HV
3128      *hv;
3129
3130    Image
3131      *clone,
3132      *image;
3133
3134    struct PackageInfo
3135      *info;
3136
3137    SV
3138      *perl_exception,
3139      *reference,
3140      *rv,
3141      *sv;
3142
3143    PERL_UNUSED_VAR(ref);
3144    PERL_UNUSED_VAR(ix);
3145    exception=AcquireExceptionInfo();
3146    perl_exception=newSVpv("",0);
3147    sv=NULL;
3148    if (sv_isobject(ST(0)) == 0)
3149      {
3150        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3151          PackageName);
3152        goto PerlException;
3153      }
3154    reference=SvRV(ST(0));
3155    hv=SvSTASH(reference);
3156    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3157    if (image == (Image *) NULL)
3158      {
3159        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3160          PackageName);
3161        goto PerlException;
3162      }
3163    /*
3164      Create blessed Perl array for the returned image.
3165    */
3166    av=newAV();
3167    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3168    SvREFCNT_dec(av);
3169    for ( ; image; image=image->next)
3170    {
3171      clone=CloneImage(image,0,0,MagickTrue,exception);
3172      if (clone == (Image *) NULL)
3173        break;
3174      AddImageToRegistry(sv,clone);
3175      rv=newRV(sv);
3176      av_push(av,sv_bless(rv,hv));
3177      SvREFCNT_dec(sv);
3178    }
3179    exception=DestroyExceptionInfo(exception);
3180    SvREFCNT_dec(perl_exception);
3181    XSRETURN(1);
3182
3183  PerlException:
3184    InheritPerlException(exception,perl_exception);
3185    exception=DestroyExceptionInfo(exception);
3186    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3187    SvPOK_on(perl_exception);
3188    ST(0)=sv_2mortal(perl_exception);
3189    XSRETURN(1);
3190  }
3191
3192#
3193###############################################################################
3194#                                                                             #
3195#                                                                             #
3196#                                                                             #
3197#   C L O N E                                                                 #
3198#                                                                             #
3199#                                                                             #
3200#                                                                             #
3201###############################################################################
3202#
3203#
3204void
3205CLONE(ref,...)
3206  SV *ref;
3207  CODE:
3208  {
3209    PERL_UNUSED_VAR(ref);
3210    if (magick_registry != (SplayTreeInfo *) NULL)
3211      {
3212        register Image
3213          *p;
3214
3215        ResetSplayTreeIterator(magick_registry);
3216        p=(Image *) GetNextKeyInSplayTree(magick_registry);
3217        while (p != (Image *) NULL)
3218        {
3219          ReferenceImage(p);
3220          p=(Image *) GetNextKeyInSplayTree(magick_registry);
3221        }
3222      }
3223  }
3224
3225#
3226###############################################################################
3227#                                                                             #
3228#                                                                             #
3229#                                                                             #
3230#   C o a l e s c e                                                           #
3231#                                                                             #
3232#                                                                             #
3233#                                                                             #
3234###############################################################################
3235#
3236#
3237void
3238Coalesce(ref)
3239  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3240  ALIAS:
3241    CoalesceImage   = 1
3242    coalesce        = 2
3243    coalesceimage   = 3
3244  PPCODE:
3245  {
3246    AV
3247      *av;
3248
3249    ExceptionInfo
3250      *exception;
3251
3252    HV
3253      *hv;
3254
3255    Image
3256      *image;
3257
3258    struct PackageInfo
3259      *info;
3260
3261    SV
3262      *av_reference,
3263      *perl_exception,
3264      *reference,
3265      *rv,
3266      *sv;
3267
3268    PERL_UNUSED_VAR(ref);
3269    PERL_UNUSED_VAR(ix);
3270    exception=AcquireExceptionInfo();
3271    perl_exception=newSVpv("",0);
3272    sv=NULL;
3273    if (sv_isobject(ST(0)) == 0)
3274      {
3275        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3276          PackageName);
3277        goto PerlException;
3278      }
3279    reference=SvRV(ST(0));
3280    hv=SvSTASH(reference);
3281    av=newAV();
3282    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3283    SvREFCNT_dec(av);
3284    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3285    if (image == (Image *) NULL)
3286      {
3287        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3288          PackageName);
3289        goto PerlException;
3290      }
3291    image=CoalesceImages(image,exception);
3292    if (image == (Image *) NULL)
3293      goto PerlException;
3294    for ( ; image; image=image->next)
3295    {
3296      AddImageToRegistry(sv,image);
3297      rv=newRV(sv);
3298      av_push(av,sv_bless(rv,hv));
3299      SvREFCNT_dec(sv);
3300    }
3301    exception=DestroyExceptionInfo(exception);
3302    ST(0)=av_reference;
3303    SvREFCNT_dec(perl_exception);
3304    XSRETURN(1);
3305
3306  PerlException:
3307    InheritPerlException(exception,perl_exception);
3308    exception=DestroyExceptionInfo(exception);
3309    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3310    SvPOK_on(perl_exception);
3311    ST(0)=sv_2mortal(perl_exception);
3312    XSRETURN(1);
3313  }
3314
3315#
3316###############################################################################
3317#                                                                             #
3318#                                                                             #
3319#                                                                             #
3320#   C o m p a r e                                                             #
3321#                                                                             #
3322#                                                                             #
3323#                                                                             #
3324###############################################################################
3325#
3326#
3327void
3328Compare(ref,...)
3329  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3330  ALIAS:
3331    CompareImages = 1
3332    compare      = 2
3333    compareimage = 3
3334  PPCODE:
3335  {
3336    AV
3337      *av;
3338
3339    char
3340      *attribute;
3341
3342    double
3343      distortion;
3344
3345    ExceptionInfo
3346      *exception;
3347
3348    HV
3349      *hv;
3350
3351    Image
3352      *difference_image,
3353      *image,
3354      *reconstruct_image;
3355
3356    MetricType
3357      metric;
3358
3359    register ssize_t
3360      i;
3361
3362    ssize_t
3363      option;
3364
3365    struct PackageInfo
3366      *info;
3367
3368    SV
3369      *av_reference,
3370      *perl_exception,
3371      *reference,
3372      *rv,
3373      *sv;
3374
3375    PERL_UNUSED_VAR(ref);
3376    PERL_UNUSED_VAR(ix);
3377    exception=AcquireExceptionInfo();
3378    perl_exception=newSVpv("",0);
3379    sv=NULL;
3380    av=NULL;
3381    attribute=NULL;
3382    if (sv_isobject(ST(0)) == 0)
3383      {
3384        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3385          PackageName);
3386        goto PerlException;
3387      }
3388    reference=SvRV(ST(0));
3389    hv=SvSTASH(reference);
3390    av=newAV();
3391    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3392    SvREFCNT_dec(av);
3393    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3394    if (image == (Image *) NULL)
3395      {
3396        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3397          PackageName);
3398        goto PerlException;
3399      }
3400    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3401    /*
3402      Get attribute.
3403    */
3404    reconstruct_image=image;
3405    metric=RootMeanSquaredErrorMetric;
3406    for (i=2; i < items; i+=2)
3407    {
3408      attribute=(char *) SvPV(ST(i-1),na);
3409      switch (*attribute)
3410      {
3411        case 'C':
3412        case 'c':
3413        {
3414          if (LocaleCompare(attribute,"channel") == 0)
3415            {
3416              ssize_t
3417                option;
3418
3419              option=ParseChannelOption(SvPV(ST(i),na));
3420              if (option < 0)
3421                {
3422                  ThrowPerlException(exception,OptionError,
3423                    "UnrecognizedType",SvPV(ST(i),na));
3424                  return;
3425                }
3426              (void) SetPixelChannelMask(image,(ChannelType) option);
3427              break;
3428            }
3429          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3430            attribute);
3431          break;
3432        }
3433        case 'F':
3434        case 'f':
3435        {
3436          if (LocaleCompare(attribute,"fuzz") == 0)
3437            {
3438              image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3439              break;
3440            }
3441          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3442            attribute);
3443          break;
3444        }
3445        case 'I':
3446        case 'i':
3447        {
3448          if (LocaleCompare(attribute,"image") == 0)
3449            {
3450              reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3451                (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3452              break;
3453            }
3454          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3455            attribute);
3456          break;
3457        }
3458        case 'M':
3459        case 'm':
3460        {
3461          if (LocaleCompare(attribute,"metric") == 0)
3462            {
3463              option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3464                SvPV(ST(i),na));
3465              if (option < 0)
3466                {
3467                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3468                    SvPV(ST(i),na));
3469                  break;
3470                }
3471              metric=(MetricType) option;
3472              break;
3473            }
3474          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3475            attribute);
3476          break;
3477        }
3478        default:
3479        {
3480          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3481            attribute);
3482          break;
3483        }
3484      }
3485    }
3486    difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3487      exception);
3488    if (difference_image != (Image *) NULL)
3489      {
3490        difference_image->error.mean_error_per_pixel=distortion;
3491        AddImageToRegistry(sv,difference_image);
3492        rv=newRV(sv);
3493        av_push(av,sv_bless(rv,hv));
3494        SvREFCNT_dec(sv);
3495      }
3496    exception=DestroyExceptionInfo(exception);
3497    ST(0)=av_reference;
3498    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3499    XSRETURN(1);
3500
3501  PerlException:
3502    InheritPerlException(exception,perl_exception);
3503    exception=DestroyExceptionInfo(exception);
3504    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3505    SvPOK_on(perl_exception);
3506    ST(0)=sv_2mortal(perl_exception);
3507    XSRETURN(1);
3508  }
3509
3510#
3511###############################################################################
3512#                                                                             #
3513#                                                                             #
3514#                                                                             #
3515#   C o m p l e x I m a g e s                                                 #
3516#                                                                             #
3517#                                                                             #
3518#                                                                             #
3519###############################################################################
3520#
3521#
3522void
3523ComplexImages(ref,...)
3524  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3525  ALIAS:
3526    ComplexImages   = 1
3527    compleximages   = 2
3528  PPCODE:
3529  {
3530    AV
3531      *av;
3532
3533    char
3534      *attribute,
3535      *p;
3536
3537    ComplexOperator
3538      op;
3539
3540    ExceptionInfo
3541      *exception;
3542
3543    HV
3544      *hv;
3545
3546    Image
3547      *image;
3548
3549    register ssize_t
3550      i;
3551
3552    struct PackageInfo
3553      *info;
3554
3555    SV
3556      *perl_exception,
3557      *reference,
3558      *rv,
3559      *sv;
3560
3561    PERL_UNUSED_VAR(ref);
3562    PERL_UNUSED_VAR(ix);
3563    exception=AcquireExceptionInfo();
3564    perl_exception=newSVpv("",0);
3565    sv=NULL;
3566    if (sv_isobject(ST(0)) == 0)
3567      {
3568        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3569          PackageName);
3570        goto PerlException;
3571      }
3572    reference=SvRV(ST(0));
3573    hv=SvSTASH(reference);
3574    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3575    if (image == (Image *) NULL)
3576      {
3577        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3578          PackageName);
3579        goto PerlException;
3580      }
3581    op=UndefinedComplexOperator;
3582    if (items == 2)
3583      {
3584        ssize_t
3585          in;
3586
3587        in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3588          SvPV(ST(1),na));
3589        if (in < 0)
3590          {
3591            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3592              SvPV(ST(1),na));
3593            return;
3594          }
3595        op=(ComplexOperator) in;
3596      }
3597    else
3598      for (i=2; i < items; i+=2)
3599      {
3600        attribute=(char *) SvPV(ST(i-1),na);
3601        switch (*attribute)
3602        {
3603          case 'O':
3604          case 'o':
3605          {
3606            if (LocaleCompare(attribute,"operator") == 0)
3607              {
3608                ssize_t
3609                  in;
3610
3611                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3612                  MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3613                if (in < 0)
3614                  {
3615                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
3616                      SvPV(ST(i),na));
3617                    return;
3618                  }
3619                op=(ComplexOperator) in;
3620                break;
3621              }
3622            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3623              attribute);
3624            break;
3625          }
3626          default:
3627          {
3628            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3629              attribute);
3630            break;
3631          }
3632        }
3633      }
3634    image=ComplexImages(image,op,exception);
3635    if (image == (Image *) NULL)
3636      goto PerlException;
3637    /*
3638      Create blessed Perl array for the returned image.
3639    */
3640    av=newAV();
3641    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3642    SvREFCNT_dec(av);
3643    AddImageToRegistry(sv,image);
3644    rv=newRV(sv);
3645    av_push(av,sv_bless(rv,hv));
3646    SvREFCNT_dec(sv);
3647    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3648    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3649      "complex-%.*s",(int) (MagickPathExtent-9),
3650      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3651    (void) CopyMagickString(image->filename,info->image_info->filename,
3652      MagickPathExtent);
3653    SetImageInfo(info->image_info,0,exception);
3654    exception=DestroyExceptionInfo(exception);
3655    SvREFCNT_dec(perl_exception);
3656    XSRETURN(1);
3657
3658  PerlException:
3659    InheritPerlException(exception,perl_exception);
3660    exception=DestroyExceptionInfo(exception);
3661    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3662    SvPOK_on(perl_exception);
3663    ST(0)=sv_2mortal(perl_exception);
3664    XSRETURN(1);
3665  }
3666
3667#
3668###############################################################################
3669#                                                                             #
3670#                                                                             #
3671#                                                                             #
3672#   C o m p a r e L a y e r s                                                 #
3673#                                                                             #
3674#                                                                             #
3675#                                                                             #
3676###############################################################################
3677#
3678#
3679void
3680CompareLayers(ref,...)
3681  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3682  ALIAS:
3683    CompareImagesLayers   = 1
3684    comparelayers        = 2
3685    compareimagelayers   = 3
3686  PPCODE:
3687  {
3688    AV
3689      *av;
3690
3691    char
3692      *attribute;
3693
3694    ExceptionInfo
3695      *exception;
3696
3697    HV
3698      *hv;
3699
3700    Image
3701      *image;
3702
3703    LayerMethod
3704      method;
3705
3706    register ssize_t
3707      i;
3708
3709    ssize_t
3710      option;
3711
3712    struct PackageInfo
3713      *info;
3714
3715    SV
3716      *av_reference,
3717      *perl_exception,
3718      *reference,
3719      *rv,
3720      *sv;
3721
3722    PERL_UNUSED_VAR(ref);
3723    PERL_UNUSED_VAR(ix);
3724    exception=AcquireExceptionInfo();
3725    perl_exception=newSVpv("",0);
3726    sv=NULL;
3727    if (sv_isobject(ST(0)) == 0)
3728      {
3729        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3730          PackageName);
3731        goto PerlException;
3732      }
3733    reference=SvRV(ST(0));
3734    hv=SvSTASH(reference);
3735    av=newAV();
3736    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3737    SvREFCNT_dec(av);
3738    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3739    if (image == (Image *) NULL)
3740      {
3741        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3742          PackageName);
3743        goto PerlException;
3744      }
3745    method=CompareAnyLayer;
3746    for (i=2; i < items; i+=2)
3747    {
3748      attribute=(char *) SvPV(ST(i-1),na);
3749      switch (*attribute)
3750      {
3751        case 'M':
3752        case 'm':
3753        {
3754          if (LocaleCompare(attribute,"method") == 0)
3755            {
3756              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3757                SvPV(ST(i),na));
3758              if (option < 0)
3759                {
3760                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3761                    SvPV(ST(i),na));
3762                  break;
3763                }
3764               method=(LayerMethod) option;
3765              break;
3766            }
3767          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3768            attribute);
3769          break;
3770        }
3771        default:
3772        {
3773          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3774            attribute);
3775          break;
3776        }
3777      }
3778    }
3779    image=CompareImagesLayers(image,method,exception);
3780    if (image == (Image *) NULL)
3781      goto PerlException;
3782    for ( ; image; image=image->next)
3783    {
3784      AddImageToRegistry(sv,image);
3785      rv=newRV(sv);
3786      av_push(av,sv_bless(rv,hv));
3787      SvREFCNT_dec(sv);
3788    }
3789    exception=DestroyExceptionInfo(exception);
3790    ST(0)=av_reference;
3791    SvREFCNT_dec(perl_exception);
3792    XSRETURN(1);
3793
3794  PerlException:
3795    InheritPerlException(exception,perl_exception);
3796    exception=DestroyExceptionInfo(exception);
3797    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3798    SvPOK_on(perl_exception);
3799    ST(0)=sv_2mortal(perl_exception);
3800    XSRETURN(1);
3801  }
3802
3803#
3804###############################################################################
3805#                                                                             #
3806#                                                                             #
3807#                                                                             #
3808#   D e s t r o y                                                             #
3809#                                                                             #
3810#                                                                             #
3811#                                                                             #
3812###############################################################################
3813#
3814#
3815void
3816DESTROY(ref)
3817  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3818  PPCODE:
3819  {
3820    SV
3821      *reference;
3822
3823    PERL_UNUSED_VAR(ref);
3824    if (sv_isobject(ST(0)) == 0)
3825      croak("ReferenceIsNotMyType");
3826    reference=SvRV(ST(0));
3827    switch (SvTYPE(reference))
3828    {
3829      case SVt_PVAV:
3830      {
3831        char
3832          message[MagickPathExtent];
3833
3834        const SV
3835          *key;
3836
3837        HV
3838          *hv;
3839
3840        GV
3841          **gvp;
3842
3843        struct PackageInfo
3844          *info;
3845
3846        SV
3847          *sv;
3848
3849        /*
3850          Array (AV *) reference
3851        */
3852        (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3853          XS_VERSION,reference);
3854        hv=gv_stashpv(PackageName, FALSE);
3855        if (!hv)
3856          break;
3857        gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3858        if (!gvp)
3859          break;
3860        sv=GvSV(*gvp);
3861        if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3862          {
3863            info=INT2PTR(struct PackageInfo *,SvIV(sv));
3864            DestroyPackageInfo(info);
3865          }
3866        key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3867        (void) key;
3868        break;
3869      }
3870      case SVt_PVMG:
3871      {
3872        Image
3873          *image;
3874
3875        /*
3876          Blessed scalar = (Image *) SvIV(reference)
3877        */
3878        image=INT2PTR(Image *,SvIV(reference));
3879        if (image != (Image *) NULL)
3880          DeleteImageFromRegistry(reference,image);
3881        break;
3882      }
3883      default:
3884        break;
3885    }
3886  }
3887
3888#
3889###############################################################################
3890#                                                                             #
3891#                                                                             #
3892#                                                                             #
3893#   D i s p l a y                                                             #
3894#                                                                             #
3895#                                                                             #
3896#                                                                             #
3897###############################################################################
3898#
3899#
3900void
3901Display(ref,...)
3902  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3903  ALIAS:
3904    DisplayImage  = 1
3905    display       = 2
3906    displayimage  = 3
3907  PPCODE:
3908  {
3909    ExceptionInfo
3910      *exception;
3911
3912    Image
3913      *image;
3914
3915    register ssize_t
3916      i;
3917
3918    struct PackageInfo
3919      *info,
3920      *package_info;
3921
3922    SV
3923      *perl_exception,
3924      *reference;
3925
3926    PERL_UNUSED_VAR(ref);
3927    PERL_UNUSED_VAR(ix);
3928    exception=AcquireExceptionInfo();
3929    perl_exception=newSVpv("",0);
3930    package_info=(struct PackageInfo *) NULL;
3931    if (sv_isobject(ST(0)) == 0)
3932      {
3933        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3934          PackageName);
3935        goto PerlException;
3936      }
3937    reference=SvRV(ST(0));
3938    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3939    if (image == (Image *) NULL)
3940      {
3941        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3942          PackageName);
3943        goto PerlException;
3944      }
3945    package_info=ClonePackageInfo(info,exception);
3946    if (items == 2)
3947      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3948    else
3949      if (items > 2)
3950        for (i=2; i < items; i+=2)
3951          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3952            exception);
3953    (void) DisplayImages(package_info->image_info,image,exception);
3954    (void) CatchImageException(image);
3955
3956  PerlException:
3957    if (package_info != (struct PackageInfo *) NULL)
3958      DestroyPackageInfo(package_info);
3959    InheritPerlException(exception,perl_exception);
3960    exception=DestroyExceptionInfo(exception);
3961    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3962    SvPOK_on(perl_exception);
3963    ST(0)=sv_2mortal(perl_exception);
3964    XSRETURN(1);
3965  }
3966
3967#
3968###############################################################################
3969#                                                                             #
3970#                                                                             #
3971#                                                                             #
3972#   E v a l u a t e I m a g e s                                               #
3973#                                                                             #
3974#                                                                             #
3975#                                                                             #
3976###############################################################################
3977#
3978#
3979void
3980EvaluateImages(ref,...)
3981  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3982  ALIAS:
3983    EvaluateImages   = 1
3984    evaluateimages   = 2
3985  PPCODE:
3986  {
3987    AV
3988      *av;
3989
3990    char
3991      *attribute,
3992      *p;
3993
3994    ExceptionInfo
3995      *exception;
3996
3997    HV
3998      *hv;
3999
4000    Image
4001      *image;
4002
4003    MagickEvaluateOperator
4004      op;
4005
4006    register ssize_t
4007      i;
4008
4009    struct PackageInfo
4010      *info;
4011
4012    SV
4013      *perl_exception,
4014      *reference,
4015      *rv,
4016      *sv;
4017
4018    PERL_UNUSED_VAR(ref);
4019    PERL_UNUSED_VAR(ix);
4020    exception=AcquireExceptionInfo();
4021    perl_exception=newSVpv("",0);
4022    sv=NULL;
4023    if (sv_isobject(ST(0)) == 0)
4024      {
4025        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4026          PackageName);
4027        goto PerlException;
4028      }
4029    reference=SvRV(ST(0));
4030    hv=SvSTASH(reference);
4031    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4032    if (image == (Image *) NULL)
4033      {
4034        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4035          PackageName);
4036        goto PerlException;
4037      }
4038    op=MeanEvaluateOperator;
4039    if (items == 2)
4040      {
4041        ssize_t
4042          in;
4043
4044        in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4045          SvPV(ST(1),na));
4046        if (in < 0)
4047          {
4048            ThrowPerlException(exception,OptionError,"UnrecognizedType",
4049              SvPV(ST(1),na));
4050            return;
4051          }
4052        op=(MagickEvaluateOperator) in;
4053      }
4054    else
4055      for (i=2; i < items; i+=2)
4056      {
4057        attribute=(char *) SvPV(ST(i-1),na);
4058        switch (*attribute)
4059        {
4060          case 'O':
4061          case 'o':
4062          {
4063            if (LocaleCompare(attribute,"operator") == 0)
4064              {
4065                ssize_t
4066                  in;
4067
4068                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4069                  MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4070                if (in < 0)
4071                  {
4072                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
4073                      SvPV(ST(i),na));
4074                    return;
4075                  }
4076                op=(MagickEvaluateOperator) in;
4077                break;
4078              }
4079            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4080              attribute);
4081            break;
4082          }
4083          default:
4084          {
4085            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4086              attribute);
4087            break;
4088          }
4089        }
4090      }
4091    image=EvaluateImages(image,op,exception);
4092    if (image == (Image *) NULL)
4093      goto PerlException;
4094    /*
4095      Create blessed Perl array for the returned image.
4096    */
4097    av=newAV();
4098    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4099    SvREFCNT_dec(av);
4100    AddImageToRegistry(sv,image);
4101    rv=newRV(sv);
4102    av_push(av,sv_bless(rv,hv));
4103    SvREFCNT_dec(sv);
4104    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4105    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4106      "evaluate-%.*s",(int) (MagickPathExtent-9),
4107      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4108    (void) CopyMagickString(image->filename,info->image_info->filename,
4109      MagickPathExtent);
4110    SetImageInfo(info->image_info,0,exception);
4111    exception=DestroyExceptionInfo(exception);
4112    SvREFCNT_dec(perl_exception);
4113    XSRETURN(1);
4114
4115  PerlException:
4116    InheritPerlException(exception,perl_exception);
4117    exception=DestroyExceptionInfo(exception);
4118    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4119    SvPOK_on(perl_exception);
4120    ST(0)=sv_2mortal(perl_exception);
4121    XSRETURN(1);
4122  }
4123
4124#
4125###############################################################################
4126#                                                                             #
4127#                                                                             #
4128#                                                                             #
4129#   F e a t u r e s                                                           #
4130#                                                                             #
4131#                                                                             #
4132#                                                                             #
4133###############################################################################
4134#
4135#
4136void
4137Features(ref,...)
4138  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4139  ALIAS:
4140    FeaturesImage = 1
4141    features      = 2
4142    featuresimage = 3
4143  PPCODE:
4144  {
4145#define ChannelFeatures(channel,direction) \
4146{ \
4147  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4148    channel_features[channel].angular_second_moment[direction]); \
4149  PUSHs(sv_2mortal(newSVpv(message,0))); \
4150  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4151    channel_features[channel].contrast[direction]); \
4152  PUSHs(sv_2mortal(newSVpv(message,0))); \
4153  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4154    channel_features[channel].contrast[direction]); \
4155  PUSHs(sv_2mortal(newSVpv(message,0))); \
4156  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4157    channel_features[channel].variance_sum_of_squares[direction]); \
4158  PUSHs(sv_2mortal(newSVpv(message,0))); \
4159  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4160    channel_features[channel].inverse_difference_moment[direction]); \
4161  PUSHs(sv_2mortal(newSVpv(message,0))); \
4162  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4163    channel_features[channel].sum_average[direction]); \
4164  PUSHs(sv_2mortal(newSVpv(message,0))); \
4165  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4166    channel_features[channel].sum_variance[direction]); \
4167  PUSHs(sv_2mortal(newSVpv(message,0))); \
4168  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4169    channel_features[channel].sum_entropy[direction]); \
4170  PUSHs(sv_2mortal(newSVpv(message,0))); \
4171  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4172    channel_features[channel].entropy[direction]); \
4173  PUSHs(sv_2mortal(newSVpv(message,0))); \
4174  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4175    channel_features[channel].difference_variance[direction]); \
4176  PUSHs(sv_2mortal(newSVpv(message,0))); \
4177  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4178    channel_features[channel].difference_entropy[direction]); \
4179  PUSHs(sv_2mortal(newSVpv(message,0))); \
4180  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4181    channel_features[channel].measure_of_correlation_1[direction]); \
4182  PUSHs(sv_2mortal(newSVpv(message,0))); \
4183  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4184    channel_features[channel].measure_of_correlation_2[direction]); \
4185  PUSHs(sv_2mortal(newSVpv(message,0))); \
4186  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4187    channel_features[channel].maximum_correlation_coefficient[direction]); \
4188  PUSHs(sv_2mortal(newSVpv(message,0))); \
4189}
4190
4191    AV
4192      *av;
4193
4194    char
4195      *attribute,
4196      message[MagickPathExtent];
4197
4198    ChannelFeatures
4199      *channel_features;
4200
4201    double
4202      distance;
4203
4204    ExceptionInfo
4205      *exception;
4206
4207    Image
4208      *image;
4209
4210    register ssize_t
4211      i;
4212
4213    ssize_t
4214      count;
4215
4216    struct PackageInfo
4217      *info;
4218
4219    SV
4220      *perl_exception,
4221      *reference;
4222
4223    PERL_UNUSED_VAR(ref);
4224    PERL_UNUSED_VAR(ix);
4225    exception=AcquireExceptionInfo();
4226    perl_exception=newSVpv("",0);
4227    av=NULL;
4228    if (sv_isobject(ST(0)) == 0)
4229      {
4230        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4231          PackageName);
4232        goto PerlException;
4233      }
4234    reference=SvRV(ST(0));
4235    av=newAV();
4236    SvREFCNT_dec(av);
4237    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4238    if (image == (Image *) NULL)
4239      {
4240        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4241          PackageName);
4242        goto PerlException;
4243      }
4244    distance=1.0;
4245    for (i=2; i < items; i+=2)
4246    {
4247      attribute=(char *) SvPV(ST(i-1),na);
4248      switch (*attribute)
4249      {
4250        case 'D':
4251        case 'd':
4252        {
4253          if (LocaleCompare(attribute,"distance") == 0)
4254            {
4255              distance=StringToLong((char *) SvPV(ST(1),na));
4256              break;
4257            }
4258          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4259            attribute);
4260          break;
4261        }
4262        default:
4263        {
4264          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4265            attribute);
4266          break;
4267        }
4268      }
4269    }
4270    count=0;
4271    for ( ; image; image=image->next)
4272    {
4273      register ssize_t
4274        j;
4275
4276      channel_features=GetImageFeatures(image,distance,exception);
4277      if (channel_features == (ChannelFeatures *) NULL)
4278        continue;
4279      count++;
4280      for (j=0; j < 4; j++)
4281      {
4282        for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4283        {
4284          PixelChannel channel=GetPixelChannelChannel(image,i);
4285          PixelTrait traits=GetPixelChannelTraits(image,channel);
4286          if (traits == UndefinedPixelTrait)
4287            continue;
4288          EXTEND(sp,14*(i+1)*count);
4289          ChannelFeatures(channel,j);
4290        }
4291      }
4292      channel_features=(ChannelFeatures *)
4293        RelinquishMagickMemory(channel_features);
4294    }
4295
4296  PerlException:
4297    InheritPerlException(exception,perl_exception);
4298    exception=DestroyExceptionInfo(exception);
4299    SvREFCNT_dec(perl_exception);
4300  }
4301
4302#
4303###############################################################################
4304#                                                                             #
4305#                                                                             #
4306#                                                                             #
4307#   F l a t t e n                                                             #
4308#                                                                             #
4309#                                                                             #
4310#                                                                             #
4311###############################################################################
4312#
4313#
4314void
4315Flatten(ref,...)
4316  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4317  ALIAS:
4318    FlattenImage   = 1
4319    flatten        = 2
4320    flattenimage   = 3
4321  PPCODE:
4322  {
4323    AV
4324      *av;
4325
4326    char
4327      *attribute,
4328      *p;
4329
4330    ExceptionInfo
4331      *exception;
4332
4333    HV
4334      *hv;
4335
4336    Image
4337      *image;
4338
4339    PixelInfo
4340      background_color;
4341
4342    register ssize_t
4343      i;
4344
4345    struct PackageInfo
4346      *info;
4347
4348    SV
4349      *perl_exception,
4350      *reference,
4351      *rv,
4352      *sv;
4353
4354    PERL_UNUSED_VAR(ref);
4355    PERL_UNUSED_VAR(ix);
4356    exception=AcquireExceptionInfo();
4357    perl_exception=newSVpv("",0);
4358    sv=NULL;
4359    if (sv_isobject(ST(0)) == 0)
4360      {
4361        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4362          PackageName);
4363        goto PerlException;
4364      }
4365    reference=SvRV(ST(0));
4366    hv=SvSTASH(reference);
4367    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4368    if (image == (Image *) NULL)
4369      {
4370        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4371          PackageName);
4372        goto PerlException;
4373      }
4374    background_color=image->background_color;
4375    if (items == 2)
4376      (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4377        &background_color,exception);
4378    else
4379      for (i=2; i < items; i+=2)
4380      {
4381        attribute=(char *) SvPV(ST(i-1),na);
4382        switch (*attribute)
4383        {
4384          case 'B':
4385          case 'b':
4386          {
4387            if (LocaleCompare(attribute,"background") == 0)
4388              {
4389                (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4390                  AllCompliance,&background_color,exception);
4391                break;
4392              }
4393            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4394              attribute);
4395            break;
4396          }
4397          default:
4398          {
4399            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4400              attribute);
4401            break;
4402          }
4403        }
4404      }
4405    image->background_color=background_color;
4406    image=MergeImageLayers(image,FlattenLayer,exception);
4407    if (image == (Image *) NULL)
4408      goto PerlException;
4409    /*
4410      Create blessed Perl array for the returned image.
4411    */
4412    av=newAV();
4413    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4414    SvREFCNT_dec(av);
4415    AddImageToRegistry(sv,image);
4416    rv=newRV(sv);
4417    av_push(av,sv_bless(rv,hv));
4418    SvREFCNT_dec(sv);
4419    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4420    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4421      "flatten-%.*s",(int) (MagickPathExtent-9),
4422      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4423    (void) CopyMagickString(image->filename,info->image_info->filename,
4424      MagickPathExtent);
4425    SetImageInfo(info->image_info,0,exception);
4426    exception=DestroyExceptionInfo(exception);
4427    SvREFCNT_dec(perl_exception);
4428    XSRETURN(1);
4429
4430  PerlException:
4431    InheritPerlException(exception,perl_exception);
4432    exception=DestroyExceptionInfo(exception);
4433    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4434    SvPOK_on(perl_exception);  /* return messages in string context */
4435    ST(0)=sv_2mortal(perl_exception);
4436    XSRETURN(1);
4437  }
4438
4439#
4440###############################################################################
4441#                                                                             #
4442#                                                                             #
4443#                                                                             #
4444#   F x                                                                       #
4445#                                                                             #
4446#                                                                             #
4447#                                                                             #
4448###############################################################################
4449#
4450#
4451void
4452Fx(ref,...)
4453  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4454  ALIAS:
4455    FxImage  = 1
4456    fx       = 2
4457    fximage  = 3
4458  PPCODE:
4459  {
4460    AV
4461      *av;
4462
4463    char
4464      *attribute,
4465      expression[MagickPathExtent];
4466
4467    ChannelType
4468      channel,
4469      channel_mask;
4470
4471    ExceptionInfo
4472      *exception;
4473
4474    HV
4475      *hv;
4476
4477    Image
4478      *image;
4479
4480    register ssize_t
4481      i;
4482
4483    struct PackageInfo
4484      *info;
4485
4486    SV
4487      *av_reference,
4488      *perl_exception,
4489      *reference,
4490      *rv,
4491      *sv;
4492
4493    PERL_UNUSED_VAR(ref);
4494    PERL_UNUSED_VAR(ix);
4495    exception=AcquireExceptionInfo();
4496    perl_exception=newSVpv("",0);
4497    sv=NULL;
4498    attribute=NULL;
4499    av=NULL;
4500    if (sv_isobject(ST(0)) == 0)
4501      {
4502        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4503          PackageName);
4504        goto PerlException;
4505      }
4506    reference=SvRV(ST(0));
4507    hv=SvSTASH(reference);
4508    av=newAV();
4509    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4510    SvREFCNT_dec(av);
4511    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4512    if (image == (Image *) NULL)
4513      {
4514        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4515          PackageName);
4516        goto PerlException;
4517      }
4518    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4519    /*
4520      Get options.
4521    */
4522    channel=DefaultChannels;
4523    (void) CopyMagickString(expression,"u",MagickPathExtent);
4524    if (items == 2)
4525      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),
4526        MagickPathExtent);
4527    else
4528      for (i=2; i < items; i+=2)
4529      {
4530        attribute=(char *) SvPV(ST(i-1),na);
4531        switch (*attribute)
4532        {
4533          case 'C':
4534          case 'c':
4535          {
4536            if (LocaleCompare(attribute,"channel") == 0)
4537              {
4538                ssize_t
4539                  option;
4540
4541                option=ParseChannelOption(SvPV(ST(i),na));
4542                if (option < 0)
4543                  {
4544                    ThrowPerlException(exception,OptionError,
4545                      "UnrecognizedType",SvPV(ST(i),na));
4546                    return;
4547                  }
4548                channel=(ChannelType) option;
4549                break;
4550              }
4551            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4552              attribute);
4553            break;
4554          }
4555          case 'E':
4556          case 'e':
4557          {
4558            if (LocaleCompare(attribute,"expression") == 0)
4559              {
4560                (void) CopyMagickString(expression,SvPV(ST(i),na),
4561                  MagickPathExtent);
4562                break;
4563              }
4564            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4565              attribute);
4566            break;
4567          }
4568          default:
4569          {
4570            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4571              attribute);
4572            break;
4573          }
4574        }
4575      }
4576    channel_mask=SetImageChannelMask(image,channel);
4577    image=FxImage(image,expression,exception);
4578    if (image != (Image *) NULL)
4579      (void) SetImageChannelMask(image,channel_mask);
4580    if (image == (Image *) NULL)
4581      goto PerlException;
4582    for ( ; image; image=image->next)
4583    {
4584      AddImageToRegistry(sv,image);
4585      rv=newRV(sv);
4586      av_push(av,sv_bless(rv,hv));
4587      SvREFCNT_dec(sv);
4588    }
4589    exception=DestroyExceptionInfo(exception);
4590    ST(0)=av_reference;
4591    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4592    XSRETURN(1);
4593
4594  PerlException:
4595    InheritPerlException(exception,perl_exception);
4596    exception=DestroyExceptionInfo(exception);
4597    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4598    SvPOK_on(perl_exception);
4599    ST(0)=sv_2mortal(perl_exception);
4600    XSRETURN(1);
4601  }
4602
4603#
4604###############################################################################
4605#                                                                             #
4606#                                                                             #
4607#                                                                             #
4608#   G e t                                                                     #
4609#                                                                             #
4610#                                                                             #
4611#                                                                             #
4612###############################################################################
4613#
4614#
4615void
4616Get(ref,...)
4617  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4618  ALIAS:
4619    GetAttributes = 1
4620    GetAttribute  = 2
4621    get           = 3
4622    getattributes = 4
4623    getattribute  = 5
4624  PPCODE:
4625  {
4626    char
4627      *attribute,
4628      color[MagickPathExtent];
4629
4630    const char
4631      *value;
4632
4633    ExceptionInfo
4634      *exception;
4635
4636    Image
4637      *image;
4638
4639    long
4640      j;
4641
4642    register ssize_t
4643      i;
4644
4645    struct PackageInfo
4646      *info;
4647
4648    SV
4649      *perl_exception,
4650      *reference,
4651      *s;
4652
4653    PERL_UNUSED_VAR(ref);
4654    PERL_UNUSED_VAR(ix);
4655    exception=AcquireExceptionInfo();
4656    perl_exception=newSVpv("",0);
4657    if (sv_isobject(ST(0)) == 0)
4658      {
4659        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4660          PackageName);
4661        XSRETURN_EMPTY;
4662      }
4663    reference=SvRV(ST(0));
4664    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4665    if (image == (Image *) NULL && !info)
4666      XSRETURN_EMPTY;
4667    EXTEND(sp,items);
4668    for (i=1; i < items; i++)
4669    {
4670      attribute=(char *) SvPV(ST(i),na);
4671      s=NULL;
4672      switch (*attribute)
4673      {
4674        case 'A':
4675        case 'a':
4676        {
4677          if (LocaleCompare(attribute,"adjoin") == 0)
4678            {
4679              if (info)
4680                s=newSViv((ssize_t) info->image_info->adjoin);
4681              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4682              continue;
4683            }
4684          if (LocaleCompare(attribute,"antialias") == 0)
4685            {
4686              if (info)
4687                s=newSViv((ssize_t) info->image_info->antialias);
4688              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4689              continue;
4690            }
4691          if (LocaleCompare(attribute,"area") == 0)
4692            {
4693              s=newSViv(GetMagickResource(AreaResource));
4694              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4695              continue;
4696            }
4697          if (LocaleCompare(attribute,"attenuate") == 0)
4698            {
4699              const char
4700                *value;
4701
4702              value=GetImageProperty(image,attribute,exception);
4703              if (value != (const char *) NULL)
4704                s=newSVpv(value,0);
4705              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4706              continue;
4707            }
4708          if (LocaleCompare(attribute,"authenticate") == 0)
4709            {
4710              if (info)
4711                {
4712                  const char
4713                    *option;
4714
4715                  option=GetImageOption(info->image_info,attribute);
4716                  if (option != (const char *) NULL)
4717                    s=newSVpv(option,0);
4718                }
4719              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4720              continue;
4721            }
4722          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4723            attribute);
4724          break;
4725        }
4726        case 'B':
4727        case 'b':
4728        {
4729          if (LocaleCompare(attribute,"background") == 0)
4730            {
4731              if (image == (Image *) NULL)
4732                break;
4733              (void) FormatLocaleString(color,MagickPathExtent,
4734                "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4735                (double) image->background_color.green,
4736                (double) image->background_color.blue,
4737                (double) image->background_color.alpha);
4738              s=newSVpv(color,0);
4739              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4740              continue;
4741            }
4742          if (LocaleCompare(attribute,"base-columns") == 0)
4743            {
4744              if (image != (Image *) NULL)
4745                s=newSViv((ssize_t) image->magick_columns);
4746              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4747              continue;
4748            }
4749          if (LocaleCompare(attribute,"base-filename") == 0)
4750            {
4751              if (image != (Image *) NULL)
4752                s=newSVpv(image->magick_filename,0);
4753              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4754              continue;
4755            }
4756          if (LocaleCompare(attribute,"base-height") == 0)
4757            {
4758              if (image != (Image *) NULL)
4759                s=newSViv((ssize_t) image->magick_rows);
4760              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761              continue;
4762            }
4763          if (LocaleCompare(attribute,"base-rows") == 0)
4764            {
4765              if (image != (Image *) NULL)
4766                s=newSViv((ssize_t) image->magick_rows);
4767              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4768              continue;
4769            }
4770          if (LocaleCompare(attribute,"base-width") == 0)
4771            {
4772              if (image != (Image *) NULL)
4773                s=newSViv((ssize_t) image->magick_columns);
4774              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4775              continue;
4776            }
4777          if (LocaleCompare(attribute,"blue-primary") == 0)
4778            {
4779              if (image == (Image *) NULL)
4780                break;
4781              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
4782                image->chromaticity.blue_primary.x,
4783                image->chromaticity.blue_primary.y);
4784              s=newSVpv(color,0);
4785              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4786              continue;
4787            }
4788          if (LocaleCompare(attribute,"bordercolor") == 0)
4789            {
4790              if (image == (Image *) NULL)
4791                break;
4792              (void) FormatLocaleString(color,MagickPathExtent,
4793                "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4794                (double) image->border_color.green,
4795                (double) image->border_color.blue,
4796                (double) image->border_color.alpha);
4797              s=newSVpv(color,0);
4798              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4799              continue;
4800            }
4801          if (LocaleCompare(attribute,"bounding-box") == 0)
4802            {
4803              char
4804                geometry[MagickPathExtent];
4805
4806              RectangleInfo
4807                page;
4808
4809              if (image == (Image *) NULL)
4810                break;
4811              page=GetImageBoundingBox(image,exception);
4812              (void) FormatLocaleString(geometry,MagickPathExtent,
4813                "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4814                page.height,(double) page.x,(double) page.y);
4815              s=newSVpv(geometry,0);
4816              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4817              continue;
4818            }
4819          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4820            attribute);
4821          break;
4822        }
4823        case 'C':
4824        case 'c':
4825        {
4826          if (LocaleCompare(attribute,"class") == 0)
4827            {
4828              if (image == (Image *) NULL)
4829                break;
4830              s=newSViv(image->storage_class);
4831              (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4832                image->storage_class));
4833              SvIOK_on(s);
4834              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4835              continue;
4836            }
4837          if (LocaleCompare(attribute,"clip-mask") == 0)
4838            {
4839              if (image != (Image *) NULL)
4840                {
4841                  Image
4842                    *mask_image;
4843
4844                  SV
4845                    *sv;
4846
4847                  sv=NULL;
4848                  if ((image->channels & WriteMaskChannel) == 0)
4849                    (void) ClipImage(image,exception);
4850                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4851                  if (mask_image != (Image *) NULL)
4852                    {
4853                      AddImageToRegistry(sv,mask_image);
4854                      s=sv_bless(newRV(sv),SvSTASH(reference));
4855                    }
4856                }
4857              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4858              continue;
4859            }
4860          if (LocaleCompare(attribute,"clip-path") == 0)
4861            {
4862              if (image != (Image *) NULL)
4863                {
4864                  Image
4865                    *mask_image;
4866
4867                  SV
4868                    *sv;
4869
4870                  sv=NULL;
4871                  if ((image->channels & WriteMaskChannel) == 0)
4872                    (void) ClipImage(image,exception);
4873                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4874                  if (mask_image != (Image *) NULL)
4875                    {
4876                      AddImageToRegistry(sv,mask_image);
4877                      s=sv_bless(newRV(sv),SvSTASH(reference));
4878                    }
4879                }
4880              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4881              continue;
4882            }
4883          if (LocaleCompare(attribute,"compression") == 0)
4884            {
4885              j=info ? info->image_info->compression : image ?
4886                image->compression : UndefinedCompression;
4887              if (info)
4888                if (info->image_info->compression == UndefinedCompression)
4889                  j=image->compression;
4890              s=newSViv(j);
4891              (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4892                j));
4893              SvIOK_on(s);
4894              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4895              continue;
4896            }
4897          if (LocaleCompare(attribute,"colorspace") == 0)
4898            {
4899              j=image ? image->colorspace : RGBColorspace;
4900              s=newSViv(j);
4901              (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4902                j));
4903              SvIOK_on(s);
4904              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4905              continue;
4906            }
4907          if (LocaleCompare(attribute,"colors") == 0)
4908            {
4909              if (image != (Image *) NULL)
4910                s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4911                  exception));
4912              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4913              continue;
4914            }
4915          if (LocaleNCompare(attribute,"colormap",8) == 0)
4916            {
4917              int
4918                items;
4919
4920              if (image == (Image *) NULL || !image->colormap)
4921                break;
4922              j=0;
4923              items=sscanf(attribute,"%*[^[][%ld",&j);
4924              (void) items;
4925              if (j > (ssize_t) image->colors)
4926                j%=image->colors;
4927              (void) FormatLocaleString(color,MagickPathExtent,
4928                "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4929                (double) image->colormap[j].green,
4930                (double) image->colormap[j].blue,
4931                (double) image->colormap[j].alpha);
4932              s=newSVpv(color,0);
4933              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4934              continue;
4935            }
4936          if (LocaleCompare(attribute,"columns") == 0)
4937            {
4938              if (image != (Image *) NULL)
4939                s=newSViv((ssize_t) image->columns);
4940              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4941              continue;
4942            }
4943          if (LocaleCompare(attribute,"comment") == 0)
4944            {
4945              const char
4946                *value;
4947
4948              value=GetImageProperty(image,attribute,exception);
4949              if (value != (const char *) NULL)
4950                s=newSVpv(value,0);
4951              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952              continue;
4953            }
4954          if (LocaleCompare(attribute,"copyright") == 0)
4955            {
4956              s=newSVpv(GetMagickCopyright(),0);
4957              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958              continue;
4959            }
4960          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4961            attribute);
4962          break;
4963        }
4964        case 'D':
4965        case 'd':
4966        {
4967          if (LocaleCompare(attribute,"density") == 0)
4968            {
4969              char
4970                geometry[MagickPathExtent];
4971
4972              if (image == (Image *) NULL)
4973                break;
4974              (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
4975                image->resolution.x,image->resolution.y);
4976              s=newSVpv(geometry,0);
4977              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978              continue;
4979            }
4980          if (LocaleCompare(attribute,"delay") == 0)
4981            {
4982              if (image != (Image *) NULL)
4983                s=newSViv((ssize_t) image->delay);
4984              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4985              continue;
4986            }
4987          if (LocaleCompare(attribute,"depth") == 0)
4988            {
4989              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4990              if (image != (Image *) NULL)
4991                s=newSViv((ssize_t) GetImageDepth(image,exception));
4992              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4993              continue;
4994            }
4995          if (LocaleCompare(attribute,"directory") == 0)
4996            {
4997              if (image && image->directory)
4998                s=newSVpv(image->directory,0);
4999              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000              continue;
5001            }
5002          if (LocaleCompare(attribute,"dispose") == 0)
5003            {
5004              if (image == (Image *) NULL)
5005                break;
5006
5007              s=newSViv(image->dispose);
5008              (void) sv_setpv(s,
5009                CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5010              SvIOK_on(s);
5011              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5012              continue;
5013            }
5014          if (LocaleCompare(attribute,"disk") == 0)
5015            {
5016              s=newSViv(GetMagickResource(DiskResource));
5017              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018              continue;
5019            }
5020          if (LocaleCompare(attribute,"dither") == 0)
5021            {
5022              if (info)
5023                s=newSViv((ssize_t) info->image_info->dither);
5024              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5025              continue;
5026            }
5027          if (LocaleCompare(attribute,"display") == 0)  /* same as server */
5028            {
5029              if (info && info->image_info->server_name)
5030                s=newSVpv(info->image_info->server_name,0);
5031              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5032              continue;
5033            }
5034          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5035            attribute);
5036          break;
5037        }
5038        case 'E':
5039        case 'e':
5040        {
5041          if (LocaleCompare(attribute,"elapsed-time") == 0)
5042            {
5043              if (image != (Image *) NULL)
5044                s=newSVnv(GetElapsedTime(&image->timer));
5045              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5046              continue;
5047            }
5048          if (LocaleCompare(attribute,"endian") == 0)
5049            {
5050              j=info ? info->image_info->endian : image ? image->endian :
5051                UndefinedEndian;
5052              s=newSViv(j);
5053              (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5054              SvIOK_on(s);
5055              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5056              continue;
5057            }
5058          if (LocaleCompare(attribute,"error") == 0)
5059            {
5060              if (image != (Image *) NULL)
5061                s=newSVnv(image->error.mean_error_per_pixel);
5062              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5063              continue;
5064            }
5065          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5066            attribute);
5067          break;
5068        }
5069        case 'F':
5070        case 'f':
5071        {
5072          if (LocaleCompare(attribute,"filesize") == 0)
5073            {
5074              if (image != (Image *) NULL)
5075                s=newSViv((ssize_t) GetBlobSize(image));
5076              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5077              continue;
5078            }
5079          if (LocaleCompare(attribute,"filename") == 0)
5080            {
5081              if (image != (Image *) NULL)
5082                s=newSVpv(image->filename,0);
5083              else
5084                if (info && *info->image_info->filename)
5085                  s=newSVpv(info->image_info->filename,0);
5086              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5087              continue;
5088            }
5089          if (LocaleCompare(attribute,"filter") == 0)
5090            {
5091              s=image ? newSViv(image->filter) : newSViv(0);
5092              (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5093                image->filter));
5094              SvIOK_on(s);
5095              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5096              continue;
5097            }
5098          if (LocaleCompare(attribute,"font") == 0)
5099            {
5100              if (info && info->image_info->font)
5101                s=newSVpv(info->image_info->font,0);
5102              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5103              continue;
5104            }
5105          if (LocaleCompare(attribute,"foreground") == 0)
5106            continue;
5107          if (LocaleCompare(attribute,"format") == 0)
5108            {
5109              const MagickInfo
5110                *magick_info;
5111
5112              magick_info=(const MagickInfo *) NULL;
5113              if (info && (*info->image_info->magick != '\0'))
5114                magick_info=GetMagickInfo(info->image_info->magick,exception);
5115              if (image != (Image *) NULL)
5116                magick_info=GetMagickInfo(image->magick,exception);
5117              if ((magick_info != (const MagickInfo *) NULL) &&
5118                  (*magick_info->description != '\0'))
5119                s=newSVpv((char *) magick_info->description,0);
5120              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5121              continue;
5122            }
5123          if (LocaleCompare(attribute,"fuzz") == 0)
5124            {
5125              if (info)
5126                s=newSVnv(info->image_info->fuzz);
5127              if (image != (Image *) NULL)
5128                s=newSVnv(image->fuzz);
5129              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5130              continue;
5131            }
5132          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5133            attribute);
5134          break;
5135        }
5136        case 'G':
5137        case 'g':
5138        {
5139          if (LocaleCompare(attribute,"gamma") == 0)
5140            {
5141              if (image != (Image *) NULL)
5142                s=newSVnv(image->gamma);
5143              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5144              continue;
5145            }
5146          if (LocaleCompare(attribute,"geometry") == 0)
5147            {
5148              if (image && image->geometry)
5149                s=newSVpv(image->geometry,0);
5150              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151              continue;
5152            }
5153          if (LocaleCompare(attribute,"gravity") == 0)
5154            {
5155              s=image ? newSViv(image->gravity) : newSViv(0);
5156              (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5157                image->gravity));
5158              SvIOK_on(s);
5159              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160              continue;
5161            }
5162          if (LocaleCompare(attribute,"green-primary") == 0)
5163            {
5164              if (image == (Image *) NULL)
5165                break;
5166              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5167                image->chromaticity.green_primary.x,
5168                image->chromaticity.green_primary.y);
5169              s=newSVpv(color,0);
5170              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5171              continue;
5172            }
5173          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5174            attribute);
5175          break;
5176        }
5177        case 'H':
5178        case 'h':
5179        {
5180          if (LocaleCompare(attribute,"height") == 0)
5181            {
5182              if (image != (Image *) NULL)
5183                s=newSViv((ssize_t) image->rows);
5184              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185              continue;
5186            }
5187          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5188            attribute);
5189          break;
5190        }
5191        case 'I':
5192        case 'i':
5193        {
5194          if (LocaleCompare(attribute,"icc") == 0)
5195            {
5196              if (image != (Image *) NULL)
5197                {
5198                  const StringInfo
5199                    *profile;
5200
5201                  profile=GetImageProfile(image,"icc");
5202                  if (profile != (StringInfo *) NULL)
5203                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5204                      GetStringInfoLength(profile));
5205                }
5206              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207              continue;
5208            }
5209          if (LocaleCompare(attribute,"icm") == 0)
5210            {
5211              if (image != (Image *) NULL)
5212                {
5213                  const StringInfo
5214                    *profile;
5215
5216                  profile=GetImageProfile(image,"icm");
5217                  if (profile != (const StringInfo *) NULL)
5218                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5219                      GetStringInfoLength(profile));
5220                }
5221              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5222              continue;
5223            }
5224          if (LocaleCompare(attribute,"id") == 0)
5225            {
5226              if (image != (Image *) NULL)
5227                {
5228                  char
5229                    key[MagickPathExtent];
5230
5231                  MagickBooleanType
5232                    status;
5233
5234                  static ssize_t
5235                    id = 0;
5236
5237                  (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5238                    id);
5239                  status=SetImageRegistry(ImageRegistryType,key,image,
5240                    exception);
5241                  (void) status;
5242                  s=newSViv(id++);
5243                }
5244              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5245              continue;
5246            }
5247          if (LocaleNCompare(attribute,"index",5) == 0)
5248            {
5249              char
5250                name[MagickPathExtent];
5251
5252              int
5253                items;
5254
5255              long
5256                x,
5257                y;
5258
5259              register const Quantum
5260                *p;
5261
5262              CacheView
5263                *image_view;
5264
5265              if (image == (Image *) NULL)
5266                break;
5267              if (image->storage_class != PseudoClass)
5268                break;
5269              x=0;
5270              y=0;
5271              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5272              (void) items;
5273              image_view=AcquireVirtualCacheView(image,exception);
5274              p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5275              if (p != (const Quantum *) NULL)
5276                {
5277                  (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5278                    GetPixelIndex(image,p));
5279                  s=newSVpv(name,0);
5280                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5281                }
5282              image_view=DestroyCacheView(image_view);
5283              continue;
5284            }
5285          if (LocaleCompare(attribute,"iptc") == 0)
5286            {
5287              if (image != (Image *) NULL)
5288                {
5289                  const StringInfo
5290                    *profile;
5291
5292                  profile=GetImageProfile(image,"iptc");
5293                  if (profile != (const StringInfo *) NULL)
5294                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5295                      GetStringInfoLength(profile));
5296                }
5297              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298              continue;
5299            }
5300          if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5301            {
5302              if (image != (Image *) NULL)
5303                s=newSViv((ssize_t) image->iterations);
5304              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5305              continue;
5306            }
5307          if (LocaleCompare(attribute,"interlace") == 0)
5308            {
5309              j=info ? info->image_info->interlace : image ? image->interlace :
5310                UndefinedInterlace;
5311              s=newSViv(j);
5312              (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5313                j));
5314              SvIOK_on(s);
5315              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316              continue;
5317            }
5318          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5319            attribute);
5320          break;
5321        }
5322        case 'L':
5323        case 'l':
5324        {
5325          if (LocaleCompare(attribute,"label") == 0)
5326            {
5327              const char
5328                *value;
5329
5330              if (image == (Image *) NULL)
5331                break;
5332              value=GetImageProperty(image,"Label",exception);
5333              if (value != (const char *) NULL)
5334                s=newSVpv(value,0);
5335              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5336              continue;
5337            }
5338          if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5339            {
5340              if (image != (Image *) NULL)
5341                s=newSViv((ssize_t) image->iterations);
5342              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343              continue;
5344            }
5345          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5346            attribute);
5347          break;
5348        }
5349        case 'M':
5350        case 'm':
5351        {
5352          if (LocaleCompare(attribute,"magick") == 0)
5353            {
5354              if (info && *info->image_info->magick)
5355                s=newSVpv(info->image_info->magick,0);
5356              if (image != (Image *) NULL)
5357                s=newSVpv(image->magick,0);
5358              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5359              continue;
5360            }
5361          if (LocaleCompare(attribute,"map") == 0)
5362            {
5363              s=newSViv(GetMagickResource(MapResource));
5364              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5365              continue;
5366            }
5367          if (LocaleCompare(attribute,"maximum-error") == 0)
5368            {
5369              if (image != (Image *) NULL)
5370                s=newSVnv(image->error.normalized_maximum_error);
5371              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5372              continue;
5373            }
5374          if (LocaleCompare(attribute,"memory") == 0)
5375            {
5376              s=newSViv(GetMagickResource(MemoryResource));
5377              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5378              continue;
5379            }
5380          if (LocaleCompare(attribute,"mean-error") == 0)
5381            {
5382              if (image != (Image *) NULL)
5383                s=newSVnv(image->error.normalized_mean_error);
5384              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5385              continue;
5386            }
5387          if (LocaleCompare(attribute,"mime") == 0)
5388            {
5389              if (info && *info->image_info->magick)
5390                s=newSVpv(MagickToMime(info->image_info->magick),0);
5391              if (image != (Image *) NULL)
5392                s=newSVpv(MagickToMime(image->magick),0);
5393              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5394              continue;
5395            }
5396          if (LocaleCompare(attribute,"mattecolor") == 0)
5397            {
5398              if (image == (Image *) NULL)
5399                break;
5400              (void) FormatLocaleString(color,MagickPathExtent,
5401                "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5402                (double) image->alpha_color.green,
5403                (double) image->alpha_color.blue,
5404                (double) image->alpha_color.alpha);
5405              s=newSVpv(color,0);
5406              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5407              continue;
5408            }
5409          if (LocaleCompare(attribute,"matte") == 0)
5410            {
5411              if (image != (Image *) NULL)
5412                s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5413                  1 : 0);
5414              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415              continue;
5416            }
5417          if (LocaleCompare(attribute,"mime") == 0)
5418            {
5419              const char
5420                *magick;
5421
5422              magick=NULL;
5423              if (info && *info->image_info->magick)
5424                magick=info->image_info->magick;
5425              if (image != (Image *) NULL)
5426                magick=image->magick;
5427              if (magick)
5428                {
5429                  char
5430                    *mime;
5431
5432                  mime=MagickToMime(magick);
5433                  s=newSVpv(mime,0);
5434                  mime=(char *) RelinquishMagickMemory(mime);
5435                }
5436              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5437              continue;
5438            }
5439          if (LocaleCompare(attribute,"monochrome") == 0)
5440            {
5441              if (image == (Image *) NULL)
5442                continue;
5443              j=info ? info->image_info->monochrome :
5444                SetImageMonochrome(image,exception);
5445              s=newSViv(j);
5446              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447              continue;
5448            }
5449          if (LocaleCompare(attribute,"montage") == 0)
5450            {
5451              if (image && image->montage)
5452                s=newSVpv(image->montage,0);
5453              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5454              continue;
5455            }
5456          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5457            attribute);
5458          break;
5459        }
5460        case 'O':
5461        case 'o':
5462        {
5463          if (LocaleCompare(attribute,"orientation") == 0)
5464            {
5465              j=info ? info->image_info->orientation : image ?
5466                image->orientation : UndefinedOrientation;
5467              s=newSViv(j);
5468              (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5469                j));
5470              SvIOK_on(s);
5471              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5472              continue;
5473            }
5474          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5475            attribute);
5476          break;
5477        }
5478        case 'P':
5479        case 'p':
5480        {
5481          if (LocaleCompare(attribute,"page") == 0)
5482            {
5483              if (info && info->image_info->page)
5484                s=newSVpv(info->image_info->page,0);
5485              if (image != (Image *) NULL)
5486                {
5487                  char
5488                    geometry[MagickPathExtent];
5489
5490                  (void) FormatLocaleString(geometry,MagickPathExtent,
5491                    "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5492                    (double) image->page.height,(double) image->page.x,(double)
5493                    image->page.y);
5494                  s=newSVpv(geometry,0);
5495                }
5496              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497              continue;
5498            }
5499          if (LocaleCompare(attribute,"page.x") == 0)
5500            {
5501              if (image != (Image *) NULL)
5502                s=newSViv((ssize_t) image->page.x);
5503              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5504              continue;
5505            }
5506          if (LocaleCompare(attribute,"page.y") == 0)
5507            {
5508              if (image != (Image *) NULL)
5509                s=newSViv((ssize_t) image->page.y);
5510              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5511              continue;
5512            }
5513          if (LocaleNCompare(attribute,"pixel",5) == 0)
5514            {
5515              char
5516                tuple[MagickPathExtent];
5517
5518              int
5519                items;
5520
5521              long
5522                x,
5523                y;
5524
5525              register const Quantum
5526                *p;
5527
5528              if (image == (Image *) NULL)
5529                break;
5530              x=0;
5531              y=0;
5532              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5533              (void) items;
5534              p=GetVirtualPixels(image,x,y,1,1,exception);
5535              if (image->colorspace != CMYKColorspace)
5536                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5537                  QuantumFormat "," QuantumFormat "," QuantumFormat,
5538                  GetPixelRed(image,p),GetPixelGreen(image,p),
5539                  GetPixelBlue(image,p),GetPixelAlpha(image,p));
5540              else
5541                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5542                  QuantumFormat "," QuantumFormat "," QuantumFormat ","
5543                  QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5544                  GetPixelBlue(image,p),GetPixelBlack(image,p),
5545                  GetPixelAlpha(image,p));
5546              s=newSVpv(tuple,0);
5547              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5548              continue;
5549            }
5550          if (LocaleCompare(attribute,"pointsize") == 0)
5551            {
5552              if (info)
5553                s=newSViv((ssize_t) info->image_info->pointsize);
5554              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5555              continue;
5556            }
5557          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5558            attribute);
5559          break;
5560        }
5561        case 'Q':
5562        case 'q':
5563        {
5564          if (LocaleCompare(attribute,"quality") == 0)
5565            {
5566              if (info)
5567                s=newSViv((ssize_t) info->image_info->quality);
5568              if (image != (Image *) NULL)
5569                s=newSViv((ssize_t) image->quality);
5570              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5571              continue;
5572            }
5573          if (LocaleCompare(attribute,"quantum") == 0)
5574            {
5575              if (info)
5576                s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5577              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578              continue;
5579            }
5580          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5581            attribute);
5582          break;
5583        }
5584        case 'R':
5585        case 'r':
5586        {
5587          if (LocaleCompare(attribute,"rendering-intent") == 0)
5588            {
5589              s=newSViv(image->rendering_intent);
5590              (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5591                image->rendering_intent));
5592              SvIOK_on(s);
5593              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594              continue;
5595            }
5596          if (LocaleCompare(attribute,"red-primary") == 0)
5597            {
5598              if (image == (Image *) NULL)
5599                break;
5600              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5601                image->chromaticity.red_primary.x,
5602                image->chromaticity.red_primary.y);
5603              s=newSVpv(color,0);
5604              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5605              continue;
5606            }
5607          if (LocaleCompare(attribute,"rows") == 0)
5608            {
5609              if (image != (Image *) NULL)
5610                s=newSViv((ssize_t) image->rows);
5611              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5612              continue;
5613            }
5614          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5615            attribute);
5616          break;
5617        }
5618        case 'S':
5619        case 's':
5620        {
5621          if (LocaleCompare(attribute,"sampling-factor") == 0)
5622            {
5623              if (info && info->image_info->sampling_factor)
5624                s=newSVpv(info->image_info->sampling_factor,0);
5625              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626              continue;
5627            }
5628          if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5629            {
5630              if (info && info->image_info->server_name)
5631                s=newSVpv(info->image_info->server_name,0);
5632              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5633              continue;
5634            }
5635          if (LocaleCompare(attribute,"size") == 0)
5636            {
5637              if (info && info->image_info->size)
5638                s=newSVpv(info->image_info->size,0);
5639              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5640              continue;
5641            }
5642          if (LocaleCompare(attribute,"scene") == 0)
5643            {
5644              if (image != (Image *) NULL)
5645                s=newSViv((ssize_t) image->scene);
5646              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5647              continue;
5648            }
5649          if (LocaleCompare(attribute,"scenes") == 0)
5650            {
5651              if (image != (Image *) NULL)
5652                s=newSViv((ssize_t) info->image_info->number_scenes);
5653              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5654              continue;
5655            }
5656          if (LocaleCompare(attribute,"signature") == 0)
5657            {
5658              const char
5659                *value;
5660
5661              if (image == (Image *) NULL)
5662                break;
5663              (void) SignatureImage(image,exception);
5664              value=GetImageProperty(image,"Signature",exception);
5665              if (value != (const char *) NULL)
5666                s=newSVpv(value,0);
5667              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5668              continue;
5669            }
5670          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5671            attribute);
5672          break;
5673        }
5674        case 'T':
5675        case 't':
5676        {
5677          if (LocaleCompare(attribute,"taint") == 0)
5678            {
5679              if (image != (Image *) NULL)
5680                s=newSViv((ssize_t) IsTaintImage(image));
5681              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5682              continue;
5683            }
5684          if (LocaleCompare(attribute,"texture") == 0)
5685            {
5686              if (info && info->image_info->texture)
5687                s=newSVpv(info->image_info->texture,0);
5688              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5689              continue;
5690            }
5691          if (LocaleCompare(attribute,"total-ink-density") == 0)
5692            {
5693              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5694              if (image != (Image *) NULL)
5695                s=newSVnv(GetImageTotalInkDensity(image,exception));
5696              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5697              continue;
5698            }
5699          if (LocaleCompare(attribute,"transparent-color") == 0)
5700            {
5701              if (image == (Image *) NULL)
5702                break;
5703              (void) FormatLocaleString(color,MagickPathExtent,
5704                "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5705                (double) image->transparent_color.green,
5706                (double) image->transparent_color.blue,
5707                (double) image->transparent_color.alpha);
5708              s=newSVpv(color,0);
5709              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5710              continue;
5711            }
5712          if (LocaleCompare(attribute,"type") == 0)
5713            {
5714              if (image == (Image *) NULL)
5715                break;
5716              j=(ssize_t) GetImageType(image);
5717              s=newSViv(j);
5718              (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5719              SvIOK_on(s);
5720              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5721              continue;
5722            }
5723          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5724            attribute);
5725          break;
5726        }
5727        case 'U':
5728        case 'u':
5729        {
5730          if (LocaleCompare(attribute,"units") == 0)
5731            {
5732              j=info ? info->image_info->units : image ? image->units :
5733                UndefinedResolution;
5734              if (info && (info->image_info->units == UndefinedResolution))
5735                if (image)
5736                  j=image->units;
5737              if (j == UndefinedResolution)
5738                s=newSVpv("undefined units",0);
5739              else
5740                if (j == PixelsPerInchResolution)
5741                  s=newSVpv("pixels / inch",0);
5742                else
5743                  s=newSVpv("pixels / centimeter",0);
5744              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5745              continue;
5746            }
5747          if (LocaleCompare(attribute,"user-time") == 0)
5748            {
5749              if (image != (Image *) NULL)
5750                s=newSVnv(GetUserTime(&image->timer));
5751              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5752              continue;
5753            }
5754          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5755            attribute);
5756          break;
5757        }
5758        case 'V':
5759        case 'v':
5760        {
5761          if (LocaleCompare(attribute,"verbose") == 0)
5762            {
5763              if (info)
5764                s=newSViv((ssize_t) info->image_info->verbose);
5765              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5766              continue;
5767            }
5768          if (LocaleCompare(attribute,"version") == 0)
5769            {
5770              s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5771              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5772              continue;
5773            }
5774          if (LocaleCompare(attribute,"virtual-pixel") == 0)
5775            {
5776              if (image == (Image *) NULL)
5777                break;
5778              j=(ssize_t) GetImageVirtualPixelMethod(image);
5779              s=newSViv(j);
5780              (void) sv_setpv(s,CommandOptionToMnemonic(
5781                MagickVirtualPixelOptions,j));
5782              SvIOK_on(s);
5783              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5784              continue;
5785            }
5786          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5787            attribute);
5788          break;
5789        }
5790        case 'W':
5791        case 'w':
5792        {
5793          if (LocaleCompare(attribute,"white-point") == 0)
5794            {
5795              if (image == (Image *) NULL)
5796                break;
5797              (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5798                image->chromaticity.white_point.x,
5799                image->chromaticity.white_point.y);
5800              s=newSVpv(color,0);
5801              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5802              continue;
5803            }
5804          if (LocaleCompare(attribute,"width") == 0)
5805            {
5806              if (image != (Image *) NULL)
5807                s=newSViv((ssize_t) image->columns);
5808              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5809              continue;
5810            }
5811          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5812             attribute);
5813          break;
5814        }
5815        case 'X':
5816        case 'x':
5817        {
5818          if (LocaleCompare(attribute,"xmp") == 0)
5819            {
5820              if (image != (Image *) NULL)
5821                {
5822                  const StringInfo
5823                    *profile;
5824
5825                  profile=GetImageProfile(image,"xmp");
5826                  if (profile != (StringInfo *) NULL)
5827                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5828                      GetStringInfoLength(profile));
5829                }
5830              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5831              continue;
5832            }
5833          if (LocaleCompare(attribute,"x-resolution") == 0)
5834            {
5835              if (image != (Image *) NULL)
5836                s=newSVnv(image->resolution.x);
5837              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5838              continue;
5839            }
5840          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5841            attribute);
5842          break;
5843        }
5844        case 'Y':
5845        case 'y':
5846        {
5847          if (LocaleCompare(attribute,"y-resolution") == 0)
5848            {
5849              if (image != (Image *) NULL)
5850                s=newSVnv(image->resolution.y);
5851              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5852              continue;
5853            }
5854          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5855            attribute);
5856          break;
5857        }
5858        default:
5859          break;
5860      }
5861      if (image == (Image *) NULL)
5862        ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5863          attribute)
5864      else
5865        {
5866          value=GetImageProperty(image,attribute,exception);
5867          if (value != (const char *) NULL)
5868            {
5869              s=newSVpv(value,0);
5870              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5871            }
5872          else
5873            if (*attribute != '%')
5874              ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5875                attribute)
5876            else
5877              {
5878                 char
5879                   *meta;
5880
5881                 meta=InterpretImageProperties(info ? info->image_info :
5882                   (ImageInfo *) NULL,image,attribute,exception);
5883                 s=newSVpv(meta,0);
5884                 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5885                 meta=(char *) RelinquishMagickMemory(meta);
5886              }
5887        }
5888    }
5889    exception=DestroyExceptionInfo(exception);
5890    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5891  }
5892
5893#
5894###############################################################################
5895#                                                                             #
5896#                                                                             #
5897#                                                                             #
5898#   G e t A u t h e n t i c P i x e l s                                       #
5899#                                                                             #
5900#                                                                             #
5901#                                                                             #
5902###############################################################################
5903#
5904#
5905void *
5906GetAuthenticPixels(ref,...)
5907  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5908  ALIAS:
5909    getauthenticpixels = 1
5910    GetImagePixels = 2
5911    getimagepixels = 3
5912  CODE:
5913  {
5914    char
5915      *attribute;
5916
5917    ExceptionInfo
5918      *exception;
5919
5920    Image
5921      *image;
5922
5923    RectangleInfo
5924      region;
5925
5926    ssize_t
5927      i;
5928
5929    struct PackageInfo
5930      *info;
5931
5932    SV
5933      *perl_exception,
5934      *reference;
5935
5936    void
5937      *blob = NULL;
5938
5939    PERL_UNUSED_VAR(ref);
5940    PERL_UNUSED_VAR(ix);
5941    exception=AcquireExceptionInfo();
5942    perl_exception=newSVpv("",0);
5943    if (sv_isobject(ST(0)) == 0)
5944      {
5945        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5946          PackageName);
5947        goto PerlException;
5948      }
5949    reference=SvRV(ST(0));
5950
5951    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5952    if (image == (Image *) NULL)
5953      {
5954        ThrowPerlException(exception,OptionError,"NoImagesDefined",
5955          PackageName);
5956        goto PerlException;
5957      }
5958
5959    region.x=0;
5960    region.y=0;
5961    region.width=image->columns;
5962    region.height=1;
5963    if (items == 1)
5964      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5965    for (i=2; i < items; i+=2)
5966    {
5967      attribute=(char *) SvPV(ST(i-1),na);
5968      switch (*attribute)
5969      {
5970        case 'g':
5971        case 'G':
5972        {
5973          if (LocaleCompare(attribute,"geometry") == 0)
5974            {
5975              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5976              break;
5977            }
5978          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5979            attribute);
5980          break;
5981        }
5982        case 'H':
5983        case 'h':
5984        {
5985          if (LocaleCompare(attribute,"height") == 0)
5986            {
5987              region.height=SvIV(ST(i));
5988              continue;
5989            }
5990          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5991            attribute);
5992          break;
5993        }
5994        case 'X':
5995        case 'x':
5996        {
5997          if (LocaleCompare(attribute,"x") == 0)
5998            {
5999              region.x=SvIV(ST(i));
6000              continue;
6001            }
6002          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6003            attribute);
6004          break;
6005        }
6006        case 'Y':
6007        case 'y':
6008        {
6009          if (LocaleCompare(attribute,"y") == 0)
6010            {
6011              region.y=SvIV(ST(i));
6012              continue;
6013            }
6014          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6015            attribute);
6016          break;
6017        }
6018        case 'W':
6019        case 'w':
6020        {
6021          if (LocaleCompare(attribute,"width") == 0)
6022            {
6023              region.width=SvIV(ST(i));
6024              continue;
6025            }
6026          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6027            attribute);
6028          break;
6029        }
6030      }
6031    }
6032    blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6033      region.height,exception);
6034    if (blob != (void *) NULL)
6035      goto PerlEnd;
6036
6037  PerlException:
6038    InheritPerlException(exception,perl_exception);
6039    exception=DestroyExceptionInfo(exception);
6040    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6041
6042  PerlEnd:
6043    RETVAL = blob;
6044  }
6045  OUTPUT:
6046    RETVAL
6047
6048#
6049###############################################################################
6050#                                                                             #
6051#                                                                             #
6052#                                                                             #
6053#   G e t V i r t u a l P i x e l s                                           #
6054#                                                                             #
6055#                                                                             #
6056#                                                                             #
6057###############################################################################
6058#
6059#
6060void *
6061GetVirtualPixels(ref,...)
6062  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6063  ALIAS:
6064    getvirtualpixels = 1
6065    AcquireImagePixels = 2
6066    acquireimagepixels = 3
6067  CODE:
6068  {
6069    char
6070      *attribute;
6071
6072    const void
6073      *blob = NULL;
6074
6075    ExceptionInfo
6076      *exception;
6077
6078    Image
6079      *image;
6080
6081    RectangleInfo
6082      region;
6083
6084    ssize_t
6085      i;
6086
6087    struct PackageInfo
6088      *info;
6089
6090    SV
6091      *perl_exception,
6092      *reference;
6093
6094    PERL_UNUSED_VAR(ref);
6095    PERL_UNUSED_VAR(ix);
6096    exception=AcquireExceptionInfo();
6097    perl_exception=newSVpv("",0);
6098    if (sv_isobject(ST(0)) == 0)
6099      {
6100        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6101          PackageName);
6102        goto PerlException;
6103      }
6104    reference=SvRV(ST(0));
6105
6106    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6107    if (image == (Image *) NULL)
6108      {
6109        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6110          PackageName);
6111        goto PerlException;
6112      }
6113
6114    region.x=0;
6115    region.y=0;
6116    region.width=image->columns;
6117    region.height=1;
6118    if (items == 1)
6119      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6120    for (i=2; i < items; i+=2)
6121    {
6122      attribute=(char *) SvPV(ST(i-1),na);
6123      switch (*attribute)
6124      {
6125        case 'g':
6126        case 'G':
6127        {
6128          if (LocaleCompare(attribute,"geometry") == 0)
6129            {
6130              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6131              break;
6132            }
6133          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6134            attribute);
6135          break;
6136        }
6137        case 'H':
6138        case 'h':
6139        {
6140          if (LocaleCompare(attribute,"height") == 0)
6141            {
6142              region.height=SvIV(ST(i));
6143              continue;
6144            }
6145          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6146            attribute);
6147          break;
6148        }
6149        case 'X':
6150        case 'x':
6151        {
6152          if (LocaleCompare(attribute,"x") == 0)
6153            {
6154              region.x=SvIV(ST(i));
6155              continue;
6156            }
6157          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6158            attribute);
6159          break;
6160        }
6161        case 'Y':
6162        case 'y':
6163        {
6164          if (LocaleCompare(attribute,"y") == 0)
6165            {
6166              region.y=SvIV(ST(i));
6167              continue;
6168            }
6169          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6170            attribute);
6171          break;
6172        }
6173        case 'W':
6174        case 'w':
6175        {
6176          if (LocaleCompare(attribute,"width") == 0)
6177            {
6178              region.width=SvIV(ST(i));
6179              continue;
6180            }
6181          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6182            attribute);
6183          break;
6184        }
6185      }
6186    }
6187    blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6188      region.height,exception);
6189    if (blob != (void *) NULL)
6190      goto PerlEnd;
6191
6192  PerlException:
6193    InheritPerlException(exception,perl_exception);
6194    exception=DestroyExceptionInfo(exception);
6195    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6196
6197  PerlEnd:
6198    RETVAL = (void *) blob;
6199  }
6200  OUTPUT:
6201    RETVAL
6202
6203#
6204###############################################################################
6205#                                                                             #
6206#                                                                             #
6207#                                                                             #
6208#   G e t A u t h e n t i c M e t a c o n t e n t                             #
6209#                                                                             #
6210#                                                                             #
6211#                                                                             #
6212###############################################################################
6213#
6214#
6215void *
6216GetAuthenticMetacontent(ref,...)
6217  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6218  ALIAS:
6219    getauthenticmetacontent = 1
6220    GetMetacontent = 2
6221    getmetacontent = 3
6222  CODE:
6223  {
6224    ExceptionInfo
6225      *exception;
6226
6227    Image
6228      *image;
6229
6230    struct PackageInfo
6231      *info;
6232
6233    SV
6234      *perl_exception,
6235      *reference;
6236
6237    void
6238      *blob = NULL;
6239
6240    PERL_UNUSED_VAR(ref);
6241    PERL_UNUSED_VAR(ix);
6242    exception=AcquireExceptionInfo();
6243    perl_exception=newSVpv("",0);
6244    if (sv_isobject(ST(0)) == 0)
6245      {
6246        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6247          PackageName);
6248        goto PerlException;
6249      }
6250    reference=SvRV(ST(0));
6251
6252    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6253    if (image == (Image *) NULL)
6254      {
6255        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6256          PackageName);
6257        goto PerlException;
6258      }
6259
6260    blob=(void *) GetAuthenticMetacontent(image);
6261    if (blob != (void *) NULL)
6262      goto PerlEnd;
6263
6264  PerlException:
6265    InheritPerlException(exception,perl_exception);
6266    exception=DestroyExceptionInfo(exception);
6267    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6268
6269  PerlEnd:
6270    RETVAL = blob;
6271  }
6272  OUTPUT:
6273    RETVAL
6274
6275#
6276###############################################################################
6277#                                                                             #
6278#                                                                             #
6279#                                                                             #
6280#   G e t V i r t u a l M e t a c o n t e n t                                 #
6281#                                                                             #
6282#                                                                             #
6283#                                                                             #
6284###############################################################################
6285#
6286#
6287void *
6288GetVirtualMetacontent(ref,...)
6289  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6290  ALIAS:
6291    getvirtualmetacontent = 1
6292  CODE:
6293  {
6294    ExceptionInfo
6295      *exception;
6296
6297    Image
6298      *image;
6299
6300    struct PackageInfo
6301      *info;
6302
6303    SV
6304      *perl_exception,
6305      *reference;
6306
6307    void
6308      *blob = NULL;
6309
6310    PERL_UNUSED_VAR(ref);
6311    PERL_UNUSED_VAR(ix);
6312    exception=AcquireExceptionInfo();
6313    perl_exception=newSVpv("",0);
6314    if (sv_isobject(ST(0)) == 0)
6315      {
6316        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6317          PackageName);
6318        goto PerlException;
6319      }
6320    reference=SvRV(ST(0));
6321
6322    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6323    if (image == (Image *) NULL)
6324      {
6325        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6326          PackageName);
6327        goto PerlException;
6328      }
6329
6330    blob=(void *) GetVirtualMetacontent(image);
6331    if (blob != (void *) NULL)
6332      goto PerlEnd;
6333
6334  PerlException:
6335    InheritPerlException(exception,perl_exception);
6336    exception=DestroyExceptionInfo(exception);
6337    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6338
6339  PerlEnd:
6340    RETVAL = blob;
6341  }
6342  OUTPUT:
6343    RETVAL
6344
6345#
6346###############################################################################
6347#                                                                             #
6348#                                                                             #
6349#                                                                             #
6350#   H i s t o g r a m                                                         #
6351#                                                                             #
6352#                                                                             #
6353#                                                                             #
6354###############################################################################
6355#
6356#
6357void
6358Histogram(ref,...)
6359  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6360  ALIAS:
6361    HistogramImage = 1
6362    histogram      = 2
6363    histogramimage = 3
6364  PPCODE:
6365  {
6366    AV
6367      *av;
6368
6369    char
6370      message[MagickPathExtent];
6371
6372    PixelInfo
6373      *histogram;
6374
6375    ExceptionInfo
6376      *exception;
6377
6378    Image
6379      *image;
6380
6381    register ssize_t
6382      i;
6383
6384    ssize_t
6385      count;
6386
6387    struct PackageInfo
6388      *info;
6389
6390    SV
6391      *perl_exception,
6392      *reference;
6393
6394    size_t
6395      number_colors;
6396
6397    PERL_UNUSED_VAR(ref);
6398    PERL_UNUSED_VAR(ix);
6399    exception=AcquireExceptionInfo();
6400    perl_exception=newSVpv("",0);
6401    av=NULL;
6402    if (sv_isobject(ST(0)) == 0)
6403      {
6404        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6405          PackageName);
6406        goto PerlException;
6407      }
6408    reference=SvRV(ST(0));
6409    av=newAV();
6410    SvREFCNT_dec(av);
6411    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6412    if (image == (Image *) NULL)
6413      {
6414        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6415          PackageName);
6416        goto PerlException;
6417      }
6418    count=0;
6419    for ( ; image; image=image->next)
6420    {
6421      histogram=GetImageHistogram(image,&number_colors,exception);
6422      if (histogram == (PixelInfo *) NULL)
6423        continue;
6424      count+=(ssize_t) number_colors;
6425      EXTEND(sp,6*count);
6426      for (i=0; i < (ssize_t) number_colors; i++)
6427      {
6428        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6429          histogram[i].red);
6430        PUSHs(sv_2mortal(newSVpv(message,0)));
6431        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6432          histogram[i].green);
6433        PUSHs(sv_2mortal(newSVpv(message,0)));
6434        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6435          histogram[i].blue);
6436        PUSHs(sv_2mortal(newSVpv(message,0)));
6437        if (image->colorspace == CMYKColorspace)
6438          {
6439            (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6440              histogram[i].black);
6441            PUSHs(sv_2mortal(newSVpv(message,0)));
6442          }
6443        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6444          histogram[i].alpha);
6445        PUSHs(sv_2mortal(newSVpv(message,0)));
6446        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6447          histogram[i].count);
6448        PUSHs(sv_2mortal(newSVpv(message,0)));
6449      }
6450      histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6451    }
6452
6453  PerlException:
6454    InheritPerlException(exception,perl_exception);
6455    exception=DestroyExceptionInfo(exception);
6456    SvREFCNT_dec(perl_exception);
6457  }
6458
6459#
6460###############################################################################
6461#                                                                             #
6462#                                                                             #
6463#                                                                             #
6464#   G e t P i x e l                                                           #
6465#                                                                             #
6466#                                                                             #
6467#                                                                             #
6468###############################################################################
6469#
6470#
6471void
6472GetPixel(ref,...)
6473  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6474  ALIAS:
6475    getpixel = 1
6476    getPixel = 2
6477  PPCODE:
6478  {
6479    AV
6480      *av;
6481
6482    char
6483      *attribute;
6484
6485    ExceptionInfo
6486      *exception;
6487
6488    Image
6489      *image;
6490
6491    MagickBooleanType
6492      normalize;
6493
6494    RectangleInfo
6495      region;
6496
6497    register const Quantum
6498      *p;
6499
6500    register ssize_t
6501      i;
6502
6503    ssize_t
6504      option;
6505
6506    struct PackageInfo
6507      *info;
6508
6509    SV
6510      *perl_exception,
6511      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6512
6513    PERL_UNUSED_VAR(ref);
6514    PERL_UNUSED_VAR(ix);
6515    exception=AcquireExceptionInfo();
6516    perl_exception=newSVpv("",0);
6517    reference=SvRV(ST(0));
6518    av=(AV *) reference;
6519    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6520      exception);
6521    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6522    if (image == (Image *) NULL)
6523      {
6524        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6525          PackageName);
6526        goto PerlException;
6527      }
6528    normalize=MagickTrue;
6529    region.x=0;
6530    region.y=0;
6531    region.width=image->columns;
6532    region.height=1;
6533    if (items == 1)
6534      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6535    for (i=2; i < items; i+=2)
6536    {
6537      attribute=(char *) SvPV(ST(i-1),na);
6538      switch (*attribute)
6539      {
6540        case 'C':
6541        case 'c':
6542        {
6543          if (LocaleCompare(attribute,"channel") == 0)
6544            {
6545              ssize_t
6546                option;
6547
6548              option=ParseChannelOption(SvPV(ST(i),na));
6549              if (option < 0)
6550                {
6551                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6552                    SvPV(ST(i),na));
6553                  return;
6554                }
6555              (void) SetPixelChannelMask(image,(ChannelType) option);
6556              break;
6557            }
6558          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6559            attribute);
6560          break;
6561        }
6562        case 'g':
6563        case 'G':
6564        {
6565          if (LocaleCompare(attribute,"geometry") == 0)
6566            {
6567              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6568              break;
6569            }
6570          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6571            attribute);
6572          break;
6573        }
6574        case 'N':
6575        case 'n':
6576        {
6577          if (LocaleCompare(attribute,"normalize") == 0)
6578            {
6579              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6580                SvPV(ST(i),na));
6581              if (option < 0)
6582                {
6583                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6584                    SvPV(ST(i),na));
6585                  break;
6586                }
6587             normalize=option != 0 ? MagickTrue : MagickFalse;
6588             break;
6589            }
6590          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6591            attribute);
6592          break;
6593        }
6594        case 'x':
6595        case 'X':
6596        {
6597          if (LocaleCompare(attribute,"x") == 0)
6598            {
6599              region.x=SvIV(ST(i));
6600              break;
6601            }
6602          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6603            attribute);
6604          break;
6605        }
6606        case 'y':
6607        case 'Y':
6608        {
6609          if (LocaleCompare(attribute,"y") == 0)
6610            {
6611              region.y=SvIV(ST(i));
6612              break;
6613            }
6614          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6615            attribute);
6616          break;
6617        }
6618        default:
6619        {
6620          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6621            attribute);
6622          break;
6623        }
6624      }
6625    }
6626    p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6627    if (p == (const Quantum *) NULL)
6628      PUSHs(&sv_undef);
6629    else
6630      {
6631        double
6632          scale;
6633
6634        scale=1.0;
6635        if (normalize != MagickFalse)
6636          scale=1.0/QuantumRange;
6637        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6638          PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6639        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6640          PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6641        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6642          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6643        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6644            (image->colorspace == CMYKColorspace))
6645          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6646        if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6647          PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6648      }
6649
6650  PerlException:
6651    InheritPerlException(exception,perl_exception);
6652    exception=DestroyExceptionInfo(exception);
6653    SvREFCNT_dec(perl_exception);
6654  }
6655
6656#
6657###############################################################################
6658#                                                                             #
6659#                                                                             #
6660#                                                                             #
6661#   G e t P i x e l s                                                         #
6662#                                                                             #
6663#                                                                             #
6664#                                                                             #
6665###############################################################################
6666#
6667#
6668void
6669GetPixels(ref,...)
6670  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6671  ALIAS:
6672    getpixels = 1
6673    getPixels = 2
6674  PPCODE:
6675  {
6676    AV
6677      *av;
6678
6679    char
6680      *attribute;
6681
6682    const char
6683      *map;
6684
6685    ExceptionInfo
6686      *exception;
6687
6688    Image
6689      *image;
6690
6691    MagickBooleanType
6692      normalize,
6693      status;
6694
6695    RectangleInfo
6696      region;
6697
6698    register ssize_t
6699      i;
6700
6701    ssize_t
6702      option;
6703
6704    struct PackageInfo
6705      *info;
6706
6707    SV
6708      *perl_exception,
6709      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6710
6711    PERL_UNUSED_VAR(ref);
6712    PERL_UNUSED_VAR(ix);
6713    exception=AcquireExceptionInfo();
6714    perl_exception=newSVpv("",0);
6715    reference=SvRV(ST(0));
6716    av=(AV *) reference;
6717    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6718      exception);
6719    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6720    if (image == (Image *) NULL)
6721      {
6722        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6723          PackageName);
6724        goto PerlException;
6725      }
6726    map="RGB";
6727    if (image->alpha_trait != UndefinedPixelTrait)
6728      map="RGBA";
6729    if (image->colorspace == CMYKColorspace)
6730      {
6731        map="CMYK";
6732        if (image->alpha_trait != UndefinedPixelTrait)
6733          map="CMYKA";
6734      }
6735    normalize=MagickFalse;
6736    region.x=0;
6737    region.y=0;
6738    region.width=image->columns;
6739    region.height=1;
6740    if (items == 1)
6741      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6742    for (i=2; i < items; i+=2)
6743    {
6744      attribute=(char *) SvPV(ST(i-1),na);
6745      switch (*attribute)
6746      {
6747        case 'g':
6748        case 'G':
6749        {
6750          if (LocaleCompare(attribute,"geometry") == 0)
6751            {
6752              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6753              break;
6754            }
6755          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6756            attribute);
6757          break;
6758        }
6759        case 'H':
6760        case 'h':
6761        {
6762          if (LocaleCompare(attribute,"height") == 0)
6763            {
6764              region.height=SvIV(ST(i));
6765              break;
6766            }
6767          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6768            attribute);
6769          break;
6770        }
6771        case 'M':
6772        case 'm':
6773        {
6774          if (LocaleCompare(attribute,"map") == 0)
6775            {
6776              map=SvPV(ST(i),na);
6777              break;
6778            }
6779          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6780            attribute);
6781          break;
6782        }
6783        case 'N':
6784        case 'n':
6785        {
6786          if (LocaleCompare(attribute,"normalize") == 0)
6787            {
6788              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6789                SvPV(ST(i),na));
6790              if (option < 0)
6791                {
6792                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6793                    SvPV(ST(i),na));
6794                  break;
6795                }
6796             normalize=option != 0 ? MagickTrue : MagickFalse;
6797             break;
6798            }
6799          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6800            attribute);
6801          break;
6802        }
6803        case 'W':
6804        case 'w':
6805        {
6806          if (LocaleCompare(attribute,"width") == 0)
6807            {
6808              region.width=SvIV(ST(i));
6809              break;
6810            }
6811          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6812            attribute);
6813          break;
6814        }
6815        case 'x':
6816        case 'X':
6817        {
6818          if (LocaleCompare(attribute,"x") == 0)
6819            {
6820              region.x=SvIV(ST(i));
6821              break;
6822            }
6823          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6824            attribute);
6825          break;
6826        }
6827        case 'y':
6828        case 'Y':
6829        {
6830          if (LocaleCompare(attribute,"y") == 0)
6831            {
6832              region.y=SvIV(ST(i));
6833              break;
6834            }
6835          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6836            attribute);
6837          break;
6838        }
6839        default:
6840        {
6841          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6842            attribute);
6843          break;
6844        }
6845      }
6846    }
6847    if (normalize != MagickFalse)
6848      {
6849        float
6850          *pixels;
6851
6852        pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6853          region.height*sizeof(*pixels));
6854        if (pixels == (float *) NULL)
6855          {
6856            ThrowPerlException(exception,ResourceLimitError,
6857              "MemoryAllocationFailed",PackageName);
6858            goto PerlException;
6859          }
6860        status=ExportImagePixels(image,region.x,region.y,region.width,
6861          region.height,map,FloatPixel,pixels,exception);
6862        if (status == MagickFalse)
6863          PUSHs(&sv_undef);
6864        else
6865          {
6866            EXTEND(sp,strlen(map)*region.width*region.height);
6867            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6868              PUSHs(sv_2mortal(newSVnv(pixels[i])));
6869          }
6870        pixels=(float *) RelinquishMagickMemory(pixels);
6871      }
6872    else
6873      {
6874        Quantum
6875          *pixels;
6876
6877        pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6878          region.height*sizeof(*pixels));
6879        if (pixels == (Quantum *) NULL)
6880          {
6881            ThrowPerlException(exception,ResourceLimitError,
6882              "MemoryAllocationFailed",PackageName);
6883            goto PerlException;
6884          }
6885        status=ExportImagePixels(image,region.x,region.y,region.width,
6886          region.height,map,QuantumPixel,pixels,exception);
6887        if (status == MagickFalse)
6888          PUSHs(&sv_undef);
6889        else
6890          {
6891            EXTEND(sp,strlen(map)*region.width*region.height);
6892            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6893              PUSHs(sv_2mortal(newSViv(pixels[i])));
6894          }
6895        pixels=(Quantum *) RelinquishMagickMemory(pixels);
6896      }
6897
6898  PerlException:
6899    InheritPerlException(exception,perl_exception);
6900    exception=DestroyExceptionInfo(exception);
6901    SvREFCNT_dec(perl_exception);
6902  }
6903
6904#
6905###############################################################################
6906#                                                                             #
6907#                                                                             #
6908#                                                                             #
6909#   I m a g e T o B l o b                                                     #
6910#                                                                             #
6911#                                                                             #
6912#                                                                             #
6913###############################################################################
6914#
6915#
6916void
6917ImageToBlob(ref,...)
6918  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6919  ALIAS:
6920    ImageToBlob  = 1
6921    imagetoblob  = 2
6922    toblob       = 3
6923    blob         = 4
6924  PPCODE:
6925  {
6926    char
6927      filename[MagickPathExtent];
6928
6929    ExceptionInfo
6930      *exception;
6931
6932    Image
6933      *image,
6934      *next;
6935
6936    register ssize_t
6937      i;
6938
6939    struct PackageInfo
6940      *info,
6941      *package_info;
6942
6943    size_t
6944      length;
6945
6946    ssize_t
6947      scene;
6948
6949    SV
6950      *perl_exception,
6951      *reference;
6952
6953    void
6954      *blob;
6955
6956    PERL_UNUSED_VAR(ref);
6957    PERL_UNUSED_VAR(ix);
6958    exception=AcquireExceptionInfo();
6959    perl_exception=newSVpv("",0);
6960    package_info=(struct PackageInfo *) NULL;
6961    if (sv_isobject(ST(0)) == 0)
6962      {
6963        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6964          PackageName);
6965        goto PerlException;
6966      }
6967    reference=SvRV(ST(0));
6968    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6969    if (image == (Image *) NULL)
6970      {
6971        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6972          PackageName);
6973        goto PerlException;
6974      }
6975    package_info=ClonePackageInfo(info,exception);
6976    for (i=2; i < items; i+=2)
6977      SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6978    (void) CopyMagickString(filename,package_info->image_info->filename,
6979      MagickPathExtent);
6980    scene=0;
6981    for (next=image; next; next=next->next)
6982    {
6983      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6984      next->scene=scene++;
6985    }
6986    SetImageInfo(package_info->image_info,(unsigned int)
6987      GetImageListLength(image),exception);
6988    EXTEND(sp,(ssize_t) GetImageListLength(image));
6989    for ( ; image; image=image->next)
6990    {
6991      length=0;
6992      blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6993      if (blob != (char *) NULL)
6994        {
6995          PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6996          blob=(unsigned char *) RelinquishMagickMemory(blob);
6997        }
6998      if (package_info->image_info->adjoin)
6999        break;
7000    }
7001
7002  PerlException:
7003    if (package_info != (struct PackageInfo *) NULL)
7004      DestroyPackageInfo(package_info);
7005    InheritPerlException(exception,perl_exception);
7006    exception=DestroyExceptionInfo(exception);
7007    SvREFCNT_dec(perl_exception);  /* throw away all errors */
7008  }
7009
7010#
7011###############################################################################
7012#                                                                             #
7013#                                                                             #
7014#                                                                             #
7015#   L a y e r s                                                               #
7016#                                                                             #
7017#                                                                             #
7018#                                                                             #
7019###############################################################################
7020#
7021#
7022void
7023Layers(ref,...)
7024  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7025  ALIAS:
7026    Layers                = 1
7027    layers           = 2
7028    OptimizeImageLayers   = 3
7029    optimizelayers        = 4
7030    optimizeimagelayers   = 5
7031  PPCODE:
7032  {
7033    AV
7034      *av;
7035
7036    char
7037      *attribute;
7038
7039    CompositeOperator
7040      compose;
7041
7042    ExceptionInfo
7043      *exception;
7044
7045    HV
7046      *hv;
7047
7048    Image
7049      *image,
7050      *layers;
7051
7052    LayerMethod
7053      method;
7054
7055    register ssize_t
7056      i;
7057
7058    ssize_t
7059      option,
7060      sp;
7061
7062    struct PackageInfo
7063      *info;
7064
7065    SV
7066      *av_reference,
7067      *perl_exception,
7068      *reference,
7069      *rv,
7070      *sv;
7071
7072    PERL_UNUSED_VAR(ref);
7073    PERL_UNUSED_VAR(ix);
7074    exception=AcquireExceptionInfo();
7075    perl_exception=newSVpv("",0);
7076    sv=NULL;
7077    if (sv_isobject(ST(0)) == 0)
7078      {
7079        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7080          PackageName);
7081        goto PerlException;
7082      }
7083    reference=SvRV(ST(0));
7084    hv=SvSTASH(reference);
7085    av=newAV();
7086    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7087    SvREFCNT_dec(av);
7088    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7089    if (image == (Image *) NULL)
7090      {
7091        ThrowPerlException(exception,OptionError,"NoImagesDefined",
7092          PackageName);
7093        goto PerlException;
7094      }
7095    compose=image->compose;
7096    method=OptimizeLayer;
7097    for (i=2; i < items; i+=2)
7098    {
7099      attribute=(char *) SvPV(ST(i-1),na);
7100      switch (*attribute)
7101      {
7102        case 'C':
7103        case 'c':
7104        {
7105          if (LocaleCompare(attribute,"compose") == 0)
7106            {
7107              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7108                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7109              if (sp < 0)
7110                {
7111                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7112                    SvPV(ST(i),na));
7113                  break;
7114                }
7115              compose=(CompositeOperator) sp;
7116              break;
7117            }
7118          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7119            attribute);
7120          break;
7121        }
7122        case 'M':
7123        case 'm':
7124        {
7125          if (LocaleCompare(attribute,"method") == 0)
7126            {
7127              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7128                SvPV(ST(i),na));
7129              if (option < 0)
7130                {
7131                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7132                    SvPV(ST(i),na));
7133                  break;
7134                }
7135              method=(LayerMethod) option;
7136              break;
7137            }
7138          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7139            attribute);
7140          break;
7141        }
7142        default:
7143        {
7144          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7145            attribute);
7146          break;
7147        }
7148      }
7149    }
7150    layers=(Image *) NULL;
7151    switch (method)
7152    {
7153      case CompareAnyLayer:
7154      case CompareClearLayer:
7155      case CompareOverlayLayer:
7156      default:
7157      {
7158        layers=CompareImagesLayers(image,method,exception);
7159        break;
7160      }
7161      case MergeLayer:
7162      case FlattenLayer:
7163      case MosaicLayer:
7164      {
7165        layers=MergeImageLayers(image,method,exception);
7166        break;
7167      }
7168      case DisposeLayer:
7169      {
7170        layers=DisposeImages(image,exception);
7171        break;
7172      }
7173      case OptimizeImageLayer:
7174      {
7175        layers=OptimizeImageLayers(image,exception);
7176        break;
7177      }
7178      case OptimizePlusLayer:
7179      {
7180        layers=OptimizePlusImageLayers(image,exception);
7181        break;
7182      }
7183      case OptimizeTransLayer:
7184      {
7185        OptimizeImageTransparency(image,exception);
7186        break;
7187      }
7188      case RemoveDupsLayer:
7189      {
7190        RemoveDuplicateLayers(&image,exception);
7191        break;
7192      }
7193      case RemoveZeroLayer:
7194      {
7195        RemoveZeroDelayLayers(&image,exception);
7196        break;
7197      }
7198      case OptimizeLayer:
7199      {
7200        QuantizeInfo
7201          *quantize_info;
7202
7203        /*
7204          General Purpose, GIF Animation Optimizer.
7205        */
7206        layers=CoalesceImages(image,exception);
7207        if (layers == (Image *) NULL)
7208          break;
7209        image=layers;
7210        layers=OptimizeImageLayers(image,exception);
7211        if (layers == (Image *) NULL)
7212          break;
7213        image=DestroyImageList(image);
7214        image=layers;
7215        layers=(Image *) NULL;
7216        OptimizeImageTransparency(image,exception);
7217        quantize_info=AcquireQuantizeInfo(info->image_info);
7218        (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7219        quantize_info=DestroyQuantizeInfo(quantize_info);
7220        break;
7221      }
7222      case CompositeLayer:
7223      {
7224        Image
7225          *source;
7226
7227        RectangleInfo
7228          geometry;
7229
7230        /*
7231          Split image sequence at the first 'NULL:' image.
7232        */
7233        source=image;
7234        while (source != (Image *) NULL)
7235        {
7236          source=GetNextImageInList(source);
7237          if ((source != (Image *) NULL) &&
7238              (LocaleCompare(source->magick,"NULL") == 0))
7239            break;
7240        }
7241        if (source != (Image *) NULL)
7242          {
7243            if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7244                (GetNextImageInList(source) == (Image *) NULL))
7245              source=(Image *) NULL;
7246            else
7247              {
7248                /*
7249                  Separate the two lists, junk the null: image.
7250                */
7251                source=SplitImageList(source->previous);
7252                DeleteImageFromList(&source);
7253              }
7254          }
7255        if (source == (Image *) NULL)
7256          {
7257            (void) ThrowMagickException(exception,GetMagickModule(),
7258              OptionError,"MissingNullSeparator","layers Composite");
7259            break;
7260          }
7261        /*
7262          Adjust offset with gravity and virtual canvas.
7263        */
7264        SetGeometry(image,&geometry);
7265        (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7266        geometry.width=source->page.width != 0 ? source->page.width :
7267          source->columns;
7268        geometry.height=source->page.height != 0 ? source->page.height :
7269          source->rows;
7270        GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7271          image->columns,image->page.height != 0 ? image->page.height :
7272          image->rows,image->gravity,&geometry);
7273        CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7274        source=DestroyImageList(source);
7275        break;
7276      }
7277    }
7278    if (layers != (Image *) NULL)
7279      image=layers;
7280    else
7281      image=CloneImage(image,0,0,MagickTrue,exception);
7282    if (image == (Image *) NULL)
7283      goto PerlException;
7284    for ( ; image; image=image->next)
7285    {
7286      AddImageToRegistry(sv,image);
7287      rv=newRV(sv);
7288      av_push(av,sv_bless(rv,hv));
7289      SvREFCNT_dec(sv);
7290    }
7291    exception=DestroyExceptionInfo(exception);
7292    ST(0)=av_reference;
7293    SvREFCNT_dec(perl_exception);
7294    XSRETURN(1);
7295
7296  PerlException:
7297    InheritPerlException(exception,perl_exception);
7298    exception=DestroyExceptionInfo(exception);
7299    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7300    SvPOK_on(perl_exception);
7301    ST(0)=sv_2mortal(perl_exception);
7302    XSRETURN(1);
7303  }
7304
7305#
7306###############################################################################
7307#                                                                             #
7308#                                                                             #
7309#                                                                             #
7310#   M a g i c k T o M i m e                                                   #
7311#                                                                             #
7312#                                                                             #
7313#                                                                             #
7314###############################################################################
7315#
7316#
7317SV *
7318MagickToMime(ref,name)
7319  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7320  char *name
7321  ALIAS:
7322    magicktomime = 1
7323  CODE:
7324  {
7325    char
7326      *mime;
7327
7328    PERL_UNUSED_VAR(ref);
7329    PERL_UNUSED_VAR(ix);
7330    mime=MagickToMime(name);
7331    RETVAL=newSVpv(mime,0);
7332    mime=(char *) RelinquishMagickMemory(mime);
7333  }
7334  OUTPUT:
7335    RETVAL
7336
7337#
7338###############################################################################
7339#                                                                             #
7340#                                                                             #
7341#                                                                             #
7342#   M o g r i f y                                                             #
7343#                                                                             #
7344#                                                                             #
7345#                                                                             #
7346###############################################################################
7347#
7348#
7349void
7350Mogrify(ref,...)
7351  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7352  ALIAS:
7353    Comment            =   1
7354    CommentImage       =   2
7355    Label              =   3
7356    LabelImage         =   4
7357    AddNoise           =   5
7358    AddNoiseImage      =   6
7359    Colorize           =   7
7360    ColorizeImage      =   8
7361    Border             =   9
7362    BorderImage        =  10
7363    Blur               =  11
7364    BlurImage          =  12
7365    Chop               =  13
7366    ChopImage          =  14
7367    Crop               =  15
7368    CropImage          =  16
7369    Despeckle          =  17
7370    DespeckleImage     =  18
7371    Edge               =  19
7372    EdgeImage          =  20
7373    Emboss             =  21
7374    EmbossImage        =  22
7375    Enhance            =  23
7376    EnhanceImage       =  24
7377    Flip               =  25
7378    FlipImage          =  26
7379    Flop               =  27
7380    FlopImage          =  28
7381    Frame              =  29
7382    FrameImage         =  30
7383    Implode            =  31
7384    ImplodeImage       =  32
7385    Magnify            =  33
7386    MagnifyImage       =  34
7387    MedianFilter       =  35
7388    MedianConvolveImage  =  36
7389    Minify             =  37
7390    MinifyImage        =  38
7391    OilPaint           =  39
7392    OilPaintImage      =  40
7393    ReduceNoise        =  41
7394    ReduceNoiseImage   =  42
7395    Roll               =  43
7396    RollImage          =  44
7397    Rotate             =  45
7398    RotateImage        =  46
7399    Sample             =  47
7400    SampleImage        =  48
7401    Scale              =  49
7402    ScaleImage         =  50
7403    Shade              =  51
7404    ShadeImage         =  52
7405    Sharpen            =  53
7406    SharpenImage       =  54
7407    Shear              =  55
7408    ShearImage         =  56
7409    Spread             =  57
7410    SpreadImage        =  58
7411    Swirl              =  59
7412    SwirlImage         =  60
7413    Resize             =  61
7414    ResizeImage        =  62
7415    Zoom               =  63
7416    ZoomImage          =  64
7417    Annotate           =  65
7418    AnnotateImage      =  66
7419    ColorFloodfill     =  67
7420    ColorFloodfillImage=  68
7421    Composite          =  69
7422    CompositeImage     =  70
7423    Contrast           =  71
7424    ContrastImage      =  72
7425    CycleColormap      =  73
7426    CycleColormapImage =  74
7427    Draw               =  75
7428    DrawImage          =  76
7429    Equalize           =  77
7430    EqualizeImage      =  78
7431    Gamma              =  79
7432    GammaImage         =  80
7433    Map                =  81
7434    MapImage           =  82
7435    MatteFloodfill     =  83
7436    MatteFloodfillImage=  84
7437    Modulate           =  85
7438    ModulateImage      =  86
7439    Negate             =  87
7440    NegateImage        =  88
7441    Normalize          =  89
7442    NormalizeImage     =  90
7443    NumberColors       =  91
7444    NumberColorsImage  =  92
7445    Opaque             =  93
7446    OpaqueImage        =  94
7447    Quantize           =  95
7448    QuantizeImage      =  96
7449    Raise              =  97
7450    RaiseImage         =  98
7451    Segment            =  99
7452    SegmentImage       = 100
7453    Signature          = 101
7454    SignatureImage     = 102
7455    Solarize           = 103
7456    SolarizeImage      = 104
7457    Sync               = 105
7458    SyncImage          = 106
7459    Texture            = 107
7460    TextureImage       = 108
7461    Evaluate           = 109
7462    EvaluateImage      = 110
7463    Transparent        = 111
7464    TransparentImage   = 112
7465    Threshold          = 113
7466    ThresholdImage     = 114
7467    Charcoal           = 115
7468    CharcoalImage      = 116
7469    Trim               = 117
7470    TrimImage          = 118
7471    Wave               = 119
7472    WaveImage          = 120
7473    Separate           = 121
7474    SeparateImage      = 122
7475    Stereo             = 125
7476    StereoImage        = 126
7477    Stegano            = 127
7478    SteganoImage       = 128
7479    Deconstruct        = 129
7480    DeconstructImage   = 130
7481    GaussianBlur       = 131
7482    GaussianBlurImage  = 132
7483    Convolve           = 133
7484    ConvolveImage      = 134
7485    Profile            = 135
7486    ProfileImage       = 136
7487    UnsharpMask        = 137
7488    UnsharpMaskImage   = 138
7489    MotionBlur         = 139
7490    MotionBlurImage    = 140
7491    OrderedDither      = 141
7492    OrderedDitherImage = 142
7493    Shave              = 143
7494    ShaveImage         = 144
7495    Level              = 145
7496    LevelImage         = 146
7497    Clip               = 147
7498    ClipImage          = 148
7499    AffineTransform    = 149
7500    AffineTransformImage = 150
7501    Difference         = 151
7502    DifferenceImage    = 152
7503    AdaptiveThreshold  = 153
7504    AdaptiveThresholdImage = 154
7505    Resample           = 155
7506    ResampleImage      = 156
7507    Describe           = 157
7508    DescribeImage      = 158
7509    BlackThreshold     = 159
7510    BlackThresholdImage= 160
7511    WhiteThreshold     = 161
7512    WhiteThresholdImage= 162
7513    RotationalBlur     = 163
7514    RotationalBlurImage= 164
7515    Thumbnail          = 165
7516    ThumbnailImage     = 166
7517    Strip              = 167
7518    StripImage         = 168
7519    Tint               = 169
7520    TintImage          = 170
7521    Channel            = 171
7522    ChannelImage       = 172
7523    Splice             = 173
7524    SpliceImage        = 174
7525    Posterize          = 175
7526    PosterizeImage     = 176
7527    Shadow             = 177
7528    ShadowImage        = 178
7529    Identify           = 179
7530    IdentifyImage      = 180
7531    SepiaTone          = 181
7532    SepiaToneImage     = 182
7533    SigmoidalContrast  = 183
7534    SigmoidalContrastImage = 184
7535    Extent             = 185
7536    ExtentImage        = 186
7537    Vignette           = 187
7538    VignetteImage      = 188
7539    ContrastStretch    = 189
7540    ContrastStretchImage = 190
7541    Sans0              = 191
7542    Sans0Image         = 192
7543    Sans1              = 193
7544    Sans1Image         = 194
7545    AdaptiveSharpen    = 195
7546    AdaptiveSharpenImage = 196
7547    Transpose          = 197
7548    TransposeImage     = 198
7549    Transverse         = 199
7550    TransverseImage    = 200
7551    AutoOrient         = 201
7552    AutoOrientImage    = 202
7553    AdaptiveBlur       = 203
7554    AdaptiveBlurImage  = 204
7555    Sketch             = 205
7556    SketchImage        = 206
7557    UniqueColors       = 207
7558    UniqueColorsImage  = 208
7559    AdaptiveResize     = 209
7560    AdaptiveResizeImage= 210
7561    ClipMask           = 211
7562    ClipMaskImage      = 212
7563    LinearStretch      = 213
7564    LinearStretchImage = 214
7565    ColorMatrix        = 215
7566    ColorMatrixImage   = 216
7567    Mask               = 217
7568    MaskImage          = 218
7569    Polaroid           = 219
7570    PolaroidImage      = 220
7571    FloodfillPaint     = 221
7572    FloodfillPaintImage= 222
7573    Distort            = 223
7574    DistortImage       = 224
7575    Clut               = 225
7576    ClutImage          = 226
7577    LiquidRescale      = 227
7578    LiquidRescaleImage = 228
7579    Encipher           = 229
7580    EncipherImage      = 230
7581    Decipher           = 231
7582    DecipherImage      = 232
7583    Deskew             = 233
7584    DeskewImage        = 234
7585    Remap              = 235
7586    RemapImage         = 236
7587    SparseColor        = 237
7588    SparseColorImage   = 238
7589    Function           = 239
7590    FunctionImage      = 240
7591    SelectiveBlur      = 241
7592    SelectiveBlurImage = 242
7593    HaldClut           = 243
7594    HaldClutImage      = 244
7595    BlueShift          = 245
7596    BlueShiftImage     = 246
7597    ForwardFourierTransform  = 247
7598    ForwardFourierTransformImage = 248
7599    InverseFourierTransform = 249
7600    InverseFourierTransformImage = 250
7601    ColorDecisionList  = 251
7602    ColorDecisionListImage = 252
7603    AutoGamma          = 253
7604    AutoGammaImage     = 254
7605    AutoLevel          = 255
7606    AutoLevelImage     = 256
7607    LevelColors        = 257
7608    LevelImageColors   = 258
7609    Clamp              = 259
7610    ClampImage         = 260
7611    BrightnessContrast = 261
7612    BrightnessContrastImage = 262
7613    Morphology         = 263
7614    MorphologyImage    = 264
7615    Mode               = 265
7616    ModeImage          = 266
7617    Statistic          = 267
7618    StatisticImage     = 268
7619    Perceptible        = 269
7620    PerceptibleImage   = 270
7621    Poly               = 271
7622    PolyImage          = 272
7623    Grayscale          = 273
7624    GrayscaleImage     = 274
7625    CannyEdge          = 275
7626    CannyEdgeImage     = 276
7627    HoughLine          = 277
7628    HoughLineImage     = 278
7629    MeanShift          = 279
7630    MeanShiftImage     = 280
7631    Kuwahara           = 281
7632    KuwaharaImage      = 282
7633    ConnectedComponents = 283
7634    ConnectedComponentsImage = 284
7635    CopyPixels         = 285
7636    CopyImagePixels    = 286
7637    Color              = 287
7638    ColorImage         = 288
7639    WaveletDenoise     = 289
7640    WaveletDenoiseImage= 290
7641    Colorspace         = 291
7642    ColorspaceImage    = 292
7643    AutoThreshold      = 293
7644    AutoThresholdImage = 294
7645    RangeThreshold     = 295
7646    RangeThresholdImage= 296
7647    CLAHE              = 297
7648    CLAHEImage         = 298
7649    MogrifyRegion      = 666
7650  PPCODE:
7651  {
7652    AffineMatrix
7653      affine,
7654      current;
7655
7656    char
7657      attribute_flag[MaxArguments],
7658      message[MagickPathExtent];
7659
7660    ChannelType
7661      channel,
7662      channel_mask;
7663
7664    CompositeOperator
7665      compose;
7666
7667    const char
7668      *attribute,
7669      *value;
7670
7671    double
7672      angle;
7673
7674    ExceptionInfo
7675      *exception;
7676
7677    GeometryInfo
7678      geometry_info;
7679
7680    Image
7681      *image,
7682      *next;
7683
7684    MagickStatusType
7685      flags;
7686
7687    PixelInfo
7688      fill_color;
7689
7690    RectangleInfo
7691      geometry,
7692      region_info;
7693
7694    register ssize_t
7695      i;
7696
7697    ssize_t
7698      base,
7699      j,
7700      number_images;
7701
7702    struct Methods
7703      *rp;
7704
7705    struct PackageInfo
7706      *info;
7707
7708    SV
7709      *perl_exception,
7710      **pv,
7711      *reference,
7712      **reference_vector;
7713
7714    struct ArgumentList
7715      argument_list[MaxArguments];
7716
7717    PERL_UNUSED_VAR(ref);
7718    PERL_UNUSED_VAR(ix);
7719    exception=AcquireExceptionInfo();
7720    perl_exception=newSVpv("",0);
7721    reference_vector=NULL;
7722    number_images=0;
7723    base=2;
7724    if (sv_isobject(ST(0)) == 0)
7725      {
7726        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7727          PackageName);
7728        goto PerlException;
7729      }
7730    reference=SvRV(ST(0));
7731    region_info.width=0;
7732    region_info.height=0;
7733    region_info.x=0;
7734    region_info.y=0;
7735    image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7736    if (ix && (ix != 666))
7737      {
7738        /*
7739          Called as Method(...)
7740        */
7741        ix=(ix+1)/2;
7742        rp=(&Methods[ix-1]);
7743        attribute=rp->name;
7744      }
7745    else
7746      {
7747        /*
7748          Called as Mogrify("Method",...)
7749        */
7750        attribute=(char *) SvPV(ST(1),na);
7751        if (ix)
7752          {
7753            flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7754            attribute=(char *) SvPV(ST(2),na);
7755            base++;
7756          }
7757        for (rp=Methods; ; rp++)
7758        {
7759          if (rp >= EndOf(Methods))
7760            {
7761              ThrowPerlException(exception,OptionError,
7762                "UnrecognizedPerlMagickMethod",attribute);
7763              goto PerlException;
7764            }
7765          if (strEQcase(attribute,rp->name))
7766            break;
7767        }
7768        ix=rp-Methods+1;
7769        base++;
7770      }
7771    if (image == (Image *) NULL)
7772      {
7773        ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7774        goto PerlException;
7775      }
7776    Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7777    Zero(&attribute_flag,NumberOf(attribute_flag),char);
7778    for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7779    {
7780      Arguments
7781        *pp,
7782        *qq;
7783
7784      ssize_t
7785        ssize_test;
7786
7787      struct ArgumentList
7788        *al;
7789
7790      SV
7791        *sv;
7792
7793      sv=NULL;
7794      ssize_test=0;
7795      pp=(Arguments *) NULL;
7796      qq=rp->arguments;
7797      if (i == items)
7798        {
7799          pp=rp->arguments,
7800          sv=ST(i-1);
7801        }
7802      else
7803        for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7804        {
7805          if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7806            break;
7807          if (strEQcase(attribute,qq->method) > ssize_test)
7808            {
7809              pp=qq;
7810              ssize_test=strEQcase(attribute,qq->method);
7811            }
7812        }
7813      if (pp == (Arguments *) NULL)
7814        {
7815          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7816            attribute);
7817          goto continue_outer_loop;
7818        }
7819      al=(&argument_list[pp-rp->arguments]);
7820      switch (pp->type)
7821      {
7822        case ArrayReference:
7823        {
7824          if (SvTYPE(sv) != SVt_RV)
7825            {
7826              (void) FormatLocaleString(message,MagickPathExtent,
7827                "invalid %.60s value",pp->method);
7828              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7829              goto continue_outer_loop;
7830            }
7831          al->array_reference=SvRV(sv);
7832          break;
7833        }
7834        case RealReference:
7835        {
7836          al->real_reference=SvNV(sv);
7837          break;
7838        }
7839        case FileReference:
7840        {
7841          al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7842          break;
7843        }
7844        case ImageReference:
7845        {
7846          if (!sv_isobject(sv) ||
7847              !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7848                (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7849            {
7850              ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7851                PackageName);
7852              goto PerlException;
7853            }
7854          break;
7855        }
7856        case IntegerReference:
7857        {
7858          al->integer_reference=SvIV(sv);
7859          break;
7860        }
7861        case StringReference:
7862        {
7863          al->string_reference=(char *) SvPV(sv,al->length);
7864          if (sv_isobject(sv))
7865            al->image_reference=SetupList(aTHX_ SvRV(sv),
7866              (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7867          break;
7868        }
7869        default:
7870        {
7871          /*
7872            Is a string; look up name.
7873          */
7874          if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7875            {
7876              al->string_reference=(char *) SvPV(sv,al->length);
7877              al->integer_reference=(-1);
7878              break;
7879            }
7880          al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7881            MagickFalse,SvPV(sv,na));
7882          if (pp->type == MagickChannelOptions)
7883            al->integer_reference=ParseChannelOption(SvPV(sv,na));
7884          if ((al->integer_reference < 0) &&
7885              ((al->integer_reference=SvIV(sv)) <= 0))
7886            {
7887              (void) FormatLocaleString(message,MagickPathExtent,
7888                "invalid %.60s value",pp->method);
7889              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7890              goto continue_outer_loop;
7891            }
7892          break;
7893        }
7894      }
7895      attribute_flag[pp-rp->arguments]++;
7896      continue_outer_loop: ;
7897    }
7898    (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7899    pv=reference_vector;
7900    SetGeometryInfo(&geometry_info);
7901    channel=DefaultChannels;
7902    for (next=image; next; next=next->next)
7903    {
7904      image=next;
7905      SetGeometry(image,&geometry);
7906      if ((region_info.width*region_info.height) != 0)
7907        (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
7908      switch (ix)
7909      {
7910        default:
7911        {
7912          (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
7913            ix);
7914          ThrowPerlException(exception,OptionError,
7915            "UnrecognizedPerlMagickMethod",message);
7916          goto PerlException;
7917        }
7918        case 1:  /* Comment */
7919        {
7920          if (attribute_flag[0] == 0)
7921            argument_list[0].string_reference=(char *) NULL;
7922          (void) SetImageProperty(image,"comment",InterpretImageProperties(
7923            info ? info->image_info : (ImageInfo *) NULL,image,
7924            argument_list[0].string_reference,exception),exception);
7925          break;
7926        }
7927        case 2:  /* Label */
7928        {
7929          if (attribute_flag[0] == 0)
7930            argument_list[0].string_reference=(char *) NULL;
7931          (void) SetImageProperty(image,"label",InterpretImageProperties(
7932            info ? info->image_info : (ImageInfo *) NULL,image,
7933            argument_list[0].string_reference,exception),exception);
7934          break;
7935        }
7936        case 3:  /* AddNoise */
7937        {
7938          double
7939            attenuate;
7940
7941          if (attribute_flag[0] == 0)
7942            argument_list[0].integer_reference=UniformNoise;
7943          attenuate=1.0;
7944          if (attribute_flag[1] != 0)
7945            attenuate=argument_list[1].real_reference;
7946          if (attribute_flag[2] != 0)
7947            channel=(ChannelType) argument_list[2].integer_reference;
7948          channel_mask=SetImageChannelMask(image,channel);
7949          image=AddNoiseImage(image,(NoiseType)
7950            argument_list[0].integer_reference,attenuate,exception);
7951          if (image != (Image *) NULL)
7952            (void) SetImageChannelMask(image,channel_mask);
7953          break;
7954        }
7955        case 4:  /* Colorize */
7956        {
7957          PixelInfo
7958            target;
7959
7960          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,0,0,
7961            &target,exception);
7962          if (attribute_flag[0] != 0)
7963            (void) QueryColorCompliance(argument_list[0].string_reference,
7964              AllCompliance,&target,exception);
7965          if (attribute_flag[1] == 0)
7966            argument_list[1].string_reference="100%";
7967          image=ColorizeImage(image,argument_list[1].string_reference,&target,
7968            exception);
7969          break;
7970        }
7971        case 5:  /* Border */
7972        {
7973          CompositeOperator
7974            compose;
7975
7976          geometry.width=0;
7977          geometry.height=0;
7978          if (attribute_flag[0] != 0)
7979            flags=ParsePageGeometry(image,argument_list[0].string_reference,
7980              &geometry,exception);
7981          if (attribute_flag[1] != 0)
7982            geometry.width=argument_list[1].integer_reference;
7983          if (attribute_flag[2] != 0)
7984            geometry.height=argument_list[2].integer_reference;
7985          if (attribute_flag[3] != 0)
7986            QueryColorCompliance(argument_list[3].string_reference,
7987              AllCompliance,&image->border_color,exception);
7988          if (attribute_flag[4] != 0)
7989            QueryColorCompliance(argument_list[4].string_reference,
7990              AllCompliance,&image->border_color,exception);
7991          if (attribute_flag[5] != 0)
7992            QueryColorCompliance(argument_list[5].string_reference,
7993              AllCompliance,&image->border_color,exception);
7994          compose=image->compose;
7995          if (attribute_flag[6] != 0)
7996            compose=(CompositeOperator) argument_list[6].integer_reference;
7997          image=BorderImage(image,&geometry,compose,exception);
7998          break;
7999        }
8000        case 6:  /* Blur */
8001        {
8002          if (attribute_flag[0] != 0)
8003            {
8004              flags=ParseGeometry(argument_list[0].string_reference,
8005                &geometry_info);
8006              if ((flags & SigmaValue) == 0)
8007                geometry_info.sigma=1.0;
8008            }
8009          if (attribute_flag[1] != 0)
8010            geometry_info.rho=argument_list[1].real_reference;
8011          if (attribute_flag[2] != 0)
8012            geometry_info.sigma=argument_list[2].real_reference;
8013          if (attribute_flag[3] != 0)
8014            channel=(ChannelType) argument_list[3].integer_reference;
8015          channel_mask=SetImageChannelMask(image,channel);
8016          image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8017            exception);
8018          if (image != (Image *) NULL)
8019            (void) SetImageChannelMask(image,channel_mask);
8020          break;
8021        }
8022        case 7:  /* Chop */
8023        {
8024          if (attribute_flag[5] != 0)
8025            image->gravity=(GravityType) argument_list[5].integer_reference;
8026          if (attribute_flag[0] != 0)
8027            flags=ParseGravityGeometry(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            geometry.x=argument_list[3].integer_reference;
8035          if (attribute_flag[4] != 0)
8036            geometry.y=argument_list[4].integer_reference;
8037          image=ChopImage(image,&geometry,exception);
8038          break;
8039        }
8040        case 8:  /* Crop */
8041        {
8042          if (attribute_flag[6] != 0)
8043            image->gravity=(GravityType) argument_list[6].integer_reference;
8044          if (attribute_flag[0] != 0)
8045            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8046              &geometry,exception);
8047          if (attribute_flag[1] != 0)
8048            geometry.width=argument_list[1].integer_reference;
8049          if (attribute_flag[2] != 0)
8050            geometry.height=argument_list[2].integer_reference;
8051          if (attribute_flag[3] != 0)
8052            geometry.x=argument_list[3].integer_reference;
8053          if (attribute_flag[4] != 0)
8054            geometry.y=argument_list[4].integer_reference;
8055          if (attribute_flag[5] != 0)
8056            image->fuzz=StringToDoubleInterval(
8057              argument_list[5].string_reference,(double) QuantumRange+1.0);
8058          image=CropImage(image,&geometry,exception);
8059          break;
8060        }
8061        case 9:  /* Despeckle */
8062        {
8063          image=DespeckleImage(image,exception);
8064          break;
8065        }
8066        case 10:  /* Edge */
8067        {
8068          if (attribute_flag[0] != 0)
8069            geometry_info.rho=argument_list[0].real_reference;
8070          image=EdgeImage(image,geometry_info.rho,exception);
8071          break;
8072        }
8073        case 11:  /* Emboss */
8074        {
8075          if (attribute_flag[0] != 0)
8076            {
8077              flags=ParseGeometry(argument_list[0].string_reference,
8078                &geometry_info);
8079              if ((flags & SigmaValue) == 0)
8080                geometry_info.sigma=1.0;
8081            }
8082          if (attribute_flag[1] != 0)
8083            geometry_info.rho=argument_list[1].real_reference;
8084          if (attribute_flag[2] != 0)
8085            geometry_info.sigma=argument_list[2].real_reference;
8086          image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8087            exception);
8088          break;
8089        }
8090        case 12:  /* Enhance */
8091        {
8092          image=EnhanceImage(image,exception);
8093          break;
8094        }
8095        case 13:  /* Flip */
8096        {
8097          image=FlipImage(image,exception);
8098          break;
8099        }
8100        case 14:  /* Flop */
8101        {
8102          image=FlopImage(image,exception);
8103          break;
8104        }
8105        case 15:  /* Frame */
8106        {
8107          CompositeOperator
8108            compose;
8109
8110          FrameInfo
8111            frame_info;
8112
8113          if (attribute_flag[0] != 0)
8114            {
8115              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8116                &geometry,exception);
8117              frame_info.width=geometry.width;
8118              frame_info.height=geometry.height;
8119              frame_info.outer_bevel=geometry.x;
8120              frame_info.inner_bevel=geometry.y;
8121            }
8122          if (attribute_flag[1] != 0)
8123            frame_info.width=argument_list[1].integer_reference;
8124          if (attribute_flag[2] != 0)
8125            frame_info.height=argument_list[2].integer_reference;
8126          if (attribute_flag[3] != 0)
8127            frame_info.inner_bevel=argument_list[3].integer_reference;
8128          if (attribute_flag[4] != 0)
8129            frame_info.outer_bevel=argument_list[4].integer_reference;
8130          if (attribute_flag[5] != 0)
8131            QueryColorCompliance(argument_list[5].string_reference,
8132              AllCompliance,&fill_color,exception);
8133          if (attribute_flag[6] != 0)
8134            QueryColorCompliance(argument_list[6].string_reference,
8135              AllCompliance,&fill_color,exception);
8136          frame_info.x=(ssize_t) frame_info.width;
8137          frame_info.y=(ssize_t) frame_info.height;
8138          frame_info.width=image->columns+2*frame_info.x;
8139          frame_info.height=image->rows+2*frame_info.y;
8140          if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8141            image->alpha_color=fill_color;
8142          compose=image->compose;
8143          if (attribute_flag[7] != 0)
8144            compose=(CompositeOperator) argument_list[7].integer_reference;
8145          image=FrameImage(image,&frame_info,compose,exception);
8146          break;
8147        }
8148        case 16:  /* Implode */
8149        {
8150          PixelInterpolateMethod
8151            method;
8152
8153          if (attribute_flag[0] == 0)
8154            argument_list[0].real_reference=0.5;
8155          method=UndefinedInterpolatePixel;
8156          if (attribute_flag[1] != 0)
8157            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8158          image=ImplodeImage(image,argument_list[0].real_reference,
8159            method,exception);
8160          break;
8161        }
8162        case 17:  /* Magnify */
8163        {
8164          image=MagnifyImage(image,exception);
8165          break;
8166        }
8167        case 18:  /* MedianFilter */
8168        {
8169          if (attribute_flag[0] != 0)
8170            {
8171              flags=ParseGeometry(argument_list[0].string_reference,
8172                &geometry_info);
8173              if ((flags & SigmaValue) == 0)
8174                geometry_info.sigma=geometry_info.rho;
8175            }
8176          if (attribute_flag[1] != 0)
8177            geometry_info.rho=argument_list[1].real_reference;
8178          if (attribute_flag[2] != 0)
8179            geometry_info.sigma=argument_list[2].real_reference;
8180          if (attribute_flag[3] != 0)
8181            channel=(ChannelType) argument_list[3].integer_reference;
8182          channel_mask=SetImageChannelMask(image,channel);
8183          image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8184            (size_t) geometry_info.sigma,exception);
8185          if (image != (Image *) NULL)
8186            (void) SetImageChannelMask(image,channel_mask);
8187          break;
8188        }
8189        case 19:  /* Minify */
8190        {
8191          image=MinifyImage(image,exception);
8192          break;
8193        }
8194        case 20:  /* OilPaint */
8195        {
8196          if (attribute_flag[0] == 0)
8197            argument_list[0].real_reference=0.0;
8198          if (attribute_flag[1] == 0)
8199            argument_list[1].real_reference=1.0;
8200          image=OilPaintImage(image,argument_list[0].real_reference,
8201            argument_list[1].real_reference,exception);
8202          break;
8203        }
8204        case 21:  /* ReduceNoise */
8205        {
8206          if (attribute_flag[0] != 0)
8207            {
8208              flags=ParseGeometry(argument_list[0].string_reference,
8209                &geometry_info);
8210              if ((flags & SigmaValue) == 0)
8211                geometry_info.sigma=1.0;
8212            }
8213          if (attribute_flag[1] != 0)
8214            geometry_info.rho=argument_list[1].real_reference;
8215          if (attribute_flag[2] != 0)
8216            geometry_info.sigma=argument_list[2].real_reference;
8217          if (attribute_flag[3] != 0)
8218            channel=(ChannelType) argument_list[3].integer_reference;
8219          channel_mask=SetImageChannelMask(image,channel);
8220          image=StatisticImage(image,NonpeakStatistic,(size_t)
8221            geometry_info.rho,(size_t) geometry_info.sigma,exception);
8222          if (image != (Image *) NULL)
8223            (void) SetImageChannelMask(image,channel_mask);
8224          break;
8225        }
8226        case 22:  /* Roll */
8227        {
8228          if (attribute_flag[0] != 0)
8229            {
8230              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8231                &geometry,exception);
8232              if ((flags & PercentValue) != 0)
8233                {
8234                  geometry.x*=(double) image->columns/100.0;
8235                  geometry.y*=(double) image->rows/100.0;
8236                }
8237            }
8238          if (attribute_flag[1] != 0)
8239            geometry.x=argument_list[1].integer_reference;
8240          if (attribute_flag[2] != 0)
8241            geometry.y=argument_list[2].integer_reference;
8242          image=RollImage(image,geometry.x,geometry.y,exception);
8243          break;
8244        }
8245        case 23:  /* Rotate */
8246        {
8247          if (attribute_flag[0] == 0)
8248            argument_list[0].real_reference=90.0;
8249          if (attribute_flag[1] != 0)
8250            {
8251              QueryColorCompliance(argument_list[1].string_reference,
8252                AllCompliance,&image->background_color,exception);
8253              if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8254                  (image->alpha_trait == UndefinedPixelTrait))
8255                (void) SetImageAlpha(image,OpaqueAlpha,exception);
8256            }
8257          image=RotateImage(image,argument_list[0].real_reference,exception);
8258          break;
8259        }
8260        case 24:  /* Sample */
8261        {
8262          if (attribute_flag[0] != 0)
8263            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8264              &geometry,exception);
8265          if (attribute_flag[1] != 0)
8266            geometry.width=argument_list[1].integer_reference;
8267          if (attribute_flag[2] != 0)
8268            geometry.height=argument_list[2].integer_reference;
8269          image=SampleImage(image,geometry.width,geometry.height,exception);
8270          break;
8271        }
8272        case 25:  /* Scale */
8273        {
8274          if (attribute_flag[0] != 0)
8275            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8276              &geometry,exception);
8277          if (attribute_flag[1] != 0)
8278            geometry.width=argument_list[1].integer_reference;
8279          if (attribute_flag[2] != 0)
8280            geometry.height=argument_list[2].integer_reference;
8281          image=ScaleImage(image,geometry.width,geometry.height,exception);
8282          break;
8283        }
8284        case 26:  /* Shade */
8285        {
8286          if (attribute_flag[0] != 0)
8287            {
8288              flags=ParseGeometry(argument_list[0].string_reference,
8289                &geometry_info);
8290              if ((flags & SigmaValue) == 0)
8291                geometry_info.sigma=0.0;
8292            }
8293          if (attribute_flag[1] != 0)
8294            geometry_info.rho=argument_list[1].real_reference;
8295          if (attribute_flag[2] != 0)
8296            geometry_info.sigma=argument_list[2].real_reference;
8297          image=ShadeImage(image,
8298            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8299            geometry_info.rho,geometry_info.sigma,exception);
8300          break;
8301        }
8302        case 27:  /* Sharpen */
8303        {
8304          if (attribute_flag[0] != 0)
8305            {
8306              flags=ParseGeometry(argument_list[0].string_reference,
8307                &geometry_info);
8308              if ((flags & SigmaValue) == 0)
8309                geometry_info.sigma=1.0;
8310            }
8311          if (attribute_flag[1] != 0)
8312            geometry_info.rho=argument_list[1].real_reference;
8313          if (attribute_flag[2] != 0)
8314            geometry_info.sigma=argument_list[2].real_reference;
8315          if (attribute_flag[3] != 0)
8316            channel=(ChannelType) argument_list[3].integer_reference;
8317          channel_mask=SetImageChannelMask(image,channel);
8318          image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8319            exception);
8320          if (image != (Image *) NULL)
8321            (void) SetImageChannelMask(image,channel_mask);
8322          break;
8323        }
8324        case 28:  /* Shear */
8325        {
8326          if (attribute_flag[0] != 0)
8327            {
8328              flags=ParseGeometry(argument_list[0].string_reference,
8329                &geometry_info);
8330              if ((flags & SigmaValue) == 0)
8331                geometry_info.sigma=geometry_info.rho;
8332            }
8333          if (attribute_flag[1] != 0)
8334            geometry_info.rho=argument_list[1].real_reference;
8335          if (attribute_flag[2] != 0)
8336            geometry_info.sigma=argument_list[2].real_reference;
8337          if (attribute_flag[3] != 0)
8338            QueryColorCompliance(argument_list[3].string_reference,
8339              AllCompliance,&image->background_color,exception);
8340          if (attribute_flag[4] != 0)
8341            QueryColorCompliance(argument_list[4].string_reference,
8342              AllCompliance,&image->background_color,exception);
8343          image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8344            exception);
8345          break;
8346        }
8347        case 29:  /* Spread */
8348        {
8349          PixelInterpolateMethod
8350            method;
8351
8352          if (attribute_flag[0] == 0)
8353            argument_list[0].real_reference=1.0;
8354          method=UndefinedInterpolatePixel;
8355          if (attribute_flag[1] != 0)
8356            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8357          image=SpreadImage(image,method,argument_list[0].real_reference,
8358            exception);
8359          break;
8360        }
8361        case 30:  /* Swirl */
8362        {
8363          PixelInterpolateMethod
8364            method;
8365
8366          if (attribute_flag[0] == 0)
8367            argument_list[0].real_reference=50.0;
8368          method=UndefinedInterpolatePixel;
8369          if (attribute_flag[1] != 0)
8370            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8371          image=SwirlImage(image,argument_list[0].real_reference,
8372            method,exception);
8373          break;
8374        }
8375        case 31:  /* Resize */
8376        case 32:  /* Zoom */
8377        {
8378          if (attribute_flag[0] != 0)
8379            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8380              &geometry,exception);
8381          if (attribute_flag[1] != 0)
8382            geometry.width=argument_list[1].integer_reference;
8383          if (attribute_flag[2] != 0)
8384            geometry.height=argument_list[2].integer_reference;
8385          if (attribute_flag[3] == 0)
8386            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8387          if (attribute_flag[4] != 0)
8388            SetImageArtifact(image,"filter:support",
8389              argument_list[4].string_reference);
8390          image=ResizeImage(image,geometry.width,geometry.height,
8391            (FilterType) argument_list[3].integer_reference,
8392            exception);
8393          break;
8394        }
8395        case 33:  /* Annotate */
8396        {
8397          DrawInfo
8398            *draw_info;
8399
8400          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8401            (DrawInfo *) NULL);
8402          if (attribute_flag[0] != 0)
8403            {
8404              char
8405                *text;
8406
8407              text=InterpretImageProperties(info ? info->image_info :
8408                (ImageInfo *) NULL,image,argument_list[0].string_reference,
8409                exception);
8410              (void) CloneString(&draw_info->text,text);
8411              text=DestroyString(text);
8412            }
8413          if (attribute_flag[1] != 0)
8414            (void) CloneString(&draw_info->font,
8415              argument_list[1].string_reference);
8416          if (attribute_flag[2] != 0)
8417            draw_info->pointsize=argument_list[2].real_reference;
8418          if (attribute_flag[3] != 0)
8419            (void) CloneString(&draw_info->density,
8420              argument_list[3].string_reference);
8421          if (attribute_flag[4] != 0)
8422            (void) QueryColorCompliance(argument_list[4].string_reference,
8423              AllCompliance,&draw_info->undercolor,exception);
8424          if (attribute_flag[5] != 0)
8425            {
8426              (void) QueryColorCompliance(argument_list[5].string_reference,
8427                AllCompliance,&draw_info->stroke,exception);
8428              if (argument_list[5].image_reference != (Image *) NULL)
8429                draw_info->stroke_pattern=CloneImage(
8430                  argument_list[5].image_reference,0,0,MagickTrue,exception);
8431            }
8432          if (attribute_flag[6] != 0)
8433            {
8434              (void) QueryColorCompliance(argument_list[6].string_reference,
8435                AllCompliance,&draw_info->fill,exception);
8436              if (argument_list[6].image_reference != (Image *) NULL)
8437                draw_info->fill_pattern=CloneImage(
8438                  argument_list[6].image_reference,0,0,MagickTrue,exception);
8439            }
8440          if (attribute_flag[7] != 0)
8441            {
8442              (void) CloneString(&draw_info->geometry,
8443                argument_list[7].string_reference);
8444              flags=ParsePageGeometry(image,argument_list[7].string_reference,
8445                &geometry,exception);
8446              if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8447                geometry_info.sigma=geometry_info.xi;
8448            }
8449          if (attribute_flag[8] != 0)
8450            (void) QueryColorCompliance(argument_list[8].string_reference,
8451              AllCompliance,&draw_info->fill,exception);
8452          if (attribute_flag[11] != 0)
8453            draw_info->gravity=(GravityType)
8454              argument_list[11].integer_reference;
8455          if (attribute_flag[25] != 0)
8456            {
8457              AV
8458                *av;
8459
8460              av=(AV *) argument_list[25].array_reference;
8461              if ((av_len(av) != 3) && (av_len(av) != 5))
8462                {
8463                  ThrowPerlException(exception,OptionError,
8464                    "affine matrix must have 4 or 6 elements",PackageName);
8465                  goto PerlException;
8466                }
8467              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8468              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8469              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8470              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8471              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8472                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8473                {
8474                  ThrowPerlException(exception,OptionError,
8475                    "affine matrix is singular",PackageName);
8476                   goto PerlException;
8477                }
8478              if (av_len(av) == 5)
8479                {
8480                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8481                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8482                }
8483            }
8484          for (j=12; j < 17; j++)
8485          {
8486            if (attribute_flag[j] == 0)
8487              continue;
8488            value=argument_list[j].string_reference;
8489            angle=argument_list[j].real_reference;
8490            current=draw_info->affine;
8491            GetAffineMatrix(&affine);
8492            switch (j)
8493            {
8494              case 12:
8495              {
8496                /*
8497                  Translate.
8498                */
8499                flags=ParseGeometry(value,&geometry_info);
8500                affine.tx=geometry_info.xi;
8501                affine.ty=geometry_info.psi;
8502                if ((flags & PsiValue) == 0)
8503                  affine.ty=affine.tx;
8504                break;
8505              }
8506              case 13:
8507              {
8508                /*
8509                  Scale.
8510                */
8511                flags=ParseGeometry(value,&geometry_info);
8512                affine.sx=geometry_info.rho;
8513                affine.sy=geometry_info.sigma;
8514                if ((flags & SigmaValue) == 0)
8515                  affine.sy=affine.sx;
8516                break;
8517              }
8518              case 14:
8519              {
8520                /*
8521                  Rotate.
8522                */
8523                if (angle == 0.0)
8524                  break;
8525                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8526                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8527                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8528                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8529                break;
8530              }
8531              case 15:
8532              {
8533                /*
8534                  SkewX.
8535                */
8536                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8537                break;
8538              }
8539              case 16:
8540              {
8541                /*
8542                  SkewY.
8543                */
8544                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8545                break;
8546              }
8547            }
8548            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8549            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8550            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8551            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8552            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8553              current.tx;
8554            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8555              current.ty;
8556          }
8557          if (attribute_flag[9] == 0)
8558            argument_list[9].real_reference=0.0;
8559          if (attribute_flag[10] == 0)
8560            argument_list[10].real_reference=0.0;
8561          if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8562            {
8563              char
8564                geometry[MagickPathExtent];
8565
8566              (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8567                (double) argument_list[9].real_reference+draw_info->affine.tx,
8568                (double) argument_list[10].real_reference+draw_info->affine.ty);
8569              (void) CloneString(&draw_info->geometry,geometry);
8570            }
8571          if (attribute_flag[17] != 0)
8572            draw_info->stroke_width=argument_list[17].real_reference;
8573          if (attribute_flag[18] != 0)
8574            {
8575              draw_info->text_antialias=
8576                argument_list[18].integer_reference != 0 ? MagickTrue :
8577                MagickFalse;
8578              draw_info->stroke_antialias=draw_info->text_antialias;
8579            }
8580          if (attribute_flag[19] != 0)
8581            (void) CloneString(&draw_info->family,
8582              argument_list[19].string_reference);
8583          if (attribute_flag[20] != 0)
8584            draw_info->style=(StyleType) argument_list[20].integer_reference;
8585          if (attribute_flag[21] != 0)
8586            draw_info->stretch=(StretchType)
8587              argument_list[21].integer_reference;
8588          if (attribute_flag[22] != 0)
8589            draw_info->weight=argument_list[22].integer_reference;
8590          if (attribute_flag[23] != 0)
8591            draw_info->align=(AlignType) argument_list[23].integer_reference;
8592          if (attribute_flag[24] != 0)
8593            (void) CloneString(&draw_info->encoding,
8594              argument_list[24].string_reference);
8595          if (attribute_flag[25] != 0)
8596            draw_info->fill_pattern=CloneImage(
8597              argument_list[25].image_reference,0,0,MagickTrue,exception);
8598          if (attribute_flag[26] != 0)
8599            draw_info->fill_pattern=CloneImage(
8600              argument_list[26].image_reference,0,0,MagickTrue,exception);
8601          if (attribute_flag[27] != 0)
8602            draw_info->stroke_pattern=CloneImage(
8603              argument_list[27].image_reference,0,0,MagickTrue,exception);
8604          if (attribute_flag[29] != 0)
8605            draw_info->kerning=argument_list[29].real_reference;
8606          if (attribute_flag[30] != 0)
8607            draw_info->interline_spacing=argument_list[30].real_reference;
8608          if (attribute_flag[31] != 0)
8609            draw_info->interword_spacing=argument_list[31].real_reference;
8610          if (attribute_flag[32] != 0)
8611            draw_info->direction=(DirectionType)
8612              argument_list[32].integer_reference;
8613          if (attribute_flag[33] != 0)
8614            draw_info->decorate=(DecorationType)
8615              argument_list[33].integer_reference;
8616          (void) AnnotateImage(image,draw_info,exception);
8617          draw_info=DestroyDrawInfo(draw_info);
8618          break;
8619        }
8620        case 34:  /* ColorFloodfill */
8621        {
8622          DrawInfo
8623            *draw_info;
8624
8625          MagickBooleanType
8626            invert;
8627
8628          PixelInfo
8629            target;
8630
8631          draw_info=CloneDrawInfo(info ? info->image_info :
8632            (ImageInfo *) NULL,(DrawInfo *) NULL);
8633          if (attribute_flag[0] != 0)
8634            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8635              &geometry,exception);
8636          if (attribute_flag[1] != 0)
8637            geometry.x=argument_list[1].integer_reference;
8638          if (attribute_flag[2] != 0)
8639            geometry.y=argument_list[2].integer_reference;
8640          if (attribute_flag[3] != 0)
8641            (void) QueryColorCompliance(argument_list[3].string_reference,
8642              AllCompliance,&draw_info->fill,exception);
8643          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8644            geometry.x,geometry.y,&target,exception);
8645          invert=MagickFalse;
8646          if (attribute_flag[4] != 0)
8647            {
8648              QueryColorCompliance(argument_list[4].string_reference,
8649                AllCompliance,&target,exception);
8650              invert=MagickTrue;
8651            }
8652          if (attribute_flag[5] != 0)
8653            image->fuzz=StringToDoubleInterval(
8654              argument_list[5].string_reference,(double) QuantumRange+1.0);
8655          if (attribute_flag[6] != 0)
8656            invert=(MagickBooleanType) argument_list[6].integer_reference;
8657          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8658            geometry.y,invert,exception);
8659          draw_info=DestroyDrawInfo(draw_info);
8660          break;
8661        }
8662        case 35:  /* Composite */
8663        {
8664          char
8665            composite_geometry[MagickPathExtent];
8666
8667          Image
8668            *composite_image,
8669            *rotate_image;
8670
8671          MagickBooleanType
8672            clip_to_self;
8673
8674          compose=OverCompositeOp;
8675          if (attribute_flag[0] != 0)
8676            composite_image=argument_list[0].image_reference;
8677          else
8678            {
8679              ThrowPerlException(exception,OptionError,
8680                "CompositeImageRequired",PackageName);
8681              goto PerlException;
8682            }
8683          /*
8684            Parameter Handling used for BOTH normal and tiled composition.
8685          */
8686          if (attribute_flag[1] != 0) /* compose */
8687            compose=(CompositeOperator) argument_list[1].integer_reference;
8688          if (attribute_flag[6] != 0) /* opacity  */
8689            {
8690              if (compose != DissolveCompositeOp)
8691                (void) SetImageAlpha(composite_image,(Quantum)
8692                  StringToDoubleInterval(argument_list[6].string_reference,
8693                  (double) QuantumRange+1.0),exception);
8694              else
8695                {
8696                  CacheView
8697                    *composite_view;
8698
8699                  double
8700                    opacity;
8701
8702                  MagickBooleanType
8703                    sync;
8704
8705                  register ssize_t
8706                    x;
8707
8708                  register Quantum
8709                    *q;
8710
8711                  ssize_t
8712                    y;
8713
8714                  /*
8715                    Handle dissolve composite operator (patch by
8716                    Kevin A. McGrail).
8717                  */
8718                  (void) CloneString(&image->geometry,
8719                    argument_list[6].string_reference);
8720                  opacity=(Quantum) StringToDoubleInterval(
8721                    argument_list[6].string_reference,(double) QuantumRange+
8722                    1.0);
8723                  if (composite_image->alpha_trait != UndefinedPixelTrait)
8724                    (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8725                  composite_view=AcquireAuthenticCacheView(composite_image,
8726                    exception);
8727                  for (y=0; y < (ssize_t) composite_image->rows ; y++)
8728                  {
8729                    q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8730                      composite_image->columns,1,exception);
8731                    for (x=0; x < (ssize_t) composite_image->columns; x++)
8732                    {
8733                      if (GetPixelAlpha(image,q) == OpaqueAlpha)
8734                        SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8735                          q);
8736                      q+=GetPixelChannels(composite_image);
8737                    }
8738                    sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8739                    if (sync == MagickFalse)
8740                      break;
8741                  }
8742                  composite_view=DestroyCacheView(composite_view);
8743                }
8744            }
8745          if (attribute_flag[9] != 0)    /* "color=>" */
8746            QueryColorCompliance(argument_list[9].string_reference,
8747              AllCompliance,&composite_image->background_color,exception);
8748          if (attribute_flag[12] != 0) /* "interpolate=>" */
8749            image->interpolate=(PixelInterpolateMethod)
8750              argument_list[12].integer_reference;
8751          if (attribute_flag[13] != 0)   /* "args=>" */
8752            (void) SetImageArtifact(composite_image,"compose:args",
8753              argument_list[13].string_reference);
8754          if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8755            (void) SetImageArtifact(composite_image,"compose:args",
8756              argument_list[14].string_reference);
8757          clip_to_self=MagickTrue;
8758          switch (compose)
8759          {
8760            case ClearCompositeOp:
8761            case SrcCompositeOp:
8762            case InCompositeOp:
8763            case SrcInCompositeOp:
8764            case OutCompositeOp:
8765            case SrcOutCompositeOp:
8766            case DstInCompositeOp:
8767            case DstAtopCompositeOp:
8768            case CopyAlphaCompositeOp:
8769            case ChangeMaskCompositeOp:
8770            case DissolveCompositeOp:
8771            case BlendCompositeOp:
8772            {
8773              clip_to_self=MagickFalse;
8774              break;
8775            }
8776            default:
8777              break;
8778          }
8779          if (attribute_flag[15] != 0)
8780            clip_to_self=(MagickBooleanType)
8781              argument_list[15].integer_reference;
8782          /*
8783            Tiling Composition (with orthogonal rotate).
8784          */
8785          rotate_image=(Image *) NULL;
8786          if (attribute_flag[8] != 0)   /* "rotate=>" */
8787            {
8788               /*
8789                 Rotate image.
8790               */
8791               rotate_image=RotateImage(composite_image,
8792                 argument_list[8].real_reference,exception);
8793               if (rotate_image == (Image *) NULL)
8794                 break;
8795            }
8796          if ((attribute_flag[7] != 0) &&
8797              (argument_list[7].integer_reference != 0)) /* tile */
8798            {
8799              ssize_t
8800                x,
8801                y;
8802
8803              /*
8804                Tile the composite image.
8805              */
8806             for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8807                for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8808                {
8809                  if (attribute_flag[8] != 0) /* rotate */
8810                    (void) CompositeImage(image,rotate_image,compose,
8811                      MagickTrue,x,y,exception);
8812                  else
8813                    (void) CompositeImage(image,composite_image,compose,
8814                      MagickTrue,x,y,exception);
8815                }
8816              if (attribute_flag[8] != 0) /* rotate */
8817                rotate_image=DestroyImage(rotate_image);
8818              break;
8819            }
8820          /*
8821            Parameter Handling used used ONLY for normal composition.
8822          */
8823          if (attribute_flag[5] != 0) /* gravity */
8824            image->gravity=(GravityType) argument_list[5].integer_reference;
8825          if (attribute_flag[2] != 0) /* geometry offset */
8826            {
8827              SetGeometry(image,&geometry);
8828              (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8829                &geometry);
8830              GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8831                &geometry);
8832            }
8833          if (attribute_flag[3] != 0) /* x offset */
8834            geometry.x=argument_list[3].integer_reference;
8835          if (attribute_flag[4] != 0) /* y offset */
8836            geometry.y=argument_list[4].integer_reference;
8837          if (attribute_flag[10] != 0) /* mask */
8838            {
8839              if ((image->compose == DisplaceCompositeOp) ||
8840                  (image->compose == DistortCompositeOp))
8841                {
8842                  /*
8843                    Merge Y displacement into X displacement image.
8844                  */
8845                  composite_image=CloneImage(composite_image,0,0,MagickTrue,
8846                    exception);
8847                  (void) CompositeImage(composite_image,
8848                    argument_list[10].image_reference,CopyGreenCompositeOp,
8849                    clip_to_self,0,0,exception);
8850                }
8851              else
8852                {
8853                  Image
8854                    *mask_image;
8855
8856                  /*
8857                    Set a blending mask for the composition.
8858                  */
8859                  mask_image=CloneImage(argument_list[10].image_reference,0,0,
8860                    MagickTrue,exception);
8861                  (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8862                    exception);
8863                  mask_image=DestroyImage(mask_image);
8864                }
8865            }
8866          if (attribute_flag[11] != 0) /* channel */
8867            channel=(ChannelType) argument_list[11].integer_reference;
8868          /*
8869            Composite two images (normal composition).
8870          */
8871          (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8872            "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8873            (double) composite_image->rows,(double) geometry.x,(double)
8874            geometry.y);
8875          flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8876            exception);
8877          channel_mask=SetImageChannelMask(image,channel);
8878          if (attribute_flag[8] == 0) /* no rotate */
8879            CompositeImage(image,composite_image,compose,clip_to_self,
8880              geometry.x,geometry.y,exception);
8881          else
8882            {
8883              /*
8884                Position adjust rotated image then composite.
8885              */
8886              geometry.x-=(ssize_t) (rotate_image->columns-
8887                composite_image->columns)/2;
8888              geometry.y-=(ssize_t) (rotate_image->rows-
8889                composite_image->rows)/2;
8890              CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8891                geometry.y,exception);
8892              rotate_image=DestroyImage(rotate_image);
8893            }
8894          if (attribute_flag[10] != 0) /* mask */
8895            {
8896              if ((image->compose == DisplaceCompositeOp) ||
8897                  (image->compose == DistortCompositeOp))
8898                composite_image=DestroyImage(composite_image);
8899              else
8900                (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8901                  exception);
8902            }
8903          (void) SetImageChannelMask(image,channel_mask);
8904          break;
8905        }
8906        case 36:  /* Contrast */
8907        {
8908          if (attribute_flag[0] == 0)
8909            argument_list[0].integer_reference=0;
8910          (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8911            MagickTrue : MagickFalse,exception);
8912          break;
8913        }
8914        case 37:  /* CycleColormap */
8915        {
8916          if (attribute_flag[0] == 0)
8917            argument_list[0].integer_reference=6;
8918          (void) CycleColormapImage(image,argument_list[0].integer_reference,
8919            exception);
8920          break;
8921        }
8922        case 38:  /* Draw */
8923        {
8924          DrawInfo
8925            *draw_info;
8926
8927          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8928            (DrawInfo *) NULL);
8929          (void) CloneString(&draw_info->primitive,"point");
8930          if (attribute_flag[0] != 0)
8931            {
8932              if (argument_list[0].integer_reference < 0)
8933                (void) CloneString(&draw_info->primitive,
8934                  argument_list[0].string_reference);
8935              else
8936                (void) CloneString(&draw_info->primitive,
8937                  CommandOptionToMnemonic(MagickPrimitiveOptions,
8938                  argument_list[0].integer_reference));
8939            }
8940          if (attribute_flag[1] != 0)
8941            {
8942              if (LocaleCompare(draw_info->primitive,"path") == 0)
8943                {
8944                  (void) ConcatenateString(&draw_info->primitive," '");
8945                  ConcatenateString(&draw_info->primitive,
8946                    argument_list[1].string_reference);
8947                  (void) ConcatenateString(&draw_info->primitive,"'");
8948                }
8949              else
8950                {
8951                  (void) ConcatenateString(&draw_info->primitive," ");
8952                  ConcatenateString(&draw_info->primitive,
8953                    argument_list[1].string_reference);
8954                }
8955            }
8956          if (attribute_flag[2] != 0)
8957            {
8958              (void) ConcatenateString(&draw_info->primitive," ");
8959              (void) ConcatenateString(&draw_info->primitive,
8960                CommandOptionToMnemonic(MagickMethodOptions,
8961                argument_list[2].integer_reference));
8962            }
8963          if (attribute_flag[3] != 0)
8964            {
8965              (void) QueryColorCompliance(argument_list[3].string_reference,
8966                AllCompliance,&draw_info->stroke,exception);
8967              if (argument_list[3].image_reference != (Image *) NULL)
8968                draw_info->stroke_pattern=CloneImage(
8969                  argument_list[3].image_reference,0,0,MagickTrue,exception);
8970            }
8971          if (attribute_flag[4] != 0)
8972            {
8973              (void) QueryColorCompliance(argument_list[4].string_reference,
8974                AllCompliance,&draw_info->fill,exception);
8975              if (argument_list[4].image_reference != (Image *) NULL)
8976                draw_info->fill_pattern=CloneImage(
8977                  argument_list[4].image_reference,0,0,MagickTrue,exception);
8978            }
8979          if (attribute_flag[5] != 0)
8980            draw_info->stroke_width=argument_list[5].real_reference;
8981          if (attribute_flag[6] != 0)
8982            (void) CloneString(&draw_info->font,
8983              argument_list[6].string_reference);
8984          if (attribute_flag[7] != 0)
8985            (void) QueryColorCompliance(argument_list[7].string_reference,
8986              AllCompliance,&draw_info->border_color,exception);
8987          if (attribute_flag[8] != 0)
8988            draw_info->affine.tx=argument_list[8].real_reference;
8989          if (attribute_flag[9] != 0)
8990            draw_info->affine.ty=argument_list[9].real_reference;
8991          if (attribute_flag[20] != 0)
8992            {
8993              AV
8994                *av;
8995
8996              av=(AV *) argument_list[20].array_reference;
8997              if ((av_len(av) != 3) && (av_len(av) != 5))
8998                {
8999                  ThrowPerlException(exception,OptionError,
9000                    "affine matrix must have 4 or 6 elements",PackageName);
9001                  goto PerlException;
9002                }
9003              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9004              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9005              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9006              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9007              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9008                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9009                {
9010                  ThrowPerlException(exception,OptionError,
9011                    "affine matrix is singular",PackageName);
9012                   goto PerlException;
9013                }
9014              if (av_len(av) == 5)
9015                {
9016                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9017                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9018                }
9019            }
9020          for (j=10; j < 15; j++)
9021          {
9022            if (attribute_flag[j] == 0)
9023              continue;
9024            value=argument_list[j].string_reference;
9025            angle=argument_list[j].real_reference;
9026            current=draw_info->affine;
9027            GetAffineMatrix(&affine);
9028            switch (j)
9029            {
9030              case 10:
9031              {
9032                /*
9033                  Translate.
9034                */
9035                flags=ParseGeometry(value,&geometry_info);
9036                affine.tx=geometry_info.xi;
9037                affine.ty=geometry_info.psi;
9038                if ((flags & PsiValue) == 0)
9039                  affine.ty=affine.tx;
9040                break;
9041              }
9042              case 11:
9043              {
9044                /*
9045                  Scale.
9046                */
9047                flags=ParseGeometry(value,&geometry_info);
9048                affine.sx=geometry_info.rho;
9049                affine.sy=geometry_info.sigma;
9050                if ((flags & SigmaValue) == 0)
9051                  affine.sy=affine.sx;
9052                break;
9053              }
9054              case 12:
9055              {
9056                /*
9057                  Rotate.
9058                */
9059                if (angle == 0.0)
9060                  break;
9061                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9062                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9063                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9064                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9065                break;
9066              }
9067              case 13:
9068              {
9069                /*
9070                  SkewX.
9071                */
9072                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9073                break;
9074              }
9075              case 14:
9076              {
9077                /*
9078                  SkewY.
9079                */
9080                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9081                break;
9082              }
9083            }
9084            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9085            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9086            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9087            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9088            draw_info->affine.tx=
9089              current.sx*affine.tx+current.ry*affine.ty+current.tx;
9090            draw_info->affine.ty=
9091              current.rx*affine.tx+current.sy*affine.ty+current.ty;
9092          }
9093          if (attribute_flag[15] != 0)
9094            draw_info->fill_pattern=CloneImage(
9095              argument_list[15].image_reference,0,0,MagickTrue,exception);
9096          if (attribute_flag[16] != 0)
9097            draw_info->pointsize=argument_list[16].real_reference;
9098          if (attribute_flag[17] != 0)
9099            {
9100              draw_info->stroke_antialias=
9101                argument_list[17].integer_reference != 0 ? MagickTrue :
9102                MagickFalse;
9103              draw_info->text_antialias=draw_info->stroke_antialias;
9104            }
9105          if (attribute_flag[18] != 0)
9106            (void) CloneString(&draw_info->density,
9107              argument_list[18].string_reference);
9108          if (attribute_flag[19] != 0)
9109            draw_info->stroke_width=argument_list[19].real_reference;
9110          if (attribute_flag[21] != 0)
9111            draw_info->dash_offset=argument_list[21].real_reference;
9112          if (attribute_flag[22] != 0)
9113            {
9114              AV
9115                *av;
9116
9117              av=(AV *) argument_list[22].array_reference;
9118              draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9119                av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9120              if (draw_info->dash_pattern != (double *) NULL)
9121                {
9122                  for (i=0; i <= av_len(av); i++)
9123                    draw_info->dash_pattern[i]=(double)
9124                      SvNV(*(av_fetch(av,i,0)));
9125                  draw_info->dash_pattern[i]=0.0;
9126                }
9127            }
9128          if (attribute_flag[23] != 0)
9129            image->interpolate=(PixelInterpolateMethod)
9130              argument_list[23].integer_reference;
9131          if ((attribute_flag[24] != 0) &&
9132              (draw_info->fill_pattern != (Image *) NULL))
9133            flags=ParsePageGeometry(draw_info->fill_pattern,
9134              argument_list[24].string_reference,
9135              &draw_info->fill_pattern->tile_offset,exception);
9136          if (attribute_flag[25] != 0)
9137            {
9138              (void) ConcatenateString(&draw_info->primitive," '");
9139              (void) ConcatenateString(&draw_info->primitive,
9140                argument_list[25].string_reference);
9141              (void) ConcatenateString(&draw_info->primitive,"'");
9142            }
9143          if (attribute_flag[26] != 0)
9144            draw_info->fill_pattern=CloneImage(
9145              argument_list[26].image_reference,0,0,MagickTrue,exception);
9146          if (attribute_flag[27] != 0)
9147            draw_info->stroke_pattern=CloneImage(
9148              argument_list[27].image_reference,0,0,MagickTrue,exception);
9149          if (attribute_flag[28] != 0)
9150            (void) CloneString(&draw_info->primitive,
9151              argument_list[28].string_reference);
9152          if (attribute_flag[29] != 0)
9153            draw_info->kerning=argument_list[29].real_reference;
9154          if (attribute_flag[30] != 0)
9155            draw_info->interline_spacing=argument_list[30].real_reference;
9156          if (attribute_flag[31] != 0)
9157            draw_info->interword_spacing=argument_list[31].real_reference;
9158          if (attribute_flag[32] != 0)
9159            draw_info->direction=(DirectionType)
9160              argument_list[32].integer_reference;
9161          DrawImage(image,draw_info,exception);
9162          draw_info=DestroyDrawInfo(draw_info);
9163          break;
9164        }
9165        case 39:  /* Equalize */
9166        {
9167          if (attribute_flag[0] != 0)
9168            channel=(ChannelType) argument_list[0].integer_reference;
9169          channel_mask=SetImageChannelMask(image,channel);
9170          (void) EqualizeImage(image,exception);
9171          (void) SetImageChannelMask(image,channel_mask);
9172          break;
9173        }
9174        case 40:  /* Gamma */
9175        {
9176          if (attribute_flag[1] != 0)
9177            channel=(ChannelType) argument_list[1].integer_reference;
9178          if (attribute_flag[2] == 0)
9179            argument_list[2].real_reference=1.0;
9180          if (attribute_flag[3] == 0)
9181            argument_list[3].real_reference=1.0;
9182          if (attribute_flag[4] == 0)
9183            argument_list[4].real_reference=1.0;
9184          if (attribute_flag[0] == 0)
9185            {
9186              (void) FormatLocaleString(message,MagickPathExtent,
9187                "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
9188                (double) argument_list[3].real_reference,
9189                (double) argument_list[4].real_reference);
9190              argument_list[0].string_reference=message;
9191            }
9192          (void) GammaImage(image,StringToDouble(
9193            argument_list[0].string_reference,(char **) NULL),exception);
9194          break;
9195        }
9196        case 41:  /* Map */
9197        {
9198          QuantizeInfo
9199            *quantize_info;
9200
9201          if (attribute_flag[0] == 0)
9202            {
9203              ThrowPerlException(exception,OptionError,"MapImageRequired",
9204                PackageName);
9205              goto PerlException;
9206            }
9207          quantize_info=AcquireQuantizeInfo(info->image_info);
9208          if (attribute_flag[1] != 0)
9209            quantize_info->dither_method=(DitherMethod)
9210              argument_list[1].integer_reference;
9211          (void) RemapImages(quantize_info,image,
9212            argument_list[0].image_reference,exception);
9213          quantize_info=DestroyQuantizeInfo(quantize_info);
9214          break;
9215        }
9216        case 42:  /* MatteFloodfill */
9217        {
9218          DrawInfo
9219            *draw_info;
9220
9221          MagickBooleanType
9222            invert;
9223
9224          PixelInfo
9225            target;
9226
9227          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9228            (DrawInfo *) NULL);
9229          if (attribute_flag[0] != 0)
9230            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9231              &geometry,exception);
9232          if (attribute_flag[1] != 0)
9233            geometry.x=argument_list[1].integer_reference;
9234          if (attribute_flag[2] != 0)
9235            geometry.y=argument_list[2].integer_reference;
9236          if (image->alpha_trait == UndefinedPixelTrait)
9237            (void) SetImageAlpha(image,OpaqueAlpha,exception);
9238          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9239            geometry.x,geometry.y,&target,exception);
9240          if (attribute_flag[4] != 0)
9241            QueryColorCompliance(argument_list[4].string_reference,
9242              AllCompliance,&target,exception);
9243          if (attribute_flag[3] != 0)
9244            target.alpha=StringToDoubleInterval(
9245              argument_list[3].string_reference,(double) (double) QuantumRange+
9246              1.0);
9247          if (attribute_flag[5] != 0)
9248            image->fuzz=StringToDoubleInterval(
9249              argument_list[5].string_reference,(double) QuantumRange+1.0);
9250          invert=MagickFalse;
9251          if (attribute_flag[6] != 0)
9252            invert=(MagickBooleanType) argument_list[6].integer_reference;
9253          channel_mask=SetImageChannelMask(image,AlphaChannel);
9254          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9255            geometry.y,invert,exception);
9256          (void) SetImageChannelMask(image,channel_mask);
9257          draw_info=DestroyDrawInfo(draw_info);
9258          break;
9259        }
9260        case 43:  /* Modulate */
9261        {
9262          char
9263            modulate[MagickPathExtent];
9264
9265          geometry_info.rho=100.0;
9266          geometry_info.sigma=100.0;
9267          geometry_info.xi=100.0;
9268          if (attribute_flag[0] != 0)
9269            (void)ParseGeometry(argument_list[0].string_reference,
9270              &geometry_info);
9271          if (attribute_flag[1] != 0)
9272            geometry_info.xi=argument_list[1].real_reference;
9273          if (attribute_flag[2] != 0)
9274            geometry_info.sigma=argument_list[2].real_reference;
9275          if (attribute_flag[3] != 0)
9276            {
9277              geometry_info.sigma=argument_list[3].real_reference;
9278              SetImageArtifact(image,"modulate:colorspace","HWB");
9279            }
9280          if (attribute_flag[4] != 0)
9281            {
9282              geometry_info.rho=argument_list[4].real_reference;
9283              SetImageArtifact(image,"modulate:colorspace","HSB");
9284            }
9285          if (attribute_flag[5] != 0)
9286            {
9287              geometry_info.sigma=argument_list[5].real_reference;
9288              SetImageArtifact(image,"modulate:colorspace","HSL");
9289            }
9290          if (attribute_flag[6] != 0)
9291            {
9292              geometry_info.rho=argument_list[6].real_reference;
9293              SetImageArtifact(image,"modulate:colorspace","HWB");
9294            }
9295          (void) FormatLocaleString(modulate,MagickPathExtent,
9296            "%.20g,%.20g,%.20g",geometry_info.rho,geometry_info.sigma,
9297            geometry_info.xi);
9298          (void) ModulateImage(image,modulate,exception);
9299          break;
9300        }
9301        case 44:  /* Negate */
9302        {
9303          if (attribute_flag[0] == 0)
9304            argument_list[0].integer_reference=0;
9305          if (attribute_flag[1] != 0)
9306            channel=(ChannelType) argument_list[1].integer_reference;
9307          channel_mask=SetImageChannelMask(image,channel);
9308          (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9309            MagickTrue : MagickFalse,exception);
9310          (void) SetImageChannelMask(image,channel_mask);
9311          break;
9312        }
9313        case 45:  /* Normalize */
9314        {
9315          if (attribute_flag[0] != 0)
9316            channel=(ChannelType) argument_list[0].integer_reference;
9317          channel_mask=SetImageChannelMask(image,channel);
9318          NormalizeImage(image,exception);
9319          (void) SetImageChannelMask(image,channel_mask);
9320          break;
9321        }
9322        case 46:  /* NumberColors */
9323          break;
9324        case 47:  /* Opaque */
9325        {
9326          MagickBooleanType
9327            invert;
9328
9329          PixelInfo
9330            fill_color,
9331            target;
9332
9333          (void) QueryColorCompliance("none",AllCompliance,&target,
9334             exception);
9335          (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9336            exception);
9337          if (attribute_flag[0] != 0)
9338            (void) QueryColorCompliance(argument_list[0].string_reference,
9339              AllCompliance,&target,exception);
9340          if (attribute_flag[1] != 0)
9341            (void) QueryColorCompliance(argument_list[1].string_reference,
9342              AllCompliance,&fill_color,exception);
9343          if (attribute_flag[2] != 0)
9344            image->fuzz=StringToDoubleInterval(
9345              argument_list[2].string_reference,(double) QuantumRange+1.0);
9346          if (attribute_flag[3] != 0)
9347            channel=(ChannelType) argument_list[3].integer_reference;
9348          invert=MagickFalse;
9349          if (attribute_flag[4] != 0)
9350            invert=(MagickBooleanType) argument_list[4].integer_reference;
9351          channel_mask=SetImageChannelMask(image,channel);
9352          (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9353          (void) SetImageChannelMask(image,channel_mask);
9354          break;
9355        }
9356        case 48:  /* Quantize */
9357        {
9358          QuantizeInfo
9359            *quantize_info;
9360
9361          quantize_info=AcquireQuantizeInfo(info->image_info);
9362          if (attribute_flag[0] != 0)
9363            quantize_info->number_colors=(size_t)
9364              argument_list[0].integer_reference;
9365          if (attribute_flag[1] != 0)
9366            quantize_info->tree_depth=(size_t)
9367              argument_list[1].integer_reference;
9368          if (attribute_flag[2] != 0)
9369            quantize_info->colorspace=(ColorspaceType)
9370              argument_list[2].integer_reference;
9371          if (attribute_flag[3] != 0)
9372            quantize_info->dither_method=(DitherMethod)
9373              argument_list[3].integer_reference;
9374          if (attribute_flag[4] != 0)
9375            quantize_info->measure_error=
9376              argument_list[4].integer_reference != 0 ? MagickTrue :
9377              MagickFalse;
9378          if (attribute_flag[6] != 0)
9379            (void) QueryColorCompliance(argument_list[6].string_reference,
9380              AllCompliance,&image->transparent_color,exception);
9381          if (attribute_flag[7] != 0)
9382            quantize_info->dither_method=(DitherMethod)
9383              argument_list[7].integer_reference;
9384          if (attribute_flag[5] && argument_list[5].integer_reference)
9385            (void) QuantizeImages(quantize_info,image,exception);
9386          else
9387            if ((image->storage_class == DirectClass) ||
9388               (image->colors > quantize_info->number_colors) ||
9389               (quantize_info->colorspace == GRAYColorspace))
9390             (void) QuantizeImage(quantize_info,image,exception);
9391           else
9392             CompressImageColormap(image,exception);
9393          quantize_info=DestroyQuantizeInfo(quantize_info);
9394          break;
9395        }
9396        case 49:  /* Raise */
9397        {
9398          if (attribute_flag[0] != 0)
9399            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9400              &geometry,exception);
9401          if (attribute_flag[1] != 0)
9402            geometry.width=argument_list[1].integer_reference;
9403          if (attribute_flag[2] != 0)
9404            geometry.height=argument_list[2].integer_reference;
9405          if (attribute_flag[3] == 0)
9406            argument_list[3].integer_reference=1;
9407          (void) RaiseImage(image,&geometry,
9408            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9409            exception);
9410          break;
9411        }
9412        case 50:  /* Segment */
9413        {
9414          ColorspaceType
9415            colorspace;
9416
9417          double
9418            cluster_threshold,
9419            smoothing_threshold;
9420
9421          MagickBooleanType
9422            verbose;
9423
9424          cluster_threshold=1.0;
9425          smoothing_threshold=1.5;
9426          colorspace=sRGBColorspace;
9427          verbose=MagickFalse;
9428          if (attribute_flag[0] != 0)
9429            {
9430              flags=ParseGeometry(argument_list[0].string_reference,
9431                &geometry_info);
9432              cluster_threshold=geometry_info.rho;
9433              if (flags & SigmaValue)
9434                smoothing_threshold=geometry_info.sigma;
9435            }
9436          if (attribute_flag[1] != 0)
9437            cluster_threshold=argument_list[1].real_reference;
9438          if (attribute_flag[2] != 0)
9439            smoothing_threshold=argument_list[2].real_reference;
9440          if (attribute_flag[3] != 0)
9441            colorspace=(ColorspaceType) argument_list[3].integer_reference;
9442          if (attribute_flag[4] != 0)
9443            verbose=argument_list[4].integer_reference != 0 ? MagickTrue :
9444              MagickFalse;
9445          (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9446            smoothing_threshold,exception);
9447          break;
9448        }
9449        case 51:  /* Signature */
9450        {
9451          (void) SignatureImage(image,exception);
9452          break;
9453        }
9454        case 52:  /* Solarize */
9455        {
9456          geometry_info.rho=QuantumRange/2.0;
9457          if (attribute_flag[0] != 0)
9458            flags=ParseGeometry(argument_list[0].string_reference,
9459              &geometry_info);
9460          if (attribute_flag[1] != 0)
9461            geometry_info.rho=StringToDoubleInterval(
9462              argument_list[1].string_reference,(double) QuantumRange+1.0);
9463          (void) SolarizeImage(image,geometry_info.rho,exception);
9464          break;
9465        }
9466        case 53:  /* Sync */
9467        {
9468          (void) SyncImage(image,exception);
9469          break;
9470        }
9471        case 54:  /* Texture */
9472        {
9473          if (attribute_flag[0] == 0)
9474            break;
9475          TextureImage(image,argument_list[0].image_reference,exception);
9476          break;
9477        }
9478        case 55:  /* Evalute */
9479        {
9480          MagickEvaluateOperator
9481            op;
9482
9483          op=SetEvaluateOperator;
9484          if (attribute_flag[0] == MagickFalse)
9485            argument_list[0].real_reference=0.0;
9486          if (attribute_flag[1] != MagickFalse)
9487            op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9488          if (attribute_flag[2] != MagickFalse)
9489            channel=(ChannelType) argument_list[2].integer_reference;
9490          channel_mask=SetImageChannelMask(image,channel);
9491          (void) EvaluateImage(image,op,argument_list[0].real_reference,
9492            exception);
9493          (void) SetImageChannelMask(image,channel_mask);
9494          break;
9495        }
9496        case 56:  /* Transparent */
9497        {
9498          double
9499            opacity;
9500
9501          MagickBooleanType
9502            invert;
9503
9504          PixelInfo
9505            target;
9506
9507          (void) QueryColorCompliance("none",AllCompliance,&target,
9508            exception);
9509          if (attribute_flag[0] != 0)
9510            (void) QueryColorCompliance(argument_list[0].string_reference,
9511              AllCompliance,&target,exception);
9512          opacity=TransparentAlpha;
9513          if (attribute_flag[1] != 0)
9514            opacity=StringToDoubleInterval(argument_list[1].string_reference,
9515              (double) QuantumRange+1.0);
9516          if (attribute_flag[2] != 0)
9517            image->fuzz=StringToDoubleInterval(
9518              argument_list[2].string_reference,(double) QuantumRange+1.0);
9519          if (attribute_flag[3] == 0)
9520            argument_list[3].integer_reference=0;
9521          invert=MagickFalse;
9522          if (attribute_flag[3] != 0)
9523            invert=(MagickBooleanType) argument_list[3].integer_reference;
9524          (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9525            invert,exception);
9526          break;
9527        }
9528        case 57:  /* Threshold */
9529        {
9530          double
9531            threshold;
9532
9533          if (attribute_flag[0] == 0)
9534            argument_list[0].string_reference="50%";
9535          if (attribute_flag[1] != 0)
9536            channel=(ChannelType) argument_list[1].integer_reference;
9537          threshold=StringToDoubleInterval(argument_list[0].string_reference,
9538            (double) QuantumRange+1.0);
9539          channel_mask=SetImageChannelMask(image,channel);
9540          (void) BilevelImage(image,threshold,exception);
9541          (void) SetImageChannelMask(image,channel_mask);
9542          break;
9543        }
9544        case 58:  /* Charcoal */
9545        {
9546          if (attribute_flag[0] != 0)
9547            {
9548              flags=ParseGeometry(argument_list[0].string_reference,
9549                &geometry_info);
9550              if ((flags & SigmaValue) == 0)
9551                geometry_info.sigma=1.0;
9552            }
9553          if (attribute_flag[1] != 0)
9554            geometry_info.rho=argument_list[1].real_reference;
9555          if (attribute_flag[2] != 0)
9556            geometry_info.sigma=argument_list[2].real_reference;
9557          image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9558            exception);
9559          break;
9560        }
9561        case 59:  /* Trim */
9562        {
9563          if (attribute_flag[0] != 0)
9564            image->fuzz=StringToDoubleInterval(
9565              argument_list[0].string_reference,(double) QuantumRange+1.0);
9566          image=TrimImage(image,exception);
9567          break;
9568        }
9569        case 60:  /* Wave */
9570        {
9571          PixelInterpolateMethod
9572            method;
9573
9574          if (attribute_flag[0] != 0)
9575            {
9576              flags=ParseGeometry(argument_list[0].string_reference,
9577                &geometry_info);
9578              if ((flags & SigmaValue) == 0)
9579                geometry_info.sigma=1.0;
9580            }
9581          if (attribute_flag[1] != 0)
9582            geometry_info.rho=argument_list[1].real_reference;
9583          if (attribute_flag[2] != 0)
9584            geometry_info.sigma=argument_list[2].real_reference;
9585          method=UndefinedInterpolatePixel;
9586          if (attribute_flag[3] != 0)
9587            method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9588          image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9589            method,exception);
9590          break;
9591        }
9592        case 61:  /* Separate */
9593        {
9594          if (attribute_flag[0] != 0)
9595            channel=(ChannelType) argument_list[0].integer_reference;
9596          image=SeparateImage(image,channel,exception);
9597          break;
9598        }
9599        case 63:  /* Stereo */
9600        {
9601          if (attribute_flag[0] == 0)
9602            {
9603              ThrowPerlException(exception,OptionError,"StereoImageRequired",
9604                PackageName);
9605              goto PerlException;
9606            }
9607          if (attribute_flag[1] != 0)
9608            geometry.x=argument_list[1].integer_reference;
9609          if (attribute_flag[2] != 0)
9610            geometry.y=argument_list[2].integer_reference;
9611          image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9612            geometry.x,geometry.y,exception);
9613          break;
9614        }
9615        case 64:  /* Stegano */
9616        {
9617          if (attribute_flag[0] == 0)
9618            {
9619              ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9620                PackageName);
9621              goto PerlException;
9622            }
9623          if (attribute_flag[1] == 0)
9624            argument_list[1].integer_reference=0;
9625          image->offset=argument_list[1].integer_reference;
9626          image=SteganoImage(image,argument_list[0].image_reference,exception);
9627          break;
9628        }
9629        case 65:  /* Deconstruct */
9630        {
9631          image=CompareImagesLayers(image,CompareAnyLayer,exception);
9632          break;
9633        }
9634        case 66:  /* GaussianBlur */
9635        {
9636          if (attribute_flag[0] != 0)
9637            {
9638              flags=ParseGeometry(argument_list[0].string_reference,
9639                &geometry_info);
9640              if ((flags & SigmaValue) == 0)
9641                geometry_info.sigma=1.0;
9642            }
9643          if (attribute_flag[1] != 0)
9644            geometry_info.rho=argument_list[1].real_reference;
9645          if (attribute_flag[2] != 0)
9646            geometry_info.sigma=argument_list[2].real_reference;
9647          if (attribute_flag[3] != 0)
9648            channel=(ChannelType) argument_list[3].integer_reference;
9649          channel_mask=SetImageChannelMask(image,channel);
9650          image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9651            exception);
9652          if (image != (Image *) NULL)
9653            (void) SetImageChannelMask(image,channel_mask);
9654          break;
9655        }
9656        case 67:  /* Convolve */
9657        {
9658          KernelInfo
9659            *kernel;
9660
9661          kernel=(KernelInfo *) NULL;
9662          if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9663            break;
9664          if (attribute_flag[0] != 0)
9665            {
9666              AV
9667                *av;
9668
9669              size_t
9670                order;
9671
9672              kernel=AcquireKernelInfo((const char *) NULL,exception);
9673              if (kernel == (KernelInfo *) NULL)
9674                break;
9675              av=(AV *) argument_list[0].array_reference;
9676              order=(size_t) sqrt(av_len(av)+1);
9677              kernel->width=order;
9678              kernel->height=order;
9679              kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9680                order*sizeof(*kernel->values));
9681              if (kernel->values == (MagickRealType *) NULL)
9682                {
9683                  kernel=DestroyKernelInfo(kernel);
9684                  ThrowPerlException(exception,ResourceLimitFatalError,
9685                    "MemoryAllocationFailed",PackageName);
9686                  goto PerlException;
9687                }
9688              for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9689                kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9690              for ( ; j < (ssize_t) (order*order); j++)
9691                kernel->values[j]=0.0;
9692            }
9693          if (attribute_flag[1] != 0)
9694            channel=(ChannelType) argument_list[1].integer_reference;
9695          if (attribute_flag[2] != 0)
9696            SetImageArtifact(image,"convolve:bias",
9697              argument_list[2].string_reference);
9698          if (attribute_flag[3] != 0)
9699            {
9700              kernel=AcquireKernelInfo(argument_list[3].string_reference,
9701                exception);
9702              if (kernel == (KernelInfo *) NULL)
9703                break;
9704            }
9705          channel_mask=SetImageChannelMask(image,channel);
9706          image=ConvolveImage(image,kernel,exception);
9707          if (image != (Image *) NULL)
9708            (void) SetImageChannelMask(image,channel_mask);
9709          kernel=DestroyKernelInfo(kernel);
9710          break;
9711        }
9712        case 68:  /* Profile */
9713        {
9714          const char
9715            *name;
9716
9717          Image
9718            *profile_image;
9719
9720          ImageInfo
9721            *profile_info;
9722
9723          StringInfo
9724            *profile;
9725
9726          name="*";
9727          if (attribute_flag[0] != 0)
9728            name=argument_list[0].string_reference;
9729          if (attribute_flag[2] != 0)
9730            image->rendering_intent=(RenderingIntent)
9731              argument_list[2].integer_reference;
9732          if (attribute_flag[3] != 0)
9733            image->black_point_compensation=
9734              argument_list[3].integer_reference != 0 ? MagickTrue :
9735              MagickFalse;
9736          if (attribute_flag[1] != 0)
9737            {
9738              if (argument_list[1].length == 0)
9739                {
9740                  /*
9741                    Remove a profile from the image.
9742                  */
9743                  (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9744                    exception);
9745                  break;
9746                }
9747              /*
9748                Associate user supplied profile with the image.
9749              */
9750              profile=AcquireStringInfo(argument_list[1].length);
9751              SetStringInfoDatum(profile,(const unsigned char *)
9752                argument_list[1].string_reference);
9753              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9754                (size_t) GetStringInfoLength(profile),exception);
9755              profile=DestroyStringInfo(profile);
9756              break;
9757            }
9758          /*
9759            Associate a profile with the image.
9760          */
9761          profile_info=CloneImageInfo(info ? info->image_info : (ImageInfo *)
9762            NULL);
9763          profile_image=ReadImages(profile_info,name,exception);
9764          if (profile_image == (Image *) NULL)
9765            break;
9766          ResetImageProfileIterator(profile_image);
9767          name=GetNextImageProfile(profile_image);
9768          while (name != (const char *) NULL)
9769          {
9770            const StringInfo
9771              *profile;
9772
9773            profile=GetImageProfile(profile_image,name);
9774            if (profile != (const StringInfo *) NULL)
9775              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9776                (size_t) GetStringInfoLength(profile),exception);
9777            name=GetNextImageProfile(profile_image);
9778          }
9779          profile_image=DestroyImage(profile_image);
9780          profile_info=DestroyImageInfo(profile_info);
9781          break;
9782        }
9783        case 69:  /* UnsharpMask */
9784        {
9785          if (attribute_flag[0] != 0)
9786            {
9787              flags=ParseGeometry(argument_list[0].string_reference,
9788                &geometry_info);
9789              if ((flags & SigmaValue) == 0)
9790                geometry_info.sigma=1.0;
9791              if ((flags & XiValue) == 0)
9792                geometry_info.xi=1.0;
9793              if ((flags & PsiValue) == 0)
9794                geometry_info.psi=0.5;
9795            }
9796          if (attribute_flag[1] != 0)
9797            geometry_info.rho=argument_list[1].real_reference;
9798          if (attribute_flag[2] != 0)
9799            geometry_info.sigma=argument_list[2].real_reference;
9800          if (attribute_flag[3] != 0)
9801            geometry_info.xi=argument_list[3].real_reference;
9802          if (attribute_flag[4] != 0)
9803            geometry_info.psi=argument_list[4].real_reference;
9804          if (attribute_flag[5] != 0)
9805            channel=(ChannelType) argument_list[5].integer_reference;
9806          channel_mask=SetImageChannelMask(image,channel);
9807          image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9808            geometry_info.xi,geometry_info.psi,exception);
9809          if (image != (Image *) NULL)
9810            (void) SetImageChannelMask(image,channel_mask);
9811          break;
9812        }
9813        case 70:  /* MotionBlur */
9814        {
9815          if (attribute_flag[0] != 0)
9816            {
9817              flags=ParseGeometry(argument_list[0].string_reference,
9818                &geometry_info);
9819              if ((flags & SigmaValue) == 0)
9820                geometry_info.sigma=1.0;
9821              if ((flags & XiValue) == 0)
9822                geometry_info.xi=1.0;
9823            }
9824          if (attribute_flag[1] != 0)
9825            geometry_info.rho=argument_list[1].real_reference;
9826          if (attribute_flag[2] != 0)
9827            geometry_info.sigma=argument_list[2].real_reference;
9828          if (attribute_flag[3] != 0)
9829            geometry_info.xi=argument_list[3].real_reference;
9830          if (attribute_flag[4] != 0)
9831            channel=(ChannelType) argument_list[4].integer_reference;
9832          channel_mask=SetImageChannelMask(image,channel);
9833          image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9834            geometry_info.xi,exception);
9835          if (image != (Image *) NULL)
9836            (void) SetImageChannelMask(image,channel_mask);
9837          break;
9838        }
9839        case 71:  /* OrderedDither */
9840        {
9841          if (attribute_flag[0] == 0)
9842            argument_list[0].string_reference="o8x8";
9843          if (attribute_flag[1] != 0)
9844            channel=(ChannelType) argument_list[1].integer_reference;
9845          channel_mask=SetImageChannelMask(image,channel);
9846          (void) OrderedDitherImage(image,argument_list[0].string_reference,
9847            exception);
9848          (void) SetImageChannelMask(image,channel_mask);
9849          break;
9850        }
9851        case 72:  /* Shave */
9852        {
9853          if (attribute_flag[0] != 0)
9854            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9855              &geometry,exception);
9856          if (attribute_flag[1] != 0)
9857            geometry.width=argument_list[1].integer_reference;
9858          if (attribute_flag[2] != 0)
9859            geometry.height=argument_list[2].integer_reference;
9860          image=ShaveImage(image,&geometry,exception);
9861          break;
9862        }
9863        case 73:  /* Level */
9864        {
9865          double
9866            black_point,
9867            gamma,
9868            white_point;
9869
9870          black_point=0.0;
9871          white_point=(double) image->columns*image->rows;
9872          gamma=1.0;
9873          if (attribute_flag[0] != 0)
9874            {
9875              flags=ParseGeometry(argument_list[0].string_reference,
9876                &geometry_info);
9877              black_point=geometry_info.rho;
9878              if ((flags & SigmaValue) != 0)
9879                white_point=geometry_info.sigma;
9880              if ((flags & XiValue) != 0)
9881                gamma=geometry_info.xi;
9882              if ((flags & PercentValue) != 0)
9883                {
9884                  black_point*=(double) (QuantumRange/100.0);
9885                  white_point*=(double) (QuantumRange/100.0);
9886                }
9887              if ((flags & SigmaValue) == 0)
9888                white_point=(double) QuantumRange-black_point;
9889            }
9890          if (attribute_flag[1] != 0)
9891            black_point=argument_list[1].real_reference;
9892          if (attribute_flag[2] != 0)
9893            white_point=argument_list[2].real_reference;
9894          if (attribute_flag[3] != 0)
9895            gamma=argument_list[3].real_reference;
9896          if (attribute_flag[4] != 0)
9897            channel=(ChannelType) argument_list[4].integer_reference;
9898          if (attribute_flag[5] != 0)
9899            {
9900              argument_list[0].real_reference=argument_list[5].real_reference;
9901              attribute_flag[0]=attribute_flag[5];
9902            }
9903          channel_mask=SetImageChannelMask(image,channel);
9904          (void) LevelImage(image,black_point,white_point,gamma,exception);
9905          (void) SetImageChannelMask(image,channel_mask);
9906          break;
9907        }
9908        case 74:  /* Clip */
9909        {
9910          if (attribute_flag[0] == 0)
9911            argument_list[0].string_reference="#1";
9912          if (attribute_flag[1] == 0)
9913            argument_list[1].integer_reference=MagickTrue;
9914          (void) ClipImagePath(image,argument_list[0].string_reference,
9915            argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9916            exception);
9917          break;
9918        }
9919        case 75:  /* AffineTransform */
9920        {
9921          DrawInfo
9922            *draw_info;
9923
9924          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9925            (DrawInfo *) NULL);
9926          if (attribute_flag[0] != 0)
9927            {
9928              AV
9929                *av;
9930
9931              av=(AV *) argument_list[0].array_reference;
9932              if ((av_len(av) != 3) && (av_len(av) != 5))
9933                {
9934                  ThrowPerlException(exception,OptionError,
9935                    "affine matrix must have 4 or 6 elements",PackageName);
9936                  goto PerlException;
9937                }
9938              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9939              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9940              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9941              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9942              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9943                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9944                {
9945                  ThrowPerlException(exception,OptionError,
9946                    "affine matrix is singular",PackageName);
9947                   goto PerlException;
9948                }
9949              if (av_len(av) == 5)
9950                {
9951                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9952                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9953                }
9954            }
9955          for (j=1; j < 6; j++)
9956          {
9957            if (attribute_flag[j] == 0)
9958              continue;
9959            value=argument_list[j].string_reference;
9960            angle=argument_list[j].real_reference;
9961            current=draw_info->affine;
9962            GetAffineMatrix(&affine);
9963            switch (j)
9964            {
9965              case 1:
9966              {
9967                /*
9968                  Translate.
9969                */
9970                flags=ParseGeometry(value,&geometry_info);
9971                affine.tx=geometry_info.xi;
9972                affine.ty=geometry_info.psi;
9973                if ((flags & PsiValue) == 0)
9974                  affine.ty=affine.tx;
9975                break;
9976              }
9977              case 2:
9978              {
9979                /*
9980                  Scale.
9981                */
9982                flags=ParseGeometry(value,&geometry_info);
9983                affine.sx=geometry_info.rho;
9984                affine.sy=geometry_info.sigma;
9985                if ((flags & SigmaValue) == 0)
9986                  affine.sy=affine.sx;
9987                break;
9988              }
9989              case 3:
9990              {
9991                /*
9992                  Rotate.
9993                */
9994                if (angle == 0.0)
9995                  break;
9996                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9997                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9998                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9999                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
10000                break;
10001              }
10002              case 4:
10003              {
10004                /*
10005                  SkewX.
10006                */
10007                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
10008                break;
10009              }
10010              case 5:
10011              {
10012                /*
10013                  SkewY.
10014                */
10015                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10016                break;
10017              }
10018            }
10019            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10020            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10021            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10022            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10023            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
10024              current.tx;
10025            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
10026              current.ty;
10027          }
10028          if (attribute_flag[6] != 0)
10029            image->interpolate=(PixelInterpolateMethod)
10030              argument_list[6].integer_reference;
10031          if (attribute_flag[7] != 0)
10032            QueryColorCompliance(argument_list[7].string_reference,
10033              AllCompliance,&image->background_color,exception);
10034          image=AffineTransformImage(image,&draw_info->affine,exception);
10035          draw_info=DestroyDrawInfo(draw_info);
10036          break;
10037        }
10038        case 76:  /* Difference */
10039        {
10040          if (attribute_flag[0] == 0)
10041            {
10042              ThrowPerlException(exception,OptionError,
10043                "ReferenceImageRequired",PackageName);
10044              goto PerlException;
10045            }
10046          if (attribute_flag[1] != 0)
10047            image->fuzz=StringToDoubleInterval(
10048              argument_list[1].string_reference,(double) QuantumRange+1.0);
10049          (void) SetImageColorMetric(image,argument_list[0].image_reference,
10050            exception);
10051          break;
10052        }
10053        case 77:  /* AdaptiveThreshold */
10054        {
10055          if (attribute_flag[0] != 0)
10056            {
10057              flags=ParseGeometry(argument_list[0].string_reference,
10058                &geometry_info);
10059              if ((flags & PercentValue) != 0)
10060                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10061            }
10062          if (attribute_flag[1] != 0)
10063            geometry_info.rho=argument_list[1].integer_reference;
10064          if (attribute_flag[2] != 0)
10065            geometry_info.sigma=argument_list[2].integer_reference;
10066          if (attribute_flag[3] != 0)
10067            geometry_info.xi=argument_list[3].integer_reference;;
10068          image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10069            (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10070          break;
10071        }
10072        case 78:  /* Resample */
10073        {
10074          size_t
10075            height,
10076            width;
10077
10078          if (attribute_flag[0] != 0)
10079            {
10080              flags=ParseGeometry(argument_list[0].string_reference,
10081                &geometry_info);
10082              if ((flags & SigmaValue) == 0)
10083                geometry_info.sigma=geometry_info.rho;
10084            }
10085          if (attribute_flag[1] != 0)
10086            geometry_info.rho=argument_list[1].real_reference;
10087          if (attribute_flag[2] != 0)
10088            geometry_info.sigma=argument_list[2].real_reference;
10089          if (attribute_flag[3] == 0)
10090            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10091          if (attribute_flag[4] == 0)
10092            SetImageArtifact(image,"filter:support",
10093              argument_list[4].string_reference);
10094          width=(size_t) (geometry_info.rho*image->columns/
10095            (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10096          height=(size_t) (geometry_info.sigma*image->rows/
10097            (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10098          image=ResizeImage(image,width,height,(FilterType)
10099            argument_list[3].integer_reference,exception);
10100          if (image != (Image *) NULL)
10101            {
10102              image->resolution.x=geometry_info.rho;
10103              image->resolution.y=geometry_info.sigma;
10104            }
10105          break;
10106        }
10107        case 79:  /* Describe */
10108        {
10109          if (attribute_flag[0] == 0)
10110            argument_list[0].file_reference=(FILE *) NULL;
10111          if (attribute_flag[1] != 0)
10112            (void) SetImageArtifact(image,"identify:features",
10113              argument_list[1].string_reference);
10114          (void) IdentifyImage(image,argument_list[0].file_reference,
10115            MagickTrue,exception);
10116          break;
10117        }
10118        case 80:  /* BlackThreshold */
10119        {
10120          if (attribute_flag[0] == 0)
10121            argument_list[0].string_reference="50%";
10122          if (attribute_flag[2] != 0)
10123            channel=(ChannelType) argument_list[2].integer_reference;
10124          channel_mask=SetImageChannelMask(image,channel);
10125          BlackThresholdImage(image,argument_list[0].string_reference,
10126            exception);
10127          (void) SetImageChannelMask(image,channel_mask);
10128          break;
10129        }
10130        case 81:  /* WhiteThreshold */
10131        {
10132          if (attribute_flag[0] == 0)
10133            argument_list[0].string_reference="50%";
10134          if (attribute_flag[2] != 0)
10135            channel=(ChannelType) argument_list[2].integer_reference;
10136          channel_mask=SetImageChannelMask(image,channel);
10137          WhiteThresholdImage(image,argument_list[0].string_reference,
10138            exception);
10139          (void) SetImageChannelMask(image,channel_mask);
10140          break;
10141        }
10142        case 82:  /* RotationalBlur */
10143        {
10144          if (attribute_flag[0] != 0)
10145            flags=ParseGeometry(argument_list[0].string_reference,
10146              &geometry_info);
10147          if (attribute_flag[1] != 0)
10148            geometry_info.rho=argument_list[1].real_reference;
10149          if (attribute_flag[2] != 0)
10150            channel=(ChannelType) argument_list[2].integer_reference;
10151          channel_mask=SetImageChannelMask(image,channel);
10152          image=RotationalBlurImage(image,geometry_info.rho,exception);
10153          if (image != (Image *) NULL)
10154            (void) SetImageChannelMask(image,channel_mask);
10155          break;
10156        }
10157        case 83:  /* Thumbnail */
10158        {
10159          if (attribute_flag[0] != 0)
10160            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10161              &geometry,exception);
10162          if (attribute_flag[1] != 0)
10163            geometry.width=argument_list[1].integer_reference;
10164          if (attribute_flag[2] != 0)
10165            geometry.height=argument_list[2].integer_reference;
10166          image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10167          break;
10168        }
10169        case 84:  /* Strip */
10170        {
10171          (void) StripImage(image,exception);
10172          break;
10173        }
10174        case 85:  /* Tint */
10175        {
10176          PixelInfo
10177            tint;
10178
10179          GetPixelInfo(image,&tint);
10180          if (attribute_flag[0] != 0)
10181            (void) QueryColorCompliance(argument_list[0].string_reference,
10182              AllCompliance,&tint,exception);
10183          if (attribute_flag[1] == 0)
10184            argument_list[1].string_reference="100";
10185          image=TintImage(image,argument_list[1].string_reference,&tint,
10186            exception);
10187          break;
10188        }
10189        case 86:  /* Channel */
10190        {
10191          if (attribute_flag[0] != 0)
10192            channel=(ChannelType) argument_list[0].integer_reference;
10193          image=SeparateImage(image,channel,exception);
10194          break;
10195        }
10196        case 87:  /* Splice */
10197        {
10198          if (attribute_flag[7] != 0)
10199            image->gravity=(GravityType) argument_list[7].integer_reference;
10200          if (attribute_flag[0] != 0)
10201            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10202              &geometry,exception);
10203          if (attribute_flag[1] != 0)
10204            geometry.width=argument_list[1].integer_reference;
10205          if (attribute_flag[2] != 0)
10206            geometry.height=argument_list[2].integer_reference;
10207          if (attribute_flag[3] != 0)
10208            geometry.x=argument_list[3].integer_reference;
10209          if (attribute_flag[4] != 0)
10210            geometry.y=argument_list[4].integer_reference;
10211          if (attribute_flag[5] != 0)
10212            image->fuzz=StringToDoubleInterval(
10213              argument_list[5].string_reference,(double) QuantumRange+1.0);
10214          if (attribute_flag[6] != 0)
10215            (void) QueryColorCompliance(argument_list[6].string_reference,
10216              AllCompliance,&image->background_color,exception);
10217          image=SpliceImage(image,&geometry,exception);
10218          break;
10219        }
10220        case 88:  /* Posterize */
10221        {
10222          if (attribute_flag[0] == 0)
10223            argument_list[0].integer_reference=3;
10224          if (attribute_flag[1] == 0)
10225            argument_list[1].integer_reference=0;
10226          (void) PosterizeImage(image,argument_list[0].integer_reference,
10227            argument_list[1].integer_reference ? RiemersmaDitherMethod :
10228            NoDitherMethod,exception);
10229          break;
10230        }
10231        case 89:  /* Shadow */
10232        {
10233          if (attribute_flag[0] != 0)
10234            {
10235              flags=ParseGeometry(argument_list[0].string_reference,
10236                &geometry_info);
10237              if ((flags & SigmaValue) == 0)
10238                geometry_info.sigma=1.0;
10239              if ((flags & XiValue) == 0)
10240                geometry_info.xi=4.0;
10241              if ((flags & PsiValue) == 0)
10242                geometry_info.psi=4.0;
10243            }
10244          if (attribute_flag[1] != 0)
10245            geometry_info.rho=argument_list[1].real_reference;
10246          if (attribute_flag[2] != 0)
10247            geometry_info.sigma=argument_list[2].real_reference;
10248          if (attribute_flag[3] != 0)
10249            geometry_info.xi=argument_list[3].integer_reference;
10250          if (attribute_flag[4] != 0)
10251            geometry_info.psi=argument_list[4].integer_reference;
10252          image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10253            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10254            ceil(geometry_info.psi-0.5),exception);
10255          break;
10256        }
10257        case 90:  /* Identify */
10258        {
10259          if (attribute_flag[0] == 0)
10260            argument_list[0].file_reference=(FILE *) NULL;
10261          if (attribute_flag[1] != 0)
10262            (void) SetImageArtifact(image,"identify:features",
10263              argument_list[1].string_reference);
10264          if ((attribute_flag[2] != 0) &&
10265              (argument_list[2].integer_reference != 0))
10266            (void) SetImageArtifact(image,"identify:unique","true");
10267          (void) IdentifyImage(image,argument_list[0].file_reference,
10268            MagickTrue,exception);
10269          break;
10270        }
10271        case 91:  /* SepiaTone */
10272        {
10273          if (attribute_flag[0] == 0)
10274            argument_list[0].real_reference=80.0*QuantumRange/100.0;
10275          image=SepiaToneImage(image,argument_list[0].real_reference,exception);
10276          break;
10277        }
10278        case 92:  /* SigmoidalContrast */
10279        {
10280          MagickBooleanType
10281            sharpen;
10282
10283          if (attribute_flag[0] != 0)
10284            {
10285              flags=ParseGeometry(argument_list[0].string_reference,
10286                &geometry_info);
10287              if ((flags & SigmaValue) == 0)
10288                geometry_info.sigma=QuantumRange/2.0;
10289              if ((flags & PercentValue) != 0)
10290                geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10291            }
10292          if (attribute_flag[1] != 0)
10293            geometry_info.rho=argument_list[1].real_reference;
10294          if (attribute_flag[2] != 0)
10295            geometry_info.sigma=argument_list[2].real_reference;
10296          if (attribute_flag[3] != 0)
10297            channel=(ChannelType) argument_list[3].integer_reference;
10298          sharpen=MagickTrue;
10299          if (attribute_flag[4] != 0)
10300            sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10301              MagickFalse;
10302          channel_mask=SetImageChannelMask(image,channel);
10303          (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10304            geometry_info.sigma,exception);
10305          (void) SetImageChannelMask(image,channel_mask);
10306          break;
10307        }
10308        case 93:  /* Extent */
10309        {
10310          if (attribute_flag[7] != 0)
10311            image->gravity=(GravityType) argument_list[7].integer_reference;
10312          if (attribute_flag[0] != 0)
10313            {
10314              int
10315                flags;
10316
10317              flags=ParseGravityGeometry(image,
10318                argument_list[0].string_reference,&geometry,exception);
10319              (void) flags;
10320              if (geometry.width == 0)
10321                geometry.width=image->columns;
10322              if (geometry.height == 0)
10323                geometry.height=image->rows;
10324            }
10325          if (attribute_flag[1] != 0)
10326            geometry.width=argument_list[1].integer_reference;
10327          if (attribute_flag[2] != 0)
10328            geometry.height=argument_list[2].integer_reference;
10329          if (attribute_flag[3] != 0)
10330            geometry.x=argument_list[3].integer_reference;
10331          if (attribute_flag[4] != 0)
10332            geometry.y=argument_list[4].integer_reference;
10333          if (attribute_flag[5] != 0)
10334            image->fuzz=StringToDoubleInterval(
10335              argument_list[5].string_reference,(double) QuantumRange+1.0);
10336          if (attribute_flag[6] != 0)
10337            (void) QueryColorCompliance(argument_list[6].string_reference,
10338              AllCompliance,&image->background_color,exception);
10339          image=ExtentImage(image,&geometry,exception);
10340          break;
10341        }
10342        case 94:  /* Vignette */
10343        {
10344          if (attribute_flag[0] != 0)
10345            {
10346              flags=ParseGeometry(argument_list[0].string_reference,
10347                &geometry_info);
10348              if ((flags & SigmaValue) == 0)
10349                geometry_info.sigma=1.0;
10350              if ((flags & XiValue) == 0)
10351                geometry_info.xi=0.1*image->columns;
10352              if ((flags & PsiValue) == 0)
10353                geometry_info.psi=0.1*image->rows;
10354            }
10355          if (attribute_flag[1] != 0)
10356            geometry_info.rho=argument_list[1].real_reference;
10357          if (attribute_flag[2] != 0)
10358            geometry_info.sigma=argument_list[2].real_reference;
10359          if (attribute_flag[3] != 0)
10360            geometry_info.xi=argument_list[3].integer_reference;
10361          if (attribute_flag[4] != 0)
10362            geometry_info.psi=argument_list[4].integer_reference;
10363          if (attribute_flag[5] != 0)
10364            (void) QueryColorCompliance(argument_list[5].string_reference,
10365              AllCompliance,&image->background_color,exception);
10366          image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10367            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10368            ceil(geometry_info.psi-0.5),exception);
10369          break;
10370        }
10371        case 95:  /* ContrastStretch */
10372        {
10373          double
10374            black_point,
10375            white_point;
10376
10377          black_point=0.0;
10378          white_point=(double) image->columns*image->rows;
10379          if (attribute_flag[0] != 0)
10380            {
10381              flags=ParseGeometry(argument_list[0].string_reference,
10382                &geometry_info);
10383              black_point=geometry_info.rho;
10384              white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10385                black_point;
10386              if ((flags & PercentValue) != 0)
10387                {
10388                  black_point*=(double) image->columns*image->rows/100.0;
10389                  white_point*=(double) image->columns*image->rows/100.0;
10390                }
10391              white_point=(double) image->columns*image->rows-white_point;
10392            }
10393          if (attribute_flag[1] != 0)
10394            black_point=argument_list[1].real_reference;
10395          if (attribute_flag[2] != 0)
10396            white_point=argument_list[2].real_reference;
10397          if (attribute_flag[4] != 0)
10398            channel=(ChannelType) argument_list[4].integer_reference;
10399          channel_mask=SetImageChannelMask(image,channel);
10400          (void) ContrastStretchImage(image,black_point,white_point,exception);
10401          (void) SetImageChannelMask(image,channel_mask);
10402          break;
10403        }
10404        case 96:  /* Sans0 */
10405        {
10406          break;
10407        }
10408        case 97:  /* Sans1 */
10409        {
10410          break;
10411        }
10412        case 98:  /* AdaptiveSharpen */
10413        {
10414          if (attribute_flag[0] != 0)
10415            {
10416              flags=ParseGeometry(argument_list[0].string_reference,
10417                &geometry_info);
10418              if ((flags & SigmaValue) == 0)
10419                geometry_info.sigma=1.0;
10420              if ((flags & XiValue) == 0)
10421                geometry_info.xi=0.0;
10422            }
10423          if (attribute_flag[1] != 0)
10424            geometry_info.rho=argument_list[1].real_reference;
10425          if (attribute_flag[2] != 0)
10426            geometry_info.sigma=argument_list[2].real_reference;
10427          if (attribute_flag[3] != 0)
10428            geometry_info.xi=argument_list[3].real_reference;
10429          if (attribute_flag[4] != 0)
10430            channel=(ChannelType) argument_list[4].integer_reference;
10431          channel_mask=SetImageChannelMask(image,channel);
10432          image=AdaptiveSharpenImage(image,geometry_info.rho,
10433            geometry_info.sigma,exception);
10434          if (image != (Image *) NULL)
10435            (void) SetImageChannelMask(image,channel_mask);
10436          break;
10437        }
10438        case 99:  /* Transpose */
10439        {
10440          image=TransposeImage(image,exception);
10441          break;
10442        }
10443        case 100:  /* Tranverse */
10444        {
10445          image=TransverseImage(image,exception);
10446          break;
10447        }
10448        case 101:  /* AutoOrient */
10449        {
10450          image=AutoOrientImage(image,image->orientation,exception);
10451          break;
10452        }
10453        case 102:  /* AdaptiveBlur */
10454        {
10455          if (attribute_flag[0] != 0)
10456            {
10457              flags=ParseGeometry(argument_list[0].string_reference,
10458                &geometry_info);
10459              if ((flags & SigmaValue) == 0)
10460                geometry_info.sigma=1.0;
10461              if ((flags & XiValue) == 0)
10462                geometry_info.xi=0.0;
10463            }
10464          if (attribute_flag[1] != 0)
10465            geometry_info.rho=argument_list[1].real_reference;
10466          if (attribute_flag[2] != 0)
10467            geometry_info.sigma=argument_list[2].real_reference;
10468          if (attribute_flag[3] != 0)
10469            channel=(ChannelType) argument_list[3].integer_reference;
10470          channel_mask=SetImageChannelMask(image,channel);
10471          image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10472            exception);
10473          if (image != (Image *) NULL)
10474            (void) SetImageChannelMask(image,channel_mask);
10475          break;
10476        }
10477        case 103:  /* Sketch */
10478        {
10479          if (attribute_flag[0] != 0)
10480            {
10481              flags=ParseGeometry(argument_list[0].string_reference,
10482                &geometry_info);
10483              if ((flags & SigmaValue) == 0)
10484                geometry_info.sigma=1.0;
10485              if ((flags & XiValue) == 0)
10486                geometry_info.xi=1.0;
10487            }
10488          if (attribute_flag[1] != 0)
10489            geometry_info.rho=argument_list[1].real_reference;
10490          if (attribute_flag[2] != 0)
10491            geometry_info.sigma=argument_list[2].real_reference;
10492          if (attribute_flag[3] != 0)
10493            geometry_info.xi=argument_list[3].real_reference;
10494          image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10495            geometry_info.xi,exception);
10496          break;
10497        }
10498        case 104:  /* UniqueColors */
10499        {
10500          image=UniqueImageColors(image,exception);
10501          break;
10502        }
10503        case 105:  /* AdaptiveResize */
10504        {
10505          if (attribute_flag[0] != 0)
10506            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10507              &geometry,exception);
10508          if (attribute_flag[1] != 0)
10509            geometry.width=argument_list[1].integer_reference;
10510          if (attribute_flag[2] != 0)
10511            geometry.height=argument_list[2].integer_reference;
10512          if (attribute_flag[3] != 0)
10513            image->filter=(FilterType) argument_list[4].integer_reference;
10514          if (attribute_flag[4] != 0)
10515            SetImageArtifact(image,"filter:support",
10516              argument_list[4].string_reference);
10517          image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10518            exception);
10519          break;
10520        }
10521        case 106:  /* ClipMask */
10522        {
10523          Image
10524            *mask_image;
10525
10526          if (attribute_flag[0] == 0)
10527            {
10528              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10529                PackageName);
10530              goto PerlException;
10531            }
10532          mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10533            exception);
10534          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10535          mask_image=DestroyImage(mask_image);
10536          break;
10537        }
10538        case 107:  /* LinearStretch */
10539        {
10540           double
10541             black_point,
10542             white_point;
10543
10544           black_point=0.0;
10545           white_point=(double) image->columns*image->rows;
10546           if (attribute_flag[0] != 0)
10547             {
10548               flags=ParseGeometry(argument_list[0].string_reference,
10549                 &geometry_info);
10550               if ((flags & SigmaValue) != 0)
10551                  white_point=geometry_info.sigma;
10552               if ((flags & PercentValue) != 0)
10553                 {
10554                   black_point*=(double) image->columns*image->rows/100.0;
10555                   white_point*=(double) image->columns*image->rows/100.0;
10556                 }
10557               if ((flags & SigmaValue) == 0)
10558                 white_point=(double) image->columns*image->rows-black_point;
10559             }
10560          if (attribute_flag[1] != 0)
10561            black_point=argument_list[1].real_reference;
10562          if (attribute_flag[2] != 0)
10563            white_point=argument_list[2].real_reference;
10564          (void) LinearStretchImage(image,black_point,white_point,exception);
10565          break;
10566        }
10567        case 108:  /* ColorMatrix */
10568        {
10569          AV
10570            *av;
10571
10572          double
10573            *color_matrix;
10574
10575          KernelInfo
10576            *kernel_info;
10577
10578          size_t
10579            order;
10580
10581          if (attribute_flag[0] == 0)
10582            break;
10583          av=(AV *) argument_list[0].array_reference;
10584          order=(size_t) sqrt(av_len(av)+1);
10585          color_matrix=(double *) AcquireQuantumMemory(order,order*
10586            sizeof(*color_matrix));
10587          if (color_matrix == (double *) NULL)
10588            {
10589              ThrowPerlException(exception,ResourceLimitFatalError,
10590                "MemoryAllocationFailed",PackageName);
10591              goto PerlException;
10592           }
10593          for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10594            color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10595          for ( ; j < (ssize_t) (order*order); j++)
10596            color_matrix[j]=0.0;
10597          kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10598          if (kernel_info == (KernelInfo *) NULL)
10599            break;
10600          kernel_info->width=order;
10601          kernel_info->height=order;
10602          kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10603            order*sizeof(*kernel_info->values));
10604          if (kernel_info->values != (MagickRealType *) NULL)
10605            {
10606              for (i=0; i < (ssize_t) (order*order); i++)
10607                kernel_info->values[i]=(MagickRealType) color_matrix[i];
10608              image=ColorMatrixImage(image,kernel_info,exception);
10609            }
10610          kernel_info=DestroyKernelInfo(kernel_info);
10611          color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10612          break;
10613        }
10614        case 109:  /* Mask */
10615        {
10616          Image
10617            *mask_image;
10618
10619          if (attribute_flag[0] == 0)
10620            {
10621              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10622                PackageName);
10623              goto PerlException;
10624            }
10625          mask_image=CloneImage(argument_list[0].image_reference,0,0,
10626            MagickTrue,exception);
10627          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10628          mask_image=DestroyImage(mask_image);
10629          break;
10630        }
10631        case 110:  /* Polaroid */
10632        {
10633          char
10634            *caption;
10635
10636          double
10637            angle;
10638
10639          DrawInfo
10640            *draw_info;
10641
10642          PixelInterpolateMethod
10643            method;
10644
10645          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10646            (DrawInfo *) NULL);
10647          caption=(char *) NULL;
10648          if (attribute_flag[0] != 0)
10649            caption=InterpretImageProperties(info ? info->image_info :
10650              (ImageInfo *) NULL,image,argument_list[0].string_reference,
10651              exception);
10652          angle=0.0;
10653          if (attribute_flag[1] != 0)
10654            angle=argument_list[1].real_reference;
10655          if (attribute_flag[2] != 0)
10656            (void) CloneString(&draw_info->font,
10657              argument_list[2].string_reference);
10658          if (attribute_flag[3] != 0)
10659            (void) QueryColorCompliance(argument_list[3].string_reference,
10660              AllCompliance,&draw_info->stroke,exception);
10661          if (attribute_flag[4] != 0)
10662            (void) QueryColorCompliance(argument_list[4].string_reference,
10663              AllCompliance,&draw_info->fill,exception);
10664          if (attribute_flag[5] != 0)
10665            draw_info->stroke_width=argument_list[5].real_reference;
10666          if (attribute_flag[6] != 0)
10667            draw_info->pointsize=argument_list[6].real_reference;
10668          if (attribute_flag[7] != 0)
10669            draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10670          if (attribute_flag[8] != 0)
10671            (void) QueryColorCompliance(argument_list[8].string_reference,
10672              AllCompliance,&image->background_color,exception);
10673          method=UndefinedInterpolatePixel;
10674          if (attribute_flag[9] != 0)
10675            method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10676          image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10677          draw_info=DestroyDrawInfo(draw_info);
10678          if (caption != (char *) NULL)
10679            caption=DestroyString(caption);
10680          break;
10681        }
10682        case 111:  /* FloodfillPaint */
10683        {
10684          DrawInfo
10685            *draw_info;
10686
10687          MagickBooleanType
10688            invert;
10689
10690          PixelInfo
10691            target;
10692
10693          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10694            (DrawInfo *) NULL);
10695          if (attribute_flag[0] != 0)
10696            flags=ParsePageGeometry(image,argument_list[0].string_reference,
10697              &geometry,exception);
10698          if (attribute_flag[1] != 0)
10699            geometry.x=argument_list[1].integer_reference;
10700          if (attribute_flag[2] != 0)
10701            geometry.y=argument_list[2].integer_reference;
10702          if (attribute_flag[3] != 0)
10703            (void) QueryColorCompliance(argument_list[3].string_reference,
10704              AllCompliance,&draw_info->fill,exception);
10705          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10706            geometry.x,geometry.y,&target,exception);
10707          if (attribute_flag[4] != 0)
10708            QueryColorCompliance(argument_list[4].string_reference,
10709              AllCompliance,&target,exception);
10710          if (attribute_flag[5] != 0)
10711            image->fuzz=StringToDoubleInterval(
10712              argument_list[5].string_reference,(double) QuantumRange+1.0);
10713          if (attribute_flag[6] != 0)
10714            channel=(ChannelType) argument_list[6].integer_reference;
10715          invert=MagickFalse;
10716          if (attribute_flag[7] != 0)
10717            invert=(MagickBooleanType) argument_list[7].integer_reference;
10718          channel_mask=SetImageChannelMask(image,channel);
10719          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10720            geometry.y,invert,exception);
10721          (void) SetImageChannelMask(image,channel_mask);
10722          draw_info=DestroyDrawInfo(draw_info);
10723          break;
10724        }
10725        case 112:  /* Distort */
10726        {
10727          AV
10728            *av;
10729
10730          DistortMethod
10731            method;
10732
10733          double
10734            *coordinates;
10735
10736          size_t
10737            number_coordinates;
10738
10739          VirtualPixelMethod
10740            virtual_pixel;
10741
10742          if (attribute_flag[0] == 0)
10743            break;
10744          method=UndefinedDistortion;
10745          if (attribute_flag[1] != 0)
10746            method=(DistortMethod) argument_list[1].integer_reference;
10747          av=(AV *) argument_list[0].array_reference;
10748          number_coordinates=(size_t) av_len(av)+1;
10749          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10750            sizeof(*coordinates));
10751          if (coordinates == (double *) NULL)
10752            {
10753              ThrowPerlException(exception,ResourceLimitFatalError,
10754                "MemoryAllocationFailed",PackageName);
10755              goto PerlException;
10756            }
10757          for (j=0; j < (ssize_t) number_coordinates; j++)
10758            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10759          virtual_pixel=UndefinedVirtualPixelMethod;
10760          if (attribute_flag[2] != 0)
10761            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10762              argument_list[2].integer_reference,exception);
10763          image=DistortImage(image,method,number_coordinates,coordinates,
10764            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10765            exception);
10766          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10767            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10768              exception);
10769          coordinates=(double *) RelinquishMagickMemory(coordinates);
10770          break;
10771        }
10772        case 113:  /* Clut */
10773        {
10774          PixelInterpolateMethod
10775            method;
10776
10777          if (attribute_flag[0] == 0)
10778            {
10779              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10780                PackageName);
10781              goto PerlException;
10782            }
10783          method=UndefinedInterpolatePixel;
10784          if (attribute_flag[1] != 0)
10785            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10786          if (attribute_flag[2] != 0)
10787            channel=(ChannelType) argument_list[2].integer_reference;
10788          channel_mask=SetImageChannelMask(image,channel);
10789          (void) ClutImage(image,argument_list[0].image_reference,method,
10790            exception);
10791          (void) SetImageChannelMask(image,channel_mask);
10792          break;
10793        }
10794        case 114:  /* LiquidRescale */
10795        {
10796          if (attribute_flag[0] != 0)
10797            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10798              &geometry,exception);
10799          if (attribute_flag[1] != 0)
10800            geometry.width=argument_list[1].integer_reference;
10801          if (attribute_flag[2] != 0)
10802            geometry.height=argument_list[2].integer_reference;
10803          if (attribute_flag[3] == 0)
10804            argument_list[3].real_reference=1.0;
10805          if (attribute_flag[4] == 0)
10806            argument_list[4].real_reference=0.0;
10807          image=LiquidRescaleImage(image,geometry.width,geometry.height,
10808            argument_list[3].real_reference,argument_list[4].real_reference,
10809            exception);
10810          break;
10811        }
10812        case 115:  /* EncipherImage */
10813        {
10814          (void) EncipherImage(image,argument_list[0].string_reference,
10815            exception);
10816          break;
10817        }
10818        case 116:  /* DecipherImage */
10819        {
10820          (void) DecipherImage(image,argument_list[0].string_reference,
10821            exception);
10822          break;
10823        }
10824        case 117:  /* Deskew */
10825        {
10826          geometry_info.rho=QuantumRange/2.0;
10827          if (attribute_flag[0] != 0)
10828            flags=ParseGeometry(argument_list[0].string_reference,
10829              &geometry_info);
10830          if (attribute_flag[1] != 0)
10831            geometry_info.rho=StringToDoubleInterval(
10832              argument_list[1].string_reference,(double) QuantumRange+1.0);
10833          image=DeskewImage(image,geometry_info.rho,exception);
10834          break;
10835        }
10836        case 118:  /* Remap */
10837        {
10838          QuantizeInfo
10839            *quantize_info;
10840
10841          if (attribute_flag[0] == 0)
10842            {
10843              ThrowPerlException(exception,OptionError,"RemapImageRequired",
10844                PackageName);
10845              goto PerlException;
10846            }
10847          quantize_info=AcquireQuantizeInfo(info->image_info);
10848          if (attribute_flag[1] != 0)
10849            quantize_info->dither_method=(DitherMethod)
10850              argument_list[1].integer_reference;
10851          (void) RemapImages(quantize_info,image,
10852            argument_list[0].image_reference,exception);
10853          quantize_info=DestroyQuantizeInfo(quantize_info);
10854          break;
10855        }
10856        case 119:  /* SparseColor */
10857        {
10858          AV
10859            *av;
10860
10861          double
10862            *coordinates;
10863
10864          size_t
10865            number_coordinates;
10866
10867          SparseColorMethod
10868            method;
10869
10870          VirtualPixelMethod
10871            virtual_pixel;
10872
10873          if (attribute_flag[0] == 0)
10874            break;
10875          method=UndefinedColorInterpolate;
10876          if (attribute_flag[1] != 0)
10877            method=(SparseColorMethod) argument_list[1].integer_reference;
10878          av=(AV *) argument_list[0].array_reference;
10879          number_coordinates=(size_t) av_len(av)+1;
10880          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10881            sizeof(*coordinates));
10882          if (coordinates == (double *) NULL)
10883            {
10884              ThrowPerlException(exception,ResourceLimitFatalError,
10885                "MemoryAllocationFailed",PackageName);
10886              goto PerlException;
10887            }
10888          for (j=0; j < (ssize_t) number_coordinates; j++)
10889            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10890          virtual_pixel=UndefinedVirtualPixelMethod;
10891          if (attribute_flag[2] != 0)
10892            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10893              argument_list[2].integer_reference,exception);
10894          if (attribute_flag[3] != 0)
10895            channel=(ChannelType) argument_list[3].integer_reference;
10896          channel_mask=SetImageChannelMask(image,channel);
10897          image=SparseColorImage(image,method,number_coordinates,coordinates,
10898            exception);
10899          if (image != (Image *) NULL)
10900            (void) SetImageChannelMask(image,channel_mask);
10901          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10902            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10903              exception);
10904          coordinates=(double *) RelinquishMagickMemory(coordinates);
10905          break;
10906        }
10907        case 120:  /* Function */
10908        {
10909          AV
10910            *av;
10911
10912          double
10913            *parameters;
10914
10915          MagickFunction
10916            function;
10917
10918          size_t
10919            number_parameters;
10920
10921          VirtualPixelMethod
10922            virtual_pixel;
10923
10924          if (attribute_flag[0] == 0)
10925            break;
10926          function=UndefinedFunction;
10927          if (attribute_flag[1] != 0)
10928            function=(MagickFunction) argument_list[1].integer_reference;
10929          av=(AV *) argument_list[0].array_reference;
10930          number_parameters=(size_t) av_len(av)+1;
10931          parameters=(double *) AcquireQuantumMemory(number_parameters,
10932            sizeof(*parameters));
10933          if (parameters == (double *) NULL)
10934            {
10935              ThrowPerlException(exception,ResourceLimitFatalError,
10936                "MemoryAllocationFailed",PackageName);
10937              goto PerlException;
10938            }
10939          for (j=0; j < (ssize_t) number_parameters; j++)
10940            parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10941          virtual_pixel=UndefinedVirtualPixelMethod;
10942          if (attribute_flag[2] != 0)
10943            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10944              argument_list[2].integer_reference,exception);
10945          (void) FunctionImage(image,function,number_parameters,parameters,
10946            exception);
10947          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10948            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10949              exception);
10950          parameters=(double *) RelinquishMagickMemory(parameters);
10951          break;
10952        }
10953        case 121:  /* SelectiveBlur */
10954        {
10955          if (attribute_flag[0] != 0)
10956            {
10957              flags=ParseGeometry(argument_list[0].string_reference,
10958                &geometry_info);
10959              if ((flags & SigmaValue) == 0)
10960                geometry_info.sigma=1.0;
10961              if ((flags & PercentValue) != 0)
10962                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10963            }
10964          if (attribute_flag[1] != 0)
10965            geometry_info.rho=argument_list[1].real_reference;
10966          if (attribute_flag[2] != 0)
10967            geometry_info.sigma=argument_list[2].real_reference;
10968          if (attribute_flag[3] != 0)
10969            geometry_info.xi=argument_list[3].integer_reference;;
10970          if (attribute_flag[5] != 0)
10971            channel=(ChannelType) argument_list[5].integer_reference;
10972          channel_mask=SetImageChannelMask(image,channel);
10973          image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10974            geometry_info.xi,exception);
10975          if (image != (Image *) NULL)
10976            (void) SetImageChannelMask(image,channel_mask);
10977          break;
10978        }
10979        case 122:  /* HaldClut */
10980        {
10981          if (attribute_flag[0] == 0)
10982            {
10983              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10984                PackageName);
10985              goto PerlException;
10986            }
10987          if (attribute_flag[1] != 0)
10988            channel=(ChannelType) argument_list[1].integer_reference;
10989          channel_mask=SetImageChannelMask(image,channel);
10990          (void) HaldClutImage(image,argument_list[0].image_reference,
10991            exception);
10992          (void) SetImageChannelMask(image,channel_mask);
10993          break;
10994        }
10995        case 123:  /* BlueShift */
10996        {
10997          if (attribute_flag[0] != 0)
10998            (void) ParseGeometry(argument_list[0].string_reference,
10999              &geometry_info);
11000          image=BlueShiftImage(image,geometry_info.rho,exception);
11001          break;
11002        }
11003        case 124:  /* ForwardFourierTransformImage */
11004        {
11005          image=ForwardFourierTransformImage(image,
11006            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11007            exception);
11008          break;
11009        }
11010        case 125:  /* InverseFourierTransformImage */
11011        {
11012          image=InverseFourierTransformImage(image,image->next,
11013            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11014            exception);
11015          break;
11016        }
11017        case 126:  /* ColorDecisionList */
11018        {
11019          if (attribute_flag[0] == 0)
11020            argument_list[0].string_reference=(char *) NULL;
11021          (void) ColorDecisionListImage(image,
11022            argument_list[0].string_reference,exception);
11023          break;
11024        }
11025        case 127:  /* AutoGamma */
11026        {
11027          if (attribute_flag[0] != 0)
11028            channel=(ChannelType) argument_list[0].integer_reference;
11029          channel_mask=SetImageChannelMask(image,channel);
11030          (void) AutoGammaImage(image,exception);
11031          (void) SetImageChannelMask(image,channel_mask);
11032          break;
11033        }
11034        case 128:  /* AutoLevel */
11035        {
11036          if (attribute_flag[0] != 0)
11037            channel=(ChannelType) argument_list[0].integer_reference;
11038          channel_mask=SetImageChannelMask(image,channel);
11039          (void) AutoLevelImage(image,exception);
11040          (void) SetImageChannelMask(image,channel_mask);
11041          break;
11042        }
11043        case 129:  /* LevelColors */
11044        {
11045          PixelInfo
11046            black_point,
11047            white_point;
11048
11049          (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11050            exception);
11051          (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11052            exception);
11053          if (attribute_flag[1] != 0)
11054             (void) QueryColorCompliance(
11055               argument_list[1].string_reference,AllCompliance,&black_point,
11056               exception);
11057          if (attribute_flag[2] != 0)
11058             (void) QueryColorCompliance(
11059               argument_list[2].string_reference,AllCompliance,&white_point,
11060               exception);
11061          if (attribute_flag[3] != 0)
11062            channel=(ChannelType) argument_list[3].integer_reference;
11063          channel_mask=SetImageChannelMask(image,channel);
11064          (void) LevelImageColors(image,&black_point,&white_point,
11065            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11066            exception);
11067          (void) SetImageChannelMask(image,channel_mask);
11068          break;
11069        }
11070        case 130:  /* Clamp */
11071        {
11072          if (attribute_flag[0] != 0)
11073            channel=(ChannelType) argument_list[0].integer_reference;
11074          channel_mask=SetImageChannelMask(image,channel);
11075          (void) ClampImage(image,exception);
11076          (void) SetImageChannelMask(image,channel_mask);
11077          break;
11078        }
11079        case 131:  /* BrightnessContrast */
11080        {
11081          double
11082            brightness,
11083            contrast;
11084
11085          brightness=0.0;
11086          contrast=0.0;
11087          if (attribute_flag[0] != 0)
11088            {
11089              flags=ParseGeometry(argument_list[0].string_reference,
11090                &geometry_info);
11091              brightness=geometry_info.rho;
11092              if ((flags & SigmaValue) == 0)
11093                contrast=geometry_info.sigma;
11094            }
11095          if (attribute_flag[1] != 0)
11096            brightness=argument_list[1].real_reference;
11097          if (attribute_flag[2] != 0)
11098            contrast=argument_list[2].real_reference;
11099          if (attribute_flag[4] != 0)
11100            channel=(ChannelType) argument_list[4].integer_reference;
11101          channel_mask=SetImageChannelMask(image,channel);
11102          (void) BrightnessContrastImage(image,brightness,contrast,exception);
11103          (void) SetImageChannelMask(image,channel_mask);
11104          break;
11105        }
11106        case 132:  /* Morphology */
11107        {
11108          KernelInfo
11109            *kernel;
11110
11111          MorphologyMethod
11112            method;
11113
11114          ssize_t
11115            iterations;
11116
11117          if (attribute_flag[0] == 0)
11118            break;
11119          kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11120          if (kernel == (KernelInfo *) NULL)
11121            break;
11122          if (attribute_flag[1] != 0)
11123            channel=(ChannelType) argument_list[1].integer_reference;
11124          method=UndefinedMorphology;
11125          if (attribute_flag[2] != 0)
11126            method=argument_list[2].integer_reference;
11127          iterations=1;
11128          if (attribute_flag[3] != 0)
11129            iterations=argument_list[3].integer_reference;
11130          channel_mask=SetImageChannelMask(image,channel);
11131          image=MorphologyImage(image,method,iterations,kernel,exception);
11132          if (image != (Image *) NULL)
11133            (void) SetImageChannelMask(image,channel_mask);
11134          kernel=DestroyKernelInfo(kernel);
11135          break;
11136        }
11137        case 133:  /* Mode */
11138        {
11139          if (attribute_flag[0] != 0)
11140            {
11141              flags=ParseGeometry(argument_list[0].string_reference,
11142                &geometry_info);
11143              if ((flags & SigmaValue) == 0)
11144                geometry_info.sigma=1.0;
11145            }
11146          if (attribute_flag[1] != 0)
11147            geometry_info.rho=argument_list[1].real_reference;
11148          if (attribute_flag[2] != 0)
11149            geometry_info.sigma=argument_list[2].real_reference;
11150          if (attribute_flag[3] != 0)
11151            channel=(ChannelType) argument_list[3].integer_reference;
11152          channel_mask=SetImageChannelMask(image,channel);
11153          image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11154            (size_t) geometry_info.sigma,exception);
11155          if (image != (Image *) NULL)
11156            (void) SetImageChannelMask(image,channel_mask);
11157          break;
11158        }
11159        case 134:  /* Statistic */
11160        {
11161          StatisticType
11162            statistic;
11163
11164          statistic=UndefinedStatistic;
11165          if (attribute_flag[0] != 0)
11166            {
11167              flags=ParseGeometry(argument_list[0].string_reference,
11168                &geometry_info);
11169              if ((flags & SigmaValue) == 0)
11170                geometry_info.sigma=1.0;
11171            }
11172          if (attribute_flag[1] != 0)
11173            geometry_info.rho=argument_list[1].real_reference;
11174          if (attribute_flag[2] != 0)
11175            geometry_info.sigma=argument_list[2].real_reference;
11176          if (attribute_flag[3] != 0)
11177            channel=(ChannelType) argument_list[3].integer_reference;
11178          if (attribute_flag[4] != 0)
11179            statistic=(StatisticType) argument_list[4].integer_reference;
11180          channel_mask=SetImageChannelMask(image,channel);
11181          image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11182            (size_t) geometry_info.sigma,exception);
11183          if (image != (Image *) NULL)
11184            (void) SetImageChannelMask(image,channel_mask);
11185          break;
11186        }
11187        case 135:  /* Perceptible */
11188        {
11189          double
11190            epsilon;
11191
11192          epsilon=MagickEpsilon;
11193          if (attribute_flag[0] != 0)
11194            epsilon=argument_list[0].real_reference;
11195          if (attribute_flag[1] != 0)
11196            channel=(ChannelType) argument_list[1].integer_reference;
11197          channel_mask=SetImageChannelMask(image,channel);
11198          (void) PerceptibleImage(image,epsilon,exception);
11199          (void) SetImageChannelMask(image,channel_mask);
11200          break;
11201        }
11202        case 136:  /* Poly */
11203        {
11204          AV
11205            *av;
11206
11207          double
11208            *terms;
11209
11210          size_t
11211            number_terms;
11212
11213          if (attribute_flag[0] == 0)
11214            break;
11215          if (attribute_flag[1] != 0)
11216            channel=(ChannelType) argument_list[1].integer_reference;
11217          av=(AV *) argument_list[0].array_reference;
11218          number_terms=(size_t) av_len(av);
11219          terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11220          if (terms == (double *) NULL)
11221            {
11222              ThrowPerlException(exception,ResourceLimitFatalError,
11223                "MemoryAllocationFailed",PackageName);
11224              goto PerlException;
11225            }
11226          for (j=0; j < av_len(av); j++)
11227            terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11228          image=PolynomialImage(image,number_terms >> 1,terms,exception);
11229          terms=(double *) RelinquishMagickMemory(terms);
11230          break;
11231        }
11232        case 137:  /* Grayscale */
11233        {
11234          PixelIntensityMethod
11235            method;
11236
11237          method=UndefinedPixelIntensityMethod;
11238          if (attribute_flag[0] != 0)
11239            method=(PixelIntensityMethod) argument_list[0].integer_reference;
11240          (void) GrayscaleImage(image,method,exception);
11241          break;
11242        }
11243        case 138:  /* Canny */
11244        {
11245          if (attribute_flag[0] != 0)
11246            {
11247              flags=ParseGeometry(argument_list[0].string_reference,
11248                &geometry_info);
11249              if ((flags & SigmaValue) == 0)
11250                geometry_info.sigma=1.0;
11251              if ((flags & XiValue) == 0)
11252                geometry_info.xi=0.10;
11253              if ((flags & PsiValue) == 0)
11254                geometry_info.psi=0.30;
11255              if ((flags & PercentValue) != 0)
11256                {
11257                  geometry_info.xi/=100.0;
11258                  geometry_info.psi/=100.0;
11259                }
11260            }
11261          if (attribute_flag[1] != 0)
11262            geometry_info.rho=argument_list[1].real_reference;
11263          if (attribute_flag[2] != 0)
11264            geometry_info.sigma=argument_list[2].real_reference;
11265          if (attribute_flag[3] != 0)
11266            geometry_info.xi=argument_list[3].real_reference;
11267          if (attribute_flag[4] != 0)
11268            geometry_info.psi=argument_list[4].real_reference;
11269          if (attribute_flag[5] != 0)
11270            channel=(ChannelType) argument_list[5].integer_reference;
11271          channel_mask=SetImageChannelMask(image,channel);
11272          image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11273            geometry_info.xi,geometry_info.psi,exception);
11274          if (image != (Image *) NULL)
11275            (void) SetImageChannelMask(image,channel_mask);
11276          break;
11277        }
11278        case 139:  /* HoughLine */
11279        {
11280          if (attribute_flag[0] != 0)
11281            {
11282              flags=ParseGeometry(argument_list[0].string_reference,
11283                &geometry_info);
11284              if ((flags & SigmaValue) == 0)
11285                geometry_info.sigma=geometry_info.rho;
11286              if ((flags & XiValue) == 0)
11287                geometry_info.xi=40;
11288            }
11289          if (attribute_flag[1] != 0)
11290            geometry_info.rho=(double) argument_list[1].integer_reference;
11291          if (attribute_flag[2] != 0)
11292            geometry_info.sigma=(double) argument_list[2].integer_reference;
11293          if (attribute_flag[3] != 0)
11294            geometry_info.xi=(double) argument_list[3].integer_reference;
11295          image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11296            geometry_info.sigma,(size_t) geometry_info.xi,exception);
11297          break;
11298        }
11299        case 140:  /* MeanShift */
11300        {
11301          if (attribute_flag[0] != 0)
11302            {
11303              flags=ParseGeometry(argument_list[0].string_reference,
11304                &geometry_info);
11305              if ((flags & SigmaValue) == 0)
11306                geometry_info.sigma=geometry_info.rho;
11307              if ((flags & XiValue) == 0)
11308                geometry_info.xi=0.10*QuantumRange;
11309              if ((flags & PercentValue) != 0)
11310                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11311            }
11312          if (attribute_flag[1] != 0)
11313            geometry_info.rho=(double) argument_list[1].integer_reference;
11314          if (attribute_flag[2] != 0)
11315            geometry_info.sigma=(double) argument_list[2].integer_reference;
11316          if (attribute_flag[3] != 0)
11317            geometry_info.xi=(double) argument_list[3].integer_reference;
11318          image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11319            geometry_info.sigma,geometry_info.xi,exception);
11320          break;
11321        }
11322        case 141:  /* Kuwahara */
11323        {
11324          if (attribute_flag[0] != 0)
11325            {
11326              flags=ParseGeometry(argument_list[0].string_reference,
11327                &geometry_info);
11328              if ((flags & SigmaValue) == 0)
11329                geometry_info.sigma=geometry_info.rho-0.5;
11330            }
11331          if (attribute_flag[1] != 0)
11332            geometry_info.rho=argument_list[1].real_reference;
11333          if (attribute_flag[2] != 0)
11334            geometry_info.sigma=argument_list[2].real_reference;
11335          if (attribute_flag[3] != 0)
11336            channel=(ChannelType) argument_list[3].integer_reference;
11337          channel_mask=SetImageChannelMask(image,channel);
11338          image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11339            exception);
11340          if (image != (Image *) NULL)
11341            (void) SetImageChannelMask(image,channel_mask);
11342          break;
11343        }
11344        case 142:  /* ConnectedComponents */
11345        {
11346          size_t
11347            connectivity;
11348
11349          connectivity=4;
11350          if (attribute_flag[0] != 0)
11351            connectivity=argument_list[0].integer_reference;
11352          image=ConnectedComponentsImage(image,connectivity,
11353            (CCObjectInfo **) NULL,exception);
11354          break;
11355        }
11356        case 143:  /* Copy */
11357        {
11358          Image
11359            *source_image;
11360
11361          OffsetInfo
11362            offset;
11363
11364          RectangleInfo
11365            offset_geometry;
11366
11367          source_image=image;
11368          if (attribute_flag[0] != 0)
11369            source_image=argument_list[0].image_reference;
11370          SetGeometry(source_image,&geometry);
11371          if (attribute_flag[1] != 0)
11372            flags=ParseGravityGeometry(source_image,
11373              argument_list[1].string_reference,&geometry,exception);
11374          if (attribute_flag[2] != 0)
11375            geometry.width=argument_list[2].integer_reference;
11376          if (attribute_flag[3] != 0)
11377            geometry.height=argument_list[3].integer_reference;
11378          if (attribute_flag[4] != 0)
11379            geometry.x=argument_list[4].integer_reference;
11380          if (attribute_flag[5] != 0)
11381            geometry.y=argument_list[5].integer_reference;
11382          if (attribute_flag[6] != 0)
11383            image->gravity=(GravityType) argument_list[6].integer_reference;
11384          SetGeometry(image,&offset_geometry);
11385          if (attribute_flag[7] != 0)
11386            flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11387              &offset_geometry,exception);
11388          offset.x=offset_geometry.x;
11389          offset.y=offset_geometry.y;
11390          if (attribute_flag[8] != 0)
11391            offset.x=argument_list[8].integer_reference;
11392          if (attribute_flag[9] != 0)
11393            offset.y=argument_list[9].integer_reference;
11394          (void) CopyImagePixels(image,source_image,&geometry,&offset,
11395            exception);
11396          break;
11397        }
11398        case 144:  /* Color */
11399        {
11400          PixelInfo
11401            color;
11402
11403          (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11404          if (attribute_flag[0] != 0)
11405            (void) QueryColorCompliance(argument_list[0].string_reference,
11406              AllCompliance,&color,exception);
11407          (void) SetImageColor(image,&color,exception);
11408          break;
11409        }
11410        case 145:  /* WaveletDenoise */
11411        {
11412          if (attribute_flag[0] != 0)
11413            {
11414              flags=ParseGeometry(argument_list[0].string_reference,
11415                &geometry_info);
11416              if ((flags & PercentValue) != 0)
11417                {
11418                  geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11419                  geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11420                }
11421              if ((flags & SigmaValue) == 0)
11422                geometry_info.sigma=0.0;
11423            }
11424          if (attribute_flag[1] != 0)
11425            geometry_info.rho=argument_list[1].real_reference;
11426          if (attribute_flag[2] != 0)
11427            geometry_info.sigma=argument_list[2].real_reference;
11428          if (attribute_flag[3] != 0)
11429            channel=(ChannelType) argument_list[3].integer_reference;
11430          channel_mask=SetImageChannelMask(image,channel);
11431          image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11432            exception);
11433          if (image != (Image *) NULL)
11434            (void) SetImageChannelMask(image,channel_mask);
11435          break;
11436        }
11437        case 146:  /* Colorspace */
11438        {
11439          ColorspaceType
11440            colorspace;
11441
11442          colorspace=sRGBColorspace;
11443          if (attribute_flag[0] != 0)
11444            colorspace=(ColorspaceType) argument_list[0].integer_reference;
11445          (void) TransformImageColorspace(image,colorspace,exception);
11446          break;
11447        }
11448        case 147:  /* AutoThreshold */
11449        {
11450          AutoThresholdMethod
11451            method;
11452
11453          method=UndefinedThresholdMethod;
11454          if (attribute_flag[0] != 0)
11455            method=(AutoThresholdMethod) argument_list[0].integer_reference;
11456          (void) AutoThresholdImage(image,method,exception);
11457          break;
11458        }
11459        case 148:  /* RangeThreshold */
11460        {
11461          if (attribute_flag[0] != 0)
11462            {
11463              flags=ParseGeometry(argument_list[0].string_reference,
11464                &geometry_info);
11465              if ((flags & SigmaValue) == 0)
11466                geometry_info.sigma=geometry_info.rho;
11467              if ((flags & XiValue) == 0)
11468                geometry_info.xi=geometry_info.sigma;
11469              if ((flags & PsiValue) == 0)
11470                geometry_info.psi=geometry_info.xi;
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            geometry_info.xi=argument_list[3].real_reference;
11478          if (attribute_flag[4] != 0)
11479            geometry_info.psi=argument_list[4].real_reference;
11480          if (attribute_flag[5] != 0)
11481            channel=(ChannelType) argument_list[5].integer_reference;
11482          channel_mask=SetImageChannelMask(image,channel);
11483          (void) RangeThresholdImage(image,geometry_info.rho,
11484            geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
11485          if (image != (Image *) NULL)
11486            (void) SetImageChannelMask(image,channel_mask);
11487          break;
11488        }
11489        case 149:  /* CLAHE */
11490        {
11491          if (attribute_flag[0] != 0)
11492            {
11493              flags=ParseGeometry(argument_list[0].string_reference,
11494                &geometry_info);
11495              flags=ParseRegionGeometry(image,argument_list[0].string_reference,
11496                &geometry,exception);
11497            }
11498          if (attribute_flag[1] != 0)
11499            geometry.width=argument_list[1].integer_reference;
11500          if (attribute_flag[2] != 0)
11501            geometry.height=argument_list[2].integer_reference;
11502          if (attribute_flag[3] != 0)
11503            geometry.x=argument_list[3].integer_reference;
11504          if (attribute_flag[4] != 0)
11505            geometry_info.psi=argument_list[4].real_reference;
11506          (void) CLAHEImage(image,geometry.width,geometry.height,geometry.x,
11507            geometry_info.psi,exception);
11508          break;
11509        }
11510      }
11511      if (next != (Image *) NULL)
11512        (void) CatchImageException(next);
11513      if ((region_info.width*region_info.height) != 0)
11514        (void) SetImageRegionMask(image,WritePixelMask,(const RectangleInfo *)
11515          NULL,exception);
11516      if (image != (Image *) NULL)
11517        {
11518          number_images++;
11519          if (next && (next != image))
11520            {
11521              image->next=next->next;
11522              if (image->next != (Image *) NULL)
11523                image->next->previous=image;
11524              DeleteImageFromRegistry(*pv,next);
11525            }
11526          sv_setiv(*pv,PTR2IV(image));
11527          next=image;
11528        }
11529      if (*pv)
11530        pv++;
11531    }
11532
11533  PerlException:
11534    if (reference_vector)
11535      reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11536    InheritPerlException(exception,perl_exception);
11537    exception=DestroyExceptionInfo(exception);
11538    sv_setiv(perl_exception,(IV) number_images);
11539    SvPOK_on(perl_exception);
11540    ST(0)=sv_2mortal(perl_exception);
11541    XSRETURN(1);
11542  }
11543
11544#
11545###############################################################################
11546#                                                                             #
11547#                                                                             #
11548#                                                                             #
11549#   M o n t a g e                                                             #
11550#                                                                             #
11551#                                                                             #
11552#                                                                             #
11553###############################################################################
11554#
11555#
11556void
11557Montage(ref,...)
11558  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11559  ALIAS:
11560    MontageImage  = 1
11561    montage       = 2
11562    montageimage  = 3
11563  PPCODE:
11564  {
11565    AV
11566      *av;
11567
11568    char
11569      *attribute;
11570
11571    ExceptionInfo
11572      *exception;
11573
11574    HV
11575      *hv;
11576
11577    Image
11578      *image,
11579      *next;
11580
11581    MontageInfo
11582      *montage_info;
11583
11584    PixelInfo
11585      transparent_color;
11586
11587    register ssize_t
11588      i;
11589
11590    ssize_t
11591      sp;
11592
11593    struct PackageInfo
11594      *info;
11595
11596    SV
11597      *av_reference,
11598      *perl_exception,
11599      *reference,
11600      *rv,
11601      *sv;
11602
11603    PERL_UNUSED_VAR(ref);
11604    PERL_UNUSED_VAR(ix);
11605    exception=AcquireExceptionInfo();
11606    perl_exception=newSVpv("",0);
11607    sv=NULL;
11608    attribute=NULL;
11609    if (sv_isobject(ST(0)) == 0)
11610      {
11611        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11612          PackageName);
11613        goto PerlException;
11614      }
11615    reference=SvRV(ST(0));
11616    hv=SvSTASH(reference);
11617    av=newAV();
11618    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11619    SvREFCNT_dec(av);
11620    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11621    if (image == (Image *) NULL)
11622      {
11623        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11624          PackageName);
11625        goto PerlException;
11626      }
11627    /*
11628      Get options.
11629    */
11630    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11631    montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11632    (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11633      exception);
11634    for (i=2; i < items; i+=2)
11635    {
11636      attribute=(char *) SvPV(ST(i-1),na);
11637      switch (*attribute)
11638      {
11639        case 'B':
11640        case 'b':
11641        {
11642          if (LocaleCompare(attribute,"background") == 0)
11643            {
11644              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11645                &montage_info->background_color,exception);
11646              for (next=image; next; next=next->next)
11647                next->background_color=montage_info->background_color;
11648              break;
11649            }
11650          if (LocaleCompare(attribute,"border") == 0)
11651            {
11652              montage_info->border_width=SvIV(ST(i));
11653              break;
11654            }
11655          if (LocaleCompare(attribute,"bordercolor") == 0)
11656            {
11657              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11658                &montage_info->border_color,exception);
11659              for (next=image; next; next=next->next)
11660                next->border_color=montage_info->border_color;
11661              break;
11662            }
11663          if (LocaleCompare(attribute,"borderwidth") == 0)
11664            {
11665              montage_info->border_width=SvIV(ST(i));
11666              break;
11667            }
11668          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11669            attribute);
11670          break;
11671        }
11672        case 'C':
11673        case 'c':
11674        {
11675          if (LocaleCompare(attribute,"compose") == 0)
11676            {
11677              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11678                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11679              if (sp < 0)
11680                {
11681                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11682                    SvPV(ST(i),na));
11683                  break;
11684                }
11685              for (next=image; next; next=next->next)
11686                next->compose=(CompositeOperator) sp;
11687              break;
11688            }
11689          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11690            attribute);
11691          break;
11692        }
11693        case 'F':
11694        case 'f':
11695        {
11696          if (LocaleCompare(attribute,"fill") == 0)
11697            {
11698              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11699                &montage_info->fill,exception);
11700              break;
11701            }
11702          if (LocaleCompare(attribute,"font") == 0)
11703            {
11704              (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11705              break;
11706            }
11707          if (LocaleCompare(attribute,"frame") == 0)
11708            {
11709              char
11710                *p;
11711
11712              p=SvPV(ST(i),na);
11713              if (IsGeometry(p) == MagickFalse)
11714                {
11715                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11716                    p);
11717                  break;
11718                }
11719              (void) CloneString(&montage_info->frame,p);
11720              if (*p == '\0')
11721                montage_info->frame=(char *) NULL;
11722              break;
11723            }
11724          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11725            attribute);
11726          break;
11727        }
11728        case 'G':
11729        case 'g':
11730        {
11731          if (LocaleCompare(attribute,"geometry") == 0)
11732            {
11733              char
11734                *p;
11735
11736              p=SvPV(ST(i),na);
11737              if (IsGeometry(p) == MagickFalse)
11738                {
11739                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11740                    p);
11741                  break;
11742                }
11743             (void) CloneString(&montage_info->geometry,p);
11744             if (*p == '\0')
11745               montage_info->geometry=(char *) NULL;
11746             break;
11747           }
11748         if (LocaleCompare(attribute,"gravity") == 0)
11749           {
11750             ssize_t
11751               in;
11752
11753             in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11754               MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11755             if (in < 0)
11756               {
11757                 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11758                   SvPV(ST(i),na));
11759                 return;
11760               }
11761             montage_info->gravity=(GravityType) in;
11762             for (next=image; next; next=next->next)
11763               next->gravity=(GravityType) in;
11764             break;
11765           }
11766          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11767            attribute);
11768          break;
11769        }
11770        case 'L':
11771        case 'l':
11772        {
11773          if (LocaleCompare(attribute,"label") == 0)
11774            {
11775              for (next=image; next; next=next->next)
11776                (void) SetImageProperty(next,"label",InterpretImageProperties(
11777                  info ? info->image_info : (ImageInfo *) NULL,next,
11778                  SvPV(ST(i),na),exception),exception);
11779              break;
11780            }
11781          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11782            attribute);
11783          break;
11784        }
11785        case 'M':
11786        case 'm':
11787        {
11788          if (LocaleCompare(attribute,"mattecolor") == 0)
11789            {
11790              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11791                &montage_info->alpha_color,exception);
11792              for (next=image; next; next=next->next)
11793                next->alpha_color=montage_info->alpha_color;
11794              break;
11795            }
11796          if (LocaleCompare(attribute,"mode") == 0)
11797            {
11798              ssize_t
11799                in;
11800
11801              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11802                MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11803              switch (in)
11804              {
11805                default:
11806                {
11807                  ThrowPerlException(exception,OptionError,
11808                    "UnrecognizedModeType",SvPV(ST(i),na));
11809                  break;
11810                }
11811                case FrameMode:
11812                {
11813                  (void) CloneString(&montage_info->frame,"15x15+3+3");
11814                  montage_info->shadow=MagickTrue;
11815                  break;
11816                }
11817                case UnframeMode:
11818                {
11819                  montage_info->frame=(char *) NULL;
11820                  montage_info->shadow=MagickFalse;
11821                  montage_info->border_width=0;
11822                  break;
11823                }
11824                case ConcatenateMode:
11825                {
11826                  montage_info->frame=(char *) NULL;
11827                  montage_info->shadow=MagickFalse;
11828                  (void) CloneString(&montage_info->geometry,"+0+0");
11829                  montage_info->border_width=0;
11830                }
11831              }
11832              break;
11833            }
11834          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11835            attribute);
11836          break;
11837        }
11838        case 'P':
11839        case 'p':
11840        {
11841          if (LocaleCompare(attribute,"pointsize") == 0)
11842            {
11843              montage_info->pointsize=SvIV(ST(i));
11844              break;
11845            }
11846          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11847            attribute);
11848          break;
11849        }
11850        case 'S':
11851        case 's':
11852        {
11853          if (LocaleCompare(attribute,"shadow") == 0)
11854            {
11855              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11856                MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11857              if (sp < 0)
11858                {
11859                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11860                    SvPV(ST(i),na));
11861                  break;
11862                }
11863             montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11864             break;
11865            }
11866          if (LocaleCompare(attribute,"stroke") == 0)
11867            {
11868              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11869                &montage_info->stroke,exception);
11870              break;
11871            }
11872          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11873            attribute);
11874          break;
11875        }
11876        case 'T':
11877        case 't':
11878        {
11879          if (LocaleCompare(attribute,"texture") == 0)
11880            {
11881              (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11882              break;
11883            }
11884          if (LocaleCompare(attribute,"tile") == 0)
11885            {
11886              char *p=SvPV(ST(i),na);
11887              if (IsGeometry(p) == MagickFalse)
11888                {
11889                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11890                    p);
11891                  break;
11892                }
11893              (void) CloneString(&montage_info->tile,p);
11894              if (*p == '\0')
11895                montage_info->tile=(char *) NULL;
11896              break;
11897            }
11898          if (LocaleCompare(attribute,"title") == 0)
11899            {
11900              (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11901              break;
11902            }
11903          if (LocaleCompare(attribute,"transparent") == 0)
11904            {
11905              PixelInfo
11906                transparent_color;
11907
11908              QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11909                &transparent_color,exception);
11910              for (next=image; next; next=next->next)
11911                (void) TransparentPaintImage(next,&transparent_color,
11912                  TransparentAlpha,MagickFalse,exception);
11913              break;
11914            }
11915          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11916            attribute);
11917          break;
11918        }
11919        default:
11920        {
11921          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11922            attribute);
11923          break;
11924        }
11925      }
11926    }
11927    image=MontageImageList(info->image_info,montage_info,image,exception);
11928    montage_info=DestroyMontageInfo(montage_info);
11929    if (image == (Image *) NULL)
11930      goto PerlException;
11931    if (transparent_color.alpha != TransparentAlpha)
11932      for (next=image; next; next=next->next)
11933        (void) TransparentPaintImage(next,&transparent_color,
11934          TransparentAlpha,MagickFalse,exception);
11935    for (  ; image; image=image->next)
11936    {
11937      AddImageToRegistry(sv,image);
11938      rv=newRV(sv);
11939      av_push(av,sv_bless(rv,hv));
11940      SvREFCNT_dec(sv);
11941    }
11942    exception=DestroyExceptionInfo(exception);
11943    ST(0)=av_reference;
11944    SvREFCNT_dec(perl_exception);
11945    XSRETURN(1);
11946
11947  PerlException:
11948    InheritPerlException(exception,perl_exception);
11949    exception=DestroyExceptionInfo(exception);
11950    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11951    SvPOK_on(perl_exception);
11952    ST(0)=sv_2mortal(perl_exception);
11953    XSRETURN(1);
11954  }
11955
11956#
11957###############################################################################
11958#                                                                             #
11959#                                                                             #
11960#                                                                             #
11961#   M o r p h                                                                 #
11962#                                                                             #
11963#                                                                             #
11964#                                                                             #
11965###############################################################################
11966#
11967#
11968void
11969Morph(ref,...)
11970  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11971  ALIAS:
11972    MorphImage  = 1
11973    morph       = 2
11974    morphimage  = 3
11975  PPCODE:
11976  {
11977    AV
11978      *av;
11979
11980    char
11981      *attribute;
11982
11983    ExceptionInfo
11984      *exception;
11985
11986    HV
11987      *hv;
11988
11989    Image
11990      *image;
11991
11992    register ssize_t
11993      i;
11994
11995    ssize_t
11996      number_frames;
11997
11998    struct PackageInfo
11999      *info;
12000
12001    SV
12002      *av_reference,
12003      *perl_exception,
12004      *reference,
12005      *rv,
12006      *sv;
12007
12008    PERL_UNUSED_VAR(ref);
12009    PERL_UNUSED_VAR(ix);
12010    exception=AcquireExceptionInfo();
12011    perl_exception=newSVpv("",0);
12012    sv=NULL;
12013    av=NULL;
12014    attribute=NULL;
12015    if (sv_isobject(ST(0)) == 0)
12016      {
12017        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12018          PackageName);
12019        goto PerlException;
12020      }
12021    reference=SvRV(ST(0));
12022    hv=SvSTASH(reference);
12023    av=newAV();
12024    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12025    SvREFCNT_dec(av);
12026    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12027    if (image == (Image *) NULL)
12028      {
12029        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12030          PackageName);
12031        goto PerlException;
12032      }
12033    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12034    /*
12035      Get attribute.
12036    */
12037    number_frames=30;
12038    for (i=2; i < items; i+=2)
12039    {
12040      attribute=(char *) SvPV(ST(i-1),na);
12041      switch (*attribute)
12042      {
12043        case 'F':
12044        case 'f':
12045        {
12046          if (LocaleCompare(attribute,"frames") == 0)
12047            {
12048              number_frames=SvIV(ST(i));
12049              break;
12050            }
12051          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12052            attribute);
12053          break;
12054        }
12055        default:
12056        {
12057          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12058            attribute);
12059          break;
12060        }
12061      }
12062    }
12063    image=MorphImages(image,number_frames,exception);
12064    if (image == (Image *) NULL)
12065      goto PerlException;
12066    for ( ; image; image=image->next)
12067    {
12068      AddImageToRegistry(sv,image);
12069      rv=newRV(sv);
12070      av_push(av,sv_bless(rv,hv));
12071      SvREFCNT_dec(sv);
12072    }
12073    exception=DestroyExceptionInfo(exception);
12074    ST(0)=av_reference;
12075    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12076    XSRETURN(1);
12077
12078  PerlException:
12079    InheritPerlException(exception,perl_exception);
12080    exception=DestroyExceptionInfo(exception);
12081    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12082    SvPOK_on(perl_exception);
12083    ST(0)=sv_2mortal(perl_exception);
12084    XSRETURN(1);
12085  }
12086
12087#
12088###############################################################################
12089#                                                                             #
12090#                                                                             #
12091#                                                                             #
12092#   M o s a i c                                                               #
12093#                                                                             #
12094#                                                                             #
12095#                                                                             #
12096###############################################################################
12097#
12098#
12099void
12100Mosaic(ref)
12101  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12102  ALIAS:
12103    MosaicImage   = 1
12104    mosaic        = 2
12105    mosaicimage   = 3
12106  PPCODE:
12107  {
12108    AV
12109      *av;
12110
12111    ExceptionInfo
12112      *exception;
12113
12114    HV
12115      *hv;
12116
12117    Image
12118      *image;
12119
12120    struct PackageInfo
12121      *info;
12122
12123    SV
12124      *perl_exception,
12125      *reference,
12126      *rv,
12127      *sv;
12128
12129    PERL_UNUSED_VAR(ref);
12130    PERL_UNUSED_VAR(ix);
12131    exception=AcquireExceptionInfo();
12132    perl_exception=newSVpv("",0);
12133    sv=NULL;
12134    if (sv_isobject(ST(0)) == 0)
12135      {
12136        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12137          PackageName);
12138        goto PerlException;
12139      }
12140    reference=SvRV(ST(0));
12141    hv=SvSTASH(reference);
12142    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12143    if (image == (Image *) NULL)
12144      {
12145        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12146          PackageName);
12147        goto PerlException;
12148      }
12149    image=MergeImageLayers(image,MosaicLayer,exception);
12150    /*
12151      Create blessed Perl array for the returned image.
12152    */
12153    av=newAV();
12154    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12155    SvREFCNT_dec(av);
12156    AddImageToRegistry(sv,image);
12157    rv=newRV(sv);
12158    av_push(av,sv_bless(rv,hv));
12159    SvREFCNT_dec(sv);
12160    (void) CopyMagickString(info->image_info->filename,image->filename,
12161      MagickPathExtent);
12162    SetImageInfo(info->image_info,0,exception);
12163    exception=DestroyExceptionInfo(exception);
12164    SvREFCNT_dec(perl_exception);
12165    XSRETURN(1);
12166
12167  PerlException:
12168    InheritPerlException(exception,perl_exception);
12169    exception=DestroyExceptionInfo(exception);
12170    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12171    SvPOK_on(perl_exception);  /* return messages in string context */
12172    ST(0)=sv_2mortal(perl_exception);
12173    XSRETURN(1);
12174  }
12175
12176#
12177###############################################################################
12178#                                                                             #
12179#                                                                             #
12180#                                                                             #
12181#   P e r c e p t u a l H a s h                                               #
12182#                                                                             #
12183#                                                                             #
12184#                                                                             #
12185###############################################################################
12186#
12187#
12188void
12189PerceptualHash(ref)
12190  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12191  ALIAS:
12192    PerceptualHashImage = 1
12193    perceptualhash      = 2
12194    perceptualhashimage = 3
12195  PPCODE:
12196  {
12197    AV
12198      *av;
12199
12200    ChannelPerceptualHash
12201      *channel_phash;
12202
12203    char
12204      message[MagickPathExtent];
12205
12206    ExceptionInfo
12207      *exception;
12208
12209    Image
12210      *image;
12211
12212    ssize_t
12213      count;
12214
12215    struct PackageInfo
12216      *info;
12217
12218    SV
12219      *perl_exception,
12220      *reference;
12221
12222    PERL_UNUSED_VAR(ref);
12223    PERL_UNUSED_VAR(ix);
12224    exception=AcquireExceptionInfo();
12225    perl_exception=newSVpv("",0);
12226    av=NULL;
12227    if (sv_isobject(ST(0)) == 0)
12228      {
12229        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12230          PackageName);
12231        goto PerlException;
12232      }
12233    reference=SvRV(ST(0));
12234    av=newAV();
12235    SvREFCNT_dec(av);
12236    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12237    if (image == (Image *) NULL)
12238      {
12239        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12240          PackageName);
12241        goto PerlException;
12242      }
12243    count=0;
12244    for ( ; image; image=image->next)
12245    {
12246      register size_t
12247        i;
12248
12249      channel_phash=GetImagePerceptualHash(image,exception);
12250      if (channel_phash == (ChannelPerceptualHash *) NULL)
12251        continue;
12252      count++;
12253      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
12254      {
12255        ssize_t
12256          j;
12257
12258        PixelChannel channel=GetPixelChannelChannel(image,i);
12259        PixelTrait traits=GetPixelChannelTraits(image,channel);
12260        if (traits == UndefinedPixelTrait)
12261          continue;
12262        EXTEND(sp,GetPixelChannels(image)*MaximumNumberOfPerceptualHashes*
12263          channel_phash[0].number_colorspaces*(i+1)*count);
12264        for (j=0; j < MaximumNumberOfPerceptualHashes; j++)
12265        {
12266          register ssize_t
12267            k;
12268
12269          for (k=0; k < (ssize_t) channel_phash[0].number_colorspaces; k++)
12270          {
12271            (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
12272              channel_phash[channel].phash[k][j]);
12273            PUSHs(sv_2mortal(newSVpv(message,0)));
12274          }
12275        }
12276      }
12277      channel_phash=(ChannelPerceptualHash *)
12278        RelinquishMagickMemory(channel_phash);
12279    }
12280
12281  PerlException:
12282    InheritPerlException(exception,perl_exception);
12283    exception=DestroyExceptionInfo(exception);
12284    SvREFCNT_dec(perl_exception);
12285  }
12286
12287#
12288###############################################################################
12289#                                                                             #
12290#                                                                             #
12291#                                                                             #
12292#   P i n g                                                                   #
12293#                                                                             #
12294#                                                                             #
12295#                                                                             #
12296###############################################################################
12297#
12298#
12299void
12300Ping(ref,...)
12301  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12302  ALIAS:
12303    PingImage  = 1
12304    ping       = 2
12305    pingimage  = 3
12306  PPCODE:
12307  {
12308    AV
12309      *av;
12310
12311    char
12312      **keep,
12313      **list;
12314
12315    ExceptionInfo
12316      *exception;
12317
12318    Image
12319      *image,
12320      *next;
12321
12322    int
12323      n;
12324
12325    MagickBooleanType
12326      status;
12327
12328    register char
12329      **p;
12330
12331    register ssize_t
12332      i;
12333
12334    ssize_t
12335      ac;
12336
12337    STRLEN
12338      *length;
12339
12340    struct PackageInfo
12341      *info,
12342      *package_info;
12343
12344    SV
12345      *perl_exception,
12346      *reference;
12347
12348    size_t
12349      count;
12350
12351    PERL_UNUSED_VAR(ref);
12352    PERL_UNUSED_VAR(ix);
12353    exception=AcquireExceptionInfo();
12354    perl_exception=newSVpv("",0);
12355    package_info=(struct PackageInfo *) NULL;
12356    ac=(items < 2) ? 1 : items-1;
12357    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12358    keep=list;
12359    length=(STRLEN *) NULL;
12360    if (list == (char **) NULL)
12361      {
12362        ThrowPerlException(exception,ResourceLimitError,
12363          "MemoryAllocationFailed",PackageName);
12364        goto PerlException;
12365      }
12366    keep=list;
12367    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12368    if (length == (STRLEN *) NULL)
12369      {
12370        ThrowPerlException(exception,ResourceLimitError,
12371          "MemoryAllocationFailed",PackageName);
12372        goto PerlException;
12373      }
12374    if (sv_isobject(ST(0)) == 0)
12375      {
12376        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12377          PackageName);
12378        goto PerlException;
12379      }
12380    reference=SvRV(ST(0));
12381    if (SvTYPE(reference) != SVt_PVAV)
12382      {
12383        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12384          PackageName);
12385        goto PerlException;
12386      }
12387    av=(AV *) reference;
12388    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12389      exception);
12390    package_info=ClonePackageInfo(info,exception);
12391    n=1;
12392    if (items <= 1)
12393      *list=(char *) (*package_info->image_info->filename ?
12394        package_info->image_info->filename : "XC:black");
12395    else
12396      for (n=0, i=0; i < ac; i++)
12397      {
12398        list[n]=(char *) SvPV(ST(i+1),length[n]);
12399        if ((items >= 3) && strEQcase(list[n],"blob"))
12400          {
12401            void
12402              *blob;
12403
12404            i++;
12405            blob=(void *) (SvPV(ST(i+1),length[n]));
12406            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12407          }
12408        if ((items >= 3) && strEQcase(list[n],"filename"))
12409          continue;
12410        if ((items >= 3) && strEQcase(list[n],"file"))
12411          {
12412            FILE
12413              *file;
12414
12415            PerlIO
12416              *io_info;
12417
12418            i++;
12419            io_info=IoIFP(sv_2io(ST(i+1)));
12420            if (io_info == (PerlIO *) NULL)
12421              {
12422                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12423                  PackageName);
12424                continue;
12425              }
12426            file=PerlIO_findFILE(io_info);
12427            if (file == (FILE *) NULL)
12428              {
12429                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12430                  PackageName);
12431                continue;
12432              }
12433            SetImageInfoFile(package_info->image_info,file);
12434          }
12435        if ((items >= 3) && strEQcase(list[n],"magick"))
12436          continue;
12437        n++;
12438      }
12439    list[n]=(char *) NULL;
12440    keep=list;
12441    status=ExpandFilenames(&n,&list);
12442    if (status == MagickFalse)
12443      {
12444        ThrowPerlException(exception,ResourceLimitError,
12445          "MemoryAllocationFailed",PackageName);
12446        goto PerlException;
12447      }
12448    count=0;
12449    for (i=0; i < n; i++)
12450    {
12451      (void) CopyMagickString(package_info->image_info->filename,list[i],
12452        MagickPathExtent);
12453      image=PingImage(package_info->image_info,exception);
12454      if (image == (Image *) NULL)
12455        break;
12456      if ((package_info->image_info->file != (FILE *) NULL) ||
12457          (package_info->image_info->blob != (void *) NULL))
12458        DisassociateImageStream(image);
12459      count+=GetImageListLength(image);
12460      EXTEND(sp,4*count);
12461      for (next=image; next; next=next->next)
12462      {
12463        PUSHs(sv_2mortal(newSViv(next->columns)));
12464        PUSHs(sv_2mortal(newSViv(next->rows)));
12465        PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12466        PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12467      }
12468      image=DestroyImageList(image);
12469    }
12470    /*
12471      Free resources.
12472    */
12473    for (i=0; i < n; i++)
12474      if (list[i] != (char *) NULL)
12475        for (p=keep; list[i] != *p++; )
12476          if (*p == NULL)
12477            {
12478              list[i]=(char *) RelinquishMagickMemory(list[i]);
12479              break;
12480            }
12481
12482  PerlException:
12483    if (package_info != (struct PackageInfo *) NULL)
12484      DestroyPackageInfo(package_info);
12485    if (list && (list != keep))
12486      list=(char **) RelinquishMagickMemory(list);
12487    if (keep)
12488      keep=(char **) RelinquishMagickMemory(keep);
12489    if (length)
12490      length=(STRLEN *) RelinquishMagickMemory(length);
12491    InheritPerlException(exception,perl_exception);
12492    exception=DestroyExceptionInfo(exception);
12493    SvREFCNT_dec(perl_exception);  /* throw away all errors */
12494  }
12495
12496#
12497###############################################################################
12498#                                                                             #
12499#                                                                             #
12500#                                                                             #
12501#   P r e v i e w                                                             #
12502#                                                                             #
12503#                                                                             #
12504#                                                                             #
12505###############################################################################
12506#
12507#
12508void
12509Preview(ref,...)
12510  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12511  ALIAS:
12512    PreviewImage = 1
12513    preview      = 2
12514    previewimage = 3
12515  PPCODE:
12516  {
12517    AV
12518      *av;
12519
12520    ExceptionInfo
12521      *exception;
12522
12523    HV
12524      *hv;
12525
12526    Image
12527      *image,
12528      *preview_image;
12529
12530    PreviewType
12531      preview_type;
12532
12533    struct PackageInfo
12534      *info;
12535
12536    SV
12537      *av_reference,
12538      *perl_exception,
12539      *reference,
12540      *rv,
12541      *sv;
12542
12543    PERL_UNUSED_VAR(ref);
12544    PERL_UNUSED_VAR(ix);
12545    exception=AcquireExceptionInfo();
12546    perl_exception=newSVpv("",0);
12547    sv=NULL;
12548    av=NULL;
12549    if (sv_isobject(ST(0)) == 0)
12550      {
12551        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12552          PackageName);
12553        goto PerlException;
12554      }
12555    reference=SvRV(ST(0));
12556    hv=SvSTASH(reference);
12557    av=newAV();
12558    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12559    SvREFCNT_dec(av);
12560    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12561    if (image == (Image *) NULL)
12562      {
12563        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12564          PackageName);
12565        goto PerlException;
12566      }
12567    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12568    preview_type=GammaPreview;
12569    if (items > 1)
12570      preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
12571        MagickFalse,SvPV(ST(1),na));
12572    for ( ; image; image=image->next)
12573    {
12574      preview_image=PreviewImage(image,preview_type,exception);
12575      if (preview_image == (Image *) NULL)
12576        goto PerlException;
12577      AddImageToRegistry(sv,preview_image);
12578      rv=newRV(sv);
12579      av_push(av,sv_bless(rv,hv));
12580      SvREFCNT_dec(sv);
12581    }
12582    exception=DestroyExceptionInfo(exception);
12583    ST(0)=av_reference;
12584    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12585    XSRETURN(1);
12586
12587  PerlException:
12588    InheritPerlException(exception,perl_exception);
12589    exception=DestroyExceptionInfo(exception);
12590    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12591    SvPOK_on(perl_exception);
12592    ST(0)=sv_2mortal(perl_exception);
12593    XSRETURN(1);
12594  }
12595
12596#
12597###############################################################################
12598#                                                                             #
12599#                                                                             #
12600#                                                                             #
12601#   Q u e r y C o l o r                                                       #
12602#                                                                             #
12603#                                                                             #
12604#                                                                             #
12605###############################################################################
12606#
12607#
12608void
12609QueryColor(ref,...)
12610  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12611  ALIAS:
12612    querycolor = 1
12613  PPCODE:
12614  {
12615    char
12616      *name;
12617
12618    ExceptionInfo
12619      *exception;
12620
12621    PixelInfo
12622      color;
12623
12624    register ssize_t
12625      i;
12626
12627    SV
12628      *perl_exception;
12629
12630    PERL_UNUSED_VAR(ref);
12631    PERL_UNUSED_VAR(ix);
12632    exception=AcquireExceptionInfo();
12633    perl_exception=newSVpv("",0);
12634    if (items == 1)
12635      {
12636        const ColorInfo
12637          **colorlist;
12638
12639        size_t
12640          colors;
12641
12642        colorlist=GetColorInfoList("*",&colors,exception);
12643        EXTEND(sp,colors);
12644        for (i=0; i < (ssize_t) colors; i++)
12645        {
12646          PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12647        }
12648        colorlist=(const ColorInfo **)
12649          RelinquishMagickMemory((ColorInfo **) colorlist);
12650        goto PerlException;
12651      }
12652    EXTEND(sp,5*items);
12653    for (i=1; i < items; i++)
12654    {
12655      name=(char *) SvPV(ST(i),na);
12656      if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12657        {
12658          PUSHs(&sv_undef);
12659          continue;
12660        }
12661      PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12662      PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12663      PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12664      if (color.colorspace == CMYKColorspace)
12665        PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12666      if (color.alpha_trait != UndefinedPixelTrait)
12667        PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12668    }
12669
12670  PerlException:
12671    InheritPerlException(exception,perl_exception);
12672    exception=DestroyExceptionInfo(exception);
12673    SvREFCNT_dec(perl_exception);
12674  }
12675
12676#
12677###############################################################################
12678#                                                                             #
12679#                                                                             #
12680#                                                                             #
12681#   Q u e r y C o l o r N a m e                                               #
12682#                                                                             #
12683#                                                                             #
12684#                                                                             #
12685###############################################################################
12686#
12687#
12688void
12689QueryColorname(ref,...)
12690  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12691  ALIAS:
12692    querycolorname = 1
12693  PPCODE:
12694  {
12695    AV
12696      *av;
12697
12698    char
12699      message[MagickPathExtent];
12700
12701    ExceptionInfo
12702      *exception;
12703
12704    Image
12705      *image;
12706
12707    PixelInfo
12708      target_color;
12709
12710    register ssize_t
12711      i;
12712
12713    struct PackageInfo
12714      *info;
12715
12716    SV
12717      *perl_exception,
12718      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12719
12720    PERL_UNUSED_VAR(ref);
12721    PERL_UNUSED_VAR(ix);
12722    exception=AcquireExceptionInfo();
12723    perl_exception=newSVpv("",0);
12724    reference=SvRV(ST(0));
12725    av=(AV *) reference;
12726    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12727      exception);
12728    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12729    if (image == (Image *) NULL)
12730      {
12731        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12732          PackageName);
12733        goto PerlException;
12734      }
12735    EXTEND(sp,items);
12736    for (i=1; i < items; i++)
12737    {
12738      (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12739        exception);
12740      (void) QueryColorname(image,&target_color,SVGCompliance,message,
12741        exception);
12742      PUSHs(sv_2mortal(newSVpv(message,0)));
12743    }
12744
12745  PerlException:
12746    InheritPerlException(exception,perl_exception);
12747    exception=DestroyExceptionInfo(exception);
12748    SvREFCNT_dec(perl_exception);
12749  }
12750
12751#
12752###############################################################################
12753#                                                                             #
12754#                                                                             #
12755#                                                                             #
12756#   Q u e r y F o n t                                                         #
12757#                                                                             #
12758#                                                                             #
12759#                                                                             #
12760###############################################################################
12761#
12762#
12763void
12764QueryFont(ref,...)
12765  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12766  ALIAS:
12767    queryfont = 1
12768  PPCODE:
12769  {
12770    char
12771      *name,
12772      message[MagickPathExtent];
12773
12774    ExceptionInfo
12775      *exception;
12776
12777    register ssize_t
12778      i;
12779
12780    SV
12781      *perl_exception;
12782
12783    volatile const TypeInfo
12784      *type_info;
12785
12786    PERL_UNUSED_VAR(ref);
12787    PERL_UNUSED_VAR(ix);
12788    exception=AcquireExceptionInfo();
12789    perl_exception=newSVpv("",0);
12790    if (items == 1)
12791      {
12792        const TypeInfo
12793          **typelist;
12794
12795        size_t
12796          types;
12797
12798        typelist=GetTypeInfoList("*",&types,exception);
12799        EXTEND(sp,types);
12800        for (i=0; i < (ssize_t) types; i++)
12801        {
12802          PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12803        }
12804        typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12805          typelist);
12806        goto PerlException;
12807      }
12808    EXTEND(sp,10*items);
12809    for (i=1; i < items; i++)
12810    {
12811      name=(char *) SvPV(ST(i),na);
12812      type_info=GetTypeInfo(name,exception);
12813      if (type_info == (TypeInfo *) NULL)
12814        {
12815          PUSHs(&sv_undef);
12816          continue;
12817        }
12818      if (type_info->name == (char *) NULL)
12819        PUSHs(&sv_undef);
12820      else
12821        PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12822      if (type_info->description == (char *) NULL)
12823        PUSHs(&sv_undef);
12824      else
12825        PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12826      if (type_info->family == (char *) NULL)
12827        PUSHs(&sv_undef);
12828      else
12829        PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12830      if (type_info->style == UndefinedStyle)
12831        PUSHs(&sv_undef);
12832      else
12833        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12834          type_info->style),0)));
12835      if (type_info->stretch == UndefinedStretch)
12836        PUSHs(&sv_undef);
12837      else
12838        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12839          type_info->stretch),0)));
12840      (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12841        type_info->weight);
12842      PUSHs(sv_2mortal(newSVpv(message,0)));
12843      if (type_info->encoding == (char *) NULL)
12844        PUSHs(&sv_undef);
12845      else
12846        PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12847      if (type_info->foundry == (char *) NULL)
12848        PUSHs(&sv_undef);
12849      else
12850        PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12851      if (type_info->format == (char *) NULL)
12852        PUSHs(&sv_undef);
12853      else
12854        PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12855      if (type_info->metrics == (char *) NULL)
12856        PUSHs(&sv_undef);
12857      else
12858        PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12859      if (type_info->glyphs == (char *) NULL)
12860        PUSHs(&sv_undef);
12861      else
12862        PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12863    }
12864
12865  PerlException:
12866    InheritPerlException(exception,perl_exception);
12867    exception=DestroyExceptionInfo(exception);
12868    SvREFCNT_dec(perl_exception);
12869  }
12870
12871#
12872###############################################################################
12873#                                                                             #
12874#                                                                             #
12875#                                                                             #
12876#   Q u e r y F o n t M e t r i c s                                           #
12877#                                                                             #
12878#                                                                             #
12879#                                                                             #
12880###############################################################################
12881#
12882#
12883void
12884QueryFontMetrics(ref,...)
12885  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12886  ALIAS:
12887    queryfontmetrics = 1
12888  PPCODE:
12889  {
12890    AffineMatrix
12891      affine,
12892      current;
12893
12894    AV
12895      *av;
12896
12897    char
12898      *attribute;
12899
12900    double
12901      x,
12902      y;
12903
12904    DrawInfo
12905      *draw_info;
12906
12907    ExceptionInfo
12908      *exception;
12909
12910    GeometryInfo
12911      geometry_info;
12912
12913    Image
12914      *image;
12915
12916    MagickBooleanType
12917      status;
12918
12919    MagickStatusType
12920      flags;
12921
12922    register ssize_t
12923      i;
12924
12925    ssize_t
12926      type;
12927
12928    struct PackageInfo
12929      *info,
12930      *package_info;
12931
12932    SV
12933      *perl_exception,
12934      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12935
12936    TypeMetric
12937      metrics;
12938
12939    PERL_UNUSED_VAR(ref);
12940    PERL_UNUSED_VAR(ix);
12941    exception=AcquireExceptionInfo();
12942    package_info=(struct PackageInfo *) NULL;
12943    perl_exception=newSVpv("",0);
12944    reference=SvRV(ST(0));
12945    av=(AV *) reference;
12946    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12947      exception);
12948    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12949    if (image == (Image *) NULL)
12950      {
12951        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12952          PackageName);
12953        goto PerlException;
12954      }
12955    package_info=ClonePackageInfo(info,exception);
12956    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12957    CloneString(&draw_info->text,"");
12958    current=draw_info->affine;
12959    GetAffineMatrix(&affine);
12960    x=0.0;
12961    y=0.0;
12962    EXTEND(sp,7*items);
12963    for (i=2; i < items; i+=2)
12964    {
12965      attribute=(char *) SvPV(ST(i-1),na);
12966      switch (*attribute)
12967      {
12968        case 'A':
12969        case 'a':
12970        {
12971          if (LocaleCompare(attribute,"antialias") == 0)
12972            {
12973              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12974                SvPV(ST(i),na));
12975              if (type < 0)
12976                {
12977                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12978                    SvPV(ST(i),na));
12979                  break;
12980                }
12981              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12982              break;
12983            }
12984          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12985            attribute);
12986          break;
12987        }
12988        case 'd':
12989        case 'D':
12990        {
12991          if (LocaleCompare(attribute,"density") == 0)
12992            {
12993              CloneString(&draw_info->density,SvPV(ST(i),na));
12994              break;
12995            }
12996          if (LocaleCompare(attribute,"direction") == 0)
12997            {
12998              draw_info->direction=(DirectionType) ParseCommandOption(
12999                MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
13000              break;
13001            }
13002          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13003            attribute);
13004          break;
13005        }
13006        case 'e':
13007        case 'E':
13008        {
13009          if (LocaleCompare(attribute,"encoding") == 0)
13010            {
13011              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13012              break;
13013            }
13014          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13015            attribute);
13016          break;
13017        }
13018        case 'f':
13019        case 'F':
13020        {
13021          if (LocaleCompare(attribute,"family") == 0)
13022            {
13023              CloneString(&draw_info->family,SvPV(ST(i),na));
13024              break;
13025            }
13026          if (LocaleCompare(attribute,"fill") == 0)
13027            {
13028              if (info)
13029                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13030                  &draw_info->fill,exception);
13031              break;
13032            }
13033          if (LocaleCompare(attribute,"font") == 0)
13034            {
13035              CloneString(&draw_info->font,SvPV(ST(i),na));
13036              break;
13037            }
13038          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13039            attribute);
13040          break;
13041        }
13042        case 'g':
13043        case 'G':
13044        {
13045          if (LocaleCompare(attribute,"geometry") == 0)
13046            {
13047              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13048              break;
13049            }
13050          if (LocaleCompare(attribute,"gravity") == 0)
13051            {
13052              draw_info->gravity=(GravityType) ParseCommandOption(
13053                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13054              break;
13055            }
13056          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13057            attribute);
13058          break;
13059        }
13060        case 'i':
13061        case 'I':
13062        {
13063          if (LocaleCompare(attribute,"interline-spacing") == 0)
13064            {
13065              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13066              draw_info->interline_spacing=geometry_info.rho;
13067              break;
13068            }
13069          if (LocaleCompare(attribute,"interword-spacing") == 0)
13070            {
13071              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13072              draw_info->interword_spacing=geometry_info.rho;
13073              break;
13074            }
13075          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13076            attribute);
13077          break;
13078        }
13079        case 'k':
13080        case 'K':
13081        {
13082          if (LocaleCompare(attribute,"kerning") == 0)
13083            {
13084              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13085              draw_info->kerning=geometry_info.rho;
13086              break;
13087            }
13088          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13089            attribute);
13090          break;
13091        }
13092        case 'p':
13093        case 'P':
13094        {
13095          if (LocaleCompare(attribute,"pointsize") == 0)
13096            {
13097              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13098              draw_info->pointsize=geometry_info.rho;
13099              break;
13100            }
13101          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13102            attribute);
13103          break;
13104        }
13105        case 'r':
13106        case 'R':
13107        {
13108          if (LocaleCompare(attribute,"rotate") == 0)
13109            {
13110              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13111              affine.rx=geometry_info.rho;
13112              affine.ry=geometry_info.sigma;
13113              if ((flags & SigmaValue) == 0)
13114                affine.ry=affine.rx;
13115              break;
13116            }
13117          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13118            attribute);
13119          break;
13120        }
13121        case 's':
13122        case 'S':
13123        {
13124          if (LocaleCompare(attribute,"scale") == 0)
13125            {
13126              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13127              affine.sx=geometry_info.rho;
13128              affine.sy=geometry_info.sigma;
13129              if ((flags & SigmaValue) == 0)
13130                affine.sy=affine.sx;
13131              break;
13132            }
13133          if (LocaleCompare(attribute,"skew") == 0)
13134            {
13135              double
13136                x_angle,
13137                y_angle;
13138
13139              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13140              x_angle=geometry_info.rho;
13141              y_angle=geometry_info.sigma;
13142              if ((flags & SigmaValue) == 0)
13143                y_angle=x_angle;
13144              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13145              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13146              break;
13147            }
13148          if (LocaleCompare(attribute,"stroke") == 0)
13149            {
13150              if (info)
13151                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13152                  &draw_info->stroke,exception);
13153              break;
13154            }
13155          if (LocaleCompare(attribute,"style") == 0)
13156            {
13157              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13158                SvPV(ST(i),na));
13159              if (type < 0)
13160                {
13161                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13162                    SvPV(ST(i),na));
13163                  break;
13164                }
13165              draw_info->style=(StyleType) type;
13166              break;
13167            }
13168          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13169            attribute);
13170          break;
13171        }
13172        case 't':
13173        case 'T':
13174        {
13175          if (LocaleCompare(attribute,"text") == 0)
13176            {
13177              CloneString(&draw_info->text,SvPV(ST(i),na));
13178              break;
13179            }
13180          if (LocaleCompare(attribute,"translate") == 0)
13181            {
13182              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13183              affine.tx=geometry_info.rho;
13184              affine.ty=geometry_info.sigma;
13185              if ((flags & SigmaValue) == 0)
13186                affine.ty=affine.tx;
13187              break;
13188            }
13189          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13190            attribute);
13191          break;
13192        }
13193        case 'w':
13194        case 'W':
13195        {
13196          if (LocaleCompare(attribute,"weight") == 0)
13197            {
13198              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13199              draw_info->weight=(size_t) geometry_info.rho;
13200              break;
13201            }
13202          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13203            attribute);
13204          break;
13205        }
13206        case 'x':
13207        case 'X':
13208        {
13209          if (LocaleCompare(attribute,"x") == 0)
13210            {
13211              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13212              x=geometry_info.rho;
13213              break;
13214            }
13215          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13216            attribute);
13217          break;
13218        }
13219        case 'y':
13220        case 'Y':
13221        {
13222          if (LocaleCompare(attribute,"y") == 0)
13223            {
13224              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13225              y=geometry_info.rho;
13226              break;
13227            }
13228          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13229            attribute);
13230          break;
13231        }
13232        default:
13233        {
13234          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13235            attribute);
13236          break;
13237        }
13238      }
13239    }
13240    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13241    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13242    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13243    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13244    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13245    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13246    if (draw_info->geometry == (char *) NULL)
13247      {
13248        draw_info->geometry=AcquireString((char *) NULL);
13249        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13250          "%.20g,%.20g",x,y);
13251      }
13252    status=GetTypeMetrics(image,draw_info,&metrics,exception);
13253    (void) CatchImageException(image);
13254    if (status == MagickFalse)
13255      PUSHs(&sv_undef);
13256    else
13257      {
13258        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13259        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13260        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13261        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13262        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13263        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13264        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13265        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13266        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13267        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13268        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13269        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13270        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13271      }
13272    draw_info=DestroyDrawInfo(draw_info);
13273
13274  PerlException:
13275    if (package_info != (struct PackageInfo *) NULL)
13276      DestroyPackageInfo(package_info);
13277    InheritPerlException(exception,perl_exception);
13278    exception=DestroyExceptionInfo(exception);
13279    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13280  }
13281
13282#
13283###############################################################################
13284#                                                                             #
13285#                                                                             #
13286#                                                                             #
13287#   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                         #
13288#                                                                             #
13289#                                                                             #
13290#                                                                             #
13291###############################################################################
13292#
13293#
13294void
13295QueryMultilineFontMetrics(ref,...)
13296  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13297  ALIAS:
13298    querymultilinefontmetrics = 1
13299  PPCODE:
13300  {
13301    AffineMatrix
13302      affine,
13303      current;
13304
13305    AV
13306      *av;
13307
13308    char
13309      *attribute;
13310
13311    double
13312      x,
13313      y;
13314
13315    DrawInfo
13316      *draw_info;
13317
13318    ExceptionInfo
13319      *exception;
13320
13321    GeometryInfo
13322      geometry_info;
13323
13324    Image
13325      *image;
13326
13327    MagickBooleanType
13328      status;
13329
13330    MagickStatusType
13331      flags;
13332
13333    register ssize_t
13334      i;
13335
13336    ssize_t
13337      type;
13338
13339    struct PackageInfo
13340      *info,
13341      *package_info;
13342
13343    SV
13344      *perl_exception,
13345      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13346
13347    TypeMetric
13348      metrics;
13349
13350    PERL_UNUSED_VAR(ref);
13351    PERL_UNUSED_VAR(ix);
13352    exception=AcquireExceptionInfo();
13353    package_info=(struct PackageInfo *) NULL;
13354    perl_exception=newSVpv("",0);
13355    reference=SvRV(ST(0));
13356    av=(AV *) reference;
13357    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13358      exception);
13359    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13360    if (image == (Image *) NULL)
13361      {
13362        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13363          PackageName);
13364        goto PerlException;
13365      }
13366    package_info=ClonePackageInfo(info,exception);
13367    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13368    CloneString(&draw_info->text,"");
13369    current=draw_info->affine;
13370    GetAffineMatrix(&affine);
13371    x=0.0;
13372    y=0.0;
13373    EXTEND(sp,7*items);
13374    for (i=2; i < items; i+=2)
13375    {
13376      attribute=(char *) SvPV(ST(i-1),na);
13377      switch (*attribute)
13378      {
13379        case 'A':
13380        case 'a':
13381        {
13382          if (LocaleCompare(attribute,"antialias") == 0)
13383            {
13384              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13385                SvPV(ST(i),na));
13386              if (type < 0)
13387                {
13388                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13389                    SvPV(ST(i),na));
13390                  break;
13391                }
13392              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13393              break;
13394            }
13395          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13396            attribute);
13397          break;
13398        }
13399        case 'd':
13400        case 'D':
13401        {
13402          if (LocaleCompare(attribute,"density") == 0)
13403            {
13404              CloneString(&draw_info->density,SvPV(ST(i),na));
13405              break;
13406            }
13407          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13408            attribute);
13409          break;
13410        }
13411        case 'e':
13412        case 'E':
13413        {
13414          if (LocaleCompare(attribute,"encoding") == 0)
13415            {
13416              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13417              break;
13418            }
13419          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13420            attribute);
13421          break;
13422        }
13423        case 'f':
13424        case 'F':
13425        {
13426          if (LocaleCompare(attribute,"family") == 0)
13427            {
13428              CloneString(&draw_info->family,SvPV(ST(i),na));
13429              break;
13430            }
13431          if (LocaleCompare(attribute,"fill") == 0)
13432            {
13433              if (info)
13434                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13435                  &draw_info->fill,exception);
13436              break;
13437            }
13438          if (LocaleCompare(attribute,"font") == 0)
13439            {
13440              CloneString(&draw_info->font,SvPV(ST(i),na));
13441              break;
13442            }
13443          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13444            attribute);
13445          break;
13446        }
13447        case 'g':
13448        case 'G':
13449        {
13450          if (LocaleCompare(attribute,"geometry") == 0)
13451            {
13452              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13453              break;
13454            }
13455          if (LocaleCompare(attribute,"gravity") == 0)
13456            {
13457              draw_info->gravity=(GravityType) ParseCommandOption(
13458                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13459              break;
13460            }
13461          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13462            attribute);
13463          break;
13464        }
13465        case 'p':
13466        case 'P':
13467        {
13468          if (LocaleCompare(attribute,"pointsize") == 0)
13469            {
13470              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13471              draw_info->pointsize=geometry_info.rho;
13472              break;
13473            }
13474          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13475            attribute);
13476          break;
13477        }
13478        case 'r':
13479        case 'R':
13480        {
13481          if (LocaleCompare(attribute,"rotate") == 0)
13482            {
13483              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13484              affine.rx=geometry_info.rho;
13485              affine.ry=geometry_info.sigma;
13486              if ((flags & SigmaValue) == 0)
13487                affine.ry=affine.rx;
13488              break;
13489            }
13490          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13491            attribute);
13492          break;
13493        }
13494        case 's':
13495        case 'S':
13496        {
13497          if (LocaleCompare(attribute,"scale") == 0)
13498            {
13499              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13500              affine.sx=geometry_info.rho;
13501              affine.sy=geometry_info.sigma;
13502              if ((flags & SigmaValue) == 0)
13503                affine.sy=affine.sx;
13504              break;
13505            }
13506          if (LocaleCompare(attribute,"skew") == 0)
13507            {
13508              double
13509                x_angle,
13510                y_angle;
13511
13512              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13513              x_angle=geometry_info.rho;
13514              y_angle=geometry_info.sigma;
13515              if ((flags & SigmaValue) == 0)
13516                y_angle=x_angle;
13517              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13518              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13519              break;
13520            }
13521          if (LocaleCompare(attribute,"stroke") == 0)
13522            {
13523              if (info)
13524                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13525                  &draw_info->stroke,exception);
13526              break;
13527            }
13528          if (LocaleCompare(attribute,"style") == 0)
13529            {
13530              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13531                SvPV(ST(i),na));
13532              if (type < 0)
13533                {
13534                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13535                    SvPV(ST(i),na));
13536                  break;
13537                }
13538              draw_info->style=(StyleType) type;
13539              break;
13540            }
13541          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13542            attribute);
13543          break;
13544        }
13545        case 't':
13546        case 'T':
13547        {
13548          if (LocaleCompare(attribute,"text") == 0)
13549            {
13550              CloneString(&draw_info->text,SvPV(ST(i),na));
13551              break;
13552            }
13553          if (LocaleCompare(attribute,"translate") == 0)
13554            {
13555              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13556              affine.tx=geometry_info.rho;
13557              affine.ty=geometry_info.sigma;
13558              if ((flags & SigmaValue) == 0)
13559                affine.ty=affine.tx;
13560              break;
13561            }
13562          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13563            attribute);
13564          break;
13565        }
13566        case 'w':
13567        case 'W':
13568        {
13569          if (LocaleCompare(attribute,"weight") == 0)
13570            {
13571              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13572              draw_info->weight=(size_t) geometry_info.rho;
13573              break;
13574            }
13575          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13576            attribute);
13577          break;
13578        }
13579        case 'x':
13580        case 'X':
13581        {
13582          if (LocaleCompare(attribute,"x") == 0)
13583            {
13584              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13585              x=geometry_info.rho;
13586              break;
13587            }
13588          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13589            attribute);
13590          break;
13591        }
13592        case 'y':
13593        case 'Y':
13594        {
13595          if (LocaleCompare(attribute,"y") == 0)
13596            {
13597              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13598              y=geometry_info.rho;
13599              break;
13600            }
13601          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13602            attribute);
13603          break;
13604        }
13605        default:
13606        {
13607          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13608            attribute);
13609          break;
13610        }
13611      }
13612    }
13613    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13614    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13615    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13616    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13617    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13618    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13619    if (draw_info->geometry == (char *) NULL)
13620      {
13621        draw_info->geometry=AcquireString((char *) NULL);
13622        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13623          "%.20g,%.20g",x,y);
13624      }
13625    status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13626    (void) CatchException(exception);
13627    if (status == MagickFalse)
13628      PUSHs(&sv_undef);
13629    else
13630      {
13631        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13632        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13633        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13634        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13635        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13636        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13637        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13638        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13639        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13640        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13641        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13642        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13643        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13644      }
13645    draw_info=DestroyDrawInfo(draw_info);
13646
13647  PerlException:
13648    if (package_info != (struct PackageInfo *) NULL)
13649      DestroyPackageInfo(package_info);
13650    InheritPerlException(exception,perl_exception);
13651    exception=DestroyExceptionInfo(exception);
13652    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13653  }
13654
13655#
13656###############################################################################
13657#                                                                             #
13658#                                                                             #
13659#                                                                             #
13660#   Q u e r y F o r m a t                                                     #
13661#                                                                             #
13662#                                                                             #
13663#                                                                             #
13664###############################################################################
13665#
13666#
13667void
13668QueryFormat(ref,...)
13669  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13670  ALIAS:
13671    queryformat = 1
13672  PPCODE:
13673  {
13674    char
13675      *name;
13676
13677    ExceptionInfo
13678      *exception;
13679
13680    register ssize_t
13681      i;
13682
13683    SV
13684      *perl_exception;
13685
13686    volatile const MagickInfo
13687      *magick_info;
13688
13689    PERL_UNUSED_VAR(ref);
13690    PERL_UNUSED_VAR(ix);
13691    exception=AcquireExceptionInfo();
13692    perl_exception=newSVpv("",0);
13693    if (items == 1)
13694      {
13695        char
13696          format[MagickPathExtent];
13697
13698        const MagickInfo
13699          **format_list;
13700
13701        size_t
13702          types;
13703
13704        format_list=GetMagickInfoList("*",&types,exception);
13705        EXTEND(sp,types);
13706        for (i=0; i < (ssize_t) types; i++)
13707        {
13708          (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13709          LocaleLower(format);
13710          PUSHs(sv_2mortal(newSVpv(format,0)));
13711        }
13712        format_list=(const MagickInfo **)
13713          RelinquishMagickMemory((MagickInfo *) format_list);
13714        goto PerlException;
13715      }
13716    EXTEND(sp,8*items);
13717    for (i=1; i < items; i++)
13718    {
13719      name=(char *) SvPV(ST(i),na);
13720      magick_info=GetMagickInfo(name,exception);
13721      if (magick_info == (const MagickInfo *) NULL)
13722        {
13723          PUSHs(&sv_undef);
13724          continue;
13725        }
13726      if (magick_info->description == (char *) NULL)
13727        PUSHs(&sv_undef);
13728      else
13729        PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13730      if (magick_info->module == (char *) NULL)
13731        PUSHs(&sv_undef);
13732      else
13733        PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13734    }
13735
13736  PerlException:
13737    InheritPerlException(exception,perl_exception);
13738    exception=DestroyExceptionInfo(exception);
13739    SvREFCNT_dec(perl_exception);
13740  }
13741
13742#
13743###############################################################################
13744#                                                                             #
13745#                                                                             #
13746#                                                                             #
13747#   Q u e r y O p t i o n                                                     #
13748#                                                                             #
13749#                                                                             #
13750#                                                                             #
13751###############################################################################
13752#
13753#
13754void
13755QueryOption(ref,...)
13756  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13757  ALIAS:
13758    queryoption = 1
13759  PPCODE:
13760  {
13761    char
13762      **options;
13763
13764    ExceptionInfo
13765      *exception;
13766
13767    register ssize_t
13768      i;
13769
13770    ssize_t
13771      j,
13772      option;
13773
13774    SV
13775      *perl_exception;
13776
13777    PERL_UNUSED_VAR(ref);
13778    PERL_UNUSED_VAR(ix);
13779    exception=AcquireExceptionInfo();
13780    perl_exception=newSVpv("",0);
13781    EXTEND(sp,8*items);
13782    for (i=1; i < items; i++)
13783    {
13784      option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13785        SvPV(ST(i),na));
13786      options=GetCommandOptions((CommandOption) option);
13787      if (options == (char **) NULL)
13788        PUSHs(&sv_undef);
13789      else
13790        {
13791          for (j=0; options[j] != (char *) NULL; j++)
13792            PUSHs(sv_2mortal(newSVpv(options[j],0)));
13793          options=DestroyStringList(options);
13794        }
13795    }
13796
13797    InheritPerlException(exception,perl_exception);
13798    exception=DestroyExceptionInfo(exception);
13799    SvREFCNT_dec(perl_exception);
13800  }
13801
13802#
13803###############################################################################
13804#                                                                             #
13805#                                                                             #
13806#                                                                             #
13807#   R e a d                                                                   #
13808#                                                                             #
13809#                                                                             #
13810#                                                                             #
13811###############################################################################
13812#
13813#
13814void
13815Read(ref,...)
13816  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13817  ALIAS:
13818    ReadImage  = 1
13819    read       = 2
13820    readimage  = 3
13821  PPCODE:
13822  {
13823    AV
13824      *av;
13825
13826    char
13827      **keep,
13828      **list;
13829
13830    ExceptionInfo
13831      *exception;
13832
13833    HV
13834      *hv;
13835
13836    Image
13837      *image;
13838
13839    int
13840      n;
13841
13842    MagickBooleanType
13843      status;
13844
13845    register char
13846      **p;
13847
13848    register ssize_t
13849      i;
13850
13851    ssize_t
13852      ac,
13853      number_images;
13854
13855    STRLEN
13856      *length;
13857
13858    struct PackageInfo
13859      *info,
13860      *package_info;
13861
13862    SV
13863      *perl_exception,  /* Perl variable for storing messages */
13864      *reference,
13865      *rv,
13866      *sv;
13867
13868    PERL_UNUSED_VAR(ref);
13869    PERL_UNUSED_VAR(ix);
13870    exception=AcquireExceptionInfo();
13871    perl_exception=newSVpv("",0);
13872    sv=NULL;
13873    package_info=(struct PackageInfo *) NULL;
13874    number_images=0;
13875    ac=(items < 2) ? 1 : items-1;
13876    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13877    keep=list;
13878    length=(STRLEN *) NULL;
13879    if (list == (char **) NULL)
13880      {
13881        ThrowPerlException(exception,ResourceLimitError,
13882          "MemoryAllocationFailed",PackageName);
13883        goto PerlException;
13884      }
13885    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13886    if (length == (STRLEN *) NULL)
13887      {
13888        ThrowPerlException(exception,ResourceLimitError,
13889          "MemoryAllocationFailed",PackageName);
13890        goto PerlException;
13891      }
13892    if (sv_isobject(ST(0)) == 0)
13893      {
13894        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13895          PackageName);
13896        goto PerlException;
13897      }
13898    reference=SvRV(ST(0));
13899    hv=SvSTASH(reference);
13900    if (SvTYPE(reference) != SVt_PVAV)
13901      {
13902        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13903          PackageName);
13904        goto PerlException;
13905      }
13906    av=(AV *) reference;
13907    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13908      exception);
13909    package_info=ClonePackageInfo(info,exception);
13910    n=1;
13911    if (items <= 1)
13912      *list=(char *) (*package_info->image_info->filename ?
13913        package_info->image_info->filename : "XC:black");
13914    else
13915      for (n=0, i=0; i < ac; i++)
13916      {
13917        list[n]=(char *) SvPV(ST(i+1),length[n]);
13918        if ((items >= 3) && strEQcase(list[n],"blob"))
13919          {
13920            void
13921              *blob;
13922
13923            i++;
13924            blob=(void *) (SvPV(ST(i+1),length[n]));
13925            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13926          }
13927        if ((items >= 3) && strEQcase(list[n],"filename"))
13928          continue;
13929        if ((items >= 3) && strEQcase(list[n],"file"))
13930          {
13931            FILE
13932              *file;
13933
13934            PerlIO
13935              *io_info;
13936
13937            i++;
13938            io_info=IoIFP(sv_2io(ST(i+1)));
13939            if (io_info == (PerlIO *) NULL)
13940              {
13941                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13942                  PackageName);
13943                continue;
13944              }
13945            file=PerlIO_findFILE(io_info);
13946            if (file == (FILE *) NULL)
13947              {
13948                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13949                  PackageName);
13950                continue;
13951              }
13952            SetImageInfoFile(package_info->image_info,file);
13953          }
13954        if ((items >= 3) && strEQcase(list[n],"magick"))
13955          continue;
13956        n++;
13957      }
13958    list[n]=(char *) NULL;
13959    keep=list;
13960    status=ExpandFilenames(&n,&list);
13961    if (status == MagickFalse)
13962      {
13963        ThrowPerlException(exception,ResourceLimitError,
13964          "MemoryAllocationFailed",PackageName);
13965        goto PerlException;
13966      }
13967    number_images=0;
13968    for (i=0; i < n; i++)
13969    {
13970      if ((package_info->image_info->file == (FILE *) NULL) &&
13971          (package_info->image_info->blob == (void *) NULL))
13972        image=ReadImages(package_info->image_info,list[i],exception);
13973      else
13974        {
13975          image=ReadImages(package_info->image_info,
13976            package_info->image_info->filename,exception);
13977          if (image != (Image *) NULL)
13978            DisassociateImageStream(image);
13979        }
13980      if (image == (Image *) NULL)
13981        break;
13982      for ( ; image; image=image->next)
13983      {
13984        AddImageToRegistry(sv,image);
13985        rv=newRV(sv);
13986        av_push(av,sv_bless(rv,hv));
13987        SvREFCNT_dec(sv);
13988        number_images++;
13989      }
13990    }
13991    /*
13992      Free resources.
13993    */
13994    for (i=0; i < n; i++)
13995      if (list[i] != (char *) NULL)
13996        for (p=keep; list[i] != *p++; )
13997          if (*p == (char *) NULL)
13998            {
13999              list[i]=(char *) RelinquishMagickMemory(list[i]);
14000              break;
14001            }
14002
14003  PerlException:
14004    if (package_info != (struct PackageInfo *) NULL)
14005      DestroyPackageInfo(package_info);
14006    if (list && (list != keep))
14007      list=(char **) RelinquishMagickMemory(list);
14008    if (keep)
14009      keep=(char **) RelinquishMagickMemory(keep);
14010    if (length)
14011      length=(STRLEN *) RelinquishMagickMemory(length);
14012    InheritPerlException(exception,perl_exception);
14013    exception=DestroyExceptionInfo(exception);
14014    sv_setiv(perl_exception,(IV) number_images);
14015    SvPOK_on(perl_exception);
14016    ST(0)=sv_2mortal(perl_exception);
14017    XSRETURN(1);
14018  }
14019
14020#
14021###############################################################################
14022#                                                                             #
14023#                                                                             #
14024#                                                                             #
14025#   R e m o t e                                                               #
14026#                                                                             #
14027#                                                                             #
14028#                                                                             #
14029###############################################################################
14030#
14031#
14032void
14033Remote(ref,...)
14034  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14035  ALIAS:
14036    RemoteCommand  = 1
14037    remote         = 2
14038    remoteCommand  = 3
14039  PPCODE:
14040  {
14041    AV
14042      *av;
14043
14044    ExceptionInfo
14045      *exception;
14046
14047    register ssize_t
14048      i;
14049
14050    SV
14051      *perl_exception,
14052      *reference;
14053
14054    struct PackageInfo
14055      *info;
14056
14057    PERL_UNUSED_VAR(ref);
14058    PERL_UNUSED_VAR(ix);
14059    exception=AcquireExceptionInfo();
14060    perl_exception=newSVpv("",0);
14061    reference=SvRV(ST(0));
14062    av=(AV *) reference;
14063    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14064      exception);
14065    for (i=1; i < items; i++)
14066      (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
14067        SvPV(ST(i),na),exception);
14068    InheritPerlException(exception,perl_exception);
14069    exception=DestroyExceptionInfo(exception);
14070    SvREFCNT_dec(perl_exception);    /* throw away all errors */
14071  }
14072
14073#
14074###############################################################################
14075#                                                                             #
14076#                                                                             #
14077#                                                                             #
14078#   S e t                                                                     #
14079#                                                                             #
14080#                                                                             #
14081#                                                                             #
14082###############################################################################
14083#
14084#
14085void
14086Set(ref,...)
14087  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14088  ALIAS:
14089    SetAttributes  = 1
14090    SetAttribute   = 2
14091    set            = 3
14092    setattributes  = 4
14093    setattribute   = 5
14094  PPCODE:
14095  {
14096    ExceptionInfo
14097      *exception;
14098
14099    Image
14100      *image;
14101
14102    register ssize_t
14103      i;
14104
14105    struct PackageInfo
14106      *info;
14107
14108    SV
14109      *perl_exception,
14110      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14111
14112    PERL_UNUSED_VAR(ref);
14113    PERL_UNUSED_VAR(ix);
14114    exception=AcquireExceptionInfo();
14115    perl_exception=newSVpv("",0);
14116    if (sv_isobject(ST(0)) == 0)
14117      {
14118        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14119          PackageName);
14120        goto PerlException;
14121      }
14122    reference=SvRV(ST(0));
14123    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14124    if (items == 2)
14125      SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14126    else
14127      for (i=2; i < items; i+=2)
14128        SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14129
14130  PerlException:
14131    InheritPerlException(exception,perl_exception);
14132    exception=DestroyExceptionInfo(exception);
14133    sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14134    SvPOK_on(perl_exception);
14135    ST(0)=sv_2mortal(perl_exception);
14136    XSRETURN(1);
14137  }
14138
14139#
14140###############################################################################
14141#                                                                             #
14142#                                                                             #
14143#                                                                             #
14144#   S e t P i x e l                                                           #
14145#                                                                             #
14146#                                                                             #
14147#                                                                             #
14148###############################################################################
14149#
14150#
14151void
14152SetPixel(ref,...)
14153  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14154  ALIAS:
14155    setpixel = 1
14156    setPixel = 2
14157  PPCODE:
14158  {
14159    AV
14160      *av;
14161
14162    char
14163      *attribute;
14164
14165    ChannelType
14166      channel,
14167      channel_mask;
14168
14169    ExceptionInfo
14170      *exception;
14171
14172    Image
14173      *image;
14174
14175    MagickBooleanType
14176      normalize;
14177
14178    RectangleInfo
14179      region;
14180
14181    register ssize_t
14182      i;
14183
14184    register Quantum
14185      *q;
14186
14187    ssize_t
14188      option;
14189
14190    struct PackageInfo
14191      *info;
14192
14193    SV
14194      *perl_exception,
14195      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14196
14197    PERL_UNUSED_VAR(ref);
14198    PERL_UNUSED_VAR(ix);
14199    exception=AcquireExceptionInfo();
14200    perl_exception=newSVpv("",0);
14201    reference=SvRV(ST(0));
14202    av=(AV *) reference;
14203    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14204      exception);
14205    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14206    if (image == (Image *) NULL)
14207      {
14208        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14209          PackageName);
14210        goto PerlException;
14211      }
14212    av=(AV *) NULL;
14213    normalize=MagickTrue;
14214    region.x=0;
14215    region.y=0;
14216    region.width=image->columns;
14217    region.height=1;
14218    if (items == 1)
14219      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14220    channel=DefaultChannels;
14221    for (i=2; i < items; i+=2)
14222    {
14223      attribute=(char *) SvPV(ST(i-1),na);
14224      switch (*attribute)
14225      {
14226        case 'C':
14227        case 'c':
14228        {
14229          if (LocaleCompare(attribute,"channel") == 0)
14230            {
14231              ssize_t
14232                option;
14233
14234              option=ParseChannelOption(SvPV(ST(i),na));
14235              if (option < 0)
14236                {
14237                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14238                    SvPV(ST(i),na));
14239                  return;
14240                }
14241              channel=(ChannelType) option;
14242              break;
14243            }
14244          if (LocaleCompare(attribute,"color") == 0)
14245            {
14246              if (SvTYPE(ST(i)) != SVt_RV)
14247                {
14248                  char
14249                    message[MagickPathExtent];
14250
14251                  (void) FormatLocaleString(message,MagickPathExtent,
14252                    "invalid %.60s value",attribute);
14253                  ThrowPerlException(exception,OptionError,message,
14254                    SvPV(ST(i),na));
14255                }
14256              av=(AV *) SvRV(ST(i));
14257              break;
14258            }
14259          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14260            attribute);
14261          break;
14262        }
14263        case 'g':
14264        case 'G':
14265        {
14266          if (LocaleCompare(attribute,"geometry") == 0)
14267            {
14268              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14269              break;
14270            }
14271          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14272            attribute);
14273          break;
14274        }
14275        case 'N':
14276        case 'n':
14277        {
14278          if (LocaleCompare(attribute,"normalize") == 0)
14279            {
14280              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14281                SvPV(ST(i),na));
14282              if (option < 0)
14283                {
14284                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14285                    SvPV(ST(i),na));
14286                  break;
14287                }
14288             normalize=option != 0 ? MagickTrue : MagickFalse;
14289             break;
14290            }
14291          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14292            attribute);
14293          break;
14294        }
14295        case 'x':
14296        case 'X':
14297        {
14298          if (LocaleCompare(attribute,"x") == 0)
14299            {
14300              region.x=SvIV(ST(i));
14301              break;
14302            }
14303          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14304            attribute);
14305          break;
14306        }
14307        case 'y':
14308        case 'Y':
14309        {
14310          if (LocaleCompare(attribute,"y") == 0)
14311            {
14312              region.y=SvIV(ST(i));
14313              break;
14314            }
14315          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14316            attribute);
14317          break;
14318        }
14319        default:
14320        {
14321          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14322            attribute);
14323          break;
14324        }
14325      }
14326    }
14327    (void) SetImageStorageClass(image,DirectClass,exception);
14328    channel_mask=SetImageChannelMask(image,channel);
14329    q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14330    if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14331        (SvTYPE(av) != SVt_PVAV))
14332      PUSHs(&sv_undef);
14333    else
14334      {
14335        double
14336          scale;
14337
14338        register ssize_t
14339          i;
14340
14341        i=0;
14342        scale=1.0;
14343        if (normalize != MagickFalse)
14344          scale=QuantumRange;
14345        if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14346            (i <= av_len(av)))
14347          {
14348            SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14349              av_fetch(av,i,0)))),q);
14350            i++;
14351          }
14352        if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14353            (i <= av_len(av)))
14354          {
14355            SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14356              av_fetch(av,i,0)))),q);
14357            i++;
14358          }
14359        if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14360            (i <= av_len(av)))
14361          {
14362            SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14363              av_fetch(av,i,0)))),q);
14364            i++;
14365          }
14366        if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14367            (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14368          {
14369            SetPixelBlack(image,ClampToQuantum(scale*
14370              SvNV(*(av_fetch(av,i,0)))),q);
14371            i++;
14372          }
14373        if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14374            (i <= av_len(av)))
14375          {
14376            SetPixelAlpha(image,ClampToQuantum(scale*
14377              SvNV(*(av_fetch(av,i,0)))),q);
14378            i++;
14379          }
14380        (void) SyncAuthenticPixels(image,exception);
14381      }
14382    (void) SetImageChannelMask(image,channel_mask);
14383
14384  PerlException:
14385    InheritPerlException(exception,perl_exception);
14386    exception=DestroyExceptionInfo(exception);
14387    SvREFCNT_dec(perl_exception);
14388  }
14389
14390#
14391###############################################################################
14392#                                                                             #
14393#                                                                             #
14394#                                                                             #
14395#   S e t P i x e l s                                                         #
14396#                                                                             #
14397#                                                                             #
14398#                                                                             #
14399###############################################################################
14400#
14401#
14402void
14403SetPixels(ref,...)
14404  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14405  ALIAS:
14406    setpixels = 1
14407    setPixels = 2
14408  PPCODE:
14409  {
14410    AV
14411      *av;
14412
14413    char
14414      *attribute;
14415
14416    ChannelType
14417      channel,
14418      channel_mask;
14419
14420    ExceptionInfo
14421      *exception;
14422
14423    Image
14424      *image;
14425
14426    RectangleInfo
14427      region;
14428
14429    register ssize_t
14430      i;
14431
14432    register Quantum
14433      *q;
14434
14435    struct PackageInfo
14436      *info;
14437
14438    SV
14439      *perl_exception,
14440      *reference;  /* reference is the SV* of ref=SvIV(reference) */
14441
14442    PERL_UNUSED_VAR(ref);
14443    PERL_UNUSED_VAR(ix);
14444    exception=AcquireExceptionInfo();
14445    perl_exception=newSVpv("",0);
14446    reference=SvRV(ST(0));
14447    av=(AV *) reference;
14448    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14449      exception);
14450    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14451    if (image == (Image *) NULL)
14452      {
14453        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14454          PackageName);
14455        goto PerlException;
14456      }
14457    av=(AV *) NULL;
14458    region.x=0;
14459    region.y=0;
14460    region.width=image->columns;
14461    region.height=1;
14462    if (items == 1)
14463      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14464    channel=DefaultChannels;
14465    for (i=2; i < items; i+=2)
14466    {
14467      attribute=(char *) SvPV(ST(i-1),na);
14468      switch (*attribute)
14469      {
14470        case 'C':
14471        case 'c':
14472        {
14473          if (LocaleCompare(attribute,"channel") == 0)
14474            {
14475              ssize_t
14476                option;
14477
14478              option=ParseChannelOption(SvPV(ST(i),na));
14479              if (option < 0)
14480                {
14481                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14482                    SvPV(ST(i),na));
14483                  return;
14484                }
14485              channel=(ChannelType) option;
14486              break;
14487            }
14488          if (LocaleCompare(attribute,"color") == 0)
14489            {
14490              if (SvTYPE(ST(i)) != SVt_RV)
14491                {
14492                  char
14493                    message[MagickPathExtent];
14494
14495                  (void) FormatLocaleString(message,MagickPathExtent,
14496                    "invalid %.60s value",attribute);
14497                  ThrowPerlException(exception,OptionError,message,
14498                    SvPV(ST(i),na));
14499                }
14500              av=(AV *) SvRV(ST(i));
14501              break;
14502            }
14503          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14504            attribute);
14505          break;
14506        }
14507        case 'g':
14508        case 'G':
14509        {
14510          if (LocaleCompare(attribute,"geometry") == 0)
14511            {
14512              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14513              break;
14514            }
14515          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14516            attribute);
14517          break;
14518        }
14519        case 'h':
14520        case 'H':
14521        {
14522          if (LocaleCompare(attribute,"height") == 0)
14523            {
14524              region.height=SvIV(ST(i));
14525              break;
14526            }
14527          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14528            attribute);
14529          break;
14530        }
14531        case 'w':
14532        case 'W':
14533        {
14534          if (LocaleCompare(attribute,"width") == 0)
14535            {
14536              region.width=SvIV(ST(i));
14537              break;
14538            }
14539          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14540            attribute);
14541          break;
14542        }
14543        case 'x':
14544        case 'X':
14545        {
14546          if (LocaleCompare(attribute,"x") == 0)
14547            {
14548              region.x=SvIV(ST(i));
14549              break;
14550            }
14551          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14552            attribute);
14553          break;
14554        }
14555        case 'y':
14556        case 'Y':
14557        {
14558          if (LocaleCompare(attribute,"y") == 0)
14559            {
14560              region.y=SvIV(ST(i));
14561              break;
14562            }
14563          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14564            attribute);
14565          break;
14566        }
14567        default:
14568        {
14569          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14570            attribute);
14571          break;
14572        }
14573      }
14574    }
14575    (void) SetImageStorageClass(image,DirectClass,exception);
14576    channel_mask=SetImageChannelMask(image,channel);
14577    q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14578      exception);
14579    if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14580        (SvTYPE(av) != SVt_PVAV))
14581      PUSHs(&sv_undef);
14582    else
14583      {
14584        double
14585          scale;
14586
14587        register ssize_t
14588          i,
14589          n,
14590          number_pixels;
14591
14592        i=0;
14593        n=0;
14594        scale=(double) QuantumRange;
14595        number_pixels=region.width*region.height;
14596        while ((n < number_pixels) && (i < av_len(av)))
14597        {
14598          if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14599              (i <= av_len(av)))
14600            {
14601              SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14602                av_fetch(av,i,0)))),q);
14603              i++;
14604            }
14605          if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14606              (i <= av_len(av)))
14607            {
14608              SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14609                av_fetch(av,i,0)))),q);
14610              i++;
14611            }
14612          if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14613              (i <= av_len(av)))
14614            {
14615              SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14616                av_fetch(av,i,0)))),q);
14617              i++;
14618            }
14619          if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14620              (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14621            {
14622             SetPixelBlack(image,ClampToQuantum(scale*
14623                SvNV(*(av_fetch(av,i,0)))),q);
14624              i++;
14625            }
14626          if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14627              (i <= av_len(av)))
14628            {
14629              SetPixelAlpha(image,ClampToQuantum(scale*
14630                SvNV(*(av_fetch(av,i,0)))),q);
14631              i++;
14632            }
14633         	n++;
14634         	q+=image->number_channels;
14635        }
14636        (void) SyncAuthenticPixels(image,exception);
14637      }
14638    (void) SetImageChannelMask(image,channel_mask);
14639
14640  PerlException:
14641    InheritPerlException(exception,perl_exception);
14642    exception=DestroyExceptionInfo(exception);
14643    SvREFCNT_dec(perl_exception);
14644  }
14645
14646#
14647###############################################################################
14648#                                                                             #
14649#                                                                             #
14650#                                                                             #
14651#   S m u s h                                                                 #
14652#                                                                             #
14653#                                                                             #
14654#                                                                             #
14655###############################################################################
14656#
14657#
14658void
14659Smush(ref,...)
14660  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14661  ALIAS:
14662    SmushImage  = 1
14663    smush       = 2
14664    smushimage  = 3
14665  PPCODE:
14666  {
14667    AV
14668      *av;
14669
14670    char
14671      *attribute;
14672
14673    ExceptionInfo
14674      *exception;
14675
14676    HV
14677      *hv;
14678
14679    Image
14680      *image;
14681
14682    register ssize_t
14683      i;
14684
14685    ssize_t
14686      offset,
14687      stack;
14688
14689    struct PackageInfo
14690      *info;
14691
14692    SV
14693      *av_reference,
14694      *perl_exception,
14695      *reference,
14696      *rv,
14697      *sv;
14698
14699    PERL_UNUSED_VAR(ref);
14700    PERL_UNUSED_VAR(ix);
14701    exception=AcquireExceptionInfo();
14702    perl_exception=newSVpv("",0);
14703    sv=NULL;
14704    attribute=NULL;
14705    av=NULL;
14706    if (sv_isobject(ST(0)) == 0)
14707      {
14708        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14709          PackageName);
14710        goto PerlException;
14711      }
14712    reference=SvRV(ST(0));
14713    hv=SvSTASH(reference);
14714    av=newAV();
14715    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14716    SvREFCNT_dec(av);
14717    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14718    if (image == (Image *) NULL)
14719      {
14720        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14721          PackageName);
14722        goto PerlException;
14723      }
14724    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14725    /*
14726      Get options.
14727    */
14728    offset=0;
14729    stack=MagickTrue;
14730    for (i=2; i < items; i+=2)
14731    {
14732      attribute=(char *) SvPV(ST(i-1),na);
14733      switch (*attribute)
14734      {
14735        case 'O':
14736        case 'o':
14737        {
14738          if (LocaleCompare(attribute,"offset") == 0)
14739            {
14740              offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14741              break;
14742            }
14743          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14744            attribute);
14745          break;
14746        }
14747        case 'S':
14748        case 's':
14749        {
14750          if (LocaleCompare(attribute,"stack") == 0)
14751            {
14752              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14753                SvPV(ST(i),na));
14754              if (stack < 0)
14755                {
14756                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14757                    SvPV(ST(i),na));
14758                  return;
14759                }
14760              break;
14761            }
14762          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14763            attribute);
14764          break;
14765        }
14766        default:
14767        {
14768          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14769            attribute);
14770          break;
14771        }
14772      }
14773    }
14774    image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14775      exception);
14776    if (image == (Image *) NULL)
14777      goto PerlException;
14778    for ( ; image; image=image->next)
14779    {
14780      AddImageToRegistry(sv,image);
14781      rv=newRV(sv);
14782      av_push(av,sv_bless(rv,hv));
14783      SvREFCNT_dec(sv);
14784    }
14785    exception=DestroyExceptionInfo(exception);
14786    ST(0)=av_reference;
14787    SvREFCNT_dec(perl_exception);
14788    XSRETURN(1);
14789
14790  PerlException:
14791    InheritPerlException(exception,perl_exception);
14792    exception=DestroyExceptionInfo(exception);
14793    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14794    SvPOK_on(perl_exception);
14795    ST(0)=sv_2mortal(perl_exception);
14796    XSRETURN(1);
14797  }
14798
14799#
14800###############################################################################
14801#                                                                             #
14802#                                                                             #
14803#                                                                             #
14804#   S t a t i s t i c s                                                       #
14805#                                                                             #
14806#                                                                             #
14807#                                                                             #
14808###############################################################################
14809#
14810#
14811void
14812Statistics(ref)
14813  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14814  ALIAS:
14815    StatisticsImage = 1
14816    statistics      = 2
14817    statisticsimage = 3
14818  PPCODE:
14819  {
14820#define ChannelStatistics(channel) \
14821{ \
14822  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14823    (double) channel_statistics[channel].depth); \
14824  PUSHs(sv_2mortal(newSVpv(message,0))); \
14825  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14826    channel_statistics[channel].minima/QuantumRange); \
14827  PUSHs(sv_2mortal(newSVpv(message,0))); \
14828  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14829    channel_statistics[channel].maxima/QuantumRange); \
14830  PUSHs(sv_2mortal(newSVpv(message,0))); \
14831  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14832    channel_statistics[channel].mean/QuantumRange); \
14833  PUSHs(sv_2mortal(newSVpv(message,0))); \
14834  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14835    channel_statistics[channel].standard_deviation/QuantumRange); \
14836  PUSHs(sv_2mortal(newSVpv(message,0))); \
14837  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14838    channel_statistics[channel].kurtosis); \
14839  PUSHs(sv_2mortal(newSVpv(message,0))); \
14840  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14841    channel_statistics[channel].skewness); \
14842  PUSHs(sv_2mortal(newSVpv(message,0))); \
14843  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14844    channel_statistics[channel].entropy); \
14845  PUSHs(sv_2mortal(newSVpv(message,0))); \
14846}
14847
14848    AV
14849      *av;
14850
14851    char
14852      message[MagickPathExtent];
14853
14854    ChannelStatistics
14855      *channel_statistics;
14856
14857    ExceptionInfo
14858      *exception;
14859
14860    Image
14861      *image;
14862
14863    ssize_t
14864      count;
14865
14866    struct PackageInfo
14867      *info;
14868
14869    SV
14870      *perl_exception,
14871      *reference;
14872
14873    PERL_UNUSED_VAR(ref);
14874    PERL_UNUSED_VAR(ix);
14875    exception=AcquireExceptionInfo();
14876    perl_exception=newSVpv("",0);
14877    av=NULL;
14878    if (sv_isobject(ST(0)) == 0)
14879      {
14880        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14881          PackageName);
14882        goto PerlException;
14883      }
14884    reference=SvRV(ST(0));
14885    av=newAV();
14886    SvREFCNT_dec(av);
14887    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14888    if (image == (Image *) NULL)
14889      {
14890        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14891          PackageName);
14892        goto PerlException;
14893      }
14894    count=0;
14895    for ( ; image; image=image->next)
14896    {
14897      register size_t
14898        i;
14899
14900      channel_statistics=GetImageStatistics(image,exception);
14901      if (channel_statistics == (ChannelStatistics *) NULL)
14902        continue;
14903      count++;
14904      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14905      {
14906        PixelChannel channel=GetPixelChannelChannel(image,i);
14907        PixelTrait traits=GetPixelChannelTraits(image,channel);
14908        if (traits == UndefinedPixelTrait)
14909          continue;
14910        EXTEND(sp,8*(i+1)*count);
14911        ChannelStatistics(channel);
14912      }
14913      EXTEND(sp,8*(i+1)*count);
14914      ChannelStatistics(CompositePixelChannel);
14915      channel_statistics=(ChannelStatistics *)
14916        RelinquishMagickMemory(channel_statistics);
14917    }
14918
14919  PerlException:
14920    InheritPerlException(exception,perl_exception);
14921    exception=DestroyExceptionInfo(exception);
14922    SvREFCNT_dec(perl_exception);
14923  }
14924
14925#
14926###############################################################################
14927#                                                                             #
14928#                                                                             #
14929#                                                                             #
14930#   S y n c A u t h e n t i c P i x e l s                                     #
14931#                                                                             #
14932#                                                                             #
14933#                                                                             #
14934###############################################################################
14935#
14936#
14937void
14938SyncAuthenticPixels(ref,...)
14939  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14940  ALIAS:
14941    Syncauthenticpixels = 1
14942    SyncImagePixels = 2
14943    syncimagepixels = 3
14944  CODE:
14945  {
14946    ExceptionInfo
14947      *exception;
14948
14949    Image
14950      *image;
14951
14952    MagickBooleanType
14953      status;
14954
14955    struct PackageInfo
14956      *info;
14957
14958    SV
14959      *perl_exception,
14960      *reference;
14961
14962    PERL_UNUSED_VAR(ref);
14963    PERL_UNUSED_VAR(ix);
14964    exception=AcquireExceptionInfo();
14965    perl_exception=newSVpv("",0);
14966    if (sv_isobject(ST(0)) == 0)
14967      {
14968        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14969          PackageName);
14970        goto PerlException;
14971      }
14972
14973    reference=SvRV(ST(0));
14974    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14975    if (image == (Image *) NULL)
14976      {
14977        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14978          PackageName);
14979        goto PerlException;
14980      }
14981
14982    status=SyncAuthenticPixels(image,exception);
14983    if (status != MagickFalse)
14984      return;
14985
14986  PerlException:
14987    InheritPerlException(exception,perl_exception);
14988    exception=DestroyExceptionInfo(exception);
14989    SvREFCNT_dec(perl_exception);  /* throw away all errors */
14990  }
14991
14992
14993#
14994###############################################################################
14995#                                                                             #
14996#                                                                             #
14997#                                                                             #
14998#   W r i t e                                                                 #
14999#                                                                             #
15000#                                                                             #
15001#                                                                             #
15002###############################################################################
15003#
15004#
15005void
15006Write(ref,...)
15007  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
15008  ALIAS:
15009    WriteImage    = 1
15010    write         = 2
15011    writeimage    = 3
15012  PPCODE:
15013  {
15014    char
15015      filename[MagickPathExtent];
15016
15017    ExceptionInfo
15018      *exception;
15019
15020    Image
15021      *image,
15022      *next;
15023
15024    register ssize_t
15025      i;
15026
15027    ssize_t
15028      number_images,
15029      scene;
15030
15031    struct PackageInfo
15032      *info,
15033      *package_info;
15034
15035    SV
15036      *perl_exception,
15037      *reference;
15038
15039    PERL_UNUSED_VAR(ref);
15040    PERL_UNUSED_VAR(ix);
15041    exception=AcquireExceptionInfo();
15042    perl_exception=newSVpv("",0);
15043    number_images=0;
15044    package_info=(struct PackageInfo *) NULL;
15045    if (sv_isobject(ST(0)) == 0)
15046      {
15047        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
15048          PackageName);
15049        goto PerlException;
15050      }
15051    reference=SvRV(ST(0));
15052    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
15053    if (image == (Image *) NULL)
15054      {
15055        ThrowPerlException(exception,OptionError,"NoImagesDefined",
15056          PackageName);
15057        goto PerlException;
15058      }
15059    scene=0;
15060    for (next=image; next; next=next->next)
15061      next->scene=scene++;
15062    package_info=ClonePackageInfo(info,exception);
15063    if (items == 2)
15064      SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
15065    else
15066      if (items > 2)
15067        for (i=2; i < items; i+=2)
15068          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
15069            exception);
15070    (void) CopyMagickString(filename,package_info->image_info->filename,
15071      MagickPathExtent);
15072    for (next=image; next; next=next->next)
15073      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
15074    *package_info->image_info->magick='\0';
15075    SetImageInfo(package_info->image_info,(unsigned int)
15076      GetImageListLength(image),exception);
15077    for (next=image; next; next=next->next)
15078    {
15079      (void) WriteImage(package_info->image_info,next,exception);
15080      number_images++;
15081      if (package_info->image_info->adjoin)
15082        break;
15083    }
15084
15085  PerlException:
15086    if (package_info != (struct PackageInfo *) NULL)
15087      DestroyPackageInfo(package_info);
15088    InheritPerlException(exception,perl_exception);
15089    exception=DestroyExceptionInfo(exception);
15090    sv_setiv(perl_exception,(IV) number_images);
15091    SvPOK_on(perl_exception);
15092    ST(0)=sv_2mortal(perl_exception);
15093    XSRETURN(1);
15094  }
15095