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-2016 ImageMagick Studio LLC, a non-profit organization      %
27%  dedicated to making software imaging solutions freely available.           %
28%                                                                             %
29%  You may not use this file except in compliance with the License.  You may  %
30%  obtain a copy of the License at                                            %
31%                                                                             %
32%    http://www.imagemagick.org/script/license.php                            %
33%                                                                             %
34%  Unless required by applicable law or agreed to in writing, software        %
35%  distributed under the License is distributed on an "AS IS" BASIS,          %
36%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37%  See the License for the specific language governing permissions and        %
38%  limitations under the License.                                             %
39%                                                                             %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42%  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43%  the module to read, manipulate, or write an image or image sequence from
44%  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45%
46*/
47
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  33
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  ArrayReference = (~0),
146  RealReference = (~0)-1,
147  FileReference = (~0)-2,
148  ImageReference = (~0)-3,
149  IntegerReference = (~0)-4,
150  StringReference = (~0)-5
151} MagickReference;
152
153typedef struct _Arguments
154{
155  const char
156    *method;
157
158  ssize_t
159    type;
160} Arguments;
161
162struct ArgumentList
163{
164  ssize_t
165    integer_reference;
166
167  double
168    real_reference;
169
170  const char
171    *string_reference;
172
173  Image
174    *image_reference;
175
176  SV
177    *array_reference;
178
179  FILE
180    *file_reference;
181
182  size_t
183    length;
184};
185
186struct PackageInfo
187{
188  ImageInfo
189    *image_info;
190};
191
192typedef void
193  *Image__Magick__@MAGICK_ABI_SUFFIX@;  /* data type for the Image::Magick::@MAGICK_ABI_NAME@ package */
194
195/*
196  Static declarations.
197*/
198static struct
199  Methods
200  {
201    const char
202      *name;
203
204    Arguments
205      arguments[MaxArguments];
206  } Methods[] =
207  {
208    { "Comment", { {"comment", StringReference} } },
209    { "Label", { {"label", StringReference} } },
210    { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211      {"channel", MagickChannelOptions} } },
212    { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213    { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214      {"height", IntegerReference}, {"fill", StringReference},
215      {"bordercolor", StringReference}, {"color", StringReference},
216      {"compose", MagickComposeOptions} } },
217    { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219    { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220      {"height", IntegerReference}, {"x", IntegerReference},
221      {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222    { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223      {"height", IntegerReference}, {"x", IntegerReference},
224      {"y", IntegerReference}, {"fuzz", StringReference},
225      {"gravity", MagickGravityOptions} } },
226    { "Despeckle", },
227    { "Edge", { {"radius", RealReference} } },
228    { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229      {"sigma", RealReference} } },
230    { "Enhance", },
231    { "Flip", },
232    { "Flop", },
233    { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234      {"height", IntegerReference}, {"inner", IntegerReference},
235      {"outer", IntegerReference}, {"fill", StringReference},
236      {"color", StringReference}, {"compose", MagickComposeOptions} } },
237    { "Implode", { {"amount", RealReference},
238      {"interpolate", MagickInterpolateOptions} } },
239    { "Magnify", },
240    { "MedianFilter", { {"geometry", StringReference},
241      {"width", IntegerReference}, {"height", IntegerReference},
242      {"channel", MagickChannelOptions} } },
243    { "Minify", },
244    { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245    { "ReduceNoise", { {"geometry", StringReference},
246      {"width", IntegerReference},{"height", IntegerReference},
247      {"channel", MagickChannelOptions} } },
248    { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249      {"y", IntegerReference} } },
250    { "Rotate", { {"degrees", RealReference},
251      {"background", StringReference} } },
252    { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253      {"height", IntegerReference} } },
254    { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255      {"height", IntegerReference} } },
256    { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257      {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258    { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260    { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261      {"y", RealReference}, { "fill", StringReference},
262      {"color", StringReference} } },
263    { "Spread", { {"radius", RealReference},
264      {"interpolate", MagickInterpolateOptions} } },
265    { "Swirl", { {"degrees", RealReference},
266      {"interpolate", MagickInterpolateOptions} } },
267    { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268      {"height", IntegerReference}, {"filter", MagickFilterOptions},
269      {"support", StringReference } } },
270    { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271      {"height", IntegerReference}, {"filter", MagickFilterOptions},
272      {"support", RealReference } } },
273    { "Annotate", { {"text", StringReference}, {"font", StringReference},
274      {"pointsize", RealReference}, {"density", StringReference},
275      {"undercolor", StringReference}, {"stroke", StringReference},
276      {"fill", StringReference}, {"geometry", StringReference},
277      {"sans", StringReference}, {"x", RealReference},
278      {"y", RealReference}, {"gravity", MagickGravityOptions},
279      {"translate", StringReference}, {"scale", StringReference},
280      {"rotate", RealReference}, {"skewX", RealReference},
281      {"skewY", RealReference}, {"strokewidth", RealReference},
282      {"antialias", MagickBooleanOptions}, {"family", StringReference},
283      {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284      {"weight", IntegerReference}, {"align", MagickAlignOptions},
285      {"encoding", StringReference}, {"affine", ArrayReference},
286      {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287      {"tile", ImageReference}, {"kerning", RealReference},
288      {"interline-spacing", RealReference},
289      {"interword-spacing", RealReference},
290      {"direction", MagickDirectionOptions} } },
291    { "ColorFloodfill", { {"geometry", StringReference},
292      {"x", IntegerReference}, {"y", IntegerReference},
293      {"fill", StringReference}, {"bordercolor", StringReference},
294      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295    { "Composite", { {"image", ImageReference},
296      {"compose", MagickComposeOptions}, {"geometry", StringReference},
297      {"x", IntegerReference}, {"y", IntegerReference},
298      {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299      {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300      {"color", StringReference}, {"mask", ImageReference},
301      {"channel", MagickChannelOptions},
302      {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303      {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304    { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305    { "CycleColormap", { {"display", IntegerReference} } },
306    { "Draw", { {"primitive", MagickPrimitiveOptions},
307      {"points", StringReference}, {"method", MagickMethodOptions},
308      {"stroke", StringReference}, {"fill", StringReference},
309      {"strokewidth", RealReference}, {"font", StringReference},
310      {"bordercolor", StringReference}, {"x", RealReference},
311      {"y", RealReference}, {"translate", StringReference},
312      {"scale", StringReference}, {"rotate", RealReference},
313      {"skewX", RealReference}, {"skewY", RealReference},
314      {"tile", ImageReference}, {"pointsize", RealReference},
315      {"antialias", MagickBooleanOptions}, {"density", StringReference},
316      {"linewidth", RealReference}, {"affine", ArrayReference},
317      {"stroke-dashoffset", RealReference},
318      {"stroke-dasharray", ArrayReference},
319      {"interpolate", MagickInterpolateOptions},
320      {"origin", StringReference}, {"text", StringReference},
321      {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322      {"vector-graphics", StringReference}, {"kerning", RealReference},
323      {"interline-spacing", RealReference},
324      {"interword-spacing", RealReference},
325      {"direction", MagickDirectionOptions} } },
326    { "Equalize", { {"channel", MagickChannelOptions} } },
327    { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328      {"red", RealReference}, {"green", RealReference},
329      {"blue", RealReference} } },
330    { "Map", { {"image", ImageReference},
331      {"dither-method", MagickDitherOptions} } },
332    { "MatteFloodfill", { {"geometry", StringReference},
333      {"x", IntegerReference}, {"y", IntegerReference},
334      {"opacity", StringReference}, {"bordercolor", StringReference},
335      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336    { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337      {"saturation", RealReference}, {"whiteness", RealReference},
338      {"brightness", RealReference}, {"lightness", RealReference},
339      {"blackness", RealReference} } },
340    { "Negate", { {"gray", MagickBooleanOptions},
341      {"channel", MagickChannelOptions} } },
342    { "Normalize", { {"channel", MagickChannelOptions} } },
343    { "NumberColors", },
344    { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346      {"invert", MagickBooleanOptions} } },
347    { "Quantize", { {"colors", IntegerReference},
348      {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349      {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350      {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351      {"dither-method", MagickDitherOptions} } },
352    { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353      {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354    { "Segment", { {"geometry", StringReference},
355      {"cluster-threshold", RealReference},
356      {"smoothing-threshold", RealReference},
357      {"colorspace", MagickColorspaceOptions},
358      {"verbose", MagickBooleanOptions} } },
359    { "Signature", },
360    { "Solarize", { {"geometry", StringReference},
361      {"threshold", StringReference} } },
362    { "Sync", },
363    { "Texture", { {"texture", ImageReference} } },
364    { "Evaluate", { {"value", RealReference},
365      {"operator", MagickEvaluateOptions},
366      {"channel", MagickChannelOptions} } },
367    { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369    { "Threshold", { {"threshold", StringReference},
370      {"channel", MagickChannelOptions} } },
371    { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372      {"sigma", RealReference} } },
373    { "Trim", { {"fuzz", StringReference} } },
374    { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375      {"wavelength", RealReference},
376      {"interpolate", MagickInterpolateOptions} } },
377    { "Separate", { {"channel", MagickChannelOptions} } },
378    { "Condense", },
379    { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380      {"y", IntegerReference} } },
381    { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382    { "Deconstruct", },
383    { "GaussianBlur", { {"geometry", StringReference},
384      {"radius", RealReference}, {"sigma", RealReference},
385      {"channel", MagickChannelOptions} } },
386    { "Convolve", { {"coefficients", ArrayReference},
387      {"channel", MagickChannelOptions}, {"bias", StringReference},
388      {"kernel", StringReference} } },
389    { "Profile", { {"name", StringReference}, {"profile", StringReference},
390      { "rendering-intent", MagickIntentOptions},
391      { "black-point-compensation", MagickBooleanOptions} } },
392    { "UnsharpMask", { {"geometry", StringReference},
393      {"radius", RealReference}, {"sigma", RealReference},
394      {"gain", RealReference}, {"threshold", RealReference},
395      {"channel", MagickChannelOptions} } },
396    { "MotionBlur", { {"geometry", StringReference},
397      {"radius", RealReference}, {"sigma", RealReference},
398      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399    { "OrderedDither", { {"threshold", StringReference},
400      {"channel", MagickChannelOptions} } },
401    { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402      {"height", IntegerReference} } },
403    { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404      {"white-point", RealReference}, {"gamma", RealReference},
405      {"channel", MagickChannelOptions}, {"level", StringReference} } },
406    { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407    { "AffineTransform", { {"affine", ArrayReference},
408      {"translate", StringReference}, {"scale", StringReference},
409      {"rotate", RealReference}, {"skewX", RealReference},
410      {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411      {"background", StringReference} } },
412    { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413    { "AdaptiveThreshold", { {"geometry", StringReference},
414      {"width", IntegerReference}, {"height", IntegerReference} } },
415    { "Resample", { {"density", StringReference}, {"x", RealReference},
416      {"y", RealReference}, {"filter", MagickFilterOptions},
417      {"support", RealReference } } },
418    { "Describe", { {"file", FileReference} } },
419    { "BlackThreshold", { {"threshold", StringReference},
420      {"channel", MagickChannelOptions} } },
421    { "WhiteThreshold", { {"threshold", StringReference},
422      {"channel", MagickChannelOptions} } },
423    { "RotationalBlur", { {"geometry", StringReference},
424      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425    { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426      {"height", IntegerReference} } },
427    { "Strip", },
428    { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429    { "Channel", { {"channel", MagickChannelOptions} } },
430    { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431      {"height", IntegerReference}, {"x", IntegerReference},
432      {"y", IntegerReference}, {"fuzz", StringReference},
433      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434    { "Posterize", { {"levels", IntegerReference},
435      {"dither", MagickBooleanOptions} } },
436    { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437      {"sigma", RealReference}, {"x", IntegerReference},
438      {"y", IntegerReference} } },
439    { "Identify", { {"file", FileReference}, {"features", StringReference},
440      {"unique", MagickBooleanOptions} } },
441    { "SepiaTone", { {"threshold", RealReference} } },
442    { "SigmoidalContrast", { {"geometry", StringReference},
443      {"contrast", RealReference}, {"mid-point", RealReference},
444      {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445    { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446      {"height", IntegerReference}, {"x", IntegerReference},
447      {"y", IntegerReference}, {"fuzz", StringReference},
448      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449    { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450      {"sigma", RealReference}, {"x", IntegerReference},
451      {"y", IntegerReference}, {"background", StringReference} } },
452    { "ContrastStretch", { {"levels", StringReference},
453      {"black-point", RealReference},{"white-point", RealReference},
454      {"channel", MagickChannelOptions} } },
455    { "Sans0", },
456    { "Sans1", },
457    { "AdaptiveSharpen", { {"geometry", StringReference},
458      {"radius", RealReference}, {"sigma", RealReference},
459      {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460    { "Transpose", },
461    { "Transverse", },
462    { "AutoOrient", },
463    { "AdaptiveBlur", { {"geometry", StringReference},
464      {"radius", RealReference}, {"sigma", RealReference},
465      {"channel", MagickChannelOptions} } },
466    { "Sketch", { {"geometry", StringReference},
467      {"radius", RealReference}, {"sigma", RealReference},
468      {"angle", RealReference} } },
469    { "UniqueColors", },
470    { "AdaptiveResize", { {"geometry", StringReference},
471      {"width", IntegerReference}, {"height", IntegerReference},
472      {"filter", MagickFilterOptions}, {"support", StringReference },
473      {"blur", RealReference } } },
474    { "ClipMask", { {"mask", ImageReference} } },
475    { "LinearStretch", { {"levels", StringReference},
476      {"black-point", RealReference},{"white-point", RealReference} } },
477    { "ColorMatrix", { {"matrix", ArrayReference} } },
478    { "Mask", { {"mask", ImageReference} } },
479    { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480      {"font", StringReference}, {"stroke", StringReference},
481      {"fill", StringReference}, {"strokewidth", RealReference},
482      {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483      {"background", StringReference},
484      {"interpolate", MagickInterpolateOptions} } },
485    { "FloodfillPaint", { {"geometry", StringReference},
486      {"x", IntegerReference}, {"y", IntegerReference},
487      {"fill", StringReference}, {"bordercolor", StringReference},
488      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489      {"invert", MagickBooleanOptions} } },
490    { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491      {"virtual-pixel", MagickVirtualPixelOptions},
492      {"best-fit", MagickBooleanOptions} } },
493    { "Clut", { {"image", ImageReference},
494      {"interpolate", MagickInterpolateOptions},
495      {"channel", MagickChannelOptions} } },
496    { "LiquidRescale", { {"geometry", StringReference},
497      {"width", IntegerReference}, {"height", IntegerReference},
498      {"delta-x", RealReference}, {"rigidity", RealReference } } },
499    { "Encipher", { {"passphrase", StringReference} } },
500    { "Decipher", { {"passphrase", StringReference} } },
501    { "Deskew", { {"geometry", StringReference},
502      {"threshold", StringReference} } },
503    { "Remap", { {"image", ImageReference},
504      {"dither-method", MagickDitherOptions} } },
505    { "SparseColor", { {"points", ArrayReference},
506      {"method", MagickSparseColorOptions},
507      {"virtual-pixel", MagickVirtualPixelOptions},
508      {"channel", MagickChannelOptions} } },
509    { "Function", { {"parameters", ArrayReference},
510      {"function", MagickFunctionOptions},
511      {"virtual-pixel", MagickVirtualPixelOptions} } },
512    { "SelectiveBlur", { {"geometry", StringReference},
513      {"radius", RealReference}, {"sigma", RealReference},
514      {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515    { "HaldClut", { {"image", ImageReference},
516      {"channel", MagickChannelOptions} } },
517    { "BlueShift", { {"factor", StringReference} } },
518    { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519    { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520    { "ColorDecisionList", {
521      {"color-correction-collection", StringReference} } },
522    { "AutoGamma", { {"channel", MagickChannelOptions} } },
523    { "AutoLevel", { {"channel", MagickChannelOptions} } },
524    { "LevelColors", { {"invert", MagickBooleanOptions},
525      {"black-point", StringReference}, {"white-point", StringReference},
526      {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527    { "Clamp", { {"channel", MagickChannelOptions} } },
528    { "BrightnessContrast", { {"levels", StringReference},
529      {"brightness", RealReference},{"contrast", RealReference},
530      {"channel", MagickChannelOptions} } },
531    { "Morphology", { {"kernel", StringReference},
532      {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533      {"iterations", IntegerReference} } },
534    { "Mode", { {"geometry", StringReference},
535      {"width", IntegerReference},{"height", IntegerReference},
536      {"channel", MagickChannelOptions} } },
537    { "Statistic", { {"geometry", StringReference},
538      {"width", IntegerReference},{"height", IntegerReference},
539      {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
540    { "Perceptible", { {"epsilon", RealReference},
541      {"channel", MagickChannelOptions} } },
542    { "Poly", { {"terms", ArrayReference},
543      {"channel", MagickChannelOptions} } },
544    { "Grayscale", { {"method", MagickNoiseOptions} } },
545    { "CannyEdge", { {"geometry", StringReference},
546      {"radius", RealReference}, {"sigma", RealReference},
547      {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
548    { "HoughLine", { {"geometry", StringReference},
549      {"width", IntegerReference}, {"height", IntegerReference},
550      {"threshold", IntegerReference} } },
551    { "MeanShift", { {"geometry", StringReference},
552      {"width", IntegerReference}, {"height", IntegerReference},
553      {"distance", RealReference} } },
554    { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
555      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
556    { "ConnectedComponents", { {"connectivity", IntegerReference} } },
557    { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
558      {"width", IntegerReference}, {"height", IntegerReference},
559      {"x", IntegerReference}, {"y", IntegerReference},
560      {"gravity", MagickGravityOptions}, {"offset", StringReference},
561      {"dx", IntegerReference}, {"dy", IntegerReference} } },
562    { "Color", { {"color", StringReference} } },
563    { "WaveletDenoise", {  {"geometry", StringReference},
564      {"threshold", RealReference}, {"softness", RealReference},
565      {"channel", MagickChannelOptions} } },
566  };
567
568static SplayTreeInfo
569  *magick_registry = (SplayTreeInfo *) NULL;
570
571/*
572  Forward declarations.
573*/
574static Image
575  *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
576
577static ssize_t
578  strEQcase(const char *,const char *);
579
580/*
581%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582%                                                                             %
583%                                                                             %
584%                                                                             %
585%   C l o n e P a c k a g e I n f o                                           %
586%                                                                             %
587%                                                                             %
588%                                                                             %
589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590%
591%  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
592%  a new one.
593%
594%  The format of the ClonePackageInfo routine is:
595%
596%      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
597%        exception)
598%
599%  A description of each parameter follows:
600%
601%    o info: a structure of type info.
602%
603%    o exception: Return any errors or warnings in this structure.
604%
605*/
606static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
607  ExceptionInfo *exception)
608{
609  struct PackageInfo
610    *clone_info;
611
612  clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
613  if (clone_info == (struct PackageInfo *) NULL)
614    {
615      ThrowPerlException(exception,ResourceLimitError,
616        "UnableToClonePackageInfo",PackageName);
617      return((struct PackageInfo *) NULL);
618    }
619  if (info == (struct PackageInfo *) NULL)
620    {
621      clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
622      return(clone_info);
623    }
624  *clone_info=(*info);
625  clone_info->image_info=CloneImageInfo(info->image_info);
626  return(clone_info);
627}
628
629/*
630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631%                                                                             %
632%                                                                             %
633%                                                                             %
634%   c o n s t a n t                                                           %
635%                                                                             %
636%                                                                             %
637%                                                                             %
638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639%
640%  constant() returns a double value for the specified name.
641%
642%  The format of the constant routine is:
643%
644%      double constant(char *name,ssize_t sans)
645%
646%  A description of each parameter follows:
647%
648%    o value: Method constant returns a double value for the specified name.
649%
650%    o name: The name of the constant.
651%
652%    o sans: This integer value is not used.
653%
654*/
655static double constant(char *name,ssize_t sans)
656{
657  (void) sans;
658  errno=0;
659  switch (*name)
660  {
661    case 'B':
662    {
663      if (strEQ(name,"BlobError"))
664        return(BlobError);
665      if (strEQ(name,"BlobWarning"))
666        return(BlobWarning);
667      break;
668    }
669    case 'C':
670    {
671      if (strEQ(name,"CacheError"))
672        return(CacheError);
673      if (strEQ(name,"CacheWarning"))
674        return(CacheWarning);
675      if (strEQ(name,"CoderError"))
676        return(CoderError);
677      if (strEQ(name,"CoderWarning"))
678        return(CoderWarning);
679      if (strEQ(name,"ConfigureError"))
680        return(ConfigureError);
681      if (strEQ(name,"ConfigureWarning"))
682        return(ConfigureWarning);
683      if (strEQ(name,"CorruptImageError"))
684        return(CorruptImageError);
685      if (strEQ(name,"CorruptImageWarning"))
686        return(CorruptImageWarning);
687      break;
688    }
689    case 'D':
690    {
691      if (strEQ(name,"DelegateError"))
692        return(DelegateError);
693      if (strEQ(name,"DelegateWarning"))
694        return(DelegateWarning);
695      if (strEQ(name,"DrawError"))
696        return(DrawError);
697      if (strEQ(name,"DrawWarning"))
698        return(DrawWarning);
699      break;
700    }
701    case 'E':
702    {
703      if (strEQ(name,"ErrorException"))
704        return(ErrorException);
705      if (strEQ(name,"ExceptionError"))
706        return(CoderError);
707      if (strEQ(name,"ExceptionWarning"))
708        return(CoderWarning);
709      break;
710    }
711    case 'F':
712    {
713      if (strEQ(name,"FatalErrorException"))
714        return(FatalErrorException);
715      if (strEQ(name,"FileOpenError"))
716        return(FileOpenError);
717      if (strEQ(name,"FileOpenWarning"))
718        return(FileOpenWarning);
719      break;
720    }
721    case 'I':
722    {
723      if (strEQ(name,"ImageError"))
724        return(ImageError);
725      if (strEQ(name,"ImageWarning"))
726        return(ImageWarning);
727      break;
728    }
729    case 'M':
730    {
731      if (strEQ(name,"MaxRGB"))
732        return(QuantumRange);
733      if (strEQ(name,"MissingDelegateError"))
734        return(MissingDelegateError);
735      if (strEQ(name,"MissingDelegateWarning"))
736        return(MissingDelegateWarning);
737      if (strEQ(name,"ModuleError"))
738        return(ModuleError);
739      if (strEQ(name,"ModuleWarning"))
740        return(ModuleWarning);
741      break;
742    }
743    case 'O':
744    {
745      if (strEQ(name,"Opaque"))
746        return(OpaqueAlpha);
747      if (strEQ(name,"OptionError"))
748        return(OptionError);
749      if (strEQ(name,"OptionWarning"))
750        return(OptionWarning);
751      break;
752    }
753    case 'Q':
754    {
755      if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
756        return(MAGICKCORE_QUANTUM_DEPTH);
757      if (strEQ(name,"QuantumDepth"))
758        return(MAGICKCORE_QUANTUM_DEPTH);
759      if (strEQ(name,"QuantumRange"))
760        return(QuantumRange);
761      break;
762    }
763    case 'R':
764    {
765      if (strEQ(name,"ResourceLimitError"))
766        return(ResourceLimitError);
767      if (strEQ(name,"ResourceLimitWarning"))
768        return(ResourceLimitWarning);
769      if (strEQ(name,"RegistryError"))
770        return(RegistryError);
771      if (strEQ(name,"RegistryWarning"))
772        return(RegistryWarning);
773      break;
774    }
775    case 'S':
776    {
777      if (strEQ(name,"StreamError"))
778        return(StreamError);
779      if (strEQ(name,"StreamWarning"))
780        return(StreamWarning);
781      if (strEQ(name,"Success"))
782        return(0);
783      break;
784    }
785    case 'T':
786    {
787      if (strEQ(name,"Transparent"))
788        return(TransparentAlpha);
789      if (strEQ(name,"TypeError"))
790        return(TypeError);
791      if (strEQ(name,"TypeWarning"))
792        return(TypeWarning);
793      break;
794    }
795    case 'W':
796    {
797      if (strEQ(name,"WarningException"))
798        return(WarningException);
799      break;
800    }
801    case 'X':
802    {
803      if (strEQ(name,"XServerError"))
804        return(XServerError);
805      if (strEQ(name,"XServerWarning"))
806        return(XServerWarning);
807      break;
808    }
809  }
810  errno=EINVAL;
811  return(0);
812}
813
814/*
815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816%                                                                             %
817%                                                                             %
818%                                                                             %
819%   D e s t r o y P a c k a g e I n f o                                       %
820%                                                                             %
821%                                                                             %
822%                                                                             %
823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824%
825%  Method DestroyPackageInfo frees a previously created info structure.
826%
827%  The format of the DestroyPackageInfo routine is:
828%
829%      DestroyPackageInfo(struct PackageInfo *info)
830%
831%  A description of each parameter follows:
832%
833%    o info: a structure of type info.
834%
835*/
836static void DestroyPackageInfo(struct PackageInfo *info)
837{
838  info->image_info=DestroyImageInfo(info->image_info);
839  info=(struct PackageInfo *) RelinquishMagickMemory(info);
840}
841
842/*
843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844%                                                                             %
845%                                                                             %
846%                                                                             %
847%   G e t L i s t                                                             %
848%                                                                             %
849%                                                                             %
850%                                                                             %
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852%
853%  Method GetList is recursively called by SetupList to traverse the
854%  Image__Magick reference.  If building an reference_vector (see SetupList),
855%  *current is the current position in *reference_vector and *last is the final
856%  entry in *reference_vector.
857%
858%  The format of the GetList routine is:
859%
860%      GetList(info)
861%
862%  A description of each parameter follows:
863%
864%    o info: a structure of type info.
865%
866*/
867static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
868  ssize_t *current,ssize_t *last,ExceptionInfo *exception)
869{
870  Image
871    *image;
872
873  if (reference == (SV *) NULL)
874    return(NULL);
875  switch (SvTYPE(reference))
876  {
877    case SVt_PVAV:
878    {
879      AV
880        *av;
881
882      Image
883        *head,
884        *previous;
885
886      register ssize_t
887        i;
888
889      ssize_t
890        n;
891
892      /*
893        Array of images.
894      */
895      previous=(Image *) NULL;
896      head=(Image *) NULL;
897      av=(AV *) reference;
898      n=av_len(av);
899      for (i=0; i <= n; i++)
900      {
901        SV
902          **rv;
903
904        rv=av_fetch(av,i,0);
905        if (rv && *rv && sv_isobject(*rv))
906          {
907            image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
908              exception);
909            if (image == (Image *) NULL)
910              continue;
911            if (image == previous)
912              {
913                image=CloneImage(image,0,0,MagickTrue,exception);
914                if (image == (Image *) NULL)
915                  return(NULL);
916              }
917            image->previous=previous;
918            *(previous ? &previous->next : &head)=image;
919            for (previous=image; previous->next; previous=previous->next) ;
920          }
921      }
922      return(head);
923    }
924    case SVt_PVMG:
925    {
926      /*
927        Blessed scalar, one image.
928      */
929      image=INT2PTR(Image *,SvIV(reference));
930      if (image == (Image *) NULL)
931        return(NULL);
932      image->previous=(Image *) NULL;
933      image->next=(Image *) NULL;
934      if (reference_vector)
935        {
936          if (*current == *last)
937            {
938              *last+=256;
939              if (*reference_vector == (SV **) NULL)
940                *reference_vector=(SV **) AcquireQuantumMemory(*last,
941                  sizeof(*reference_vector));
942              else
943                *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
944                  *last,sizeof(*reference_vector));
945            }
946          if (*reference_vector == (SV **) NULL)
947            {
948              ThrowPerlException(exception,ResourceLimitError,
949                "MemoryAllocationFailed",PackageName);
950              return((Image *) NULL);
951            }
952          (*reference_vector)[*current]=reference;
953          (*reference_vector)[++(*current)]=NULL;
954        }
955      return(image);
956    }
957    default:
958      break;
959  }
960  (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
961    (double) SvTYPE(reference));
962  return((Image *) NULL);
963}
964
965/*
966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
967%                                                                             %
968%                                                                             %
969%                                                                             %
970%   G e t P a c k a g e I n f o                                               %
971%                                                                             %
972%                                                                             %
973%                                                                             %
974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975%
976%  Method GetPackageInfo looks up or creates an info structure for the given
977%  Image__Magick reference.  If it does create a new one, the information in
978%  package_info is used to initialize it.
979%
980%  The format of the GetPackageInfo routine is:
981%
982%      struct PackageInfo *GetPackageInfo(void *reference,
983%        struct PackageInfo *package_info,ExceptionInfo *exception)
984%
985%  A description of each parameter follows:
986%
987%    o info: a structure of type info.
988%
989%    o exception: Return any errors or warnings in this structure.
990%
991*/
992static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
993  struct PackageInfo *package_info,ExceptionInfo *exception)
994{
995  char
996    message[MagickPathExtent];
997
998  struct PackageInfo
999    *clone_info;
1000
1001  SV
1002    *sv;
1003
1004  (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1005    PackageName,XS_VERSION,reference);
1006  sv=perl_get_sv(message,(TRUE | 0x02));
1007  if (sv == (SV *) NULL)
1008    {
1009      ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1010        message);
1011      return(package_info);
1012    }
1013  if (SvREFCNT(sv) == 0)
1014    (void) SvREFCNT_inc(sv);
1015  if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1016    return(clone_info);
1017  clone_info=ClonePackageInfo(package_info,exception);
1018  sv_setiv(sv,PTR2IV(clone_info));
1019  return(clone_info);
1020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024%                                                                             %
1025%                                                                             %
1026%                                                                             %
1027%   S e t A t t r i b u t e                                                   %
1028%                                                                             %
1029%                                                                             %
1030%                                                                             %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033%  SetAttribute() sets the attribute to the value in sval.  This can change
1034%  either or both of image or info.
1035%
1036%  The format of the SetAttribute routine is:
1037%
1038%      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1039%        SV *sval,ExceptionInfo *exception)
1040%
1041%  A description of each parameter follows:
1042%
1043%    o list: a list of strings.
1044%
1045%    o string: a character string.
1046%
1047*/
1048
1049static double SiPrefixToDoubleInterval(const char *string,const double interval)
1050{
1051  char
1052    *q;
1053
1054  double
1055    value;
1056
1057  value=InterpretSiPrefixValue(string,&q);
1058  if (*q == '%')
1059    value*=interval/100.0;
1060  return(value);
1061}
1062
1063static inline double StringToDouble(const char *string,char **sentinal)
1064{
1065  return(InterpretLocaleValue(string,sentinal));
1066}
1067
1068static double StringToDoubleInterval(const char *string,const double interval)
1069{
1070  char
1071    *q;
1072
1073  double
1074    value;
1075
1076  value=InterpretLocaleValue(string,&q);
1077  if (*q == '%')
1078    value*=interval/100.0;
1079  return(value);
1080}
1081
1082static inline ssize_t StringToLong(const char *value)
1083{
1084  return(strtol(value,(char **) NULL,10));
1085}
1086
1087static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1088  const char *attribute,SV *sval,ExceptionInfo *exception)
1089{
1090  GeometryInfo
1091    geometry_info;
1092
1093  long
1094    x,
1095    y;
1096
1097  PixelInfo
1098    pixel;
1099
1100  MagickStatusType
1101    flags;
1102
1103  PixelInfo
1104    *color,
1105    target_color;
1106
1107  ssize_t
1108    sp;
1109
1110  switch (*attribute)
1111  {
1112    case 'A':
1113    case 'a':
1114    {
1115      if (LocaleCompare(attribute,"adjoin") == 0)
1116        {
1117          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1118            SvPV(sval,na)) : SvIV(sval);
1119          if (sp < 0)
1120            {
1121              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1122                SvPV(sval,na));
1123              break;
1124            }
1125          if (info)
1126            info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1127          break;
1128        }
1129      if (LocaleCompare(attribute,"alpha") == 0)
1130        {
1131          sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1132            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1133          if (sp < 0)
1134            {
1135              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1136                SvPV(sval,na));
1137              break;
1138            }
1139          for ( ; image; image=image->next)
1140            (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1141              exception);
1142          break;
1143        }
1144      if (LocaleCompare(attribute,"antialias") == 0)
1145        {
1146          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1147            SvPV(sval,na)) : SvIV(sval);
1148          if (sp < 0)
1149            {
1150              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1151                SvPV(sval,na));
1152              break;
1153            }
1154          if (info)
1155            info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1156          break;
1157        }
1158      if (LocaleCompare(attribute,"area-limit") == 0)
1159        {
1160          MagickSizeType
1161            limit;
1162
1163          limit=MagickResourceInfinity;
1164          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1165            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1166              100.0);
1167          (void) SetMagickResourceLimit(AreaResource,limit);
1168          break;
1169        }
1170      if (LocaleCompare(attribute,"attenuate") == 0)
1171        {
1172          if (info)
1173            (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1174          break;
1175        }
1176      if (LocaleCompare(attribute,"authenticate") == 0)
1177        {
1178          if (info)
1179            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1180          break;
1181        }
1182      if (info)
1183        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1184      for ( ; image; image=image->next)
1185        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1186      break;
1187    }
1188    case 'B':
1189    case 'b':
1190    {
1191      if (LocaleCompare(attribute,"background") == 0)
1192        {
1193          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1194            exception);
1195          if (info)
1196            info->image_info->background_color=target_color;
1197          for ( ; image; image=image->next)
1198            image->background_color=target_color;
1199          break;
1200        }
1201      if (LocaleCompare(attribute,"blue-primary") == 0)
1202        {
1203          for ( ; image; image=image->next)
1204          {
1205            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1206            image->chromaticity.blue_primary.x=geometry_info.rho;
1207            image->chromaticity.blue_primary.y=geometry_info.sigma;
1208            if ((flags & SigmaValue) == 0)
1209              image->chromaticity.blue_primary.y=
1210                image->chromaticity.blue_primary.x;
1211          }
1212          break;
1213        }
1214      if (LocaleCompare(attribute,"bordercolor") == 0)
1215        {
1216          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1217            exception);
1218          if (info)
1219            info->image_info->border_color=target_color;
1220          for ( ; image; image=image->next)
1221            image->border_color=target_color;
1222          break;
1223        }
1224      if (info)
1225        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1226      for ( ; image; image=image->next)
1227        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1228      break;
1229    }
1230    case 'C':
1231    case 'c':
1232    {
1233      if (LocaleCompare(attribute,"cache-threshold") == 0)
1234        {
1235          (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1236            SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1237          (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1238            (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1239          break;
1240        }
1241      if (LocaleCompare(attribute,"clip-mask") == 0)
1242        {
1243          Image
1244            *clip_mask;
1245
1246          clip_mask=(Image *) NULL;
1247          if (SvPOK(sval))
1248            clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1249          for ( ; image; image=image->next)
1250            SetImageMask(image,ReadPixelMask,clip_mask,exception);
1251          break;
1252        }
1253      if (LocaleNCompare(attribute,"colormap",8) == 0)
1254        {
1255          for ( ; image; image=image->next)
1256          {
1257            int
1258              items;
1259
1260            long
1261              i;
1262
1263            if (image->storage_class == DirectClass)
1264              continue;
1265            i=0;
1266            items=sscanf(attribute,"%*[^[][%ld",&i);
1267            (void) items;
1268            if (i > (ssize_t) image->colors)
1269              i%=image->colors;
1270            if ((strchr(SvPV(sval,na),',') == 0) ||
1271                (strchr(SvPV(sval,na),')') != 0))
1272              QueryColorCompliance(SvPV(sval,na),AllCompliance,
1273                image->colormap+i,exception);
1274            else
1275              {
1276                color=image->colormap+i;
1277                pixel.red=color->red;
1278                pixel.green=color->green;
1279                pixel.blue=color->blue;
1280                flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1281                pixel.red=geometry_info.rho;
1282                pixel.green=geometry_info.sigma;
1283                pixel.blue=geometry_info.xi;
1284                color->red=ClampToQuantum(pixel.red);
1285                color->green=ClampToQuantum(pixel.green);
1286                color->blue=ClampToQuantum(pixel.blue);
1287              }
1288          }
1289          break;
1290        }
1291      if (LocaleCompare(attribute,"colorspace") == 0)
1292        {
1293          sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1294            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1295          if (sp < 0)
1296            {
1297              ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1298                SvPV(sval,na));
1299              break;
1300            }
1301          for ( ; image; image=image->next)
1302            (void) TransformImageColorspace(image,(ColorspaceType) sp,
1303              exception);
1304          break;
1305        }
1306      if (LocaleCompare(attribute,"comment") == 0)
1307        {
1308          for ( ; image; image=image->next)
1309            (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1310              info ? info->image_info : (ImageInfo *) NULL,image,
1311              SvPV(sval,na),exception),exception);
1312          break;
1313        }
1314      if (LocaleCompare(attribute,"compression") == 0)
1315        {
1316          sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1317            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1318          if (sp < 0)
1319            {
1320              ThrowPerlException(exception,OptionError,
1321                "UnrecognizedImageCompression",SvPV(sval,na));
1322              break;
1323            }
1324          if (info)
1325            info->image_info->compression=(CompressionType) sp;
1326          for ( ; image; image=image->next)
1327            image->compression=(CompressionType) sp;
1328          break;
1329        }
1330      if (info)
1331        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1332      for ( ; image; image=image->next)
1333        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1334      break;
1335    }
1336    case 'D':
1337    case 'd':
1338    {
1339      if (LocaleCompare(attribute,"debug") == 0)
1340        {
1341          SetLogEventMask(SvPV(sval,na));
1342          break;
1343        }
1344      if (LocaleCompare(attribute,"delay") == 0)
1345        {
1346          flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1347          for ( ; image; image=image->next)
1348          {
1349            image->delay=(size_t) floor(geometry_info.rho+0.5);
1350            if ((flags & SigmaValue) != 0)
1351              image->ticks_per_second=(ssize_t)
1352                floor(geometry_info.sigma+0.5);
1353          }
1354          break;
1355        }
1356      if (LocaleCompare(attribute,"disk-limit") == 0)
1357        {
1358          MagickSizeType
1359            limit;
1360
1361          limit=MagickResourceInfinity;
1362          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1363            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1364              100.0);
1365          (void) SetMagickResourceLimit(DiskResource,limit);
1366          break;
1367        }
1368      if (LocaleCompare(attribute,"density") == 0)
1369        {
1370          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1371            {
1372              ThrowPerlException(exception,OptionError,"MissingGeometry",
1373                SvPV(sval,na));
1374              break;
1375            }
1376          if (info)
1377            (void) CloneString(&info->image_info->density,SvPV(sval,na));
1378          for ( ; image; image=image->next)
1379          {
1380            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1381            image->resolution.x=geometry_info.rho;
1382            image->resolution.y=geometry_info.sigma;
1383            if ((flags & SigmaValue) == 0)
1384              image->resolution.y=image->resolution.x;
1385          }
1386          break;
1387        }
1388      if (LocaleCompare(attribute,"depth") == 0)
1389        {
1390          if (info)
1391            info->image_info->depth=SvIV(sval);
1392          for ( ; image; image=image->next)
1393            (void) SetImageDepth(image,SvIV(sval),exception);
1394          break;
1395        }
1396      if (LocaleCompare(attribute,"dispose") == 0)
1397        {
1398          sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1399            SvPV(sval,na)) : SvIV(sval);
1400          if (sp < 0)
1401            {
1402              ThrowPerlException(exception,OptionError,
1403                "UnrecognizedDisposeMethod",SvPV(sval,na));
1404              break;
1405            }
1406          for ( ; image; image=image->next)
1407            image->dispose=(DisposeType) sp;
1408          break;
1409        }
1410      if (LocaleCompare(attribute,"dither") == 0)
1411        {
1412          if (info)
1413            {
1414              sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1415                MagickFalse,SvPV(sval,na)) : SvIV(sval);
1416              if (sp < 0)
1417                {
1418                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
1419                    SvPV(sval,na));
1420                  break;
1421                }
1422              info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1423            }
1424          break;
1425        }
1426      if (LocaleCompare(attribute,"display") == 0)
1427        {
1428          display:
1429          if (info)
1430            (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1431          break;
1432        }
1433      if (info)
1434        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1435      for ( ; image; image=image->next)
1436        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1437      break;
1438    }
1439    case 'E':
1440    case 'e':
1441    {
1442      if (LocaleCompare(attribute,"endian") == 0)
1443        {
1444          sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1445            SvPV(sval,na)) : SvIV(sval);
1446          if (sp < 0)
1447            {
1448              ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1449                SvPV(sval,na));
1450              break;
1451            }
1452          if (info)
1453            info->image_info->endian=(EndianType) sp;
1454          for ( ; image; image=image->next)
1455            image->endian=(EndianType) sp;
1456          break;
1457        }
1458      if (LocaleCompare(attribute,"extract") == 0)
1459        {
1460          /*
1461            Set image extract geometry.
1462          */
1463          (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1464          break;
1465        }
1466      if (info)
1467        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1468      for ( ; image; image=image->next)
1469        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1470      break;
1471    }
1472    case 'F':
1473    case 'f':
1474    {
1475      if (LocaleCompare(attribute,"filename") == 0)
1476        {
1477          if (info)
1478            (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1479              MagickPathExtent);
1480          for ( ; image; image=image->next)
1481            (void) CopyMagickString(image->filename,SvPV(sval,na),
1482              MagickPathExtent);
1483          break;
1484        }
1485      if (LocaleCompare(attribute,"file") == 0)
1486        {
1487          FILE
1488            *file;
1489
1490          PerlIO
1491            *io_info;
1492
1493          if (info == (struct PackageInfo *) NULL)
1494            break;
1495          io_info=IoIFP(sv_2io(sval));
1496          if (io_info == (PerlIO *) NULL)
1497            {
1498              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                PackageName);
1500              break;
1501            }
1502          file=PerlIO_findFILE(io_info);
1503          if (file == (FILE *) NULL)
1504            {
1505              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1506                PackageName);
1507              break;
1508            }
1509          SetImageInfoFile(info->image_info,file);
1510          break;
1511        }
1512      if (LocaleCompare(attribute,"fill") == 0)
1513        {
1514          if (info)
1515            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1516          break;
1517        }
1518      if (LocaleCompare(attribute,"font") == 0)
1519        {
1520          if (info)
1521            (void) CloneString(&info->image_info->font,SvPV(sval,na));
1522          break;
1523        }
1524      if (LocaleCompare(attribute,"foreground") == 0)
1525        break;
1526      if (LocaleCompare(attribute,"fuzz") == 0)
1527        {
1528          if (info)
1529            info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1530              QuantumRange+1.0);
1531          for ( ; image; image=image->next)
1532            image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1533              QuantumRange+1.0);
1534          break;
1535        }
1536      if (info)
1537        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1538      for ( ; image; image=image->next)
1539        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1540      break;
1541    }
1542    case 'G':
1543    case 'g':
1544    {
1545      if (LocaleCompare(attribute,"gamma") == 0)
1546        {
1547          for ( ; image; image=image->next)
1548            image->gamma=SvNV(sval);
1549          break;
1550        }
1551      if (LocaleCompare(attribute,"gravity") == 0)
1552        {
1553          sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1554            SvPV(sval,na)) : SvIV(sval);
1555          if (sp < 0)
1556            {
1557              ThrowPerlException(exception,OptionError,
1558                "UnrecognizedGravityType",SvPV(sval,na));
1559              break;
1560            }
1561          if (info)
1562            SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563          for ( ; image; image=image->next)
1564            image->gravity=(GravityType) sp;
1565          break;
1566        }
1567      if (LocaleCompare(attribute,"green-primary") == 0)
1568        {
1569          for ( ; image; image=image->next)
1570          {
1571            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1572            image->chromaticity.green_primary.x=geometry_info.rho;
1573            image->chromaticity.green_primary.y=geometry_info.sigma;
1574            if ((flags & SigmaValue) == 0)
1575              image->chromaticity.green_primary.y=
1576                image->chromaticity.green_primary.x;
1577          }
1578          break;
1579        }
1580      if (info)
1581        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1582      for ( ; image; image=image->next)
1583        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1584      break;
1585    }
1586    case 'I':
1587    case 'i':
1588    {
1589      if (LocaleNCompare(attribute,"index",5) == 0)
1590        {
1591          int
1592            items;
1593
1594          long
1595            index;
1596
1597          register Quantum
1598            *q;
1599
1600          CacheView
1601            *image_view;
1602
1603          for ( ; image; image=image->next)
1604          {
1605            if (image->storage_class != PseudoClass)
1606              continue;
1607            x=0;
1608            y=0;
1609            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1610            (void) items;
1611            image_view=AcquireAuthenticCacheView(image,exception);
1612            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1613            if (q != (Quantum *) NULL)
1614              {
1615                items=sscanf(SvPV(sval,na),"%ld",&index);
1616                if ((index >= 0) && (index < (ssize_t) image->colors))
1617                  SetPixelIndex(image,index,q);
1618                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1619              }
1620            image_view=DestroyCacheView(image_view);
1621          }
1622          break;
1623        }
1624      if (LocaleCompare(attribute,"iterations") == 0)
1625        {
1626  iterations:
1627          for ( ; image; image=image->next)
1628            image->iterations=SvIV(sval);
1629          break;
1630        }
1631      if (LocaleCompare(attribute,"interlace") == 0)
1632        {
1633          sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1634            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1635          if (sp < 0)
1636            {
1637              ThrowPerlException(exception,OptionError,
1638                "UnrecognizedInterlaceType",SvPV(sval,na));
1639              break;
1640            }
1641          if (info)
1642            info->image_info->interlace=(InterlaceType) sp;
1643          for ( ; image; image=image->next)
1644            image->interlace=(InterlaceType) sp;
1645          break;
1646        }
1647      if (info)
1648        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1649      for ( ; image; image=image->next)
1650        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1651      break;
1652    }
1653    case 'L':
1654    case 'l':
1655    {
1656      if (LocaleCompare(attribute,"label") == 0)
1657        {
1658          for ( ; image; image=image->next)
1659            (void) SetImageProperty(image,"label",InterpretImageProperties(
1660              info ? info->image_info : (ImageInfo *) NULL,image,
1661              SvPV(sval,na),exception),exception);
1662          break;
1663        }
1664      if (LocaleCompare(attribute,"loop") == 0)
1665        goto iterations;
1666      if (info)
1667        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1668      for ( ; image; image=image->next)
1669        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1670      break;
1671    }
1672    case 'M':
1673    case 'm':
1674    {
1675      if (LocaleCompare(attribute,"magick") == 0)
1676        {
1677          if (info)
1678            (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1679              "%s:",SvPV(sval,na));
1680          for ( ; image; image=image->next)
1681            (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1682          break;
1683        }
1684      if (LocaleCompare(attribute,"map-limit") == 0)
1685        {
1686          MagickSizeType
1687            limit;
1688
1689          limit=MagickResourceInfinity;
1690          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1691            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1692              100.0);
1693          (void) SetMagickResourceLimit(MapResource,limit);
1694          break;
1695        }
1696      if (LocaleCompare(attribute,"mask") == 0)
1697        {
1698          Image
1699            *mask;
1700
1701          mask=(Image *) NULL;
1702          if (SvPOK(sval))
1703            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1704          for ( ; image; image=image->next)
1705            SetImageMask(image,ReadPixelMask,mask,exception);
1706          break;
1707        }
1708      if (LocaleCompare(attribute,"mattecolor") == 0)
1709        {
1710          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1711            exception);
1712          if (info)
1713            info->image_info->alpha_color=target_color;
1714          for ( ; image; image=image->next)
1715            image->alpha_color=target_color;
1716          break;
1717        }
1718      if (LocaleCompare(attribute,"matte") == 0)
1719        {
1720          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721            SvPV(sval,na)) : SvIV(sval);
1722          if (sp < 0)
1723            {
1724              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                SvPV(sval,na));
1726              break;
1727            }
1728          for ( ; image; image=image->next)
1729            image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1730          break;
1731        }
1732      if (LocaleCompare(attribute,"memory-limit") == 0)
1733        {
1734          MagickSizeType
1735            limit;
1736
1737          limit=MagickResourceInfinity;
1738          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1739            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1740              100.0);
1741          (void) SetMagickResourceLimit(MemoryResource,limit);
1742          break;
1743        }
1744      if (LocaleCompare(attribute,"monochrome") == 0)
1745        {
1746          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1747            SvPV(sval,na)) : SvIV(sval);
1748          if (sp < 0)
1749            {
1750              ThrowPerlException(exception,OptionError,"UnrecognizedType",
1751                SvPV(sval,na));
1752              break;
1753            }
1754          if (info)
1755            info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1756          for ( ; image; image=image->next)
1757            (void) SetImageType(image,BilevelType,exception);
1758          break;
1759        }
1760      if (info)
1761        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1762      for ( ; image; image=image->next)
1763        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1764      break;
1765    }
1766    case 'O':
1767    case 'o':
1768    {
1769      if (LocaleCompare(attribute,"option") == 0)
1770        {
1771          if (info)
1772            DefineImageOption(info->image_info,SvPV(sval,na));
1773          break;
1774        }
1775      if (LocaleCompare(attribute,"orientation") == 0)
1776        {
1777          sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1778            MagickFalse,SvPV(sval,na)) : SvIV(sval);
1779          if (sp < 0)
1780            {
1781              ThrowPerlException(exception,OptionError,
1782                "UnrecognizedOrientationType",SvPV(sval,na));
1783              break;
1784            }
1785          if (info)
1786            info->image_info->orientation=(OrientationType) sp;
1787          for ( ; image; image=image->next)
1788            image->orientation=(OrientationType) sp;
1789          break;
1790        }
1791      if (info)
1792        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1793      for ( ; image; image=image->next)
1794        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1795      break;
1796    }
1797    case 'P':
1798    case 'p':
1799    {
1800      if (LocaleCompare(attribute,"page") == 0)
1801        {
1802          char
1803            *geometry;
1804
1805          geometry=GetPageGeometry(SvPV(sval,na));
1806          if (info)
1807            (void) CloneString(&info->image_info->page,geometry);
1808          for ( ; image; image=image->next)
1809            (void) ParsePageGeometry(image,geometry,&image->page,exception);
1810          geometry=(char *) RelinquishMagickMemory(geometry);
1811          break;
1812        }
1813      if (LocaleNCompare(attribute,"pixel",5) == 0)
1814        {
1815          int
1816            items;
1817
1818          PixelInfo
1819            pixel;
1820
1821          register Quantum
1822            *q;
1823
1824          CacheView
1825            *image_view;
1826
1827          for ( ; image; image=image->next)
1828          {
1829            if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1830              break;
1831            x=0;
1832            y=0;
1833            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1834            (void) items;
1835            image_view=AcquireVirtualCacheView(image,exception);
1836            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1837            if (q != (Quantum *) NULL)
1838              {
1839                if ((strchr(SvPV(sval,na),',') == 0) ||
1840                    (strchr(SvPV(sval,na),')') != 0))
1841                  QueryColorCompliance(SvPV(sval,na),AllCompliance,
1842                    &pixel,exception);
1843                else
1844                  {
1845                    GetPixelInfo(image,&pixel);
1846                    flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1847                    pixel.red=geometry_info.rho;
1848                    if ((flags & SigmaValue) != 0)
1849                      pixel.green=geometry_info.sigma;
1850                    if ((flags & XiValue) != 0)
1851                      pixel.blue=geometry_info.xi;
1852                    if ((flags & PsiValue) != 0)
1853                      pixel.alpha=geometry_info.psi;
1854                    if ((flags & ChiValue) != 0)
1855                      pixel.black=geometry_info.chi;
1856                  }
1857                SetPixelRed(image,ClampToQuantum(pixel.red),q);
1858                SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1859                SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1860                if (image->colorspace == CMYKColorspace)
1861                  SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1862                SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1863                (void) SyncCacheViewAuthenticPixels(image_view,exception);
1864              }
1865            image_view=DestroyCacheView(image_view);
1866          }
1867          break;
1868        }
1869      if (LocaleCompare(attribute,"pointsize") == 0)
1870        {
1871          if (info)
1872            {
1873              (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1874              info->image_info->pointsize=geometry_info.rho;
1875            }
1876          break;
1877        }
1878      if (info)
1879        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1880      for ( ; image; image=image->next)
1881        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1882      break;
1883    }
1884    case 'Q':
1885    case 'q':
1886    {
1887      if (LocaleCompare(attribute,"quality") == 0)
1888        {
1889          if (info)
1890            info->image_info->quality=SvIV(sval);
1891          for ( ; image; image=image->next)
1892            image->quality=SvIV(sval);
1893          break;
1894        }
1895      if (info)
1896        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1897      for ( ; image; image=image->next)
1898        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1899      break;
1900    }
1901    case 'R':
1902    case 'r':
1903    {
1904      if (LocaleCompare(attribute,"read-mask") == 0)
1905        {
1906          Image
1907            *mask;
1908
1909          mask=(Image *) NULL;
1910          if (SvPOK(sval))
1911            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1912          for ( ; image; image=image->next)
1913            SetImageMask(image,ReadPixelMask,mask,exception);
1914          break;
1915        }
1916      if (LocaleCompare(attribute,"red-primary") == 0)
1917        {
1918          for ( ; image; image=image->next)
1919          {
1920            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1921            image->chromaticity.red_primary.x=geometry_info.rho;
1922            image->chromaticity.red_primary.y=geometry_info.sigma;
1923            if ((flags & SigmaValue) == 0)
1924              image->chromaticity.red_primary.y=
1925                image->chromaticity.red_primary.x;
1926          }
1927          break;
1928        }
1929      if (LocaleCompare(attribute,"render") == 0)
1930        {
1931          sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1932            SvPV(sval,na)) : SvIV(sval);
1933          if (sp < 0)
1934            {
1935              ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1936                SvPV(sval,na));
1937              break;
1938            }
1939         for ( ; image; image=image->next)
1940           image->rendering_intent=(RenderingIntent) sp;
1941         break;
1942       }
1943      if (LocaleCompare(attribute,"repage") == 0)
1944        {
1945          RectangleInfo
1946            geometry;
1947
1948          for ( ; image; image=image->next)
1949          {
1950            flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1951            if ((flags & WidthValue) != 0)
1952              {
1953                if ((flags & HeightValue) == 0)
1954                  geometry.height=geometry.width;
1955                image->page.width=geometry.width;
1956                image->page.height=geometry.height;
1957              }
1958            if ((flags & AspectValue) != 0)
1959              {
1960                if ((flags & XValue) != 0)
1961                  image->page.x+=geometry.x;
1962                if ((flags & YValue) != 0)
1963                  image->page.y+=geometry.y;
1964              }
1965            else
1966              {
1967                if ((flags & XValue) != 0)
1968                  {
1969                    image->page.x=geometry.x;
1970                    if (((flags & WidthValue) != 0) && (geometry.x > 0))
1971                      image->page.width=image->columns+geometry.x;
1972                  }
1973                if ((flags & YValue) != 0)
1974                  {
1975                    image->page.y=geometry.y;
1976                    if (((flags & HeightValue) != 0) && (geometry.y > 0))
1977                      image->page.height=image->rows+geometry.y;
1978                  }
1979              }
1980          }
1981          break;
1982        }
1983      if (info)
1984        SetImageOption(info->image_info,attribute,SvPV(sval,na));
1985      for ( ; image; image=image->next)
1986        SetImageProperty(image,attribute,SvPV(sval,na),exception);
1987      break;
1988    }
1989    case 'S':
1990    case 's':
1991    {
1992      if (LocaleCompare(attribute,"sampling-factor") == 0)
1993        {
1994          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1995            {
1996              ThrowPerlException(exception,OptionError,"MissingGeometry",
1997                SvPV(sval,na));
1998              break;
1999            }
2000          if (info)
2001            (void) CloneString(&info->image_info->sampling_factor,
2002              SvPV(sval,na));
2003          break;
2004        }
2005      if (LocaleCompare(attribute,"scene") == 0)
2006        {
2007          for ( ; image; image=image->next)
2008            image->scene=SvIV(sval);
2009          break;
2010        }
2011      if (LocaleCompare(attribute,"server") == 0)
2012        goto display;
2013      if (LocaleCompare(attribute,"size") == 0)
2014        {
2015          if (info)
2016            {
2017              if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2018                {
2019                  ThrowPerlException(exception,OptionError,"MissingGeometry",
2020                    SvPV(sval,na));
2021                  break;
2022                }
2023              (void) CloneString(&info->image_info->size,SvPV(sval,na));
2024            }
2025          break;
2026        }
2027      if (LocaleCompare(attribute,"stroke") == 0)
2028        {
2029          if (info)
2030            (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2031          break;
2032        }
2033      if (info)
2034        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2035      for ( ; image; image=image->next)
2036        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2037      break;
2038    }
2039    case 'T':
2040    case 't':
2041    {
2042      if (LocaleCompare(attribute,"texture") == 0)
2043        {
2044          if (info)
2045            (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2046          break;
2047        }
2048      if (LocaleCompare(attribute,"thread-limit") == 0)
2049        {
2050          MagickSizeType
2051            limit;
2052
2053          limit=MagickResourceInfinity;
2054          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2056              100.0);
2057          (void) SetMagickResourceLimit(ThreadResource,limit);
2058          break;
2059        }
2060      if (LocaleCompare(attribute,"tile-offset") == 0)
2061        {
2062          char
2063            *geometry;
2064
2065          geometry=GetPageGeometry(SvPV(sval,na));
2066          if (info)
2067            (void) CloneString(&info->image_info->page,geometry);
2068          for ( ; image; image=image->next)
2069            (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2070              exception);
2071          geometry=(char *) RelinquishMagickMemory(geometry);
2072          break;
2073        }
2074      if (LocaleCompare(attribute,"time-limit") == 0)
2075        {
2076          MagickSizeType
2077            limit;
2078
2079          limit=MagickResourceInfinity;
2080          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2081            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2082              100.0);
2083          (void) SetMagickResourceLimit(TimeResource,limit);
2084          break;
2085        }
2086      if (LocaleCompare(attribute,"transparent-color") == 0)
2087        {
2088          (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2089            exception);
2090          if (info)
2091            info->image_info->transparent_color=target_color;
2092          for ( ; image; image=image->next)
2093            image->transparent_color=target_color;
2094          break;
2095        }
2096      if (LocaleCompare(attribute,"type") == 0)
2097        {
2098          sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2099            SvPV(sval,na)) : SvIV(sval);
2100          if (sp < 0)
2101            {
2102              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2103                SvPV(sval,na));
2104              break;
2105            }
2106          if (info)
2107            info->image_info->type=(ImageType) sp;
2108          for ( ; image; image=image->next)
2109            SetImageType(image,(ImageType) sp,exception);
2110          break;
2111        }
2112      if (info)
2113        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2114      for ( ; image; image=image->next)
2115        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2116      break;
2117    }
2118    case 'U':
2119    case 'u':
2120    {
2121      if (LocaleCompare(attribute,"units") == 0)
2122        {
2123          sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2124            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2125          if (sp < 0)
2126            {
2127              ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2128                SvPV(sval,na));
2129              break;
2130            }
2131          if (info)
2132            info->image_info->units=(ResolutionType) sp;
2133          for ( ; image; image=image->next)
2134          {
2135            ResolutionType
2136              units;
2137
2138            units=(ResolutionType) sp;
2139            if (image->units != units)
2140              switch (image->units)
2141              {
2142                case UndefinedResolution:
2143                case PixelsPerInchResolution:
2144                {
2145                  if (units == PixelsPerCentimeterResolution)
2146                    {
2147                      image->resolution.x*=2.54;
2148                      image->resolution.y*=2.54;
2149                    }
2150                  break;
2151                }
2152                case PixelsPerCentimeterResolution:
2153                {
2154                  if (units == PixelsPerInchResolution)
2155                    {
2156                      image->resolution.x/=2.54;
2157                      image->resolution.y/=2.54;
2158                    }
2159                  break;
2160                }
2161              }
2162            image->units=units;
2163          }
2164          break;
2165        }
2166      if (info)
2167        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2168      for ( ; image; image=image->next)
2169        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2170      break;
2171    }
2172    case 'V':
2173    case 'v':
2174    {
2175      if (LocaleCompare(attribute,"verbose") == 0)
2176        {
2177          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2178            SvPV(sval,na)) : SvIV(sval);
2179          if (sp < 0)
2180            {
2181              ThrowPerlException(exception,OptionError,"UnrecognizedType",
2182                SvPV(sval,na));
2183              break;
2184            }
2185          if (info)
2186            info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2187          break;
2188        }
2189      if (LocaleCompare(attribute,"virtual-pixel") == 0)
2190        {
2191          sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2192            MagickFalse,SvPV(sval,na)) : SvIV(sval);
2193          if (sp < 0)
2194            {
2195              ThrowPerlException(exception,OptionError,
2196                "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2197              break;
2198            }
2199          for ( ; image; image=image->next)
2200            SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2201          break;
2202        }
2203      if (info)
2204        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2205      for ( ; image; image=image->next)
2206        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2207      break;
2208    }
2209    case 'W':
2210    case 'w':
2211    {
2212      if (LocaleCompare(attribute,"white-point") == 0)
2213        {
2214          for ( ; image; image=image->next)
2215          {
2216            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2217            image->chromaticity.white_point.x=geometry_info.rho;
2218            image->chromaticity.white_point.y=geometry_info.sigma;
2219            if ((flags & SigmaValue) == 0)
2220              image->chromaticity.white_point.y=
2221                image->chromaticity.white_point.x;
2222          }
2223          break;
2224        }
2225      if (LocaleCompare(attribute,"write-mask") == 0)
2226        {
2227          Image
2228            *mask;
2229
2230          mask=(Image *) NULL;
2231          if (SvPOK(sval))
2232            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2233          for ( ; image; image=image->next)
2234            SetImageMask(image,WritePixelMask,mask,exception);
2235          break;
2236        }
2237      if (info)
2238        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2239      for ( ; image; image=image->next)
2240        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2241      break;
2242    }
2243    default:
2244    {
2245      if (info)
2246        SetImageOption(info->image_info,attribute,SvPV(sval,na));
2247      for ( ; image; image=image->next)
2248        SetImageProperty(image,attribute,SvPV(sval,na),exception);
2249      break;
2250    }
2251  }
2252}
2253
2254/*
2255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256%                                                                             %
2257%                                                                             %
2258%                                                                             %
2259%   S e t u p L i s t                                                         %
2260%                                                                             %
2261%                                                                             %
2262%                                                                             %
2263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264%
2265%  Method SetupList returns the list of all the images linked by their
2266%  image->next and image->previous link lists for use with ImageMagick.  If
2267%  info is non-NULL, an info structure is returned in *info.  If
2268%  reference_vector is non-NULL,an array of SV* are returned in
2269%  *reference_vector.  Reference_vector is used when the images are going to be
2270%  replaced with new Image*'s.
2271%
2272%  The format of the SetupList routine is:
2273%
2274%      Image *SetupList(SV *reference,struct PackageInfo **info,
2275%        SV ***reference_vector,ExceptionInfo *exception)
2276%
2277%  A description of each parameter follows:
2278%
2279%    o list: a list of strings.
2280%
2281%    o string: a character string.
2282%
2283%    o exception: Return any errors or warnings in this structure.
2284%
2285*/
2286static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2287  SV ***reference_vector,ExceptionInfo *exception)
2288{
2289  Image
2290    *image;
2291
2292  ssize_t
2293    current,
2294    last;
2295
2296  if (reference_vector)
2297    *reference_vector=NULL;
2298  if (info)
2299    *info=NULL;
2300  current=0;
2301  last=0;
2302  image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2303  if (info && (SvTYPE(reference) == SVt_PVAV))
2304    *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2305      exception);
2306  return(image);
2307}
2308
2309/*
2310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311%                                                                             %
2312%                                                                             %
2313%                                                                             %
2314%   s t r E Q c a s e                                                         %
2315%                                                                             %
2316%                                                                             %
2317%                                                                             %
2318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2319%
2320%  strEQcase() compares two strings and returns 0 if they are the
2321%  same or if the second string runs out first.  The comparison is case
2322%  insensitive.
2323%
2324%  The format of the strEQcase routine is:
2325%
2326%      ssize_t strEQcase(const char *p,const char *q)
2327%
2328%  A description of each parameter follows:
2329%
2330%    o p: a character string.
2331%
2332%    o q: a character string.
2333%
2334%
2335*/
2336static ssize_t strEQcase(const char *p,const char *q)
2337{
2338  char
2339    c;
2340
2341  register ssize_t
2342    i;
2343
2344  for (i=0 ; (c=(*q)) != 0; i++)
2345  {
2346    if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2347        (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2348      return(0);
2349    p++;
2350    q++;
2351  }
2352  return(((*q == 0) && (*p == 0)) ? i : 0);
2353}
2354
2355/*
2356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2357%                                                                             %
2358%                                                                             %
2359%                                                                             %
2360%   I m a g e : : M a g i c k                                                 %
2361%                                                                             %
2362%                                                                             %
2363%                                                                             %
2364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2365%
2366%
2367*/
2368MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2369
2370PROTOTYPES: ENABLE
2371
2372BOOT:
2373  MagickCoreGenesis("PerlMagick",MagickFalse);
2374  SetWarningHandler(NULL);
2375  SetErrorHandler(NULL);
2376  magick_registry=NewSplayTree((int (*)(const void *,const void *))
2377    NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2378
2379void
2380UNLOAD()
2381  PPCODE:
2382  {
2383    if (magick_registry != (SplayTreeInfo *) NULL)
2384      magick_registry=DestroySplayTree(magick_registry);
2385    MagickCoreTerminus();
2386  }
2387
2388double
2389constant(name,argument)
2390  char *name
2391  ssize_t argument
2392
2393#
2394###############################################################################
2395#                                                                             #
2396#                                                                             #
2397#                                                                             #
2398#   A n i m a t e                                                             #
2399#                                                                             #
2400#                                                                             #
2401#                                                                             #
2402###############################################################################
2403#
2404#
2405void
2406Animate(ref,...)
2407  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2408  ALIAS:
2409    AnimateImage  = 1
2410    animate       = 2
2411    animateimage  = 3
2412  PPCODE:
2413  {
2414    ExceptionInfo
2415      *exception;
2416
2417    Image
2418      *image;
2419
2420    register ssize_t
2421      i;
2422
2423    struct PackageInfo
2424      *info,
2425      *package_info;
2426
2427    SV
2428      *perl_exception,
2429      *reference;
2430
2431    PERL_UNUSED_VAR(ref);
2432    PERL_UNUSED_VAR(ix);
2433    exception=AcquireExceptionInfo();
2434    perl_exception=newSVpv("",0);
2435    package_info=(struct PackageInfo *) NULL;
2436    if (sv_isobject(ST(0)) == 0)
2437      {
2438        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2439          PackageName);
2440        goto PerlException;
2441      }
2442    reference=SvRV(ST(0));
2443    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2444    if (image == (Image *) NULL)
2445      {
2446        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2447          PackageName);
2448        goto PerlException;
2449      }
2450    package_info=ClonePackageInfo(info,exception);
2451    if (items == 2)
2452      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2453    else
2454      if (items > 2)
2455        for (i=2; i < items; i+=2)
2456          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2457            exception);
2458    (void) AnimateImages(package_info->image_info,image,exception);
2459    (void) CatchImageException(image);
2460
2461  PerlException:
2462    if (package_info != (struct PackageInfo *) NULL)
2463      DestroyPackageInfo(package_info);
2464    InheritPerlException(exception,perl_exception);
2465    exception=DestroyExceptionInfo(exception);
2466    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2467    SvPOK_on(perl_exception);
2468    ST(0)=sv_2mortal(perl_exception);
2469    XSRETURN(1);
2470  }
2471
2472#
2473###############################################################################
2474#                                                                             #
2475#                                                                             #
2476#                                                                             #
2477#   A p p e n d                                                               #
2478#                                                                             #
2479#                                                                             #
2480#                                                                             #
2481###############################################################################
2482#
2483#
2484void
2485Append(ref,...)
2486  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2487  ALIAS:
2488    AppendImage  = 1
2489    append       = 2
2490    appendimage  = 3
2491  PPCODE:
2492  {
2493    AV
2494      *av;
2495
2496    char
2497      *attribute;
2498
2499    ExceptionInfo
2500      *exception;
2501
2502    HV
2503      *hv;
2504
2505    Image
2506      *image;
2507
2508    register ssize_t
2509      i;
2510
2511    ssize_t
2512      stack;
2513
2514    struct PackageInfo
2515      *info;
2516
2517    SV
2518      *av_reference,
2519      *perl_exception,
2520      *reference,
2521      *rv,
2522      *sv;
2523
2524    PERL_UNUSED_VAR(ref);
2525    PERL_UNUSED_VAR(ix);
2526    exception=AcquireExceptionInfo();
2527    perl_exception=newSVpv("",0);
2528    sv=NULL;
2529    attribute=NULL;
2530    av=NULL;
2531    if (sv_isobject(ST(0)) == 0)
2532      {
2533        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2534          PackageName);
2535        goto PerlException;
2536      }
2537    reference=SvRV(ST(0));
2538    hv=SvSTASH(reference);
2539    av=newAV();
2540    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2541    SvREFCNT_dec(av);
2542    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2543    if (image == (Image *) NULL)
2544      {
2545        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2546          PackageName);
2547        goto PerlException;
2548      }
2549    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2550    /*
2551      Get options.
2552    */
2553    stack=MagickTrue;
2554    for (i=2; i < items; i+=2)
2555    {
2556      attribute=(char *) SvPV(ST(i-1),na);
2557      switch (*attribute)
2558      {
2559        case 'S':
2560        case 's':
2561        {
2562          if (LocaleCompare(attribute,"stack") == 0)
2563            {
2564              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2565                SvPV(ST(i),na));
2566              if (stack < 0)
2567                {
2568                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
2569                    SvPV(ST(i),na));
2570                  return;
2571                }
2572              break;
2573            }
2574          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2575            attribute);
2576          break;
2577        }
2578        default:
2579        {
2580          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2581            attribute);
2582          break;
2583        }
2584      }
2585    }
2586    image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2587    if (image == (Image *) NULL)
2588      goto PerlException;
2589    for ( ; image; image=image->next)
2590    {
2591      AddImageToRegistry(sv,image);
2592      rv=newRV(sv);
2593      av_push(av,sv_bless(rv,hv));
2594      SvREFCNT_dec(sv);
2595    }
2596    exception=DestroyExceptionInfo(exception);
2597    ST(0)=av_reference;
2598    SvREFCNT_dec(perl_exception);
2599    XSRETURN(1);
2600
2601  PerlException:
2602    InheritPerlException(exception,perl_exception);
2603    exception=DestroyExceptionInfo(exception);
2604    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2605    SvPOK_on(perl_exception);
2606    ST(0)=sv_2mortal(perl_exception);
2607    XSRETURN(1);
2608  }
2609
2610#
2611###############################################################################
2612#                                                                             #
2613#                                                                             #
2614#                                                                             #
2615#   A v e r a g e                                                             #
2616#                                                                             #
2617#                                                                             #
2618#                                                                             #
2619###############################################################################
2620#
2621#
2622void
2623Average(ref)
2624  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2625  ALIAS:
2626    AverageImage   = 1
2627    average        = 2
2628    averageimage   = 3
2629  PPCODE:
2630  {
2631    AV
2632      *av;
2633
2634    char
2635      *p;
2636
2637    ExceptionInfo
2638      *exception;
2639
2640    HV
2641      *hv;
2642
2643    Image
2644      *image;
2645
2646    struct PackageInfo
2647      *info;
2648
2649    SV
2650      *perl_exception,
2651      *reference,
2652      *rv,
2653      *sv;
2654
2655    PERL_UNUSED_VAR(ref);
2656    PERL_UNUSED_VAR(ix);
2657    exception=AcquireExceptionInfo();
2658    perl_exception=newSVpv("",0);
2659    sv=NULL;
2660    if (sv_isobject(ST(0)) == 0)
2661      {
2662        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2663          PackageName);
2664        goto PerlException;
2665      }
2666    reference=SvRV(ST(0));
2667    hv=SvSTASH(reference);
2668    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2669    if (image == (Image *) NULL)
2670      {
2671        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2672          PackageName);
2673        goto PerlException;
2674      }
2675    image=EvaluateImages(image,MeanEvaluateOperator,exception);
2676    if (image == (Image *) NULL)
2677      goto PerlException;
2678    /*
2679      Create blessed Perl array for the returned image.
2680    */
2681    av=newAV();
2682    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2683    SvREFCNT_dec(av);
2684    AddImageToRegistry(sv,image);
2685    rv=newRV(sv);
2686    av_push(av,sv_bless(rv,hv));
2687    SvREFCNT_dec(sv);
2688    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2689    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2690      "average-%.*s",(int) (MagickPathExtent-9),
2691      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2692    (void) CopyMagickString(image->filename,info->image_info->filename,
2693      MagickPathExtent);
2694    SetImageInfo(info->image_info,0,exception);
2695    exception=DestroyExceptionInfo(exception);
2696    SvREFCNT_dec(perl_exception);
2697    XSRETURN(1);
2698
2699  PerlException:
2700    InheritPerlException(exception,perl_exception);
2701    exception=DestroyExceptionInfo(exception);
2702    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2703    SvPOK_on(perl_exception);
2704    ST(0)=sv_2mortal(perl_exception);
2705    XSRETURN(1);
2706  }
2707
2708#
2709###############################################################################
2710#                                                                             #
2711#                                                                             #
2712#                                                                             #
2713#   B l o b T o I m a g e                                                     #
2714#                                                                             #
2715#                                                                             #
2716#                                                                             #
2717###############################################################################
2718#
2719#
2720void
2721BlobToImage(ref,...)
2722  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2723  ALIAS:
2724    BlobToImage  = 1
2725    blobtoimage  = 2
2726    blobto       = 3
2727  PPCODE:
2728  {
2729    AV
2730      *av;
2731
2732    char
2733      **keep,
2734      **list;
2735
2736    ExceptionInfo
2737      *exception;
2738
2739    HV
2740      *hv;
2741
2742    Image
2743      *image;
2744
2745    register char
2746      **p;
2747
2748    register ssize_t
2749      i;
2750
2751    ssize_t
2752      ac,
2753      n,
2754      number_images;
2755
2756    STRLEN
2757      *length;
2758
2759    struct PackageInfo
2760      *info;
2761
2762    SV
2763      *perl_exception,
2764      *reference,
2765      *rv,
2766      *sv;
2767
2768    PERL_UNUSED_VAR(ref);
2769    PERL_UNUSED_VAR(ix);
2770    exception=AcquireExceptionInfo();
2771    perl_exception=newSVpv("",0);
2772    sv=NULL;
2773    number_images=0;
2774    ac=(items < 2) ? 1 : items-1;
2775    length=(STRLEN *) NULL;
2776    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2777    if (list == (char **) NULL)
2778      {
2779        ThrowPerlException(exception,ResourceLimitError,
2780          "MemoryAllocationFailed",PackageName);
2781        goto PerlException;
2782      }
2783    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2784    if (length == (STRLEN *) NULL)
2785      {
2786        ThrowPerlException(exception,ResourceLimitError,
2787          "MemoryAllocationFailed",PackageName);
2788        goto PerlException;
2789      }
2790    if (sv_isobject(ST(0)) == 0)
2791      {
2792        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2793          PackageName);
2794        goto PerlException;
2795      }
2796    reference=SvRV(ST(0));
2797    hv=SvSTASH(reference);
2798    if (SvTYPE(reference) != SVt_PVAV)
2799      {
2800        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2801          PackageName);
2802        goto PerlException;
2803      }
2804    av=(AV *) reference;
2805    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2806      exception);
2807    n=1;
2808    if (items <= 1)
2809      {
2810        ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2811        goto PerlException;
2812      }
2813    for (n=0, i=0; i < ac; i++)
2814    {
2815      list[n]=(char *) (SvPV(ST(i+1),length[n]));
2816      if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2817        {
2818          list[n]=(char *) (SvPV(ST(i+2),length[n]));
2819          continue;
2820        }
2821      n++;
2822    }
2823    list[n]=(char *) NULL;
2824    keep=list;
2825    for (i=number_images=0; i < n; i++)
2826    {
2827      image=BlobToImage(info->image_info,list[i],length[i],exception);
2828      if (image == (Image *) NULL)
2829        break;
2830      for ( ; image; image=image->next)
2831      {
2832        AddImageToRegistry(sv,image);
2833        rv=newRV(sv);
2834        av_push(av,sv_bless(rv,hv));
2835        SvREFCNT_dec(sv);
2836        number_images++;
2837      }
2838    }
2839    /*
2840      Free resources.
2841    */
2842    for (i=0; i < n; i++)
2843      if (list[i] != (char *) NULL)
2844        for (p=keep; list[i] != *p++; )
2845          if (*p == (char *) NULL)
2846            {
2847              list[i]=(char *) RelinquishMagickMemory(list[i]);
2848              break;
2849            }
2850
2851  PerlException:
2852    if (list)
2853      list=(char **) RelinquishMagickMemory(list);
2854    if (length)
2855      length=(STRLEN *) RelinquishMagickMemory(length);
2856    InheritPerlException(exception,perl_exception);
2857    exception=DestroyExceptionInfo(exception);
2858    sv_setiv(perl_exception,(IV) number_images);
2859    SvPOK_on(perl_exception);
2860    ST(0)=sv_2mortal(perl_exception);
2861    XSRETURN(1);
2862  }
2863
2864#
2865###############################################################################
2866#                                                                             #
2867#                                                                             #
2868#                                                                             #
2869#   C h a n n e l F x                                                         #
2870#                                                                             #
2871#                                                                             #
2872#                                                                             #
2873###############################################################################
2874#
2875#
2876void
2877ChannelFx(ref,...)
2878  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2879  ALIAS:
2880    ChannelFxImage  = 1
2881    channelfx       = 2
2882    channelfximage  = 3
2883  PPCODE:
2884  {
2885    AV
2886      *av;
2887
2888    char
2889      *attribute,
2890      expression[MagickPathExtent];
2891
2892    ChannelType
2893      channel,
2894      channel_mask;
2895
2896    ExceptionInfo
2897      *exception;
2898
2899    HV
2900      *hv;
2901
2902    Image
2903      *image;
2904
2905    register ssize_t
2906      i;
2907
2908    struct PackageInfo
2909      *info;
2910
2911    SV
2912      *av_reference,
2913      *perl_exception,
2914      *reference,
2915      *rv,
2916      *sv;
2917
2918    PERL_UNUSED_VAR(ref);
2919    PERL_UNUSED_VAR(ix);
2920    exception=AcquireExceptionInfo();
2921    perl_exception=newSVpv("",0);
2922    sv=NULL;
2923    attribute=NULL;
2924    av=NULL;
2925    if (sv_isobject(ST(0)) == 0)
2926      {
2927        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2928          PackageName);
2929        goto PerlException;
2930      }
2931    reference=SvRV(ST(0));
2932    hv=SvSTASH(reference);
2933    av=newAV();
2934    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2935    SvREFCNT_dec(av);
2936    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2937    if (image == (Image *) NULL)
2938      {
2939        ThrowPerlException(exception,OptionError,"NoImagesDefined",
2940          PackageName);
2941        goto PerlException;
2942      }
2943    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2944    /*
2945      Get options.
2946    */
2947    channel=DefaultChannels;
2948    (void) CopyMagickString(expression,"u",MagickPathExtent);
2949    if (items == 2)
2950      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2951    else
2952      for (i=2; i < items; i+=2)
2953      {
2954        attribute=(char *) SvPV(ST(i-1),na);
2955        switch (*attribute)
2956        {
2957          case 'C':
2958          case 'c':
2959          {
2960            if (LocaleCompare(attribute,"channel") == 0)
2961              {
2962                ssize_t
2963                  option;
2964
2965                option=ParseChannelOption(SvPV(ST(i),na));
2966                if (option < 0)
2967                  {
2968                    ThrowPerlException(exception,OptionError,
2969                      "UnrecognizedType",SvPV(ST(i),na));
2970                    return;
2971                  }
2972                channel=(ChannelType) option;
2973                break;
2974              }
2975            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2976              attribute);
2977            break;
2978          }
2979          case 'E':
2980          case 'e':
2981          {
2982            if (LocaleCompare(attribute,"expression") == 0)
2983              {
2984                (void) CopyMagickString(expression,SvPV(ST(i),na),
2985                  MagickPathExtent);
2986                break;
2987              }
2988            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2989              attribute);
2990            break;
2991          }
2992          default:
2993          {
2994            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2995              attribute);
2996            break;
2997          }
2998        }
2999      }
3000    channel_mask=SetImageChannelMask(image,channel);
3001    image=ChannelFxImage(image,expression,exception);
3002    if (image != (Image *) NULL)
3003      (void) SetImageChannelMask(image,channel_mask);
3004    if (image == (Image *) NULL)
3005      goto PerlException;
3006    for ( ; image; image=image->next)
3007    {
3008      AddImageToRegistry(sv,image);
3009      rv=newRV(sv);
3010      av_push(av,sv_bless(rv,hv));
3011      SvREFCNT_dec(sv);
3012    }
3013    exception=DestroyExceptionInfo(exception);
3014    ST(0)=av_reference;
3015    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3016    XSRETURN(1);
3017
3018  PerlException:
3019    InheritPerlException(exception,perl_exception);
3020    exception=DestroyExceptionInfo(exception);
3021    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3022    SvPOK_on(perl_exception);
3023    ST(0)=sv_2mortal(perl_exception);
3024    XSRETURN(1);
3025  }
3026
3027#
3028###############################################################################
3029#                                                                             #
3030#                                                                             #
3031#                                                                             #
3032#   C l o n e                                                                 #
3033#                                                                             #
3034#                                                                             #
3035#                                                                             #
3036###############################################################################
3037#
3038#
3039void
3040Clone(ref)
3041  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3042  ALIAS:
3043    CopyImage   = 1
3044    copy        = 2
3045    copyimage   = 3
3046    CloneImage  = 4
3047    clone       = 5
3048    cloneimage  = 6
3049    Clone       = 7
3050  PPCODE:
3051  {
3052    AV
3053      *av;
3054
3055    ExceptionInfo
3056      *exception;
3057
3058    HV
3059      *hv;
3060
3061    Image
3062      *clone,
3063      *image;
3064
3065    struct PackageInfo
3066      *info;
3067
3068    SV
3069      *perl_exception,
3070      *reference,
3071      *rv,
3072      *sv;
3073
3074    PERL_UNUSED_VAR(ref);
3075    PERL_UNUSED_VAR(ix);
3076    exception=AcquireExceptionInfo();
3077    perl_exception=newSVpv("",0);
3078    sv=NULL;
3079    if (sv_isobject(ST(0)) == 0)
3080      {
3081        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3082          PackageName);
3083        goto PerlException;
3084      }
3085    reference=SvRV(ST(0));
3086    hv=SvSTASH(reference);
3087    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3088    if (image == (Image *) NULL)
3089      {
3090        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3091          PackageName);
3092        goto PerlException;
3093      }
3094    /*
3095      Create blessed Perl array for the returned image.
3096    */
3097    av=newAV();
3098    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3099    SvREFCNT_dec(av);
3100    for ( ; image; image=image->next)
3101    {
3102      clone=CloneImage(image,0,0,MagickTrue,exception);
3103      if (clone == (Image *) NULL)
3104        break;
3105      AddImageToRegistry(sv,clone);
3106      rv=newRV(sv);
3107      av_push(av,sv_bless(rv,hv));
3108      SvREFCNT_dec(sv);
3109    }
3110    exception=DestroyExceptionInfo(exception);
3111    SvREFCNT_dec(perl_exception);
3112    XSRETURN(1);
3113
3114  PerlException:
3115    InheritPerlException(exception,perl_exception);
3116    exception=DestroyExceptionInfo(exception);
3117    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3118    SvPOK_on(perl_exception);
3119    ST(0)=sv_2mortal(perl_exception);
3120    XSRETURN(1);
3121  }
3122
3123#
3124###############################################################################
3125#                                                                             #
3126#                                                                             #
3127#                                                                             #
3128#   C L O N E                                                                 #
3129#                                                                             #
3130#                                                                             #
3131#                                                                             #
3132###############################################################################
3133#
3134#
3135void
3136CLONE(ref,...)
3137  SV *ref;
3138  CODE:
3139  {
3140    PERL_UNUSED_VAR(ref);
3141    if (magick_registry != (SplayTreeInfo *) NULL)
3142      {
3143        register Image
3144          *p;
3145
3146        ResetSplayTreeIterator(magick_registry);
3147        p=(Image *) GetNextKeyInSplayTree(magick_registry);
3148        while (p != (Image *) NULL)
3149        {
3150          ReferenceImage(p);
3151          p=(Image *) GetNextKeyInSplayTree(magick_registry);
3152        }
3153      }
3154  }
3155
3156#
3157###############################################################################
3158#                                                                             #
3159#                                                                             #
3160#                                                                             #
3161#   C o a l e s c e                                                           #
3162#                                                                             #
3163#                                                                             #
3164#                                                                             #
3165###############################################################################
3166#
3167#
3168void
3169Coalesce(ref)
3170  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3171  ALIAS:
3172    CoalesceImage   = 1
3173    coalesce        = 2
3174    coalesceimage   = 3
3175  PPCODE:
3176  {
3177    AV
3178      *av;
3179
3180    ExceptionInfo
3181      *exception;
3182
3183    HV
3184      *hv;
3185
3186    Image
3187      *image;
3188
3189    struct PackageInfo
3190      *info;
3191
3192    SV
3193      *av_reference,
3194      *perl_exception,
3195      *reference,
3196      *rv,
3197      *sv;
3198
3199    PERL_UNUSED_VAR(ref);
3200    PERL_UNUSED_VAR(ix);
3201    exception=AcquireExceptionInfo();
3202    perl_exception=newSVpv("",0);
3203    sv=NULL;
3204    if (sv_isobject(ST(0)) == 0)
3205      {
3206        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3207          PackageName);
3208        goto PerlException;
3209      }
3210    reference=SvRV(ST(0));
3211    hv=SvSTASH(reference);
3212    av=newAV();
3213    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3214    SvREFCNT_dec(av);
3215    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3216    if (image == (Image *) NULL)
3217      {
3218        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3219          PackageName);
3220        goto PerlException;
3221      }
3222    image=CoalesceImages(image,exception);
3223    if (image == (Image *) NULL)
3224      goto PerlException;
3225    for ( ; image; image=image->next)
3226    {
3227      AddImageToRegistry(sv,image);
3228      rv=newRV(sv);
3229      av_push(av,sv_bless(rv,hv));
3230      SvREFCNT_dec(sv);
3231    }
3232    exception=DestroyExceptionInfo(exception);
3233    ST(0)=av_reference;
3234    SvREFCNT_dec(perl_exception);
3235    XSRETURN(1);
3236
3237  PerlException:
3238    InheritPerlException(exception,perl_exception);
3239    exception=DestroyExceptionInfo(exception);
3240    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3241    SvPOK_on(perl_exception);
3242    ST(0)=sv_2mortal(perl_exception);
3243    XSRETURN(1);
3244  }
3245
3246#
3247###############################################################################
3248#                                                                             #
3249#                                                                             #
3250#                                                                             #
3251#   C o m p a r e                                                             #
3252#                                                                             #
3253#                                                                             #
3254#                                                                             #
3255###############################################################################
3256#
3257#
3258void
3259Compare(ref,...)
3260  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3261  ALIAS:
3262    CompareImages = 1
3263    compare      = 2
3264    compareimage = 3
3265  PPCODE:
3266  {
3267    AV
3268      *av;
3269
3270    char
3271      *attribute;
3272
3273    double
3274      distortion;
3275
3276    ExceptionInfo
3277      *exception;
3278
3279    HV
3280      *hv;
3281
3282    Image
3283      *difference_image,
3284      *image,
3285      *reconstruct_image;
3286
3287    MetricType
3288      metric;
3289
3290    register ssize_t
3291      i;
3292
3293    ssize_t
3294      option;
3295
3296    struct PackageInfo
3297      *info;
3298
3299    SV
3300      *av_reference,
3301      *perl_exception,
3302      *reference,
3303      *rv,
3304      *sv;
3305
3306    PERL_UNUSED_VAR(ref);
3307    PERL_UNUSED_VAR(ix);
3308    exception=AcquireExceptionInfo();
3309    perl_exception=newSVpv("",0);
3310    sv=NULL;
3311    av=NULL;
3312    attribute=NULL;
3313    if (sv_isobject(ST(0)) == 0)
3314      {
3315        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3316          PackageName);
3317        goto PerlException;
3318      }
3319    reference=SvRV(ST(0));
3320    hv=SvSTASH(reference);
3321    av=newAV();
3322    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3323    SvREFCNT_dec(av);
3324    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3325    if (image == (Image *) NULL)
3326      {
3327        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3328          PackageName);
3329        goto PerlException;
3330      }
3331    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3332    /*
3333      Get attribute.
3334    */
3335    reconstruct_image=image;
3336    metric=RootMeanSquaredErrorMetric;
3337    for (i=2; i < items; i+=2)
3338    {
3339      attribute=(char *) SvPV(ST(i-1),na);
3340      switch (*attribute)
3341      {
3342        case 'C':
3343        case 'c':
3344        {
3345          if (LocaleCompare(attribute,"channel") == 0)
3346            {
3347              ssize_t
3348                option;
3349
3350              option=ParseChannelOption(SvPV(ST(i),na));
3351              if (option < 0)
3352                {
3353                  ThrowPerlException(exception,OptionError,
3354                    "UnrecognizedType",SvPV(ST(i),na));
3355                  return;
3356                }
3357              (void) SetPixelChannelMask(image,(ChannelType) option);
3358              break;
3359            }
3360          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3361            attribute);
3362          break;
3363        }
3364        case 'F':
3365        case 'f':
3366        {
3367          if (LocaleCompare(attribute,"fuzz") == 0)
3368            {
3369              image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3370              break;
3371            }
3372          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3373            attribute);
3374          break;
3375        }
3376        case 'I':
3377        case 'i':
3378        {
3379          if (LocaleCompare(attribute,"image") == 0)
3380            {
3381              reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3382                (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3383              break;
3384            }
3385          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386            attribute);
3387          break;
3388        }
3389        case 'M':
3390        case 'm':
3391        {
3392          if (LocaleCompare(attribute,"metric") == 0)
3393            {
3394              option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3395                SvPV(ST(i),na));
3396              if (option < 0)
3397                {
3398                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3399                    SvPV(ST(i),na));
3400                  break;
3401                }
3402              metric=(MetricType) option;
3403              break;
3404            }
3405          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3406            attribute);
3407          break;
3408        }
3409        default:
3410        {
3411          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3412            attribute);
3413          break;
3414        }
3415      }
3416    }
3417    difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3418      exception);
3419    if (difference_image != (Image *) NULL)
3420      {
3421        difference_image->error.mean_error_per_pixel=distortion;
3422        AddImageToRegistry(sv,difference_image);
3423        rv=newRV(sv);
3424        av_push(av,sv_bless(rv,hv));
3425        SvREFCNT_dec(sv);
3426      }
3427    exception=DestroyExceptionInfo(exception);
3428    ST(0)=av_reference;
3429    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3430    XSRETURN(1);
3431
3432  PerlException:
3433    InheritPerlException(exception,perl_exception);
3434    exception=DestroyExceptionInfo(exception);
3435    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3436    SvPOK_on(perl_exception);
3437    ST(0)=sv_2mortal(perl_exception);
3438    XSRETURN(1);
3439  }
3440
3441#
3442###############################################################################
3443#                                                                             #
3444#                                                                             #
3445#                                                                             #
3446#   C o m p l e x I m a g e s                                                 #
3447#                                                                             #
3448#                                                                             #
3449#                                                                             #
3450###############################################################################
3451#
3452#
3453void
3454ComplexImages(ref)
3455  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3456  ALIAS:
3457    ComplexImages   = 1
3458    compleximages   = 2
3459  PPCODE:
3460  {
3461    AV
3462      *av;
3463
3464    char
3465      *attribute,
3466      *p;
3467
3468    ComplexOperator
3469      op;
3470
3471    ExceptionInfo
3472      *exception;
3473
3474    HV
3475      *hv;
3476
3477    Image
3478      *image;
3479
3480    register ssize_t
3481      i;
3482
3483    struct PackageInfo
3484      *info;
3485
3486    SV
3487      *perl_exception,
3488      *reference,
3489      *rv,
3490      *sv;
3491
3492    PERL_UNUSED_VAR(ref);
3493    PERL_UNUSED_VAR(ix);
3494    exception=AcquireExceptionInfo();
3495    perl_exception=newSVpv("",0);
3496    sv=NULL;
3497    if (sv_isobject(ST(0)) == 0)
3498      {
3499        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3500          PackageName);
3501        goto PerlException;
3502      }
3503    reference=SvRV(ST(0));
3504    hv=SvSTASH(reference);
3505    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3506    if (image == (Image *) NULL)
3507      {
3508        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3509          PackageName);
3510        goto PerlException;
3511      }
3512    op=UndefinedComplexOperator;
3513    if (items == 2)
3514      {
3515        ssize_t
3516          in;
3517
3518        in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3519          SvPV(ST(1),na));
3520        if (in < 0)
3521          {
3522            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3523              SvPV(ST(1),na));
3524            return;
3525          }
3526        op=(ComplexOperator) in;
3527      }
3528    else
3529      for (i=2; i < items; i+=2)
3530      {
3531        attribute=(char *) SvPV(ST(i-1),na);
3532        switch (*attribute)
3533        {
3534          case 'O':
3535          case 'o':
3536          {
3537            if (LocaleCompare(attribute,"operator") == 0)
3538              {
3539                ssize_t
3540                  in;
3541
3542                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3543                  MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3544                if (in < 0)
3545                  {
3546                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
3547                      SvPV(ST(i),na));
3548                    return;
3549                  }
3550                op=(ComplexOperator) in;
3551                break;
3552              }
3553            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3554              attribute);
3555            break;
3556          }
3557          default:
3558          {
3559            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3560              attribute);
3561            break;
3562          }
3563        }
3564      }
3565    image=ComplexImages(image,op,exception);
3566    if (image == (Image *) NULL)
3567      goto PerlException;
3568    /*
3569      Create blessed Perl array for the returned image.
3570    */
3571    av=newAV();
3572    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3573    SvREFCNT_dec(av);
3574    AddImageToRegistry(sv,image);
3575    rv=newRV(sv);
3576    av_push(av,sv_bless(rv,hv));
3577    SvREFCNT_dec(sv);
3578    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3579    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3580      "complex-%.*s",(int) (MagickPathExtent-9),
3581      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3582    (void) CopyMagickString(image->filename,info->image_info->filename,
3583      MagickPathExtent);
3584    SetImageInfo(info->image_info,0,exception);
3585    exception=DestroyExceptionInfo(exception);
3586    SvREFCNT_dec(perl_exception);
3587    XSRETURN(1);
3588
3589  PerlException:
3590    InheritPerlException(exception,perl_exception);
3591    exception=DestroyExceptionInfo(exception);
3592    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3593    SvPOK_on(perl_exception);
3594    ST(0)=sv_2mortal(perl_exception);
3595    XSRETURN(1);
3596  }
3597
3598#
3599###############################################################################
3600#                                                                             #
3601#                                                                             #
3602#                                                                             #
3603#   C o m p a r e L a y e r s                                                 #
3604#                                                                             #
3605#                                                                             #
3606#                                                                             #
3607###############################################################################
3608#
3609#
3610void
3611CompareLayers(ref)
3612  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3613  ALIAS:
3614    CompareImagesLayers   = 1
3615    comparelayers        = 2
3616    compareimagelayers   = 3
3617  PPCODE:
3618  {
3619    AV
3620      *av;
3621
3622    char
3623      *attribute;
3624
3625    ExceptionInfo
3626      *exception;
3627
3628    HV
3629      *hv;
3630
3631    Image
3632      *image;
3633
3634    LayerMethod
3635      method;
3636
3637    register ssize_t
3638      i;
3639
3640    ssize_t
3641      option;
3642
3643    struct PackageInfo
3644      *info;
3645
3646    SV
3647      *av_reference,
3648      *perl_exception,
3649      *reference,
3650      *rv,
3651      *sv;
3652
3653    PERL_UNUSED_VAR(ref);
3654    PERL_UNUSED_VAR(ix);
3655    exception=AcquireExceptionInfo();
3656    perl_exception=newSVpv("",0);
3657    sv=NULL;
3658    if (sv_isobject(ST(0)) == 0)
3659      {
3660        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3661          PackageName);
3662        goto PerlException;
3663      }
3664    reference=SvRV(ST(0));
3665    hv=SvSTASH(reference);
3666    av=newAV();
3667    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3668    SvREFCNT_dec(av);
3669    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3670    if (image == (Image *) NULL)
3671      {
3672        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3673          PackageName);
3674        goto PerlException;
3675      }
3676    method=CompareAnyLayer;
3677    for (i=2; i < items; i+=2)
3678    {
3679      attribute=(char *) SvPV(ST(i-1),na);
3680      switch (*attribute)
3681      {
3682        case 'M':
3683        case 'm':
3684        {
3685          if (LocaleCompare(attribute,"method") == 0)
3686            {
3687              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3688                SvPV(ST(i),na));
3689              if (option < 0)
3690                {
3691                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
3692                    SvPV(ST(i),na));
3693                  break;
3694                }
3695               method=(LayerMethod) option;
3696              break;
3697            }
3698          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3699            attribute);
3700          break;
3701        }
3702        default:
3703        {
3704          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3705            attribute);
3706          break;
3707        }
3708      }
3709    }
3710    image=CompareImagesLayers(image,method,exception);
3711    if (image == (Image *) NULL)
3712      goto PerlException;
3713    for ( ; image; image=image->next)
3714    {
3715      AddImageToRegistry(sv,image);
3716      rv=newRV(sv);
3717      av_push(av,sv_bless(rv,hv));
3718      SvREFCNT_dec(sv);
3719    }
3720    exception=DestroyExceptionInfo(exception);
3721    ST(0)=av_reference;
3722    SvREFCNT_dec(perl_exception);
3723    XSRETURN(1);
3724
3725  PerlException:
3726    InheritPerlException(exception,perl_exception);
3727    exception=DestroyExceptionInfo(exception);
3728    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3729    SvPOK_on(perl_exception);
3730    ST(0)=sv_2mortal(perl_exception);
3731    XSRETURN(1);
3732  }
3733
3734#
3735###############################################################################
3736#                                                                             #
3737#                                                                             #
3738#                                                                             #
3739#   D e s t r o y                                                             #
3740#                                                                             #
3741#                                                                             #
3742#                                                                             #
3743###############################################################################
3744#
3745#
3746void
3747DESTROY(ref)
3748  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3749  PPCODE:
3750  {
3751    SV
3752      *reference;
3753
3754    PERL_UNUSED_VAR(ref);
3755    if (sv_isobject(ST(0)) == 0)
3756      croak("ReferenceIsNotMyType");
3757    reference=SvRV(ST(0));
3758    switch (SvTYPE(reference))
3759    {
3760      case SVt_PVAV:
3761      {
3762        char
3763          message[MagickPathExtent];
3764
3765        const SV
3766          *key;
3767
3768        HV
3769          *hv;
3770
3771        GV
3772          **gvp;
3773
3774        struct PackageInfo
3775          *info;
3776
3777        SV
3778          *sv;
3779
3780        /*
3781          Array (AV *) reference
3782        */
3783        (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3784          XS_VERSION,reference);
3785        hv=gv_stashpv(PackageName, FALSE);
3786        if (!hv)
3787          break;
3788        gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3789        if (!gvp)
3790          break;
3791        sv=GvSV(*gvp);
3792        if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3793          {
3794            info=INT2PTR(struct PackageInfo *,SvIV(sv));
3795            DestroyPackageInfo(info);
3796          }
3797        key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3798        (void) key;
3799        break;
3800      }
3801      case SVt_PVMG:
3802      {
3803        Image
3804          *image;
3805
3806        /*
3807          Blessed scalar = (Image *) SvIV(reference)
3808        */
3809        image=INT2PTR(Image *,SvIV(reference));
3810        if (image != (Image *) NULL)
3811          DeleteImageFromRegistry(reference,image);
3812        break;
3813      }
3814      default:
3815        break;
3816    }
3817  }
3818
3819#
3820###############################################################################
3821#                                                                             #
3822#                                                                             #
3823#                                                                             #
3824#   D i s p l a y                                                             #
3825#                                                                             #
3826#                                                                             #
3827#                                                                             #
3828###############################################################################
3829#
3830#
3831void
3832Display(ref,...)
3833  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3834  ALIAS:
3835    DisplayImage  = 1
3836    display       = 2
3837    displayimage  = 3
3838  PPCODE:
3839  {
3840    ExceptionInfo
3841      *exception;
3842
3843    Image
3844      *image;
3845
3846    register ssize_t
3847      i;
3848
3849    struct PackageInfo
3850      *info,
3851      *package_info;
3852
3853    SV
3854      *perl_exception,
3855      *reference;
3856
3857    PERL_UNUSED_VAR(ref);
3858    PERL_UNUSED_VAR(ix);
3859    exception=AcquireExceptionInfo();
3860    perl_exception=newSVpv("",0);
3861    package_info=(struct PackageInfo *) NULL;
3862    if (sv_isobject(ST(0)) == 0)
3863      {
3864        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3865          PackageName);
3866        goto PerlException;
3867      }
3868    reference=SvRV(ST(0));
3869    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3870    if (image == (Image *) NULL)
3871      {
3872        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3873          PackageName);
3874        goto PerlException;
3875      }
3876    package_info=ClonePackageInfo(info,exception);
3877    if (items == 2)
3878      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3879    else
3880      if (items > 2)
3881        for (i=2; i < items; i+=2)
3882          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3883            exception);
3884    (void) DisplayImages(package_info->image_info,image,exception);
3885    (void) CatchImageException(image);
3886
3887  PerlException:
3888    if (package_info != (struct PackageInfo *) NULL)
3889      DestroyPackageInfo(package_info);
3890    InheritPerlException(exception,perl_exception);
3891    exception=DestroyExceptionInfo(exception);
3892    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3893    SvPOK_on(perl_exception);
3894    ST(0)=sv_2mortal(perl_exception);
3895    XSRETURN(1);
3896  }
3897
3898#
3899###############################################################################
3900#                                                                             #
3901#                                                                             #
3902#                                                                             #
3903#   E v a l u a t e I m a g e s                                               #
3904#                                                                             #
3905#                                                                             #
3906#                                                                             #
3907###############################################################################
3908#
3909#
3910void
3911EvaluateImages(ref)
3912  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3913  ALIAS:
3914    EvaluateImages   = 1
3915    evaluateimages   = 2
3916  PPCODE:
3917  {
3918    AV
3919      *av;
3920
3921    char
3922      *attribute,
3923      *p;
3924
3925    ExceptionInfo
3926      *exception;
3927
3928    HV
3929      *hv;
3930
3931    Image
3932      *image;
3933
3934    MagickEvaluateOperator
3935      op;
3936
3937    register ssize_t
3938      i;
3939
3940    struct PackageInfo
3941      *info;
3942
3943    SV
3944      *perl_exception,
3945      *reference,
3946      *rv,
3947      *sv;
3948
3949    PERL_UNUSED_VAR(ref);
3950    PERL_UNUSED_VAR(ix);
3951    exception=AcquireExceptionInfo();
3952    perl_exception=newSVpv("",0);
3953    sv=NULL;
3954    if (sv_isobject(ST(0)) == 0)
3955      {
3956        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3957          PackageName);
3958        goto PerlException;
3959      }
3960    reference=SvRV(ST(0));
3961    hv=SvSTASH(reference);
3962    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3963    if (image == (Image *) NULL)
3964      {
3965        ThrowPerlException(exception,OptionError,"NoImagesDefined",
3966          PackageName);
3967        goto PerlException;
3968      }
3969    op=MeanEvaluateOperator;
3970    if (items == 2)
3971      {
3972        ssize_t
3973          in;
3974
3975        in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3976          SvPV(ST(1),na));
3977        if (in < 0)
3978          {
3979            ThrowPerlException(exception,OptionError,"UnrecognizedType",
3980              SvPV(ST(1),na));
3981            return;
3982          }
3983        op=(MagickEvaluateOperator) in;
3984      }
3985    else
3986      for (i=2; i < items; i+=2)
3987      {
3988        attribute=(char *) SvPV(ST(i-1),na);
3989        switch (*attribute)
3990        {
3991          case 'O':
3992          case 'o':
3993          {
3994            if (LocaleCompare(attribute,"operator") == 0)
3995              {
3996                ssize_t
3997                  in;
3998
3999                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4000                  MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4001                if (in < 0)
4002                  {
4003                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
4004                      SvPV(ST(i),na));
4005                    return;
4006                  }
4007                op=(MagickEvaluateOperator) in;
4008                break;
4009              }
4010            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4011              attribute);
4012            break;
4013          }
4014          default:
4015          {
4016            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4017              attribute);
4018            break;
4019          }
4020        }
4021      }
4022    image=EvaluateImages(image,op,exception);
4023    if (image == (Image *) NULL)
4024      goto PerlException;
4025    /*
4026      Create blessed Perl array for the returned image.
4027    */
4028    av=newAV();
4029    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4030    SvREFCNT_dec(av);
4031    AddImageToRegistry(sv,image);
4032    rv=newRV(sv);
4033    av_push(av,sv_bless(rv,hv));
4034    SvREFCNT_dec(sv);
4035    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4036    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4037      "evaluate-%.*s",(int) (MagickPathExtent-9),
4038      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4039    (void) CopyMagickString(image->filename,info->image_info->filename,
4040      MagickPathExtent);
4041    SetImageInfo(info->image_info,0,exception);
4042    exception=DestroyExceptionInfo(exception);
4043    SvREFCNT_dec(perl_exception);
4044    XSRETURN(1);
4045
4046  PerlException:
4047    InheritPerlException(exception,perl_exception);
4048    exception=DestroyExceptionInfo(exception);
4049    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4050    SvPOK_on(perl_exception);
4051    ST(0)=sv_2mortal(perl_exception);
4052    XSRETURN(1);
4053  }
4054
4055#
4056###############################################################################
4057#                                                                             #
4058#                                                                             #
4059#                                                                             #
4060#   F e a t u r e s                                                           #
4061#                                                                             #
4062#                                                                             #
4063#                                                                             #
4064###############################################################################
4065#
4066#
4067void
4068Features(ref,...)
4069  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4070  ALIAS:
4071    FeaturesImage = 1
4072    features      = 2
4073    featuresimage = 3
4074  PPCODE:
4075  {
4076#define ChannelFeatures(channel,direction) \
4077{ \
4078  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4079    channel_features[channel].angular_second_moment[direction]); \
4080  PUSHs(sv_2mortal(newSVpv(message,0))); \
4081  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4082    channel_features[channel].contrast[direction]); \
4083  PUSHs(sv_2mortal(newSVpv(message,0))); \
4084  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4085    channel_features[channel].contrast[direction]); \
4086  PUSHs(sv_2mortal(newSVpv(message,0))); \
4087  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4088    channel_features[channel].variance_sum_of_squares[direction]); \
4089  PUSHs(sv_2mortal(newSVpv(message,0))); \
4090  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4091    channel_features[channel].inverse_difference_moment[direction]); \
4092  PUSHs(sv_2mortal(newSVpv(message,0))); \
4093  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4094    channel_features[channel].sum_average[direction]); \
4095  PUSHs(sv_2mortal(newSVpv(message,0))); \
4096  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097    channel_features[channel].sum_variance[direction]); \
4098  PUSHs(sv_2mortal(newSVpv(message,0))); \
4099  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100    channel_features[channel].sum_entropy[direction]); \
4101  PUSHs(sv_2mortal(newSVpv(message,0))); \
4102  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103    channel_features[channel].entropy[direction]); \
4104  PUSHs(sv_2mortal(newSVpv(message,0))); \
4105  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106    channel_features[channel].difference_variance[direction]); \
4107  PUSHs(sv_2mortal(newSVpv(message,0))); \
4108  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109    channel_features[channel].difference_entropy[direction]); \
4110  PUSHs(sv_2mortal(newSVpv(message,0))); \
4111  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112    channel_features[channel].measure_of_correlation_1[direction]); \
4113  PUSHs(sv_2mortal(newSVpv(message,0))); \
4114  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4115    channel_features[channel].measure_of_correlation_2[direction]); \
4116  PUSHs(sv_2mortal(newSVpv(message,0))); \
4117  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4118    channel_features[channel].maximum_correlation_coefficient[direction]); \
4119  PUSHs(sv_2mortal(newSVpv(message,0))); \
4120}
4121
4122    AV
4123      *av;
4124
4125    char
4126      *attribute,
4127      message[MagickPathExtent];
4128
4129    ChannelFeatures
4130      *channel_features;
4131
4132    double
4133      distance;
4134
4135    ExceptionInfo
4136      *exception;
4137
4138    Image
4139      *image;
4140
4141    register ssize_t
4142      i;
4143
4144    ssize_t
4145      count;
4146
4147    struct PackageInfo
4148      *info;
4149
4150    SV
4151      *perl_exception,
4152      *reference;
4153
4154    PERL_UNUSED_VAR(ref);
4155    PERL_UNUSED_VAR(ix);
4156    exception=AcquireExceptionInfo();
4157    perl_exception=newSVpv("",0);
4158    av=NULL;
4159    if (sv_isobject(ST(0)) == 0)
4160      {
4161        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4162          PackageName);
4163        goto PerlException;
4164      }
4165    reference=SvRV(ST(0));
4166    av=newAV();
4167    SvREFCNT_dec(av);
4168    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4169    if (image == (Image *) NULL)
4170      {
4171        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4172          PackageName);
4173        goto PerlException;
4174      }
4175    distance=1.0;
4176    for (i=2; i < items; i+=2)
4177    {
4178      attribute=(char *) SvPV(ST(i-1),na);
4179      switch (*attribute)
4180      {
4181        case 'D':
4182        case 'd':
4183        {
4184          if (LocaleCompare(attribute,"distance") == 0)
4185            {
4186              distance=StringToLong((char *) SvPV(ST(1),na));
4187              break;
4188            }
4189          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4190            attribute);
4191          break;
4192        }
4193        default:
4194        {
4195          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4196            attribute);
4197          break;
4198        }
4199      }
4200    }
4201    count=0;
4202    for ( ; image; image=image->next)
4203    {
4204      channel_features=GetImageFeatures(image,distance,exception);
4205      if (channel_features == (ChannelFeatures *) NULL)
4206        continue;
4207      count++;
4208      EXTEND(sp,280*count);
4209      for (i=0; i < 4; i++)
4210      {
4211        ChannelFeatures(RedChannel,i);
4212        ChannelFeatures(GreenChannel,i);
4213        ChannelFeatures(BlueChannel,i);
4214        if (image->colorspace == CMYKColorspace)
4215          ChannelFeatures(BlackChannel,i);
4216        if (image->alpha_trait != UndefinedPixelTrait)
4217          ChannelFeatures(AlphaChannel,i);
4218      }
4219      channel_features=(ChannelFeatures *)
4220        RelinquishMagickMemory(channel_features);
4221    }
4222
4223  PerlException:
4224    InheritPerlException(exception,perl_exception);
4225    exception=DestroyExceptionInfo(exception);
4226    SvREFCNT_dec(perl_exception);
4227  }
4228
4229#
4230###############################################################################
4231#                                                                             #
4232#                                                                             #
4233#                                                                             #
4234#   F l a t t e n                                                             #
4235#                                                                             #
4236#                                                                             #
4237#                                                                             #
4238###############################################################################
4239#
4240#
4241void
4242Flatten(ref)
4243  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4244  ALIAS:
4245    FlattenImage   = 1
4246    flatten        = 2
4247    flattenimage   = 3
4248  PPCODE:
4249  {
4250    AV
4251      *av;
4252
4253    char
4254      *attribute,
4255      *p;
4256
4257    ExceptionInfo
4258      *exception;
4259
4260    HV
4261      *hv;
4262
4263    Image
4264      *image;
4265
4266    PixelInfo
4267      background_color;
4268
4269    register ssize_t
4270      i;
4271
4272    struct PackageInfo
4273      *info;
4274
4275    SV
4276      *perl_exception,
4277      *reference,
4278      *rv,
4279      *sv;
4280
4281    PERL_UNUSED_VAR(ref);
4282    PERL_UNUSED_VAR(ix);
4283    exception=AcquireExceptionInfo();
4284    perl_exception=newSVpv("",0);
4285    sv=NULL;
4286    if (sv_isobject(ST(0)) == 0)
4287      {
4288        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4289          PackageName);
4290        goto PerlException;
4291      }
4292    reference=SvRV(ST(0));
4293    hv=SvSTASH(reference);
4294    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4295    if (image == (Image *) NULL)
4296      {
4297        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4298          PackageName);
4299        goto PerlException;
4300      }
4301    background_color=image->background_color;
4302    if (items == 2)
4303      (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4304        &background_color,exception);
4305    else
4306      for (i=2; i < items; i+=2)
4307      {
4308        attribute=(char *) SvPV(ST(i-1),na);
4309        switch (*attribute)
4310        {
4311          case 'B':
4312          case 'b':
4313          {
4314            if (LocaleCompare(attribute,"background") == 0)
4315              {
4316                (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4317                  AllCompliance,&background_color,exception);
4318                break;
4319              }
4320            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4321              attribute);
4322            break;
4323          }
4324          default:
4325          {
4326            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4327              attribute);
4328            break;
4329          }
4330        }
4331      }
4332    image->background_color=background_color;
4333    image=MergeImageLayers(image,FlattenLayer,exception);
4334    if (image == (Image *) NULL)
4335      goto PerlException;
4336    /*
4337      Create blessed Perl array for the returned image.
4338    */
4339    av=newAV();
4340    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4341    SvREFCNT_dec(av);
4342    AddImageToRegistry(sv,image);
4343    rv=newRV(sv);
4344    av_push(av,sv_bless(rv,hv));
4345    SvREFCNT_dec(sv);
4346    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4347    (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4348      "flatten-%.*s",(int) (MagickPathExtent-9),
4349      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4350    (void) CopyMagickString(image->filename,info->image_info->filename,
4351      MagickPathExtent);
4352    SetImageInfo(info->image_info,0,exception);
4353    exception=DestroyExceptionInfo(exception);
4354    SvREFCNT_dec(perl_exception);
4355    XSRETURN(1);
4356
4357  PerlException:
4358    InheritPerlException(exception,perl_exception);
4359    exception=DestroyExceptionInfo(exception);
4360    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4361    SvPOK_on(perl_exception);  /* return messages in string context */
4362    ST(0)=sv_2mortal(perl_exception);
4363    XSRETURN(1);
4364  }
4365
4366#
4367###############################################################################
4368#                                                                             #
4369#                                                                             #
4370#                                                                             #
4371#   F x                                                                       #
4372#                                                                             #
4373#                                                                             #
4374#                                                                             #
4375###############################################################################
4376#
4377#
4378void
4379Fx(ref,...)
4380  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4381  ALIAS:
4382    FxImage  = 1
4383    fx       = 2
4384    fximage  = 3
4385  PPCODE:
4386  {
4387    AV
4388      *av;
4389
4390    char
4391      *attribute,
4392      expression[MagickPathExtent];
4393
4394    ChannelType
4395      channel,
4396      channel_mask;
4397
4398    ExceptionInfo
4399      *exception;
4400
4401    HV
4402      *hv;
4403
4404    Image
4405      *image;
4406
4407    register ssize_t
4408      i;
4409
4410    struct PackageInfo
4411      *info;
4412
4413    SV
4414      *av_reference,
4415      *perl_exception,
4416      *reference,
4417      *rv,
4418      *sv;
4419
4420    PERL_UNUSED_VAR(ref);
4421    PERL_UNUSED_VAR(ix);
4422    exception=AcquireExceptionInfo();
4423    perl_exception=newSVpv("",0);
4424    sv=NULL;
4425    attribute=NULL;
4426    av=NULL;
4427    if (sv_isobject(ST(0)) == 0)
4428      {
4429        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4430          PackageName);
4431        goto PerlException;
4432      }
4433    reference=SvRV(ST(0));
4434    hv=SvSTASH(reference);
4435    av=newAV();
4436    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4437    SvREFCNT_dec(av);
4438    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4439    if (image == (Image *) NULL)
4440      {
4441        ThrowPerlException(exception,OptionError,"NoImagesDefined",
4442          PackageName);
4443        goto PerlException;
4444      }
4445    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4446    /*
4447      Get options.
4448    */
4449    channel=DefaultChannels;
4450    (void) CopyMagickString(expression,"u",MagickPathExtent);
4451    if (items == 2)
4452      (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4453    else
4454      for (i=2; i < items; i+=2)
4455      {
4456        attribute=(char *) SvPV(ST(i-1),na);
4457        switch (*attribute)
4458        {
4459          case 'C':
4460          case 'c':
4461          {
4462            if (LocaleCompare(attribute,"channel") == 0)
4463              {
4464                ssize_t
4465                  option;
4466
4467                option=ParseChannelOption(SvPV(ST(i),na));
4468                if (option < 0)
4469                  {
4470                    ThrowPerlException(exception,OptionError,
4471                      "UnrecognizedType",SvPV(ST(i),na));
4472                    return;
4473                  }
4474                channel=(ChannelType) option;
4475                break;
4476              }
4477            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4478              attribute);
4479            break;
4480          }
4481          case 'E':
4482          case 'e':
4483          {
4484            if (LocaleCompare(attribute,"expression") == 0)
4485              {
4486                (void) CopyMagickString(expression,SvPV(ST(i),na),
4487                  MagickPathExtent);
4488                break;
4489              }
4490            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4491              attribute);
4492            break;
4493          }
4494          default:
4495          {
4496            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4497              attribute);
4498            break;
4499          }
4500        }
4501      }
4502    channel_mask=SetImageChannelMask(image,channel);
4503    image=FxImage(image,expression,exception);
4504    if (image != (Image *) NULL)
4505      (void) SetImageChannelMask(image,channel_mask);
4506    if (image == (Image *) NULL)
4507      goto PerlException;
4508    for ( ; image; image=image->next)
4509    {
4510      AddImageToRegistry(sv,image);
4511      rv=newRV(sv);
4512      av_push(av,sv_bless(rv,hv));
4513      SvREFCNT_dec(sv);
4514    }
4515    exception=DestroyExceptionInfo(exception);
4516    ST(0)=av_reference;
4517    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4518    XSRETURN(1);
4519
4520  PerlException:
4521    InheritPerlException(exception,perl_exception);
4522    exception=DestroyExceptionInfo(exception);
4523    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4524    SvPOK_on(perl_exception);
4525    ST(0)=sv_2mortal(perl_exception);
4526    XSRETURN(1);
4527  }
4528
4529#
4530###############################################################################
4531#                                                                             #
4532#                                                                             #
4533#                                                                             #
4534#   G e t                                                                     #
4535#                                                                             #
4536#                                                                             #
4537#                                                                             #
4538###############################################################################
4539#
4540#
4541void
4542Get(ref,...)
4543  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4544  ALIAS:
4545    GetAttributes = 1
4546    GetAttribute  = 2
4547    get           = 3
4548    getattributes = 4
4549    getattribute  = 5
4550  PPCODE:
4551  {
4552    char
4553      *attribute,
4554      color[MagickPathExtent];
4555
4556    const char
4557      *value;
4558
4559    ExceptionInfo
4560      *exception;
4561
4562    Image
4563      *image;
4564
4565    long
4566      j;
4567
4568    register ssize_t
4569      i;
4570
4571    struct PackageInfo
4572      *info;
4573
4574    SV
4575      *perl_exception,
4576      *reference,
4577      *s;
4578
4579    PERL_UNUSED_VAR(ref);
4580    PERL_UNUSED_VAR(ix);
4581    exception=AcquireExceptionInfo();
4582    perl_exception=newSVpv("",0);
4583    if (sv_isobject(ST(0)) == 0)
4584      {
4585        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4586          PackageName);
4587        XSRETURN_EMPTY;
4588      }
4589    reference=SvRV(ST(0));
4590    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4591    if (image == (Image *) NULL && !info)
4592      XSRETURN_EMPTY;
4593    EXTEND(sp,items);
4594    for (i=1; i < items; i++)
4595    {
4596      attribute=(char *) SvPV(ST(i),na);
4597      s=NULL;
4598      switch (*attribute)
4599      {
4600        case 'A':
4601        case 'a':
4602        {
4603          if (LocaleCompare(attribute,"adjoin") == 0)
4604            {
4605              if (info)
4606                s=newSViv((ssize_t) info->image_info->adjoin);
4607              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4608              continue;
4609            }
4610          if (LocaleCompare(attribute,"antialias") == 0)
4611            {
4612              if (info)
4613                s=newSViv((ssize_t) info->image_info->antialias);
4614              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4615              continue;
4616            }
4617          if (LocaleCompare(attribute,"area") == 0)
4618            {
4619              s=newSViv(GetMagickResource(AreaResource));
4620              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621              continue;
4622            }
4623          if (LocaleCompare(attribute,"attenuate") == 0)
4624            {
4625              const char
4626                *value;
4627
4628              value=GetImageProperty(image,attribute,exception);
4629              if (value != (const char *) NULL)
4630                s=newSVpv(value,0);
4631              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4632              continue;
4633            }
4634          if (LocaleCompare(attribute,"authenticate") == 0)
4635            {
4636              if (info)
4637                {
4638                  const char
4639                    *option;
4640
4641                  option=GetImageOption(info->image_info,attribute);
4642                  if (option != (const char *) NULL)
4643                    s=newSVpv(option,0);
4644                }
4645              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4646              continue;
4647            }
4648          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4649            attribute);
4650          break;
4651        }
4652        case 'B':
4653        case 'b':
4654        {
4655          if (LocaleCompare(attribute,"background") == 0)
4656            {
4657              if (image == (Image *) NULL)
4658                break;
4659              (void) FormatLocaleString(color,MagickPathExtent,
4660                "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4661                (double) image->background_color.green,
4662                (double) image->background_color.blue,
4663                (double) image->background_color.alpha);
4664              s=newSVpv(color,0);
4665              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4666              continue;
4667            }
4668          if (LocaleCompare(attribute,"base-columns") == 0)
4669            {
4670              if (image != (Image *) NULL)
4671                s=newSViv((ssize_t) image->magick_columns);
4672              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4673              continue;
4674            }
4675          if (LocaleCompare(attribute,"base-filename") == 0)
4676            {
4677              if (image != (Image *) NULL)
4678                s=newSVpv(image->magick_filename,0);
4679              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4680              continue;
4681            }
4682          if (LocaleCompare(attribute,"base-height") == 0)
4683            {
4684              if (image != (Image *) NULL)
4685                s=newSViv((ssize_t) image->magick_rows);
4686              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4687              continue;
4688            }
4689          if (LocaleCompare(attribute,"base-rows") == 0)
4690            {
4691              if (image != (Image *) NULL)
4692                s=newSViv((ssize_t) image->magick_rows);
4693              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694              continue;
4695            }
4696          if (LocaleCompare(attribute,"base-width") == 0)
4697            {
4698              if (image != (Image *) NULL)
4699                s=newSViv((ssize_t) image->magick_columns);
4700              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701              continue;
4702            }
4703          if (LocaleCompare(attribute,"blue-primary") == 0)
4704            {
4705              if (image == (Image *) NULL)
4706                break;
4707              (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4708                image->chromaticity.blue_primary.x,
4709                image->chromaticity.blue_primary.y);
4710              s=newSVpv(color,0);
4711              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4712              continue;
4713            }
4714          if (LocaleCompare(attribute,"bordercolor") == 0)
4715            {
4716              if (image == (Image *) NULL)
4717                break;
4718              (void) FormatLocaleString(color,MagickPathExtent,
4719                "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4720                (double) image->border_color.green,
4721                (double) image->border_color.blue,
4722                (double) image->border_color.alpha);
4723              s=newSVpv(color,0);
4724              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4725              continue;
4726            }
4727          if (LocaleCompare(attribute,"bounding-box") == 0)
4728            {
4729              char
4730                geometry[MagickPathExtent];
4731
4732              RectangleInfo
4733                page;
4734
4735              if (image == (Image *) NULL)
4736                break;
4737              page=GetImageBoundingBox(image,exception);
4738              (void) FormatLocaleString(geometry,MagickPathExtent,
4739                "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4740                page.height,(double) page.x,(double) page.y);
4741              s=newSVpv(geometry,0);
4742              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4743              continue;
4744            }
4745          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4746            attribute);
4747          break;
4748        }
4749        case 'C':
4750        case 'c':
4751        {
4752          if (LocaleCompare(attribute,"class") == 0)
4753            {
4754              if (image == (Image *) NULL)
4755                break;
4756              s=newSViv(image->storage_class);
4757              (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4758                image->storage_class));
4759              SvIOK_on(s);
4760              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761              continue;
4762            }
4763          if (LocaleCompare(attribute,"clip-mask") == 0)
4764            {
4765              if (image != (Image *) NULL)
4766                {
4767                  Image
4768                    *mask_image;
4769
4770                  SV
4771                    *sv;
4772
4773                  sv=NULL;
4774                  if (image->read_mask == MagickFalse)
4775                    ClipImage(image,exception);
4776                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4777                  if (mask_image != (Image *) NULL)
4778                    {
4779                      AddImageToRegistry(sv,mask_image);
4780                      s=sv_bless(newRV(sv),SvSTASH(reference));
4781                    }
4782                }
4783              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4784              continue;
4785            }
4786          if (LocaleCompare(attribute,"clip-path") == 0)
4787            {
4788              if (image != (Image *) NULL)
4789                {
4790                  Image
4791                    *mask_image;
4792
4793                  SV
4794                    *sv;
4795
4796                  sv=NULL;
4797                  if (image->read_mask != MagickFalse)
4798                    ClipImage(image,exception);
4799                  mask_image=GetImageMask(image,ReadPixelMask,exception);
4800                  if (mask_image != (Image *) NULL)
4801                    {
4802                      AddImageToRegistry(sv,mask_image);
4803                      s=sv_bless(newRV(sv),SvSTASH(reference));
4804                    }
4805                }
4806              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4807              continue;
4808            }
4809          if (LocaleCompare(attribute,"compression") == 0)
4810            {
4811              j=info ? info->image_info->compression : image ?
4812                image->compression : UndefinedCompression;
4813              if (info)
4814                if (info->image_info->compression == UndefinedCompression)
4815                  j=image->compression;
4816              s=newSViv(j);
4817              (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4818                j));
4819              SvIOK_on(s);
4820              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4821              continue;
4822            }
4823          if (LocaleCompare(attribute,"colorspace") == 0)
4824            {
4825              j=image ? image->colorspace : RGBColorspace;
4826              s=newSViv(j);
4827              (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4828                j));
4829              SvIOK_on(s);
4830              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4831              continue;
4832            }
4833          if (LocaleCompare(attribute,"colors") == 0)
4834            {
4835              if (image != (Image *) NULL)
4836                s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4837                  exception));
4838              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4839              continue;
4840            }
4841          if (LocaleNCompare(attribute,"colormap",8) == 0)
4842            {
4843              int
4844                items;
4845
4846              if (image == (Image *) NULL || !image->colormap)
4847                break;
4848              j=0;
4849              items=sscanf(attribute,"%*[^[][%ld",&j);
4850              (void) items;
4851              if (j > (ssize_t) image->colors)
4852                j%=image->colors;
4853              (void) FormatLocaleString(color,MagickPathExtent,
4854                "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4855                (double) image->colormap[j].green,
4856                (double) image->colormap[j].blue,
4857                (double) image->colormap[j].alpha);
4858              s=newSVpv(color,0);
4859              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4860              continue;
4861            }
4862          if (LocaleCompare(attribute,"columns") == 0)
4863            {
4864              if (image != (Image *) NULL)
4865                s=newSViv((ssize_t) image->columns);
4866              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867              continue;
4868            }
4869          if (LocaleCompare(attribute,"comment") == 0)
4870            {
4871              const char
4872                *value;
4873
4874              value=GetImageProperty(image,attribute,exception);
4875              if (value != (const char *) NULL)
4876                s=newSVpv(value,0);
4877              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878              continue;
4879            }
4880          if (LocaleCompare(attribute,"copyright") == 0)
4881            {
4882              s=newSVpv(GetMagickCopyright(),0);
4883              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4884              continue;
4885            }
4886          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4887            attribute);
4888          break;
4889        }
4890        case 'D':
4891        case 'd':
4892        {
4893          if (LocaleCompare(attribute,"density") == 0)
4894            {
4895              char
4896                geometry[MagickPathExtent];
4897
4898              if (image == (Image *) NULL)
4899                break;
4900              (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4901                image->resolution.x,image->resolution.y);
4902              s=newSVpv(geometry,0);
4903              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4904              continue;
4905            }
4906          if (LocaleCompare(attribute,"delay") == 0)
4907            {
4908              if (image != (Image *) NULL)
4909                s=newSViv((ssize_t) image->delay);
4910              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4911              continue;
4912            }
4913          if (LocaleCompare(attribute,"depth") == 0)
4914            {
4915              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4916              if (image != (Image *) NULL)
4917                s=newSViv((ssize_t) GetImageDepth(image,exception));
4918              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4919              continue;
4920            }
4921          if (LocaleCompare(attribute,"directory") == 0)
4922            {
4923              if (image && image->directory)
4924                s=newSVpv(image->directory,0);
4925              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926              continue;
4927            }
4928          if (LocaleCompare(attribute,"dispose") == 0)
4929            {
4930              if (image == (Image *) NULL)
4931                break;
4932
4933              s=newSViv(image->dispose);
4934              (void) sv_setpv(s,
4935                CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4936              SvIOK_on(s);
4937              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938              continue;
4939            }
4940          if (LocaleCompare(attribute,"disk") == 0)
4941            {
4942              s=newSViv(GetMagickResource(DiskResource));
4943              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944              continue;
4945            }
4946          if (LocaleCompare(attribute,"dither") == 0)
4947            {
4948              if (info)
4949                s=newSViv((ssize_t) info->image_info->dither);
4950              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4951              continue;
4952            }
4953          if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4954            {
4955              if (info && info->image_info->server_name)
4956                s=newSVpv(info->image_info->server_name,0);
4957              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958              continue;
4959            }
4960          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4961            attribute);
4962          break;
4963        }
4964        case 'E':
4965        case 'e':
4966        {
4967          if (LocaleCompare(attribute,"elapsed-time") == 0)
4968            {
4969              if (image != (Image *) NULL)
4970                s=newSVnv(GetElapsedTime(&image->timer));
4971              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972              continue;
4973            }
4974          if (LocaleCompare(attribute,"endian") == 0)
4975            {
4976              j=info ? info->image_info->endian : image ? image->endian :
4977                UndefinedEndian;
4978              s=newSViv(j);
4979              (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4980              SvIOK_on(s);
4981              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982              continue;
4983            }
4984          if (LocaleCompare(attribute,"error") == 0)
4985            {
4986              if (image != (Image *) NULL)
4987                s=newSVnv(image->error.mean_error_per_pixel);
4988              PUSHs(s ? sv_2mortal(s) : &sv_undef);
4989              continue;
4990            }
4991          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4992            attribute);
4993          break;
4994        }
4995        case 'F':
4996        case 'f':
4997        {
4998          if (LocaleCompare(attribute,"filesize") == 0)
4999            {
5000              if (image != (Image *) NULL)
5001                s=newSViv((ssize_t) GetBlobSize(image));
5002              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5003              continue;
5004            }
5005          if (LocaleCompare(attribute,"filename") == 0)
5006            {
5007              if (info && info->image_info->filename &&
5008                  *info->image_info->filename)
5009                s=newSVpv(info->image_info->filename,0);
5010              if (image != (Image *) NULL)
5011                s=newSVpv(image->filename,0);
5012              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5013              continue;
5014            }
5015          if (LocaleCompare(attribute,"filter") == 0)
5016            {
5017              s=image ? newSViv(image->filter) : newSViv(0);
5018              (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5019                image->filter));
5020              SvIOK_on(s);
5021              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022              continue;
5023            }
5024          if (LocaleCompare(attribute,"font") == 0)
5025            {
5026              if (info && info->image_info->font)
5027                s=newSVpv(info->image_info->font,0);
5028              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5029              continue;
5030            }
5031          if (LocaleCompare(attribute,"foreground") == 0)
5032            continue;
5033          if (LocaleCompare(attribute,"format") == 0)
5034            {
5035              const MagickInfo
5036                *magick_info;
5037
5038              magick_info=(const MagickInfo *) NULL;
5039              if (info && (*info->image_info->magick != '\0'))
5040                magick_info=GetMagickInfo(info->image_info->magick,exception);
5041              if (image != (Image *) NULL)
5042                magick_info=GetMagickInfo(image->magick,exception);
5043              if ((magick_info != (const MagickInfo *) NULL) &&
5044                  (*magick_info->description != '\0'))
5045                s=newSVpv((char *) magick_info->description,0);
5046              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047              continue;
5048            }
5049          if (LocaleCompare(attribute,"fuzz") == 0)
5050            {
5051              if (info)
5052                s=newSVnv(info->image_info->fuzz);
5053              if (image != (Image *) NULL)
5054                s=newSVnv(image->fuzz);
5055              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5056              continue;
5057            }
5058          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5059            attribute);
5060          break;
5061        }
5062        case 'G':
5063        case 'g':
5064        {
5065          if (LocaleCompare(attribute,"gamma") == 0)
5066            {
5067              if (image != (Image *) NULL)
5068                s=newSVnv(image->gamma);
5069              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5070              continue;
5071            }
5072          if (LocaleCompare(attribute,"geometry") == 0)
5073            {
5074              if (image && image->geometry)
5075                s=newSVpv(image->geometry,0);
5076              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5077              continue;
5078            }
5079          if (LocaleCompare(attribute,"gravity") == 0)
5080            {
5081              s=image ? newSViv(image->gravity) : newSViv(0);
5082              (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5083                image->gravity));
5084              SvIOK_on(s);
5085              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086              continue;
5087            }
5088          if (LocaleCompare(attribute,"green-primary") == 0)
5089            {
5090              if (image == (Image *) NULL)
5091                break;
5092              (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5093                image->chromaticity.green_primary.x,
5094                image->chromaticity.green_primary.y);
5095              s=newSVpv(color,0);
5096              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5097              continue;
5098            }
5099          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5100            attribute);
5101          break;
5102        }
5103        case 'H':
5104        case 'h':
5105        {
5106          if (LocaleCompare(attribute,"height") == 0)
5107            {
5108              if (image != (Image *) NULL)
5109                s=newSViv((ssize_t) image->rows);
5110              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111              continue;
5112            }
5113          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5114            attribute);
5115          break;
5116        }
5117        case 'I':
5118        case 'i':
5119        {
5120          if (LocaleCompare(attribute,"icc") == 0)
5121            {
5122              if (image != (Image *) NULL)
5123                {
5124                  const StringInfo
5125                    *profile;
5126
5127                  profile=GetImageProfile(image,"icc");
5128                  if (profile != (StringInfo *) NULL)
5129                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5130                      GetStringInfoLength(profile));
5131                }
5132              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5133              continue;
5134            }
5135          if (LocaleCompare(attribute,"icm") == 0)
5136            {
5137              if (image != (Image *) NULL)
5138                {
5139                  const StringInfo
5140                    *profile;
5141
5142                  profile=GetImageProfile(image,"icm");
5143                  if (profile != (const StringInfo *) NULL)
5144                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5145                      GetStringInfoLength(profile));
5146                }
5147              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148              continue;
5149            }
5150          if (LocaleCompare(attribute,"id") == 0)
5151            {
5152              if (image != (Image *) NULL)
5153                {
5154                  char
5155                    key[MagickPathExtent];
5156
5157                  MagickBooleanType
5158                    status;
5159
5160                  static ssize_t
5161                    id = 0;
5162
5163                  (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5164                    id);
5165                  status=SetImageRegistry(ImageRegistryType,key,image,
5166                    exception);
5167                  (void) status;
5168                  s=newSViv(id++);
5169                }
5170              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5171              continue;
5172            }
5173          if (LocaleNCompare(attribute,"index",5) == 0)
5174            {
5175              char
5176                name[MagickPathExtent];
5177
5178              int
5179                items;
5180
5181              long
5182                x,
5183                y;
5184
5185              register const Quantum
5186                *p;
5187
5188              CacheView
5189                *image_view;
5190
5191              if (image == (Image *) NULL)
5192                break;
5193              if (image->storage_class != PseudoClass)
5194                break;
5195              x=0;
5196              y=0;
5197              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5198              (void) items;
5199              image_view=AcquireVirtualCacheView(image,exception);
5200              p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5201              if (p != (const Quantum *) NULL)
5202                {
5203                  (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5204                    GetPixelIndex(image,p));
5205                  s=newSVpv(name,0);
5206                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207                }
5208              image_view=DestroyCacheView(image_view);
5209              continue;
5210            }
5211          if (LocaleCompare(attribute,"iptc") == 0)
5212            {
5213              if (image != (Image *) NULL)
5214                {
5215                  const StringInfo
5216                    *profile;
5217
5218                  profile=GetImageProfile(image,"iptc");
5219                  if (profile != (const StringInfo *) NULL)
5220                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5221                      GetStringInfoLength(profile));
5222                }
5223              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5224              continue;
5225            }
5226          if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5227            {
5228              if (image != (Image *) NULL)
5229                s=newSViv((ssize_t) image->iterations);
5230              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5231              continue;
5232            }
5233          if (LocaleCompare(attribute,"interlace") == 0)
5234            {
5235              j=info ? info->image_info->interlace : image ? image->interlace :
5236                UndefinedInterlace;
5237              s=newSViv(j);
5238              (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5239                j));
5240              SvIOK_on(s);
5241              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242              continue;
5243            }
5244          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5245            attribute);
5246          break;
5247        }
5248        case 'L':
5249        case 'l':
5250        {
5251          if (LocaleCompare(attribute,"label") == 0)
5252            {
5253              const char
5254                *value;
5255
5256              if (image == (Image *) NULL)
5257                break;
5258              value=GetImageProperty(image,"Label",exception);
5259              if (value != (const char *) NULL)
5260                s=newSVpv(value,0);
5261              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5262              continue;
5263            }
5264          if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5265            {
5266              if (image != (Image *) NULL)
5267                s=newSViv((ssize_t) image->iterations);
5268              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269              continue;
5270            }
5271          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5272            attribute);
5273          break;
5274        }
5275        case 'M':
5276        case 'm':
5277        {
5278          if (LocaleCompare(attribute,"magick") == 0)
5279            {
5280              if (info && *info->image_info->magick)
5281                s=newSVpv(info->image_info->magick,0);
5282              if (image != (Image *) NULL)
5283                s=newSVpv(image->magick,0);
5284              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5285              continue;
5286            }
5287          if (LocaleCompare(attribute,"map") == 0)
5288            {
5289              s=newSViv(GetMagickResource(MapResource));
5290              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5291              continue;
5292            }
5293          if (LocaleCompare(attribute,"maximum-error") == 0)
5294            {
5295              if (image != (Image *) NULL)
5296                s=newSVnv(image->error.normalized_maximum_error);
5297              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298              continue;
5299            }
5300          if (LocaleCompare(attribute,"memory") == 0)
5301            {
5302              s=newSViv(GetMagickResource(MemoryResource));
5303              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304              continue;
5305            }
5306          if (LocaleCompare(attribute,"mean-error") == 0)
5307            {
5308              if (image != (Image *) NULL)
5309                s=newSVnv(image->error.normalized_mean_error);
5310              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5311              continue;
5312            }
5313          if (LocaleCompare(attribute,"mime") == 0)
5314            {
5315              if (info && *info->image_info->magick)
5316                s=newSVpv(MagickToMime(info->image_info->magick),0);
5317              if (image != (Image *) NULL)
5318                s=newSVpv(MagickToMime(image->magick),0);
5319              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5320              continue;
5321            }
5322          if (LocaleCompare(attribute,"mattecolor") == 0)
5323            {
5324              if (image == (Image *) NULL)
5325                break;
5326              (void) FormatLocaleString(color,MagickPathExtent,
5327                "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5328                (double) image->alpha_color.green,
5329                (double) image->alpha_color.blue,
5330                (double) image->alpha_color.alpha);
5331              s=newSVpv(color,0);
5332              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5333              continue;
5334            }
5335          if (LocaleCompare(attribute,"matte") == 0)
5336            {
5337              if (image != (Image *) NULL)
5338                s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5339                  1 : 0);
5340              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5341              continue;
5342            }
5343          if (LocaleCompare(attribute,"mime") == 0)
5344            {
5345              const char
5346                *magick;
5347
5348              magick=NULL;
5349              if (info && *info->image_info->magick)
5350                magick=info->image_info->magick;
5351              if (image != (Image *) NULL)
5352                magick=image->magick;
5353              if (magick)
5354                {
5355                  char
5356                    *mime;
5357
5358                  mime=MagickToMime(magick);
5359                  s=newSVpv(mime,0);
5360                  mime=(char *) RelinquishMagickMemory(mime);
5361                }
5362              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5363              continue;
5364            }
5365          if (LocaleCompare(attribute,"monochrome") == 0)
5366            {
5367              if (image == (Image *) NULL)
5368                continue;
5369              j=info ? info->image_info->monochrome :
5370                SetImageMonochrome(image,exception);
5371              s=newSViv(j);
5372              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5373              continue;
5374            }
5375          if (LocaleCompare(attribute,"montage") == 0)
5376            {
5377              if (image && image->montage)
5378                s=newSVpv(image->montage,0);
5379              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5380              continue;
5381            }
5382          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5383            attribute);
5384          break;
5385        }
5386        case 'O':
5387        case 'o':
5388        {
5389          if (LocaleCompare(attribute,"orientation") == 0)
5390            {
5391              j=info ? info->image_info->orientation : image ?
5392                image->orientation : UndefinedOrientation;
5393              s=newSViv(j);
5394              (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5395                j));
5396              SvIOK_on(s);
5397              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5398              continue;
5399            }
5400          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5401            attribute);
5402          break;
5403        }
5404        case 'P':
5405        case 'p':
5406        {
5407          if (LocaleCompare(attribute,"page") == 0)
5408            {
5409              if (info && info->image_info->page)
5410                s=newSVpv(info->image_info->page,0);
5411              if (image != (Image *) NULL)
5412                {
5413                  char
5414                    geometry[MagickPathExtent];
5415
5416                  (void) FormatLocaleString(geometry,MagickPathExtent,
5417                    "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5418                    (double) image->page.height,(double) image->page.x,(double)
5419                    image->page.y);
5420                  s=newSVpv(geometry,0);
5421                }
5422              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5423              continue;
5424            }
5425          if (LocaleCompare(attribute,"page.x") == 0)
5426            {
5427              if (image != (Image *) NULL)
5428                s=newSViv((ssize_t) image->page.x);
5429              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5430              continue;
5431            }
5432          if (LocaleCompare(attribute,"page.y") == 0)
5433            {
5434              if (image != (Image *) NULL)
5435                s=newSViv((ssize_t) image->page.y);
5436              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5437              continue;
5438            }
5439          if (LocaleNCompare(attribute,"pixel",5) == 0)
5440            {
5441              char
5442                tuple[MagickPathExtent];
5443
5444              int
5445                items;
5446
5447              long
5448                x,
5449                y;
5450
5451              register const Quantum
5452                *p;
5453
5454              if (image == (Image *) NULL)
5455                break;
5456              x=0;
5457              y=0;
5458              items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5459              (void) items;
5460              p=GetVirtualPixels(image,x,y,1,1,exception);
5461              if (image->colorspace != CMYKColorspace)
5462                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5463                  QuantumFormat "," QuantumFormat "," QuantumFormat,
5464                  GetPixelRed(image,p),GetPixelGreen(image,p),
5465                  GetPixelBlue(image,p),GetPixelAlpha(image,p));
5466              else
5467                (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5468                  QuantumFormat "," QuantumFormat "," QuantumFormat ","
5469                  QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5470                  GetPixelBlue(image,p),GetPixelBlack(image,p),
5471                  GetPixelAlpha(image,p));
5472              s=newSVpv(tuple,0);
5473              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5474              continue;
5475            }
5476          if (LocaleCompare(attribute,"pointsize") == 0)
5477            {
5478              if (info)
5479                s=newSViv((ssize_t) info->image_info->pointsize);
5480              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5481              continue;
5482            }
5483          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5484            attribute);
5485          break;
5486        }
5487        case 'Q':
5488        case 'q':
5489        {
5490          if (LocaleCompare(attribute,"quality") == 0)
5491            {
5492              if (info)
5493                s=newSViv((ssize_t) info->image_info->quality);
5494              if (image != (Image *) NULL)
5495                s=newSViv((ssize_t) image->quality);
5496              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497              continue;
5498            }
5499          if (LocaleCompare(attribute,"quantum") == 0)
5500            {
5501              if (info)
5502                s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5503              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5504              continue;
5505            }
5506          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5507            attribute);
5508          break;
5509        }
5510        case 'R':
5511        case 'r':
5512        {
5513          if (LocaleCompare(attribute,"rendering-intent") == 0)
5514            {
5515              s=newSViv(image->rendering_intent);
5516              (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5517                image->rendering_intent));
5518              SvIOK_on(s);
5519              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520              continue;
5521            }
5522          if (LocaleCompare(attribute,"red-primary") == 0)
5523            {
5524              if (image == (Image *) NULL)
5525                break;
5526              (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5527                image->chromaticity.red_primary.x,
5528                image->chromaticity.red_primary.y);
5529              s=newSVpv(color,0);
5530              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5531              continue;
5532            }
5533          if (LocaleCompare(attribute,"rows") == 0)
5534            {
5535              if (image != (Image *) NULL)
5536                s=newSViv((ssize_t) image->rows);
5537              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5538              continue;
5539            }
5540          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5541            attribute);
5542          break;
5543        }
5544        case 'S':
5545        case 's':
5546        {
5547          if (LocaleCompare(attribute,"sampling-factor") == 0)
5548            {
5549              if (info && info->image_info->sampling_factor)
5550                s=newSVpv(info->image_info->sampling_factor,0);
5551              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5552              continue;
5553            }
5554          if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5555            {
5556              if (info && info->image_info->server_name)
5557                s=newSVpv(info->image_info->server_name,0);
5558              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5559              continue;
5560            }
5561          if (LocaleCompare(attribute,"size") == 0)
5562            {
5563              if (info && info->image_info->size)
5564                s=newSVpv(info->image_info->size,0);
5565              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5566              continue;
5567            }
5568          if (LocaleCompare(attribute,"scene") == 0)
5569            {
5570              if (image != (Image *) NULL)
5571                s=newSViv((ssize_t) image->scene);
5572              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5573              continue;
5574            }
5575          if (LocaleCompare(attribute,"scenes") == 0)
5576            {
5577              if (image != (Image *) NULL)
5578                s=newSViv((ssize_t) info->image_info->number_scenes);
5579              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5580              continue;
5581            }
5582          if (LocaleCompare(attribute,"signature") == 0)
5583            {
5584              const char
5585                *value;
5586
5587              if (image == (Image *) NULL)
5588                break;
5589              (void) SignatureImage(image,exception);
5590              value=GetImageProperty(image,"Signature",exception);
5591              if (value != (const char *) NULL)
5592                s=newSVpv(value,0);
5593              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594              continue;
5595            }
5596          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5597            attribute);
5598          break;
5599        }
5600        case 'T':
5601        case 't':
5602        {
5603          if (LocaleCompare(attribute,"taint") == 0)
5604            {
5605              if (image != (Image *) NULL)
5606                s=newSViv((ssize_t) IsTaintImage(image));
5607              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5608              continue;
5609            }
5610          if (LocaleCompare(attribute,"texture") == 0)
5611            {
5612              if (info && info->image_info->texture)
5613                s=newSVpv(info->image_info->texture,0);
5614              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5615              continue;
5616            }
5617          if (LocaleCompare(attribute,"total-ink-density") == 0)
5618            {
5619              s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5620              if (image != (Image *) NULL)
5621                s=newSVnv(GetImageTotalInkDensity(image,exception));
5622              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5623              continue;
5624            }
5625          if (LocaleCompare(attribute,"transparent-color") == 0)
5626            {
5627              if (image == (Image *) NULL)
5628                break;
5629              (void) FormatLocaleString(color,MagickPathExtent,
5630                "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5631                (double) image->transparent_color.green,
5632                (double) image->transparent_color.blue,
5633                (double) image->transparent_color.alpha);
5634              s=newSVpv(color,0);
5635              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5636              continue;
5637            }
5638          if (LocaleCompare(attribute,"type") == 0)
5639            {
5640              if (image == (Image *) NULL)
5641                break;
5642              j=(ssize_t) GetImageType(image);
5643              s=newSViv(j);
5644              (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5645              SvIOK_on(s);
5646              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5647              continue;
5648            }
5649          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5650            attribute);
5651          break;
5652        }
5653        case 'U':
5654        case 'u':
5655        {
5656          if (LocaleCompare(attribute,"units") == 0)
5657            {
5658              j=info ? info->image_info->units : image ? image->units :
5659                UndefinedResolution;
5660              if (info && (info->image_info->units == UndefinedResolution))
5661                if (image)
5662                  j=image->units;
5663              if (j == UndefinedResolution)
5664                s=newSVpv("undefined units",0);
5665              else
5666                if (j == PixelsPerInchResolution)
5667                  s=newSVpv("pixels / inch",0);
5668                else
5669                  s=newSVpv("pixels / centimeter",0);
5670              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5671              continue;
5672            }
5673          if (LocaleCompare(attribute,"user-time") == 0)
5674            {
5675              if (image != (Image *) NULL)
5676                s=newSVnv(GetUserTime(&image->timer));
5677              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5678              continue;
5679            }
5680          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5681            attribute);
5682          break;
5683        }
5684        case 'V':
5685        case 'v':
5686        {
5687          if (LocaleCompare(attribute,"verbose") == 0)
5688            {
5689              if (info)
5690                s=newSViv((ssize_t) info->image_info->verbose);
5691              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5692              continue;
5693            }
5694          if (LocaleCompare(attribute,"version") == 0)
5695            {
5696              s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5697              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698              continue;
5699            }
5700          if (LocaleCompare(attribute,"virtual-pixel") == 0)
5701            {
5702              if (image == (Image *) NULL)
5703                break;
5704              j=(ssize_t) GetImageVirtualPixelMethod(image);
5705              s=newSViv(j);
5706              (void) sv_setpv(s,CommandOptionToMnemonic(
5707                MagickVirtualPixelOptions,j));
5708              SvIOK_on(s);
5709              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5710              continue;
5711            }
5712          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5713            attribute);
5714          break;
5715        }
5716        case 'W':
5717        case 'w':
5718        {
5719          if (LocaleCompare(attribute,"white-point") == 0)
5720            {
5721              if (image == (Image *) NULL)
5722                break;
5723              (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5724                image->chromaticity.white_point.x,
5725                image->chromaticity.white_point.y);
5726              s=newSVpv(color,0);
5727              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5728              continue;
5729            }
5730          if (LocaleCompare(attribute,"width") == 0)
5731            {
5732              if (image != (Image *) NULL)
5733                s=newSViv((ssize_t) image->columns);
5734              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5735              continue;
5736            }
5737          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5738             attribute);
5739          break;
5740        }
5741        case 'X':
5742        case 'x':
5743        {
5744          if (LocaleCompare(attribute,"xmp") == 0)
5745            {
5746              if (image != (Image *) NULL)
5747                {
5748                  const StringInfo
5749                    *profile;
5750
5751                  profile=GetImageProfile(image,"xmp");
5752                  if (profile != (StringInfo *) NULL)
5753                    s=newSVpv((const char *) GetStringInfoDatum(profile),
5754                      GetStringInfoLength(profile));
5755                }
5756              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5757              continue;
5758            }
5759          if (LocaleCompare(attribute,"x-resolution") == 0)
5760            {
5761              if (image != (Image *) NULL)
5762                s=newSVnv(image->resolution.x);
5763              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5764              continue;
5765            }
5766          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5767            attribute);
5768          break;
5769        }
5770        case 'Y':
5771        case 'y':
5772        {
5773          if (LocaleCompare(attribute,"y-resolution") == 0)
5774            {
5775              if (image != (Image *) NULL)
5776                s=newSVnv(image->resolution.y);
5777              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5778              continue;
5779            }
5780          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5781            attribute);
5782          break;
5783        }
5784        default:
5785          break;
5786      }
5787      if (image == (Image *) NULL)
5788        ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5789          attribute)
5790      else
5791        {
5792          value=GetImageProperty(image,attribute,exception);
5793          if (value != (const char *) NULL)
5794            {
5795              s=newSVpv(value,0);
5796              PUSHs(s ? sv_2mortal(s) : &sv_undef);
5797            }
5798          else
5799            if (*attribute != '%')
5800              ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5801                attribute)
5802            else
5803              {
5804                 char
5805                   *meta;
5806
5807                 meta=InterpretImageProperties(info ? info->image_info :
5808                   (ImageInfo *) NULL,image,attribute,exception);
5809                 s=newSVpv(meta,0);
5810                 PUSHs(s ? sv_2mortal(s) : &sv_undef);
5811                 meta=(char *) RelinquishMagickMemory(meta);
5812              }
5813        }
5814    }
5815    exception=DestroyExceptionInfo(exception);
5816    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5817  }
5818
5819#
5820###############################################################################
5821#                                                                             #
5822#                                                                             #
5823#                                                                             #
5824#   G e t A u t h e n t i c P i x e l s                                       #
5825#                                                                             #
5826#                                                                             #
5827#                                                                             #
5828###############################################################################
5829#
5830#
5831void *
5832GetAuthenticPixels(ref,...)
5833  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5834  ALIAS:
5835    getauthenticpixels = 1
5836    GetImagePixels = 2
5837    getimagepixels = 3
5838  CODE:
5839  {
5840    char
5841      *attribute;
5842
5843    ExceptionInfo
5844      *exception;
5845
5846    Image
5847      *image;
5848
5849    RectangleInfo
5850      region;
5851
5852    ssize_t
5853      i;
5854
5855    struct PackageInfo
5856      *info;
5857
5858    SV
5859      *perl_exception,
5860      *reference;
5861
5862    void
5863      *blob = NULL;
5864
5865    PERL_UNUSED_VAR(ref);
5866    PERL_UNUSED_VAR(ix);
5867    exception=AcquireExceptionInfo();
5868    perl_exception=newSVpv("",0);
5869    if (sv_isobject(ST(0)) == 0)
5870      {
5871        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5872          PackageName);
5873        goto PerlException;
5874      }
5875    reference=SvRV(ST(0));
5876
5877    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5878    if (image == (Image *) NULL)
5879      {
5880        ThrowPerlException(exception,OptionError,"NoImagesDefined",
5881          PackageName);
5882        goto PerlException;
5883      }
5884
5885    region.x=0;
5886    region.y=0;
5887    region.width=image->columns;
5888    region.height=1;
5889    if (items == 1)
5890      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5891    for (i=2; i < items; i+=2)
5892    {
5893      attribute=(char *) SvPV(ST(i-1),na);
5894      switch (*attribute)
5895      {
5896        case 'g':
5897        case 'G':
5898        {
5899          if (LocaleCompare(attribute,"geometry") == 0)
5900            {
5901              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5902              break;
5903            }
5904          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5905            attribute);
5906          break;
5907        }
5908        case 'H':
5909        case 'h':
5910        {
5911          if (LocaleCompare(attribute,"height") == 0)
5912            {
5913              region.height=SvIV(ST(i));
5914              continue;
5915            }
5916          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5917            attribute);
5918          break;
5919        }
5920        case 'X':
5921        case 'x':
5922        {
5923          if (LocaleCompare(attribute,"x") == 0)
5924            {
5925              region.x=SvIV(ST(i));
5926              continue;
5927            }
5928          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5929            attribute);
5930          break;
5931        }
5932        case 'Y':
5933        case 'y':
5934        {
5935          if (LocaleCompare(attribute,"y") == 0)
5936            {
5937              region.y=SvIV(ST(i));
5938              continue;
5939            }
5940          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5941            attribute);
5942          break;
5943        }
5944        case 'W':
5945        case 'w':
5946        {
5947          if (LocaleCompare(attribute,"width") == 0)
5948            {
5949              region.width=SvIV(ST(i));
5950              continue;
5951            }
5952          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5953            attribute);
5954          break;
5955        }
5956      }
5957    }
5958    blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5959      region.height,exception);
5960    if (blob != (void *) NULL)
5961      goto PerlEnd;
5962
5963  PerlException:
5964    InheritPerlException(exception,perl_exception);
5965    exception=DestroyExceptionInfo(exception);
5966    SvREFCNT_dec(perl_exception);  /* throw away all errors */
5967
5968  PerlEnd:
5969    RETVAL = blob;
5970  }
5971  OUTPUT:
5972    RETVAL
5973
5974#
5975###############################################################################
5976#                                                                             #
5977#                                                                             #
5978#                                                                             #
5979#   G e t V i r t u a l P i x e l s                                           #
5980#                                                                             #
5981#                                                                             #
5982#                                                                             #
5983###############################################################################
5984#
5985#
5986void *
5987GetVirtualPixels(ref,...)
5988  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5989  ALIAS:
5990    getvirtualpixels = 1
5991    AcquireImagePixels = 2
5992    acquireimagepixels = 3
5993  CODE:
5994  {
5995    char
5996      *attribute;
5997
5998    const void
5999      *blob = NULL;
6000
6001    ExceptionInfo
6002      *exception;
6003
6004    Image
6005      *image;
6006
6007    RectangleInfo
6008      region;
6009
6010    ssize_t
6011      i;
6012
6013    struct PackageInfo
6014      *info;
6015
6016    SV
6017      *perl_exception,
6018      *reference;
6019
6020    PERL_UNUSED_VAR(ref);
6021    PERL_UNUSED_VAR(ix);
6022    exception=AcquireExceptionInfo();
6023    perl_exception=newSVpv("",0);
6024    if (sv_isobject(ST(0)) == 0)
6025      {
6026        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6027          PackageName);
6028        goto PerlException;
6029      }
6030    reference=SvRV(ST(0));
6031
6032    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6033    if (image == (Image *) NULL)
6034      {
6035        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6036          PackageName);
6037        goto PerlException;
6038      }
6039
6040    region.x=0;
6041    region.y=0;
6042    region.width=image->columns;
6043    region.height=1;
6044    if (items == 1)
6045      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6046    for (i=2; i < items; i+=2)
6047    {
6048      attribute=(char *) SvPV(ST(i-1),na);
6049      switch (*attribute)
6050      {
6051        case 'g':
6052        case 'G':
6053        {
6054          if (LocaleCompare(attribute,"geometry") == 0)
6055            {
6056              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6057              break;
6058            }
6059          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6060            attribute);
6061          break;
6062        }
6063        case 'H':
6064        case 'h':
6065        {
6066          if (LocaleCompare(attribute,"height") == 0)
6067            {
6068              region.height=SvIV(ST(i));
6069              continue;
6070            }
6071          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6072            attribute);
6073          break;
6074        }
6075        case 'X':
6076        case 'x':
6077        {
6078          if (LocaleCompare(attribute,"x") == 0)
6079            {
6080              region.x=SvIV(ST(i));
6081              continue;
6082            }
6083          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6084            attribute);
6085          break;
6086        }
6087        case 'Y':
6088        case 'y':
6089        {
6090          if (LocaleCompare(attribute,"y") == 0)
6091            {
6092              region.y=SvIV(ST(i));
6093              continue;
6094            }
6095          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6096            attribute);
6097          break;
6098        }
6099        case 'W':
6100        case 'w':
6101        {
6102          if (LocaleCompare(attribute,"width") == 0)
6103            {
6104              region.width=SvIV(ST(i));
6105              continue;
6106            }
6107          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6108            attribute);
6109          break;
6110        }
6111      }
6112    }
6113    blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6114      region.height,exception);
6115    if (blob != (void *) NULL)
6116      goto PerlEnd;
6117
6118  PerlException:
6119    InheritPerlException(exception,perl_exception);
6120    exception=DestroyExceptionInfo(exception);
6121    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6122
6123  PerlEnd:
6124    RETVAL = (void *) blob;
6125  }
6126  OUTPUT:
6127    RETVAL
6128
6129#
6130###############################################################################
6131#                                                                             #
6132#                                                                             #
6133#                                                                             #
6134#   G e t A u t h e n t i c M e t a c o n t e n t                             #
6135#                                                                             #
6136#                                                                             #
6137#                                                                             #
6138###############################################################################
6139#
6140#
6141void *
6142GetAuthenticMetacontent(ref,...)
6143  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6144  ALIAS:
6145    getauthenticmetacontent = 1
6146    GetMetacontent = 2
6147    getmetacontent = 3
6148  CODE:
6149  {
6150    ExceptionInfo
6151      *exception;
6152
6153    Image
6154      *image;
6155
6156    struct PackageInfo
6157      *info;
6158
6159    SV
6160      *perl_exception,
6161      *reference;
6162
6163    void
6164      *blob = NULL;
6165
6166    PERL_UNUSED_VAR(ref);
6167    PERL_UNUSED_VAR(ix);
6168    exception=AcquireExceptionInfo();
6169    perl_exception=newSVpv("",0);
6170    if (sv_isobject(ST(0)) == 0)
6171      {
6172        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6173          PackageName);
6174        goto PerlException;
6175      }
6176    reference=SvRV(ST(0));
6177
6178    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6179    if (image == (Image *) NULL)
6180      {
6181        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6182          PackageName);
6183        goto PerlException;
6184      }
6185
6186    blob=(void *) GetAuthenticMetacontent(image);
6187    if (blob != (void *) NULL)
6188      goto PerlEnd;
6189
6190  PerlException:
6191    InheritPerlException(exception,perl_exception);
6192    exception=DestroyExceptionInfo(exception);
6193    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6194
6195  PerlEnd:
6196    RETVAL = blob;
6197  }
6198  OUTPUT:
6199    RETVAL
6200
6201#
6202###############################################################################
6203#                                                                             #
6204#                                                                             #
6205#                                                                             #
6206#   G e t V i r t u a l M e t a c o n t e n t                                 #
6207#                                                                             #
6208#                                                                             #
6209#                                                                             #
6210###############################################################################
6211#
6212#
6213void *
6214GetVirtualMetacontent(ref,...)
6215  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6216  ALIAS:
6217    getvirtualmetacontent = 1
6218  CODE:
6219  {
6220    ExceptionInfo
6221      *exception;
6222
6223    Image
6224      *image;
6225
6226    struct PackageInfo
6227      *info;
6228
6229    SV
6230      *perl_exception,
6231      *reference;
6232
6233    void
6234      *blob = NULL;
6235
6236    PERL_UNUSED_VAR(ref);
6237    PERL_UNUSED_VAR(ix);
6238    exception=AcquireExceptionInfo();
6239    perl_exception=newSVpv("",0);
6240    if (sv_isobject(ST(0)) == 0)
6241      {
6242        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6243          PackageName);
6244        goto PerlException;
6245      }
6246    reference=SvRV(ST(0));
6247
6248    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6249    if (image == (Image *) NULL)
6250      {
6251        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6252          PackageName);
6253        goto PerlException;
6254      }
6255
6256    blob=(void *) GetVirtualMetacontent(image);
6257    if (blob != (void *) NULL)
6258      goto PerlEnd;
6259
6260  PerlException:
6261    InheritPerlException(exception,perl_exception);
6262    exception=DestroyExceptionInfo(exception);
6263    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6264
6265  PerlEnd:
6266    RETVAL = blob;
6267  }
6268  OUTPUT:
6269    RETVAL
6270
6271#
6272###############################################################################
6273#                                                                             #
6274#                                                                             #
6275#                                                                             #
6276#   H i s t o g r a m                                                         #
6277#                                                                             #
6278#                                                                             #
6279#                                                                             #
6280###############################################################################
6281#
6282#
6283void
6284Histogram(ref,...)
6285  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6286  ALIAS:
6287    HistogramImage = 1
6288    histogram      = 2
6289    histogramimage = 3
6290  PPCODE:
6291  {
6292    AV
6293      *av;
6294
6295    char
6296      message[MagickPathExtent];
6297
6298    PixelInfo
6299      *histogram;
6300
6301    ExceptionInfo
6302      *exception;
6303
6304    Image
6305      *image;
6306
6307    register ssize_t
6308      i;
6309
6310    ssize_t
6311      count;
6312
6313    struct PackageInfo
6314      *info;
6315
6316    SV
6317      *perl_exception,
6318      *reference;
6319
6320    size_t
6321      number_colors;
6322
6323    PERL_UNUSED_VAR(ref);
6324    PERL_UNUSED_VAR(ix);
6325    exception=AcquireExceptionInfo();
6326    perl_exception=newSVpv("",0);
6327    av=NULL;
6328    if (sv_isobject(ST(0)) == 0)
6329      {
6330        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6331          PackageName);
6332        goto PerlException;
6333      }
6334    reference=SvRV(ST(0));
6335    av=newAV();
6336    SvREFCNT_dec(av);
6337    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6338    if (image == (Image *) NULL)
6339      {
6340        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6341          PackageName);
6342        goto PerlException;
6343      }
6344    count=0;
6345    for ( ; image; image=image->next)
6346    {
6347      histogram=GetImageHistogram(image,&number_colors,exception);
6348      if (histogram == (PixelInfo *) NULL)
6349        continue;
6350      count+=(ssize_t) number_colors;
6351      EXTEND(sp,6*count);
6352      for (i=0; i < (ssize_t) number_colors; i++)
6353      {
6354        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6355          histogram[i].red);
6356        PUSHs(sv_2mortal(newSVpv(message,0)));
6357        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6358          histogram[i].green);
6359        PUSHs(sv_2mortal(newSVpv(message,0)));
6360        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6361          histogram[i].blue);
6362        PUSHs(sv_2mortal(newSVpv(message,0)));
6363        if (image->colorspace == CMYKColorspace)
6364          {
6365            (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6366              histogram[i].black);
6367            PUSHs(sv_2mortal(newSVpv(message,0)));
6368          }
6369        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6370          histogram[i].alpha);
6371        PUSHs(sv_2mortal(newSVpv(message,0)));
6372        (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6373          histogram[i].count);
6374        PUSHs(sv_2mortal(newSVpv(message,0)));
6375      }
6376      histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6377    }
6378
6379  PerlException:
6380    InheritPerlException(exception,perl_exception);
6381    exception=DestroyExceptionInfo(exception);
6382    SvREFCNT_dec(perl_exception);
6383  }
6384
6385#
6386###############################################################################
6387#                                                                             #
6388#                                                                             #
6389#                                                                             #
6390#   G e t P i x e l                                                           #
6391#                                                                             #
6392#                                                                             #
6393#                                                                             #
6394###############################################################################
6395#
6396#
6397void
6398GetPixel(ref,...)
6399  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6400  ALIAS:
6401    getpixel = 1
6402    getPixel = 2
6403  PPCODE:
6404  {
6405    AV
6406      *av;
6407
6408    char
6409      *attribute;
6410
6411    ExceptionInfo
6412      *exception;
6413
6414    Image
6415      *image;
6416
6417    MagickBooleanType
6418      normalize;
6419
6420    RectangleInfo
6421      region;
6422
6423    register const Quantum
6424      *p;
6425
6426    register ssize_t
6427      i;
6428
6429    ssize_t
6430      option;
6431
6432    struct PackageInfo
6433      *info;
6434
6435    SV
6436      *perl_exception,
6437      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6438
6439    PERL_UNUSED_VAR(ref);
6440    PERL_UNUSED_VAR(ix);
6441    exception=AcquireExceptionInfo();
6442    perl_exception=newSVpv("",0);
6443    reference=SvRV(ST(0));
6444    av=(AV *) reference;
6445    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6446      exception);
6447    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6448    if (image == (Image *) NULL)
6449      {
6450        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6451          PackageName);
6452        goto PerlException;
6453      }
6454    normalize=MagickTrue;
6455    region.x=0;
6456    region.y=0;
6457    region.width=image->columns;
6458    region.height=1;
6459    if (items == 1)
6460      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6461    for (i=2; i < items; i+=2)
6462    {
6463      attribute=(char *) SvPV(ST(i-1),na);
6464      switch (*attribute)
6465      {
6466        case 'C':
6467        case 'c':
6468        {
6469          if (LocaleCompare(attribute,"channel") == 0)
6470            {
6471              ssize_t
6472                option;
6473
6474              option=ParseChannelOption(SvPV(ST(i),na));
6475              if (option < 0)
6476                {
6477                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6478                    SvPV(ST(i),na));
6479                  return;
6480                }
6481              (void) SetPixelChannelMask(image,(ChannelType) option);
6482              break;
6483            }
6484          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6485            attribute);
6486          break;
6487        }
6488        case 'g':
6489        case 'G':
6490        {
6491          if (LocaleCompare(attribute,"geometry") == 0)
6492            {
6493              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6494              break;
6495            }
6496          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6497            attribute);
6498          break;
6499        }
6500        case 'N':
6501        case 'n':
6502        {
6503          if (LocaleCompare(attribute,"normalize") == 0)
6504            {
6505              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6506                SvPV(ST(i),na));
6507              if (option < 0)
6508                {
6509                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6510                    SvPV(ST(i),na));
6511                  break;
6512                }
6513             normalize=option != 0 ? MagickTrue : MagickFalse;
6514             break;
6515            }
6516          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6517            attribute);
6518          break;
6519        }
6520        case 'x':
6521        case 'X':
6522        {
6523          if (LocaleCompare(attribute,"x") == 0)
6524            {
6525              region.x=SvIV(ST(i));
6526              break;
6527            }
6528          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6529            attribute);
6530          break;
6531        }
6532        case 'y':
6533        case 'Y':
6534        {
6535          if (LocaleCompare(attribute,"y") == 0)
6536            {
6537              region.y=SvIV(ST(i));
6538              break;
6539            }
6540          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6541            attribute);
6542          break;
6543        }
6544        default:
6545        {
6546          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6547            attribute);
6548          break;
6549        }
6550      }
6551    }
6552    p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6553    if (p == (const Quantum *) NULL)
6554      PUSHs(&sv_undef);
6555    else
6556      {
6557        double
6558          scale;
6559
6560        scale=1.0;
6561        if (normalize != MagickFalse)
6562          scale=1.0/QuantumRange;
6563        if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6564          PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6565        if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6566          PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6567        if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6568          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6569        if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6570            (image->colorspace == CMYKColorspace))
6571          PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6572        if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6573          PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6574      }
6575
6576  PerlException:
6577    InheritPerlException(exception,perl_exception);
6578    exception=DestroyExceptionInfo(exception);
6579    SvREFCNT_dec(perl_exception);
6580  }
6581
6582#
6583###############################################################################
6584#                                                                             #
6585#                                                                             #
6586#                                                                             #
6587#   G e t P i x e l s                                                         #
6588#                                                                             #
6589#                                                                             #
6590#                                                                             #
6591###############################################################################
6592#
6593#
6594void
6595GetPixels(ref,...)
6596  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6597  ALIAS:
6598    getpixels = 1
6599    getPixels = 2
6600  PPCODE:
6601  {
6602    AV
6603      *av;
6604
6605    char
6606      *attribute;
6607
6608    const char
6609      *map;
6610
6611    ExceptionInfo
6612      *exception;
6613
6614    Image
6615      *image;
6616
6617    MagickBooleanType
6618      normalize,
6619      status;
6620
6621    RectangleInfo
6622      region;
6623
6624    register ssize_t
6625      i;
6626
6627    ssize_t
6628      option;
6629
6630    struct PackageInfo
6631      *info;
6632
6633    SV
6634      *perl_exception,
6635      *reference;  /* reference is the SV* of ref=SvIV(reference) */
6636
6637    PERL_UNUSED_VAR(ref);
6638    PERL_UNUSED_VAR(ix);
6639    exception=AcquireExceptionInfo();
6640    perl_exception=newSVpv("",0);
6641    reference=SvRV(ST(0));
6642    av=(AV *) reference;
6643    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6644      exception);
6645    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6646    if (image == (Image *) NULL)
6647      {
6648        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6649          PackageName);
6650        goto PerlException;
6651      }
6652    map="RGB";
6653    if (image->alpha_trait != UndefinedPixelTrait)
6654      map="RGBA";
6655    if (image->colorspace == CMYKColorspace)
6656      {
6657        map="CMYK";
6658        if (image->alpha_trait != UndefinedPixelTrait)
6659          map="CMYKA";
6660      }
6661    normalize=MagickFalse;
6662    region.x=0;
6663    region.y=0;
6664    region.width=image->columns;
6665    region.height=1;
6666    if (items == 1)
6667      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6668    for (i=2; i < items; i+=2)
6669    {
6670      attribute=(char *) SvPV(ST(i-1),na);
6671      switch (*attribute)
6672      {
6673        case 'g':
6674        case 'G':
6675        {
6676          if (LocaleCompare(attribute,"geometry") == 0)
6677            {
6678              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6679              break;
6680            }
6681          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6682            attribute);
6683          break;
6684        }
6685        case 'H':
6686        case 'h':
6687        {
6688          if (LocaleCompare(attribute,"height") == 0)
6689            {
6690              region.height=SvIV(ST(i));
6691              break;
6692            }
6693          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6694            attribute);
6695          break;
6696        }
6697        case 'M':
6698        case 'm':
6699        {
6700          if (LocaleCompare(attribute,"map") == 0)
6701            {
6702              map=SvPV(ST(i),na);
6703              break;
6704            }
6705          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6706            attribute);
6707          break;
6708        }
6709        case 'N':
6710        case 'n':
6711        {
6712          if (LocaleCompare(attribute,"normalize") == 0)
6713            {
6714              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6715                SvPV(ST(i),na));
6716              if (option < 0)
6717                {
6718                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
6719                    SvPV(ST(i),na));
6720                  break;
6721                }
6722             normalize=option != 0 ? MagickTrue : MagickFalse;
6723             break;
6724            }
6725          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6726            attribute);
6727          break;
6728        }
6729        case 'W':
6730        case 'w':
6731        {
6732          if (LocaleCompare(attribute,"width") == 0)
6733            {
6734              region.width=SvIV(ST(i));
6735              break;
6736            }
6737          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6738            attribute);
6739          break;
6740        }
6741        case 'x':
6742        case 'X':
6743        {
6744          if (LocaleCompare(attribute,"x") == 0)
6745            {
6746              region.x=SvIV(ST(i));
6747              break;
6748            }
6749          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6750            attribute);
6751          break;
6752        }
6753        case 'y':
6754        case 'Y':
6755        {
6756          if (LocaleCompare(attribute,"y") == 0)
6757            {
6758              region.y=SvIV(ST(i));
6759              break;
6760            }
6761          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6762            attribute);
6763          break;
6764        }
6765        default:
6766        {
6767          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6768            attribute);
6769          break;
6770        }
6771      }
6772    }
6773    if (normalize != MagickFalse)
6774      {
6775        float
6776          *pixels;
6777
6778        pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6779          region.height*sizeof(*pixels));
6780        if (pixels == (float *) NULL)
6781          {
6782            ThrowPerlException(exception,ResourceLimitError,
6783              "MemoryAllocationFailed",PackageName);
6784            goto PerlException;
6785          }
6786        status=ExportImagePixels(image,region.x,region.y,region.width,
6787          region.height,map,FloatPixel,pixels,exception);
6788        if (status == MagickFalse)
6789          PUSHs(&sv_undef);
6790        else
6791          {
6792            EXTEND(sp,strlen(map)*region.width*region.height);
6793            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6794              PUSHs(sv_2mortal(newSVnv(pixels[i])));
6795          }
6796        pixels=(float *) RelinquishMagickMemory(pixels);
6797      }
6798    else
6799      {
6800        Quantum
6801          *pixels;
6802
6803        pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6804          region.height*sizeof(*pixels));
6805        if (pixels == (Quantum *) NULL)
6806          {
6807            ThrowPerlException(exception,ResourceLimitError,
6808              "MemoryAllocationFailed",PackageName);
6809            goto PerlException;
6810          }
6811        status=ExportImagePixels(image,region.x,region.y,region.width,
6812          region.height,map,QuantumPixel,pixels,exception);
6813        if (status == MagickFalse)
6814          PUSHs(&sv_undef);
6815        else
6816          {
6817            EXTEND(sp,strlen(map)*region.width*region.height);
6818            for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6819              PUSHs(sv_2mortal(newSViv(pixels[i])));
6820          }
6821        pixels=(Quantum *) RelinquishMagickMemory(pixels);
6822      }
6823
6824  PerlException:
6825    InheritPerlException(exception,perl_exception);
6826    exception=DestroyExceptionInfo(exception);
6827    SvREFCNT_dec(perl_exception);
6828  }
6829
6830#
6831###############################################################################
6832#                                                                             #
6833#                                                                             #
6834#                                                                             #
6835#   I m a g e T o B l o b                                                     #
6836#                                                                             #
6837#                                                                             #
6838#                                                                             #
6839###############################################################################
6840#
6841#
6842void
6843ImageToBlob(ref,...)
6844  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6845  ALIAS:
6846    ImageToBlob  = 1
6847    imagetoblob  = 2
6848    toblob       = 3
6849    blob         = 4
6850  PPCODE:
6851  {
6852    char
6853      filename[MagickPathExtent];
6854
6855    ExceptionInfo
6856      *exception;
6857
6858    Image
6859      *image,
6860      *next;
6861
6862    register ssize_t
6863      i;
6864
6865    struct PackageInfo
6866      *info,
6867      *package_info;
6868
6869    size_t
6870      length;
6871
6872    ssize_t
6873      scene;
6874
6875    SV
6876      *perl_exception,
6877      *reference;
6878
6879    void
6880      *blob;
6881
6882    PERL_UNUSED_VAR(ref);
6883    PERL_UNUSED_VAR(ix);
6884    exception=AcquireExceptionInfo();
6885    perl_exception=newSVpv("",0);
6886    package_info=(struct PackageInfo *) NULL;
6887    if (sv_isobject(ST(0)) == 0)
6888      {
6889        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6890          PackageName);
6891        goto PerlException;
6892      }
6893    reference=SvRV(ST(0));
6894    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6895    if (image == (Image *) NULL)
6896      {
6897        ThrowPerlException(exception,OptionError,"NoImagesDefined",
6898          PackageName);
6899        goto PerlException;
6900      }
6901    package_info=ClonePackageInfo(info,exception);
6902    for (i=2; i < items; i+=2)
6903      SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6904    (void) CopyMagickString(filename,package_info->image_info->filename,
6905      MagickPathExtent);
6906    scene=0;
6907    for (next=image; next; next=next->next)
6908    {
6909      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6910      next->scene=scene++;
6911    }
6912    SetImageInfo(package_info->image_info,(unsigned int)
6913      GetImageListLength(image),exception);
6914    EXTEND(sp,(ssize_t) GetImageListLength(image));
6915    for ( ; image; image=image->next)
6916    {
6917      length=0;
6918      blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6919      if (blob != (char *) NULL)
6920        {
6921          PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6922          blob=(unsigned char *) RelinquishMagickMemory(blob);
6923        }
6924      if (package_info->image_info->adjoin)
6925        break;
6926    }
6927
6928  PerlException:
6929    if (package_info != (struct PackageInfo *) NULL)
6930      DestroyPackageInfo(package_info);
6931    InheritPerlException(exception,perl_exception);
6932    exception=DestroyExceptionInfo(exception);
6933    SvREFCNT_dec(perl_exception);  /* throw away all errors */
6934  }
6935
6936#
6937###############################################################################
6938#                                                                             #
6939#                                                                             #
6940#                                                                             #
6941#   L a y e r s                                                               #
6942#                                                                             #
6943#                                                                             #
6944#                                                                             #
6945###############################################################################
6946#
6947#
6948void
6949Layers(ref,...)
6950  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6951  ALIAS:
6952    Layers                = 1
6953    layers           = 2
6954    OptimizeImageLayers   = 3
6955    optimizelayers        = 4
6956    optimizeimagelayers   = 5
6957  PPCODE:
6958  {
6959    AV
6960      *av;
6961
6962    char
6963      *attribute;
6964
6965    CompositeOperator
6966      compose;
6967
6968    ExceptionInfo
6969      *exception;
6970
6971    HV
6972      *hv;
6973
6974    Image
6975      *image,
6976      *layers;
6977
6978    LayerMethod
6979      method;
6980
6981    register ssize_t
6982      i;
6983
6984    ssize_t
6985      option,
6986      sp;
6987
6988    struct PackageInfo
6989      *info;
6990
6991    SV
6992      *av_reference,
6993      *perl_exception,
6994      *reference,
6995      *rv,
6996      *sv;
6997
6998    PERL_UNUSED_VAR(ref);
6999    PERL_UNUSED_VAR(ix);
7000    exception=AcquireExceptionInfo();
7001    perl_exception=newSVpv("",0);
7002    sv=NULL;
7003    if (sv_isobject(ST(0)) == 0)
7004      {
7005        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7006          PackageName);
7007        goto PerlException;
7008      }
7009    reference=SvRV(ST(0));
7010    hv=SvSTASH(reference);
7011    av=newAV();
7012    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7013    SvREFCNT_dec(av);
7014    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7015    if (image == (Image *) NULL)
7016      {
7017        ThrowPerlException(exception,OptionError,"NoImagesDefined",
7018          PackageName);
7019        goto PerlException;
7020      }
7021    compose=image->compose;
7022    method=OptimizeLayer;
7023    for (i=2; i < items; i+=2)
7024    {
7025      attribute=(char *) SvPV(ST(i-1),na);
7026      switch (*attribute)
7027      {
7028        case 'C':
7029        case 'c':
7030        {
7031          if (LocaleCompare(attribute,"compose") == 0)
7032            {
7033              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7034                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7035              if (sp < 0)
7036                {
7037                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7038                    SvPV(ST(i),na));
7039                  break;
7040                }
7041              compose=(CompositeOperator) sp;
7042              break;
7043            }
7044          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7045            attribute);
7046          break;
7047        }
7048        case 'M':
7049        case 'm':
7050        {
7051          if (LocaleCompare(attribute,"method") == 0)
7052            {
7053              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7054                SvPV(ST(i),na));
7055              if (option < 0)
7056                {
7057                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
7058                    SvPV(ST(i),na));
7059                  break;
7060                }
7061              method=(LayerMethod) option;
7062              break;
7063            }
7064          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7065            attribute);
7066          break;
7067        }
7068        default:
7069        {
7070          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7071            attribute);
7072          break;
7073        }
7074      }
7075    }
7076    layers=(Image *) NULL;
7077    switch (method)
7078    {
7079      case CompareAnyLayer:
7080      case CompareClearLayer:
7081      case CompareOverlayLayer:
7082      default:
7083      {
7084        layers=CompareImagesLayers(image,method,exception);
7085        break;
7086      }
7087      case MergeLayer:
7088      case FlattenLayer:
7089      case MosaicLayer:
7090      {
7091        layers=MergeImageLayers(image,method,exception);
7092        break;
7093      }
7094      case DisposeLayer:
7095      {
7096        layers=DisposeImages(image,exception);
7097        break;
7098      }
7099      case OptimizeImageLayer:
7100      {
7101        layers=OptimizeImageLayers(image,exception);
7102        break;
7103      }
7104      case OptimizePlusLayer:
7105      {
7106        layers=OptimizePlusImageLayers(image,exception);
7107        break;
7108      }
7109      case OptimizeTransLayer:
7110      {
7111        OptimizeImageTransparency(image,exception);
7112        break;
7113      }
7114      case RemoveDupsLayer:
7115      {
7116        RemoveDuplicateLayers(&image,exception);
7117        break;
7118      }
7119      case RemoveZeroLayer:
7120      {
7121        RemoveZeroDelayLayers(&image,exception);
7122        break;
7123      }
7124      case OptimizeLayer:
7125      {
7126        QuantizeInfo
7127          *quantize_info;
7128
7129        /*
7130          General Purpose, GIF Animation Optimizer.
7131        */
7132        layers=CoalesceImages(image,exception);
7133        if (layers == (Image *) NULL)
7134          break;
7135        image=layers;
7136        layers=OptimizeImageLayers(image,exception);
7137        if (layers == (Image *) NULL)
7138          break;
7139        image=DestroyImageList(image);
7140        image=layers;
7141        layers=(Image *) NULL;
7142        OptimizeImageTransparency(image,exception);
7143        quantize_info=AcquireQuantizeInfo(info->image_info);
7144        (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7145        quantize_info=DestroyQuantizeInfo(quantize_info);
7146        break;
7147      }
7148      case CompositeLayer:
7149      {
7150        Image
7151          *source;
7152
7153        RectangleInfo
7154          geometry;
7155
7156        /*
7157          Split image sequence at the first 'NULL:' image.
7158        */
7159        source=image;
7160        while (source != (Image *) NULL)
7161        {
7162          source=GetNextImageInList(source);
7163          if ((source != (Image *) NULL) &&
7164              (LocaleCompare(source->magick,"NULL") == 0))
7165            break;
7166        }
7167        if (source != (Image *) NULL)
7168          {
7169            if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7170                (GetNextImageInList(source) == (Image *) NULL))
7171              source=(Image *) NULL;
7172            else
7173              {
7174                /*
7175                  Separate the two lists, junk the null: image.
7176                */
7177                source=SplitImageList(source->previous);
7178                DeleteImageFromList(&source);
7179              }
7180          }
7181        if (source == (Image *) NULL)
7182          {
7183            (void) ThrowMagickException(exception,GetMagickModule(),
7184              OptionError,"MissingNullSeparator","layers Composite");
7185            break;
7186          }
7187        /*
7188          Adjust offset with gravity and virtual canvas.
7189        */
7190        SetGeometry(image,&geometry);
7191        (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7192        geometry.width=source->page.width != 0 ? source->page.width :
7193          source->columns;
7194        geometry.height=source->page.height != 0 ? source->page.height :
7195          source->rows;
7196        GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7197          image->columns,image->page.height != 0 ? image->page.height :
7198          image->rows,image->gravity,&geometry);
7199        CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7200        source=DestroyImageList(source);
7201        break;
7202      }
7203    }
7204    if (layers != (Image *) NULL)
7205      image=layers;
7206    else
7207      image=CloneImage(image,0,0,MagickTrue,exception);
7208    if (image == (Image *) NULL)
7209      goto PerlException;
7210    for ( ; image; image=image->next)
7211    {
7212      AddImageToRegistry(sv,image);
7213      rv=newRV(sv);
7214      av_push(av,sv_bless(rv,hv));
7215      SvREFCNT_dec(sv);
7216    }
7217    exception=DestroyExceptionInfo(exception);
7218    ST(0)=av_reference;
7219    SvREFCNT_dec(perl_exception);
7220    XSRETURN(1);
7221
7222  PerlException:
7223    InheritPerlException(exception,perl_exception);
7224    exception=DestroyExceptionInfo(exception);
7225    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7226    SvPOK_on(perl_exception);
7227    ST(0)=sv_2mortal(perl_exception);
7228    XSRETURN(1);
7229  }
7230
7231#
7232###############################################################################
7233#                                                                             #
7234#                                                                             #
7235#                                                                             #
7236#   M a g i c k T o M i m e                                                   #
7237#                                                                             #
7238#                                                                             #
7239#                                                                             #
7240###############################################################################
7241#
7242#
7243SV *
7244MagickToMime(ref,name)
7245  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7246  char *name
7247  ALIAS:
7248    magicktomime = 1
7249  CODE:
7250  {
7251    char
7252      *mime;
7253
7254    PERL_UNUSED_VAR(ref);
7255    PERL_UNUSED_VAR(ix);
7256    mime=MagickToMime(name);
7257    RETVAL=newSVpv(mime,0);
7258    mime=(char *) RelinquishMagickMemory(mime);
7259  }
7260  OUTPUT:
7261    RETVAL
7262
7263#
7264###############################################################################
7265#                                                                             #
7266#                                                                             #
7267#                                                                             #
7268#   M o g r i f y                                                             #
7269#                                                                             #
7270#                                                                             #
7271#                                                                             #
7272###############################################################################
7273#
7274#
7275void
7276Mogrify(ref,...)
7277  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7278  ALIAS:
7279    Comment            =   1
7280    CommentImage       =   2
7281    Label              =   3
7282    LabelImage         =   4
7283    AddNoise           =   5
7284    AddNoiseImage      =   6
7285    Colorize           =   7
7286    ColorizeImage      =   8
7287    Border             =   9
7288    BorderImage        =  10
7289    Blur               =  11
7290    BlurImage          =  12
7291    Chop               =  13
7292    ChopImage          =  14
7293    Crop               =  15
7294    CropImage          =  16
7295    Despeckle          =  17
7296    DespeckleImage     =  18
7297    Edge               =  19
7298    EdgeImage          =  20
7299    Emboss             =  21
7300    EmbossImage        =  22
7301    Enhance            =  23
7302    EnhanceImage       =  24
7303    Flip               =  25
7304    FlipImage          =  26
7305    Flop               =  27
7306    FlopImage          =  28
7307    Frame              =  29
7308    FrameImage         =  30
7309    Implode            =  31
7310    ImplodeImage       =  32
7311    Magnify            =  33
7312    MagnifyImage       =  34
7313    MedianFilter       =  35
7314    MedianConvolveImage  =  36
7315    Minify             =  37
7316    MinifyImage        =  38
7317    OilPaint           =  39
7318    OilPaintImage      =  40
7319    ReduceNoise        =  41
7320    ReduceNoiseImage   =  42
7321    Roll               =  43
7322    RollImage          =  44
7323    Rotate             =  45
7324    RotateImage        =  46
7325    Sample             =  47
7326    SampleImage        =  48
7327    Scale              =  49
7328    ScaleImage         =  50
7329    Shade              =  51
7330    ShadeImage         =  52
7331    Sharpen            =  53
7332    SharpenImage       =  54
7333    Shear              =  55
7334    ShearImage         =  56
7335    Spread             =  57
7336    SpreadImage        =  58
7337    Swirl              =  59
7338    SwirlImage         =  60
7339    Resize             =  61
7340    ResizeImage        =  62
7341    Zoom               =  63
7342    ZoomImage          =  64
7343    Annotate           =  65
7344    AnnotateImage      =  66
7345    ColorFloodfill     =  67
7346    ColorFloodfillImage=  68
7347    Composite          =  69
7348    CompositeImage     =  70
7349    Contrast           =  71
7350    ContrastImage      =  72
7351    CycleColormap      =  73
7352    CycleColormapImage =  74
7353    Draw               =  75
7354    DrawImage          =  76
7355    Equalize           =  77
7356    EqualizeImage      =  78
7357    Gamma              =  79
7358    GammaImage         =  80
7359    Map                =  81
7360    MapImage           =  82
7361    MatteFloodfill     =  83
7362    MatteFloodfillImage=  84
7363    Modulate           =  85
7364    ModulateImage      =  86
7365    Negate             =  87
7366    NegateImage        =  88
7367    Normalize          =  89
7368    NormalizeImage     =  90
7369    NumberColors       =  91
7370    NumberColorsImage  =  92
7371    Opaque             =  93
7372    OpaqueImage        =  94
7373    Quantize           =  95
7374    QuantizeImage      =  96
7375    Raise              =  97
7376    RaiseImage         =  98
7377    Segment            =  99
7378    SegmentImage       = 100
7379    Signature          = 101
7380    SignatureImage     = 102
7381    Solarize           = 103
7382    SolarizeImage      = 104
7383    Sync               = 105
7384    SyncImage          = 106
7385    Texture            = 107
7386    TextureImage       = 108
7387    Evaluate           = 109
7388    EvaluateImage      = 110
7389    Transparent        = 111
7390    TransparentImage   = 112
7391    Threshold          = 113
7392    ThresholdImage     = 114
7393    Charcoal           = 115
7394    CharcoalImage      = 116
7395    Trim               = 117
7396    TrimImage          = 118
7397    Wave               = 119
7398    WaveImage          = 120
7399    Separate           = 121
7400    SeparateImage      = 122
7401    Stereo             = 125
7402    StereoImage        = 126
7403    Stegano            = 127
7404    SteganoImage       = 128
7405    Deconstruct        = 129
7406    DeconstructImage   = 130
7407    GaussianBlur       = 131
7408    GaussianBlurImage  = 132
7409    Convolve           = 133
7410    ConvolveImage      = 134
7411    Profile            = 135
7412    ProfileImage       = 136
7413    UnsharpMask        = 137
7414    UnsharpMaskImage   = 138
7415    MotionBlur         = 139
7416    MotionBlurImage    = 140
7417    OrderedDither      = 141
7418    OrderedDitherImage = 142
7419    Shave              = 143
7420    ShaveImage         = 144
7421    Level              = 145
7422    LevelImage         = 146
7423    Clip               = 147
7424    ClipImage          = 148
7425    AffineTransform    = 149
7426    AffineTransformImage = 150
7427    Difference         = 151
7428    DifferenceImage    = 152
7429    AdaptiveThreshold  = 153
7430    AdaptiveThresholdImage = 154
7431    Resample           = 155
7432    ResampleImage      = 156
7433    Describe           = 157
7434    DescribeImage      = 158
7435    BlackThreshold     = 159
7436    BlackThresholdImage= 160
7437    WhiteThreshold     = 161
7438    WhiteThresholdImage= 162
7439    RotationalBlur     = 163
7440    RotationalBlurImage= 164
7441    Thumbnail          = 165
7442    ThumbnailImage     = 166
7443    Strip              = 167
7444    StripImage         = 168
7445    Tint               = 169
7446    TintImage          = 170
7447    Channel            = 171
7448    ChannelImage       = 172
7449    Splice             = 173
7450    SpliceImage        = 174
7451    Posterize          = 175
7452    PosterizeImage     = 176
7453    Shadow             = 177
7454    ShadowImage        = 178
7455    Identify           = 179
7456    IdentifyImage      = 180
7457    SepiaTone          = 181
7458    SepiaToneImage     = 182
7459    SigmoidalContrast  = 183
7460    SigmoidalContrastImage = 184
7461    Extent             = 185
7462    ExtentImage        = 186
7463    Vignette           = 187
7464    VignetteImage      = 188
7465    ContrastStretch    = 189
7466    ContrastStretchImage = 190
7467    Sans0              = 191
7468    Sans0Image         = 192
7469    Sans1              = 193
7470    Sans1Image         = 194
7471    AdaptiveSharpen    = 195
7472    AdaptiveSharpenImage = 196
7473    Transpose          = 197
7474    TransposeImage     = 198
7475    Transverse         = 199
7476    TransverseImage    = 200
7477    AutoOrient         = 201
7478    AutoOrientImage    = 202
7479    AdaptiveBlur       = 203
7480    AdaptiveBlurImage  = 204
7481    Sketch             = 205
7482    SketchImage        = 206
7483    UniqueColors       = 207
7484    UniqueColorsImage  = 208
7485    AdaptiveResize     = 209
7486    AdaptiveResizeImage= 210
7487    ClipMask           = 211
7488    ClipMaskImage      = 212
7489    LinearStretch      = 213
7490    LinearStretchImage = 214
7491    ColorMatrix        = 215
7492    ColorMatrixImage   = 216
7493    Mask               = 217
7494    MaskImage          = 218
7495    Polaroid           = 219
7496    PolaroidImage      = 220
7497    FloodfillPaint     = 221
7498    FloodfillPaintImage= 222
7499    Distort            = 223
7500    DistortImage       = 224
7501    Clut               = 225
7502    ClutImage          = 226
7503    LiquidRescale      = 227
7504    LiquidRescaleImage = 228
7505    Encipher           = 229
7506    EncipherImage      = 230
7507    Decipher           = 231
7508    DecipherImage      = 232
7509    Deskew             = 233
7510    DeskewImage        = 234
7511    Remap              = 235
7512    RemapImage         = 236
7513    SparseColor        = 237
7514    SparseColorImage   = 238
7515    Function           = 239
7516    FunctionImage      = 240
7517    SelectiveBlur      = 241
7518    SelectiveBlurImage = 242
7519    HaldClut           = 243
7520    HaldClutImage      = 244
7521    BlueShift          = 245
7522    BlueShiftImage     = 246
7523    ForwardFourierTransform  = 247
7524    ForwardFourierTransformImage = 248
7525    InverseFourierTransform = 249
7526    InverseFourierTransformImage = 250
7527    ColorDecisionList  = 251
7528    ColorDecisionListImage = 252
7529    AutoGamma          = 253
7530    AutoGammaImage     = 254
7531    AutoLevel          = 255
7532    AutoLevelImage     = 256
7533    LevelColors        = 257
7534    LevelImageColors   = 258
7535    Clamp              = 259
7536    ClampImage         = 260
7537    BrightnessContrast = 261
7538    BrightnessContrastImage = 262
7539    Morphology         = 263
7540    MorphologyImage    = 264
7541    Mode               = 265
7542    ModeImage          = 266
7543    Statistic          = 267
7544    StatisticImage     = 268
7545    Perceptible        = 269
7546    PerceptibleImage   = 270
7547    Poly               = 271
7548    PolyImage          = 272
7549    Grayscale          = 273
7550    GrayscaleImage     = 274
7551    CannyEdge          = 275
7552    CannyEdgeImage     = 276
7553    HoughLine          = 277
7554    HoughLineImage     = 278
7555    MeanShift          = 279
7556    MeanShiftImage     = 280
7557    Kuwahara           = 281
7558    KuwaharaImage      = 282
7559    ConnectedComponent = 283
7560    ConnectedComponentImage = 284
7561    CopyPixels         = 285
7562    CopyImagePixels    = 286
7563    Color              = 287
7564    ColorImage         = 288
7565    WaveletDenoise     = 289
7566    WaveletDenoiseImage= 290
7567    MogrifyRegion      = 666
7568  PPCODE:
7569  {
7570    AffineMatrix
7571      affine,
7572      current;
7573
7574    char
7575      attribute_flag[MaxArguments],
7576      message[MagickPathExtent];
7577
7578    ChannelType
7579      channel,
7580      channel_mask;
7581
7582    CompositeOperator
7583      compose;
7584
7585    const char
7586      *attribute,
7587      *value;
7588
7589    double
7590      angle;
7591
7592    ExceptionInfo
7593      *exception;
7594
7595    GeometryInfo
7596      geometry_info;
7597
7598    Image
7599      *image,
7600      *next,
7601      *region_image;
7602
7603    MagickBooleanType
7604      status;
7605
7606    MagickStatusType
7607      flags;
7608
7609    PixelInfo
7610      fill_color;
7611
7612    RectangleInfo
7613      geometry,
7614      region_info;
7615
7616    register ssize_t
7617      i;
7618
7619    ssize_t
7620      base,
7621      j,
7622      number_images;
7623
7624    struct Methods
7625      *rp;
7626
7627    struct PackageInfo
7628      *info;
7629
7630    SV
7631      *perl_exception,
7632      **pv,
7633      *reference,
7634      **reference_vector;
7635
7636    struct ArgumentList
7637      argument_list[MaxArguments];
7638
7639    PERL_UNUSED_VAR(ref);
7640    PERL_UNUSED_VAR(ix);
7641    exception=AcquireExceptionInfo();
7642    perl_exception=newSVpv("",0);
7643    reference_vector=NULL;
7644    region_image=NULL;
7645    number_images=0;
7646    base=2;
7647    if (sv_isobject(ST(0)) == 0)
7648      {
7649        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7650          PackageName);
7651        goto PerlException;
7652      }
7653    reference=SvRV(ST(0));
7654    region_info.width=0;
7655    region_info.height=0;
7656    region_info.x=0;
7657    region_info.y=0;
7658    region_image=(Image *) NULL;
7659    image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7660    if (ix && (ix != 666))
7661      {
7662        /*
7663          Called as Method(...)
7664        */
7665        ix=(ix+1)/2;
7666        rp=(&Methods[ix-1]);
7667        attribute=rp->name;
7668      }
7669    else
7670      {
7671        /*
7672          Called as Mogrify("Method",...)
7673        */
7674        attribute=(char *) SvPV(ST(1),na);
7675        if (ix)
7676          {
7677            flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7678            attribute=(char *) SvPV(ST(2),na);
7679            base++;
7680          }
7681        for (rp=Methods; ; rp++)
7682        {
7683          if (rp >= EndOf(Methods))
7684            {
7685              ThrowPerlException(exception,OptionError,
7686                "UnrecognizedPerlMagickMethod",attribute);
7687              goto PerlException;
7688            }
7689          if (strEQcase(attribute,rp->name))
7690            break;
7691        }
7692        ix=rp-Methods+1;
7693        base++;
7694      }
7695    if (image == (Image *) NULL)
7696      {
7697        ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7698        goto PerlException;
7699      }
7700    Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7701    Zero(&attribute_flag,NumberOf(attribute_flag),char);
7702    for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7703    {
7704      Arguments
7705        *pp,
7706        *qq;
7707
7708      ssize_t
7709        ssize_test;
7710
7711      struct ArgumentList
7712        *al;
7713
7714      SV
7715        *sv;
7716
7717      sv=NULL;
7718      ssize_test=0;
7719      pp=(Arguments *) NULL;
7720      qq=rp->arguments;
7721      if (i == items)
7722        {
7723          pp=rp->arguments,
7724          sv=ST(i-1);
7725        }
7726      else
7727        for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7728        {
7729          if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7730            break;
7731          if (strEQcase(attribute,qq->method) > ssize_test)
7732            {
7733              pp=qq;
7734              ssize_test=strEQcase(attribute,qq->method);
7735            }
7736        }
7737      if (pp == (Arguments *) NULL)
7738        {
7739          ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7740            attribute);
7741          goto continue_outer_loop;
7742        }
7743      al=(&argument_list[pp-rp->arguments]);
7744      switch (pp->type)
7745      {
7746        case ArrayReference:
7747        {
7748          if (SvTYPE(sv) != SVt_RV)
7749            {
7750              (void) FormatLocaleString(message,MagickPathExtent,
7751                "invalid %.60s value",pp->method);
7752              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7753              goto continue_outer_loop;
7754            }
7755          al->array_reference=SvRV(sv);
7756          break;
7757        }
7758        case RealReference:
7759        {
7760          al->real_reference=SvNV(sv);
7761          break;
7762        }
7763        case FileReference:
7764        {
7765          al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7766          break;
7767        }
7768        case ImageReference:
7769        {
7770          if (!sv_isobject(sv) ||
7771              !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7772                (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7773            {
7774              ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7775                PackageName);
7776              goto PerlException;
7777            }
7778          break;
7779        }
7780        case IntegerReference:
7781        {
7782          al->integer_reference=SvIV(sv);
7783          break;
7784        }
7785        case StringReference:
7786        {
7787          al->string_reference=(char *) SvPV(sv,al->length);
7788          if (sv_isobject(sv))
7789            al->image_reference=SetupList(aTHX_ SvRV(sv),
7790              (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7791          break;
7792        }
7793        default:
7794        {
7795          /*
7796            Is a string; look up name.
7797          */
7798          if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7799            {
7800              al->string_reference=(char *) SvPV(sv,al->length);
7801              al->integer_reference=(-1);
7802              break;
7803            }
7804          al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7805            MagickFalse,SvPV(sv,na));
7806          if (pp->type == MagickChannelOptions)
7807            al->integer_reference=ParseChannelOption(SvPV(sv,na));
7808          if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7809            {
7810              (void) FormatLocaleString(message,MagickPathExtent,
7811                "invalid %.60s value",pp->method);
7812              ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7813              goto continue_outer_loop;
7814            }
7815          break;
7816        }
7817      }
7818      attribute_flag[pp-rp->arguments]++;
7819      continue_outer_loop: ;
7820    }
7821    (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7822    pv=reference_vector;
7823    SetGeometryInfo(&geometry_info);
7824    channel=DefaultChannels;
7825    for (next=image; next; next=next->next)
7826    {
7827      image=next;
7828      SetGeometry(image,&geometry);
7829      if ((region_info.width*region_info.height) != 0)
7830        {
7831          region_image=image;
7832          image=CropImage(image,&region_info,exception);
7833        }
7834      switch (ix)
7835      {
7836        default:
7837        {
7838          (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7839          ThrowPerlException(exception,OptionError,
7840            "UnrecognizedPerlMagickMethod",message);
7841          goto PerlException;
7842        }
7843        case 1:  /* Comment */
7844        {
7845          if (attribute_flag[0] == 0)
7846            argument_list[0].string_reference=(char *) NULL;
7847          (void) SetImageProperty(image,"comment",InterpretImageProperties(
7848            info ? info->image_info : (ImageInfo *) NULL,image,
7849            argument_list[0].string_reference,exception),exception);
7850          break;
7851        }
7852        case 2:  /* Label */
7853        {
7854          if (attribute_flag[0] == 0)
7855            argument_list[0].string_reference=(char *) NULL;
7856          (void) SetImageProperty(image,"label",InterpretImageProperties(
7857            info ? info->image_info : (ImageInfo *) NULL,image,
7858            argument_list[0].string_reference,exception),exception);
7859          break;
7860        }
7861        case 3:  /* AddNoise */
7862        {
7863          double
7864            attenuate;
7865
7866          if (attribute_flag[0] == 0)
7867            argument_list[0].integer_reference=UniformNoise;
7868          attenuate=1.0;
7869          if (attribute_flag[1] != 0)
7870            attenuate=argument_list[1].real_reference;
7871          if (attribute_flag[2] != 0)
7872            channel=(ChannelType) argument_list[2].integer_reference;
7873          channel_mask=SetImageChannelMask(image,channel);
7874          image=AddNoiseImage(image,(NoiseType)
7875            argument_list[0].integer_reference,attenuate,exception);
7876          if (image != (Image *) NULL)
7877            (void) SetImageChannelMask(image,channel_mask);
7878          break;
7879        }
7880        case 4:  /* Colorize */
7881        {
7882          PixelInfo
7883            target;
7884
7885          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7886            0,0,&target,exception);
7887          if (attribute_flag[0] != 0)
7888            (void) QueryColorCompliance(argument_list[0].string_reference,
7889              AllCompliance,&target,exception);
7890          if (attribute_flag[1] == 0)
7891            argument_list[1].string_reference="100%";
7892          image=ColorizeImage(image,argument_list[1].string_reference,&target,
7893            exception);
7894          break;
7895        }
7896        case 5:  /* Border */
7897        {
7898          CompositeOperator
7899            compose;
7900
7901          geometry.width=0;
7902          geometry.height=0;
7903          if (attribute_flag[0] != 0)
7904            flags=ParsePageGeometry(image,argument_list[0].string_reference,
7905              &geometry,exception);
7906          if (attribute_flag[1] != 0)
7907            geometry.width=argument_list[1].integer_reference;
7908          if (attribute_flag[2] != 0)
7909            geometry.height=argument_list[2].integer_reference;
7910          if (attribute_flag[3] != 0)
7911            QueryColorCompliance(argument_list[3].string_reference,
7912              AllCompliance,&image->border_color,exception);
7913          if (attribute_flag[4] != 0)
7914            QueryColorCompliance(argument_list[4].string_reference,
7915              AllCompliance,&image->border_color,exception);
7916          if (attribute_flag[5] != 0)
7917            QueryColorCompliance(argument_list[5].string_reference,
7918              AllCompliance,&image->border_color,exception);
7919          compose=image->compose;
7920          if (attribute_flag[6] != 0)
7921            compose=(CompositeOperator) argument_list[6].integer_reference;
7922          image=BorderImage(image,&geometry,compose,exception);
7923          break;
7924        }
7925        case 6:  /* Blur */
7926        {
7927          if (attribute_flag[0] != 0)
7928            {
7929              flags=ParseGeometry(argument_list[0].string_reference,
7930                &geometry_info);
7931              if ((flags & SigmaValue) == 0)
7932                geometry_info.sigma=1.0;
7933            }
7934          if (attribute_flag[1] != 0)
7935            geometry_info.rho=argument_list[1].real_reference;
7936          if (attribute_flag[2] != 0)
7937            geometry_info.sigma=argument_list[2].real_reference;
7938          if (attribute_flag[3] != 0)
7939            channel=(ChannelType) argument_list[3].integer_reference;
7940          channel_mask=SetImageChannelMask(image,channel);
7941          image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7942            exception);
7943          if (image != (Image *) NULL)
7944            (void) SetImageChannelMask(image,channel_mask);
7945          break;
7946        }
7947        case 7:  /* Chop */
7948        {
7949          if (attribute_flag[5] != 0)
7950            image->gravity=(GravityType) argument_list[5].integer_reference;
7951          if (attribute_flag[0] != 0)
7952            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7953              &geometry,exception);
7954          if (attribute_flag[1] != 0)
7955            geometry.width=argument_list[1].integer_reference;
7956          if (attribute_flag[2] != 0)
7957            geometry.height=argument_list[2].integer_reference;
7958          if (attribute_flag[3] != 0)
7959            geometry.x=argument_list[3].integer_reference;
7960          if (attribute_flag[4] != 0)
7961            geometry.y=argument_list[4].integer_reference;
7962          image=ChopImage(image,&geometry,exception);
7963          break;
7964        }
7965        case 8:  /* Crop */
7966        {
7967          if (attribute_flag[6] != 0)
7968            image->gravity=(GravityType) argument_list[6].integer_reference;
7969          if (attribute_flag[0] != 0)
7970            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7971              &geometry,exception);
7972          if (attribute_flag[1] != 0)
7973            geometry.width=argument_list[1].integer_reference;
7974          if (attribute_flag[2] != 0)
7975            geometry.height=argument_list[2].integer_reference;
7976          if (attribute_flag[3] != 0)
7977            geometry.x=argument_list[3].integer_reference;
7978          if (attribute_flag[4] != 0)
7979            geometry.y=argument_list[4].integer_reference;
7980          if (attribute_flag[5] != 0)
7981            image->fuzz=StringToDoubleInterval(
7982              argument_list[5].string_reference,(double) QuantumRange+1.0);
7983          image=CropImage(image,&geometry,exception);
7984          break;
7985        }
7986        case 9:  /* Despeckle */
7987        {
7988          image=DespeckleImage(image,exception);
7989          break;
7990        }
7991        case 10:  /* Edge */
7992        {
7993          if (attribute_flag[0] != 0)
7994            geometry_info.rho=argument_list[0].real_reference;
7995          image=EdgeImage(image,geometry_info.rho,exception);
7996          break;
7997        }
7998        case 11:  /* Emboss */
7999        {
8000          if (attribute_flag[0] != 0)
8001            {
8002              flags=ParseGeometry(argument_list[0].string_reference,
8003                &geometry_info);
8004              if ((flags & SigmaValue) == 0)
8005                geometry_info.sigma=1.0;
8006            }
8007          if (attribute_flag[1] != 0)
8008            geometry_info.rho=argument_list[1].real_reference;
8009          if (attribute_flag[2] != 0)
8010            geometry_info.sigma=argument_list[2].real_reference;
8011          image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8012            exception);
8013          break;
8014        }
8015        case 12:  /* Enhance */
8016        {
8017          image=EnhanceImage(image,exception);
8018          break;
8019        }
8020        case 13:  /* Flip */
8021        {
8022          image=FlipImage(image,exception);
8023          break;
8024        }
8025        case 14:  /* Flop */
8026        {
8027          image=FlopImage(image,exception);
8028          break;
8029        }
8030        case 15:  /* Frame */
8031        {
8032          CompositeOperator
8033            compose;
8034
8035          FrameInfo
8036            frame_info;
8037
8038          if (attribute_flag[0] != 0)
8039            {
8040              flags=ParsePageGeometry(image,argument_list[0].string_reference,
8041                &geometry,exception);
8042              frame_info.width=geometry.width;
8043              frame_info.height=geometry.height;
8044              frame_info.outer_bevel=geometry.x;
8045              frame_info.inner_bevel=geometry.y;
8046            }
8047          if (attribute_flag[1] != 0)
8048            frame_info.width=argument_list[1].integer_reference;
8049          if (attribute_flag[2] != 0)
8050            frame_info.height=argument_list[2].integer_reference;
8051          if (attribute_flag[3] != 0)
8052            frame_info.inner_bevel=argument_list[3].integer_reference;
8053          if (attribute_flag[4] != 0)
8054            frame_info.outer_bevel=argument_list[4].integer_reference;
8055          if (attribute_flag[5] != 0)
8056            QueryColorCompliance(argument_list[5].string_reference,
8057              AllCompliance,&fill_color,exception);
8058          if (attribute_flag[6] != 0)
8059            QueryColorCompliance(argument_list[6].string_reference,
8060              AllCompliance,&fill_color,exception);
8061          frame_info.x=(ssize_t) frame_info.width;
8062          frame_info.y=(ssize_t) frame_info.height;
8063          frame_info.width=image->columns+2*frame_info.x;
8064          frame_info.height=image->rows+2*frame_info.y;
8065          if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8066            image->alpha_color=fill_color;
8067          compose=image->compose;
8068          if (attribute_flag[7] != 0)
8069            compose=(CompositeOperator) argument_list[7].integer_reference;
8070          image=FrameImage(image,&frame_info,compose,exception);
8071          break;
8072        }
8073        case 16:  /* Implode */
8074        {
8075          PixelInterpolateMethod
8076            method;
8077
8078          if (attribute_flag[0] == 0)
8079            argument_list[0].real_reference=0.5;
8080          method=UndefinedInterpolatePixel;
8081          if (attribute_flag[1] != 0)
8082            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8083          image=ImplodeImage(image,argument_list[0].real_reference,
8084            method,exception);
8085          break;
8086        }
8087        case 17:  /* Magnify */
8088        {
8089          image=MagnifyImage(image,exception);
8090          break;
8091        }
8092        case 18:  /* MedianFilter */
8093        {
8094          if (attribute_flag[0] != 0)
8095            {
8096              flags=ParseGeometry(argument_list[0].string_reference,
8097                &geometry_info);
8098              if ((flags & SigmaValue) == 0)
8099                geometry_info.sigma=geometry_info.rho;
8100            }
8101          if (attribute_flag[1] != 0)
8102            geometry_info.rho=argument_list[1].real_reference;
8103          if (attribute_flag[2] != 0)
8104            geometry_info.sigma=argument_list[2].real_reference;
8105          if (attribute_flag[3] != 0)
8106            channel=(ChannelType) argument_list[3].integer_reference;
8107          channel_mask=SetImageChannelMask(image,channel);
8108          image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8109            (size_t) geometry_info.sigma,exception);
8110          if (image != (Image *) NULL)
8111            (void) SetImageChannelMask(image,channel_mask);
8112          break;
8113        }
8114        case 19:  /* Minify */
8115        {
8116          image=MinifyImage(image,exception);
8117          break;
8118        }
8119        case 20:  /* OilPaint */
8120        {
8121          if (attribute_flag[0] == 0)
8122            argument_list[0].real_reference=0.0;
8123          if (attribute_flag[1] == 0)
8124            argument_list[1].real_reference=1.0;
8125          image=OilPaintImage(image,argument_list[0].real_reference,
8126            argument_list[1].real_reference,exception);
8127          break;
8128        }
8129        case 21:  /* ReduceNoise */
8130        {
8131          if (attribute_flag[0] != 0)
8132            {
8133              flags=ParseGeometry(argument_list[0].string_reference,
8134                &geometry_info);
8135              if ((flags & SigmaValue) == 0)
8136                geometry_info.sigma=1.0;
8137            }
8138          if (attribute_flag[1] != 0)
8139            geometry_info.rho=argument_list[1].real_reference;
8140          if (attribute_flag[2] != 0)
8141            geometry_info.sigma=argument_list[2].real_reference;
8142          if (attribute_flag[3] != 0)
8143            channel=(ChannelType) argument_list[3].integer_reference;
8144          channel_mask=SetImageChannelMask(image,channel);
8145          image=StatisticImage(image,NonpeakStatistic,(size_t)
8146            geometry_info.rho,(size_t) geometry_info.sigma,exception);
8147          if (image != (Image *) NULL)
8148            (void) SetImageChannelMask(image,channel_mask);
8149          break;
8150        }
8151        case 22:  /* Roll */
8152        {
8153          if (attribute_flag[0] != 0)
8154            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8155              &geometry,exception);
8156          if (attribute_flag[1] != 0)
8157            geometry.x=argument_list[1].integer_reference;
8158          if (attribute_flag[2] != 0)
8159            geometry.y=argument_list[2].integer_reference;
8160          image=RollImage(image,geometry.x,geometry.y,exception);
8161          break;
8162        }
8163        case 23:  /* Rotate */
8164        {
8165          if (attribute_flag[0] == 0)
8166            argument_list[0].real_reference=90.0;
8167          if (attribute_flag[1] != 0)
8168            {
8169              QueryColorCompliance(argument_list[1].string_reference,
8170                AllCompliance,&image->background_color,exception);
8171              if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8172                  (image->alpha_trait == UndefinedPixelTrait))
8173                (void) SetImageAlpha(image,OpaqueAlpha,exception);
8174            }
8175          image=RotateImage(image,argument_list[0].real_reference,exception);
8176          break;
8177        }
8178        case 24:  /* Sample */
8179        {
8180          if (attribute_flag[0] != 0)
8181            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8182              &geometry,exception);
8183          if (attribute_flag[1] != 0)
8184            geometry.width=argument_list[1].integer_reference;
8185          if (attribute_flag[2] != 0)
8186            geometry.height=argument_list[2].integer_reference;
8187          image=SampleImage(image,geometry.width,geometry.height,exception);
8188          break;
8189        }
8190        case 25:  /* Scale */
8191        {
8192          if (attribute_flag[0] != 0)
8193            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8194              &geometry,exception);
8195          if (attribute_flag[1] != 0)
8196            geometry.width=argument_list[1].integer_reference;
8197          if (attribute_flag[2] != 0)
8198            geometry.height=argument_list[2].integer_reference;
8199          image=ScaleImage(image,geometry.width,geometry.height,exception);
8200          break;
8201        }
8202        case 26:  /* Shade */
8203        {
8204          if (attribute_flag[0] != 0)
8205            {
8206              flags=ParseGeometry(argument_list[0].string_reference,
8207                &geometry_info);
8208              if ((flags & SigmaValue) == 0)
8209                geometry_info.sigma=0.0;
8210            }
8211          if (attribute_flag[1] != 0)
8212            geometry_info.rho=argument_list[1].real_reference;
8213          if (attribute_flag[2] != 0)
8214            geometry_info.sigma=argument_list[2].real_reference;
8215          image=ShadeImage(image,
8216            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8217            geometry_info.rho,geometry_info.sigma,exception);
8218          break;
8219        }
8220        case 27:  /* Sharpen */
8221        {
8222          if (attribute_flag[0] != 0)
8223            {
8224              flags=ParseGeometry(argument_list[0].string_reference,
8225                &geometry_info);
8226              if ((flags & SigmaValue) == 0)
8227                geometry_info.sigma=1.0;
8228            }
8229          if (attribute_flag[1] != 0)
8230            geometry_info.rho=argument_list[1].real_reference;
8231          if (attribute_flag[2] != 0)
8232            geometry_info.sigma=argument_list[2].real_reference;
8233          if (attribute_flag[3] != 0)
8234            channel=(ChannelType) argument_list[3].integer_reference;
8235          channel_mask=SetImageChannelMask(image,channel);
8236          image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8237            exception);
8238          if (image != (Image *) NULL)
8239            (void) SetImageChannelMask(image,channel_mask);
8240          break;
8241        }
8242        case 28:  /* Shear */
8243        {
8244          if (attribute_flag[0] != 0)
8245            {
8246              flags=ParseGeometry(argument_list[0].string_reference,
8247                &geometry_info);
8248              if ((flags & SigmaValue) == 0)
8249                geometry_info.sigma=geometry_info.rho;
8250            }
8251          if (attribute_flag[1] != 0)
8252            geometry_info.rho=argument_list[1].real_reference;
8253          if (attribute_flag[2] != 0)
8254            geometry_info.sigma=argument_list[2].real_reference;
8255          if (attribute_flag[3] != 0)
8256            QueryColorCompliance(argument_list[3].string_reference,
8257              AllCompliance,&image->background_color,exception);
8258          if (attribute_flag[4] != 0)
8259            QueryColorCompliance(argument_list[4].string_reference,
8260              AllCompliance,&image->background_color,exception);
8261          image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8262            exception);
8263          break;
8264        }
8265        case 29:  /* Spread */
8266        {
8267          PixelInterpolateMethod
8268            method;
8269
8270          if (attribute_flag[0] == 0)
8271            argument_list[0].real_reference=1.0;
8272          method=UndefinedInterpolatePixel;
8273          if (attribute_flag[1] != 0)
8274            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8275          image=SpreadImage(image,method,argument_list[0].real_reference,
8276            exception);
8277          break;
8278        }
8279        case 30:  /* Swirl */
8280        {
8281          PixelInterpolateMethod
8282            method;
8283
8284          if (attribute_flag[0] == 0)
8285            argument_list[0].real_reference=50.0;
8286          method=UndefinedInterpolatePixel;
8287          if (attribute_flag[1] != 0)
8288            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8289          image=SwirlImage(image,argument_list[0].real_reference,
8290            method,exception);
8291          break;
8292        }
8293        case 31:  /* Resize */
8294        case 32:  /* Zoom */
8295        {
8296          if (attribute_flag[0] != 0)
8297            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8298              &geometry,exception);
8299          if (attribute_flag[1] != 0)
8300            geometry.width=argument_list[1].integer_reference;
8301          if (attribute_flag[2] != 0)
8302            geometry.height=argument_list[2].integer_reference;
8303          if (attribute_flag[3] == 0)
8304            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8305          if (attribute_flag[4] != 0)
8306            SetImageArtifact(image,"filter:support",
8307              argument_list[4].string_reference);
8308          image=ResizeImage(image,geometry.width,geometry.height,
8309            (FilterType) argument_list[3].integer_reference,
8310            exception);
8311          break;
8312        }
8313        case 33:  /* Annotate */
8314        {
8315          DrawInfo
8316            *draw_info;
8317
8318          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8319            (DrawInfo *) NULL);
8320          if (attribute_flag[0] != 0)
8321            {
8322              char
8323                *text;
8324
8325              text=InterpretImageProperties(info ? info->image_info :
8326                (ImageInfo *) NULL,image,argument_list[0].string_reference,
8327                exception);
8328              (void) CloneString(&draw_info->text,text);
8329              text=DestroyString(text);
8330            }
8331          if (attribute_flag[1] != 0)
8332            (void) CloneString(&draw_info->font,
8333              argument_list[1].string_reference);
8334          if (attribute_flag[2] != 0)
8335            draw_info->pointsize=argument_list[2].real_reference;
8336          if (attribute_flag[3] != 0)
8337            (void) CloneString(&draw_info->density,
8338              argument_list[3].string_reference);
8339          if (attribute_flag[4] != 0)
8340            (void) QueryColorCompliance(argument_list[4].string_reference,
8341              AllCompliance,&draw_info->undercolor,exception);
8342          if (attribute_flag[5] != 0)
8343            {
8344              (void) QueryColorCompliance(argument_list[5].string_reference,
8345                AllCompliance,&draw_info->stroke,exception);
8346              if (argument_list[5].image_reference != (Image *) NULL)
8347                draw_info->stroke_pattern=CloneImage(
8348                  argument_list[5].image_reference,0,0,MagickTrue,exception);
8349            }
8350          if (attribute_flag[6] != 0)
8351            {
8352              (void) QueryColorCompliance(argument_list[6].string_reference,
8353                AllCompliance,&draw_info->fill,exception);
8354              if (argument_list[6].image_reference != (Image *) NULL)
8355                draw_info->fill_pattern=CloneImage(
8356                  argument_list[6].image_reference,0,0,MagickTrue,exception);
8357            }
8358          if (attribute_flag[7] != 0)
8359            {
8360              (void) CloneString(&draw_info->geometry,
8361                argument_list[7].string_reference);
8362              flags=ParsePageGeometry(image,argument_list[7].string_reference,
8363                &geometry,exception);
8364              if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8365                geometry_info.sigma=geometry_info.xi;
8366            }
8367          if (attribute_flag[8] != 0)
8368            (void) QueryColorCompliance(argument_list[8].string_reference,
8369              AllCompliance,&draw_info->fill,exception);
8370          if (attribute_flag[11] != 0)
8371            draw_info->gravity=(GravityType)
8372              argument_list[11].integer_reference;
8373          if (attribute_flag[25] != 0)
8374            {
8375              AV
8376                *av;
8377
8378              av=(AV *) argument_list[25].array_reference;
8379              if ((av_len(av) != 3) && (av_len(av) != 5))
8380                {
8381                  ThrowPerlException(exception,OptionError,
8382                    "affine matrix must have 4 or 6 elements",PackageName);
8383                  goto PerlException;
8384                }
8385              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8386              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8387              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8388              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8389              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8390                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8391                {
8392                  ThrowPerlException(exception,OptionError,
8393                    "affine matrix is singular",PackageName);
8394                   goto PerlException;
8395                }
8396              if (av_len(av) == 5)
8397                {
8398                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8399                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8400                }
8401            }
8402          for (j=12; j < 17; j++)
8403          {
8404            if (attribute_flag[j] == 0)
8405              continue;
8406            value=argument_list[j].string_reference;
8407            angle=argument_list[j].real_reference;
8408            current=draw_info->affine;
8409            GetAffineMatrix(&affine);
8410            switch (j)
8411            {
8412              case 12:
8413              {
8414                /*
8415                  Translate.
8416                */
8417                flags=ParseGeometry(value,&geometry_info);
8418                affine.tx=geometry_info.xi;
8419                affine.ty=geometry_info.psi;
8420                if ((flags & PsiValue) == 0)
8421                  affine.ty=affine.tx;
8422                break;
8423              }
8424              case 13:
8425              {
8426                /*
8427                  Scale.
8428                */
8429                flags=ParseGeometry(value,&geometry_info);
8430                affine.sx=geometry_info.rho;
8431                affine.sy=geometry_info.sigma;
8432                if ((flags & SigmaValue) == 0)
8433                  affine.sy=affine.sx;
8434                break;
8435              }
8436              case 14:
8437              {
8438                /*
8439                  Rotate.
8440                */
8441                if (angle == 0.0)
8442                  break;
8443                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8444                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8445                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8446                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8447                break;
8448              }
8449              case 15:
8450              {
8451                /*
8452                  SkewX.
8453                */
8454                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8455                break;
8456              }
8457              case 16:
8458              {
8459                /*
8460                  SkewY.
8461                */
8462                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8463                break;
8464              }
8465            }
8466            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8467            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8468            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8469            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8470            draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8471              current.tx;
8472            draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8473              current.ty;
8474          }
8475          if (attribute_flag[9] == 0)
8476            argument_list[9].real_reference=0.0;
8477          if (attribute_flag[10] == 0)
8478            argument_list[10].real_reference=0.0;
8479          if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8480            {
8481              char
8482                geometry[MagickPathExtent];
8483
8484              (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8485                (double) argument_list[9].real_reference+draw_info->affine.tx,
8486                (double) argument_list[10].real_reference+draw_info->affine.ty);
8487              (void) CloneString(&draw_info->geometry,geometry);
8488            }
8489          if (attribute_flag[17] != 0)
8490            draw_info->stroke_width=argument_list[17].real_reference;
8491          if (attribute_flag[18] != 0)
8492            {
8493              draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8494                MagickTrue : MagickFalse;
8495              draw_info->stroke_antialias=draw_info->text_antialias;
8496            }
8497          if (attribute_flag[19] != 0)
8498            (void) CloneString(&draw_info->family,
8499              argument_list[19].string_reference);
8500          if (attribute_flag[20] != 0)
8501            draw_info->style=(StyleType) argument_list[20].integer_reference;
8502          if (attribute_flag[21] != 0)
8503            draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8504          if (attribute_flag[22] != 0)
8505            draw_info->weight=argument_list[22].integer_reference;
8506          if (attribute_flag[23] != 0)
8507            draw_info->align=(AlignType) argument_list[23].integer_reference;
8508          if (attribute_flag[24] != 0)
8509            (void) CloneString(&draw_info->encoding,
8510              argument_list[24].string_reference);
8511          if (attribute_flag[25] != 0)
8512            draw_info->fill_pattern=CloneImage(
8513              argument_list[25].image_reference,0,0,MagickTrue,exception);
8514          if (attribute_flag[26] != 0)
8515            draw_info->fill_pattern=CloneImage(
8516              argument_list[26].image_reference,0,0,MagickTrue,exception);
8517          if (attribute_flag[27] != 0)
8518            draw_info->stroke_pattern=CloneImage(
8519              argument_list[27].image_reference,0,0,MagickTrue,exception);
8520          if (attribute_flag[29] != 0)
8521            draw_info->kerning=argument_list[29].real_reference;
8522          if (attribute_flag[30] != 0)
8523            draw_info->interline_spacing=argument_list[30].real_reference;
8524          if (attribute_flag[31] != 0)
8525            draw_info->interword_spacing=argument_list[31].real_reference;
8526          if (attribute_flag[32] != 0)
8527            draw_info->direction=(DirectionType)
8528              argument_list[32].integer_reference;
8529          (void) AnnotateImage(image,draw_info,exception);
8530          draw_info=DestroyDrawInfo(draw_info);
8531          break;
8532        }
8533        case 34:  /* ColorFloodfill */
8534        {
8535          DrawInfo
8536            *draw_info;
8537
8538          MagickBooleanType
8539            invert;
8540
8541          PixelInfo
8542            target;
8543
8544          draw_info=CloneDrawInfo(info ? info->image_info :
8545            (ImageInfo *) NULL,(DrawInfo *) NULL);
8546          if (attribute_flag[0] != 0)
8547            flags=ParsePageGeometry(image,argument_list[0].string_reference,
8548              &geometry,exception);
8549          if (attribute_flag[1] != 0)
8550            geometry.x=argument_list[1].integer_reference;
8551          if (attribute_flag[2] != 0)
8552            geometry.y=argument_list[2].integer_reference;
8553          if (attribute_flag[3] != 0)
8554            (void) QueryColorCompliance(argument_list[3].string_reference,
8555              AllCompliance,&draw_info->fill,exception);
8556          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8557            geometry.x,geometry.y,&target,exception);
8558          invert=MagickFalse;
8559          if (attribute_flag[4] != 0)
8560            {
8561              QueryColorCompliance(argument_list[4].string_reference,
8562                AllCompliance,&target,exception);
8563              invert=MagickTrue;
8564            }
8565          if (attribute_flag[5] != 0)
8566            image->fuzz=StringToDoubleInterval(
8567              argument_list[5].string_reference,(double) QuantumRange+1.0);
8568          if (attribute_flag[6] != 0)
8569            invert=(MagickBooleanType) argument_list[6].integer_reference;
8570          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8571            geometry.y,invert,exception);
8572          draw_info=DestroyDrawInfo(draw_info);
8573          break;
8574        }
8575        case 35:  /* Composite */
8576        {
8577          char
8578            composite_geometry[MagickPathExtent];
8579
8580          Image
8581            *composite_image,
8582            *rotate_image;
8583
8584          MagickBooleanType
8585            clip_to_self;
8586
8587          compose=OverCompositeOp;
8588          if (attribute_flag[0] != 0)
8589            composite_image=argument_list[0].image_reference;
8590          else
8591            {
8592              ThrowPerlException(exception,OptionError,
8593                "CompositeImageRequired",PackageName);
8594              goto PerlException;
8595            }
8596          /*
8597            Parameter Handling used for BOTH normal and tiled composition.
8598          */
8599          if (attribute_flag[1] != 0) /* compose */
8600            compose=(CompositeOperator) argument_list[1].integer_reference;
8601          if (attribute_flag[6] != 0) /* opacity  */
8602            {
8603              if (compose != DissolveCompositeOp)
8604                (void) SetImageAlpha(composite_image,(Quantum)
8605                  StringToDoubleInterval(argument_list[6].string_reference,
8606                  (double) QuantumRange+1.0),exception);
8607              else
8608                {
8609                  CacheView
8610                    *composite_view;
8611
8612                  double
8613                    opacity;
8614
8615                  MagickBooleanType
8616                    sync;
8617
8618                  register ssize_t
8619                    x;
8620
8621                  register Quantum
8622                    *q;
8623
8624                  ssize_t
8625                    y;
8626
8627                  /*
8628                    Handle dissolve composite operator (patch by
8629                    Kevin A. McGrail).
8630                  */
8631                  (void) CloneString(&image->geometry,
8632                    argument_list[6].string_reference);
8633                  opacity=(Quantum) StringToDoubleInterval(
8634                    argument_list[6].string_reference,(double) QuantumRange+
8635                    1.0);
8636                  if (composite_image->alpha_trait != UndefinedPixelTrait)
8637                    (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8638                  composite_view=AcquireAuthenticCacheView(composite_image,exception);
8639                  for (y=0; y < (ssize_t) composite_image->rows ; y++)
8640                  {
8641                    q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8642                      composite_image->columns,1,exception);
8643                    for (x=0; x < (ssize_t) composite_image->columns; x++)
8644                    {
8645                      if (GetPixelAlpha(image,q) == OpaqueAlpha)
8646                        SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8647                          q);
8648                      q+=GetPixelChannels(composite_image);
8649                    }
8650                    sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8651                    if (sync == MagickFalse)
8652                      break;
8653                  }
8654                  composite_view=DestroyCacheView(composite_view);
8655                }
8656            }
8657          if (attribute_flag[9] != 0)    /* "color=>" */
8658            QueryColorCompliance(argument_list[9].string_reference,
8659              AllCompliance,&composite_image->background_color,exception);
8660          if (attribute_flag[12] != 0) /* "interpolate=>" */
8661            image->interpolate=(PixelInterpolateMethod)
8662              argument_list[12].integer_reference;
8663          if (attribute_flag[13] != 0)   /* "args=>" */
8664            (void) SetImageArtifact(composite_image,"compose:args",
8665              argument_list[13].string_reference);
8666          if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8667            (void) SetImageArtifact(composite_image,"compose:args",
8668              argument_list[14].string_reference);
8669          clip_to_self=MagickTrue;
8670          if (attribute_flag[15] != 0)
8671            clip_to_self=(MagickBooleanType)
8672              argument_list[15].integer_reference;
8673          /*
8674            Tiling Composition (with orthogonal rotate).
8675          */
8676          rotate_image=(Image *) NULL;
8677          if (attribute_flag[8] != 0)   /* "rotate=>" */
8678            {
8679               /*
8680                 Rotate image.
8681               */
8682               rotate_image=RotateImage(composite_image,
8683                 argument_list[8].real_reference,exception);
8684               if (rotate_image == (Image *) NULL)
8685                 break;
8686            }
8687          if ((attribute_flag[7] != 0) &&
8688              (argument_list[7].integer_reference != 0)) /* tile */
8689            {
8690              ssize_t
8691                x,
8692                y;
8693
8694              /*
8695                Tile the composite image.
8696              */
8697             if (attribute_flag[8] != 0)   /* "tile=>" */
8698               (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8699                 "false");
8700             else
8701               (void) SetImageArtifact(composite_image,
8702                 "compose:outside-overlay","false");
8703             for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8704                for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8705                {
8706                  if (attribute_flag[8] != 0) /* rotate */
8707                    (void) CompositeImage(image,rotate_image,compose,
8708                      MagickTrue,x,y,exception);
8709                  else
8710                    (void) CompositeImage(image,composite_image,compose,
8711                      MagickTrue,x,y,exception);
8712                }
8713              if (attribute_flag[8] != 0) /* rotate */
8714                rotate_image=DestroyImage(rotate_image);
8715              break;
8716            }
8717          /*
8718            Parameter Handling used used ONLY for normal composition.
8719          */
8720          if (attribute_flag[5] != 0) /* gravity */
8721            image->gravity=(GravityType) argument_list[5].integer_reference;
8722          if (attribute_flag[2] != 0) /* geometry offset */
8723            {
8724              SetGeometry(image,&geometry);
8725              (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8726                &geometry);
8727              GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8728                &geometry);
8729            }
8730          if (attribute_flag[3] != 0) /* x offset */
8731            geometry.x=argument_list[3].integer_reference;
8732          if (attribute_flag[4] != 0) /* y offset */
8733            geometry.y=argument_list[4].integer_reference;
8734          if (attribute_flag[10] != 0) /* mask */
8735            {
8736              if ((image->compose == DisplaceCompositeOp) ||
8737                  (image->compose == DistortCompositeOp))
8738                {
8739                  /*
8740                    Merge Y displacement into X displacement image.
8741                  */
8742                  composite_image=CloneImage(composite_image,0,0,MagickTrue,
8743                    exception);
8744                  (void) CompositeImage(composite_image,
8745                    argument_list[10].image_reference,CopyGreenCompositeOp,
8746                    MagickTrue,0,0,exception);
8747                }
8748              else
8749                {
8750                  Image
8751                    *mask_image;
8752
8753                  /*
8754                    Set a blending mask for the composition.
8755                  */
8756                  mask_image=CloneImage(argument_list[10].image_reference,0,0,
8757                    MagickTrue,exception);
8758                  (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8759                    exception);
8760                  mask_image=DestroyImage(mask_image);
8761                }
8762            }
8763          if (attribute_flag[11] != 0) /* channel */
8764            channel=(ChannelType) argument_list[11].integer_reference;
8765          /*
8766            Composite two images (normal composition).
8767          */
8768          (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8769            "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8770            (double) composite_image->rows,(double) geometry.x,(double)
8771            geometry.y);
8772          flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8773            exception);
8774          channel_mask=SetImageChannelMask(image,channel);
8775          if (attribute_flag[8] == 0) /* no rotate */
8776            CompositeImage(image,composite_image,compose,clip_to_self,
8777              geometry.x,geometry.y,exception);
8778          else
8779            {
8780              /*
8781                Position adjust rotated image then composite.
8782              */
8783              geometry.x-=(ssize_t) (rotate_image->columns-
8784                composite_image->columns)/2;
8785              geometry.y-=(ssize_t) (rotate_image->rows-
8786                composite_image->rows)/2;
8787              CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8788                geometry.y,exception);
8789              rotate_image=DestroyImage(rotate_image);
8790            }
8791          if (attribute_flag[10] != 0) /* mask */
8792            {
8793              if ((image->compose == DisplaceCompositeOp) ||
8794                  (image->compose == DistortCompositeOp))
8795                composite_image=DestroyImage(composite_image);
8796              else
8797                (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8798                  exception);
8799            }
8800          (void) SetImageChannelMask(image,channel_mask);
8801          break;
8802        }
8803        case 36:  /* Contrast */
8804        {
8805          if (attribute_flag[0] == 0)
8806            argument_list[0].integer_reference=0;
8807          (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8808            MagickTrue : MagickFalse,exception);
8809          break;
8810        }
8811        case 37:  /* CycleColormap */
8812        {
8813          if (attribute_flag[0] == 0)
8814            argument_list[0].integer_reference=6;
8815          (void) CycleColormapImage(image,argument_list[0].integer_reference,
8816            exception);
8817          break;
8818        }
8819        case 38:  /* Draw */
8820        {
8821          DrawInfo
8822            *draw_info;
8823
8824          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8825            (DrawInfo *) NULL);
8826          (void) CloneString(&draw_info->primitive,"point");
8827          if (attribute_flag[0] != 0)
8828            {
8829              if (argument_list[0].integer_reference < 0)
8830                (void) CloneString(&draw_info->primitive,
8831                  argument_list[0].string_reference);
8832              else
8833                (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8834                  MagickPrimitiveOptions,argument_list[0].integer_reference));
8835            }
8836          if (attribute_flag[1] != 0)
8837            {
8838              if (LocaleCompare(draw_info->primitive,"path") == 0)
8839                {
8840                  (void) ConcatenateString(&draw_info->primitive," '");
8841                  ConcatenateString(&draw_info->primitive,
8842                    argument_list[1].string_reference);
8843                  (void) ConcatenateString(&draw_info->primitive,"'");
8844                }
8845              else
8846                {
8847                  (void) ConcatenateString(&draw_info->primitive," ");
8848                  ConcatenateString(&draw_info->primitive,
8849                    argument_list[1].string_reference);
8850                }
8851            }
8852          if (attribute_flag[2] != 0)
8853            {
8854              (void) ConcatenateString(&draw_info->primitive," ");
8855              (void) ConcatenateString(&draw_info->primitive,
8856                CommandOptionToMnemonic(MagickMethodOptions,
8857                argument_list[2].integer_reference));
8858            }
8859          if (attribute_flag[3] != 0)
8860            {
8861              (void) QueryColorCompliance(argument_list[3].string_reference,
8862                AllCompliance,&draw_info->stroke,exception);
8863              if (argument_list[3].image_reference != (Image *) NULL)
8864                draw_info->stroke_pattern=CloneImage(
8865                  argument_list[3].image_reference,0,0,MagickTrue,exception);
8866            }
8867          if (attribute_flag[4] != 0)
8868            {
8869              (void) QueryColorCompliance(argument_list[4].string_reference,
8870                AllCompliance,&draw_info->fill,exception);
8871              if (argument_list[4].image_reference != (Image *) NULL)
8872                draw_info->fill_pattern=CloneImage(
8873                  argument_list[4].image_reference,0,0,MagickTrue,exception);
8874            }
8875          if (attribute_flag[5] != 0)
8876            draw_info->stroke_width=argument_list[5].real_reference;
8877          if (attribute_flag[6] != 0)
8878            (void) CloneString(&draw_info->font,
8879              argument_list[6].string_reference);
8880          if (attribute_flag[7] != 0)
8881            (void) QueryColorCompliance(argument_list[7].string_reference,
8882              AllCompliance,&draw_info->border_color,exception);
8883          if (attribute_flag[8] != 0)
8884            draw_info->affine.tx=argument_list[8].real_reference;
8885          if (attribute_flag[9] != 0)
8886            draw_info->affine.ty=argument_list[9].real_reference;
8887          if (attribute_flag[20] != 0)
8888            {
8889              AV
8890                *av;
8891
8892              av=(AV *) argument_list[20].array_reference;
8893              if ((av_len(av) != 3) && (av_len(av) != 5))
8894                {
8895                  ThrowPerlException(exception,OptionError,
8896                    "affine matrix must have 4 or 6 elements",PackageName);
8897                  goto PerlException;
8898                }
8899              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8900              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8901              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8902              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8903              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8904                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8905                {
8906                  ThrowPerlException(exception,OptionError,
8907                    "affine matrix is singular",PackageName);
8908                   goto PerlException;
8909                }
8910              if (av_len(av) == 5)
8911                {
8912                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8913                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8914                }
8915            }
8916          for (j=10; j < 15; j++)
8917          {
8918            if (attribute_flag[j] == 0)
8919              continue;
8920            value=argument_list[j].string_reference;
8921            angle=argument_list[j].real_reference;
8922            current=draw_info->affine;
8923            GetAffineMatrix(&affine);
8924            switch (j)
8925            {
8926              case 10:
8927              {
8928                /*
8929                  Translate.
8930                */
8931                flags=ParseGeometry(value,&geometry_info);
8932                affine.tx=geometry_info.xi;
8933                affine.ty=geometry_info.psi;
8934                if ((flags & PsiValue) == 0)
8935                  affine.ty=affine.tx;
8936                break;
8937              }
8938              case 11:
8939              {
8940                /*
8941                  Scale.
8942                */
8943                flags=ParseGeometry(value,&geometry_info);
8944                affine.sx=geometry_info.rho;
8945                affine.sy=geometry_info.sigma;
8946                if ((flags & SigmaValue) == 0)
8947                  affine.sy=affine.sx;
8948                break;
8949              }
8950              case 12:
8951              {
8952                /*
8953                  Rotate.
8954                */
8955                if (angle == 0.0)
8956                  break;
8957                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8958                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8959                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8960                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8961                break;
8962              }
8963              case 13:
8964              {
8965                /*
8966                  SkewX.
8967                */
8968                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8969                break;
8970              }
8971              case 14:
8972              {
8973                /*
8974                  SkewY.
8975                */
8976                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8977                break;
8978              }
8979            }
8980            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8981            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8982            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8983            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8984            draw_info->affine.tx=
8985              current.sx*affine.tx+current.ry*affine.ty+current.tx;
8986            draw_info->affine.ty=
8987              current.rx*affine.tx+current.sy*affine.ty+current.ty;
8988          }
8989          if (attribute_flag[15] != 0)
8990            draw_info->fill_pattern=CloneImage(
8991              argument_list[15].image_reference,0,0,MagickTrue,exception);
8992          if (attribute_flag[16] != 0)
8993            draw_info->pointsize=argument_list[16].real_reference;
8994          if (attribute_flag[17] != 0)
8995            {
8996              draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8997                ? MagickTrue : MagickFalse;
8998              draw_info->text_antialias=draw_info->stroke_antialias;
8999            }
9000          if (attribute_flag[18] != 0)
9001            (void) CloneString(&draw_info->density,
9002              argument_list[18].string_reference);
9003          if (attribute_flag[19] != 0)
9004            draw_info->stroke_width=argument_list[19].real_reference;
9005          if (attribute_flag[21] != 0)
9006            draw_info->dash_offset=argument_list[21].real_reference;
9007          if (attribute_flag[22] != 0)
9008            {
9009              AV
9010                *av;
9011
9012              av=(AV *) argument_list[22].array_reference;
9013              draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9014                av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9015              if (draw_info->dash_pattern != (double *) NULL)
9016                {
9017                  for (i=0; i <= av_len(av); i++)
9018                    draw_info->dash_pattern[i]=(double)
9019                      SvNV(*(av_fetch(av,i,0)));
9020                  draw_info->dash_pattern[i]=0.0;
9021                }
9022            }
9023          if (attribute_flag[23] != 0)
9024            image->interpolate=(PixelInterpolateMethod)
9025              argument_list[23].integer_reference;
9026          if ((attribute_flag[24] != 0) &&
9027              (draw_info->fill_pattern != (Image *) NULL))
9028            flags=ParsePageGeometry(draw_info->fill_pattern,
9029              argument_list[24].string_reference,
9030              &draw_info->fill_pattern->tile_offset,exception);
9031          if (attribute_flag[25] != 0)
9032            {
9033              (void) ConcatenateString(&draw_info->primitive," '");
9034              (void) ConcatenateString(&draw_info->primitive,
9035                argument_list[25].string_reference);
9036              (void) ConcatenateString(&draw_info->primitive,"'");
9037            }
9038          if (attribute_flag[26] != 0)
9039            draw_info->fill_pattern=CloneImage(
9040              argument_list[26].image_reference,0,0,MagickTrue,exception);
9041          if (attribute_flag[27] != 0)
9042            draw_info->stroke_pattern=CloneImage(
9043              argument_list[27].image_reference,0,0,MagickTrue,exception);
9044          if (attribute_flag[28] != 0)
9045            (void) CloneString(&draw_info->primitive,
9046              argument_list[28].string_reference);
9047          if (attribute_flag[29] != 0)
9048            draw_info->kerning=argument_list[29].real_reference;
9049          if (attribute_flag[30] != 0)
9050            draw_info->interline_spacing=argument_list[30].real_reference;
9051          if (attribute_flag[31] != 0)
9052            draw_info->interword_spacing=argument_list[31].real_reference;
9053          if (attribute_flag[32] != 0)
9054            draw_info->direction=(DirectionType)
9055              argument_list[32].integer_reference;
9056          DrawImage(image,draw_info,exception);
9057          draw_info=DestroyDrawInfo(draw_info);
9058          break;
9059        }
9060        case 39:  /* Equalize */
9061        {
9062          if (attribute_flag[0] != 0)
9063            channel=(ChannelType) argument_list[0].integer_reference;
9064          channel_mask=SetImageChannelMask(image,channel);
9065          EqualizeImage(image,exception);
9066          (void) SetImageChannelMask(image,channel_mask);
9067          break;
9068        }
9069        case 40:  /* Gamma */
9070        {
9071          if (attribute_flag[1] != 0)
9072            channel=(ChannelType) argument_list[1].integer_reference;
9073          if (attribute_flag[2] == 0)
9074            argument_list[2].real_reference=1.0;
9075          if (attribute_flag[3] == 0)
9076            argument_list[3].real_reference=1.0;
9077          if (attribute_flag[4] == 0)
9078            argument_list[4].real_reference=1.0;
9079          if (attribute_flag[0] == 0)
9080            {
9081              (void) FormatLocaleString(message,MagickPathExtent,
9082                "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9083                (double) argument_list[3].real_reference,
9084                (double) argument_list[4].real_reference);
9085              argument_list[0].string_reference=message;
9086            }
9087          (void) GammaImage(image,StringToDouble(
9088            argument_list[0].string_reference,(char **) NULL),exception);
9089          break;
9090        }
9091        case 41:  /* Map */
9092        {
9093          QuantizeInfo
9094            *quantize_info;
9095
9096          if (attribute_flag[0] == 0)
9097            {
9098              ThrowPerlException(exception,OptionError,"MapImageRequired",
9099                PackageName);
9100              goto PerlException;
9101            }
9102          quantize_info=AcquireQuantizeInfo(info->image_info);
9103          if (attribute_flag[1] != 0)
9104            quantize_info->dither_method=(DitherMethod)
9105              argument_list[1].integer_reference;
9106          (void) RemapImages(quantize_info,image,
9107            argument_list[0].image_reference,exception);
9108          quantize_info=DestroyQuantizeInfo(quantize_info);
9109          break;
9110        }
9111        case 42:  /* MatteFloodfill */
9112        {
9113          DrawInfo
9114            *draw_info;
9115
9116          MagickBooleanType
9117            invert;
9118
9119          PixelInfo
9120            target;
9121
9122          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9123            (DrawInfo *) NULL);
9124          if (attribute_flag[0] != 0)
9125            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9126              &geometry,exception);
9127          if (attribute_flag[1] != 0)
9128            geometry.x=argument_list[1].integer_reference;
9129          if (attribute_flag[2] != 0)
9130            geometry.y=argument_list[2].integer_reference;
9131          if (image->alpha_trait == UndefinedPixelTrait)
9132            (void) SetImageAlpha(image,OpaqueAlpha,exception);
9133          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9134            geometry.x,geometry.y,&target,exception);
9135          if (attribute_flag[4] != 0)
9136            QueryColorCompliance(argument_list[4].string_reference,
9137              AllCompliance,&target,exception);
9138          if (attribute_flag[3] != 0)
9139            target.alpha=StringToDoubleInterval(
9140              argument_list[3].string_reference,(double) (double) QuantumRange+
9141              1.0);
9142          if (attribute_flag[5] != 0)
9143            image->fuzz=StringToDoubleInterval(
9144              argument_list[5].string_reference,(double) QuantumRange+1.0);
9145          invert=MagickFalse;
9146          if (attribute_flag[6] != 0)
9147            invert=(MagickBooleanType) argument_list[6].integer_reference;
9148          channel_mask=SetImageChannelMask(image,AlphaChannel);
9149          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9150            geometry.y,invert,exception);
9151          (void) SetImageChannelMask(image,channel_mask);
9152          draw_info=DestroyDrawInfo(draw_info);
9153          break;
9154        }
9155        case 43:  /* Modulate */
9156        {
9157          char
9158            modulate[MagickPathExtent];
9159
9160          geometry_info.rho=100.0;
9161          geometry_info.sigma=100.0;
9162          geometry_info.xi=100.0;
9163          if (attribute_flag[0] != 0)
9164            (void)ParseGeometry(argument_list[0].string_reference,
9165              &geometry_info);
9166          if (attribute_flag[1] != 0)
9167            geometry_info.xi=argument_list[1].real_reference;
9168          if (attribute_flag[2] != 0)
9169            geometry_info.sigma=argument_list[2].real_reference;
9170          if (attribute_flag[3] != 0)
9171            {
9172              geometry_info.sigma=argument_list[3].real_reference;
9173              SetImageArtifact(image,"modulate:colorspace","HWB");
9174            }
9175          if (attribute_flag[4] != 0)
9176            {
9177              geometry_info.rho=argument_list[4].real_reference;
9178              SetImageArtifact(image,"modulate:colorspace","HSB");
9179            }
9180          if (attribute_flag[5] != 0)
9181            {
9182              geometry_info.sigma=argument_list[5].real_reference;
9183              SetImageArtifact(image,"modulate:colorspace","HSL");
9184            }
9185          if (attribute_flag[6] != 0)
9186            {
9187              geometry_info.rho=argument_list[6].real_reference;
9188              SetImageArtifact(image,"modulate:colorspace","HWB");
9189            }
9190          (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9191            geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9192          (void) ModulateImage(image,modulate,exception);
9193          break;
9194        }
9195        case 44:  /* Negate */
9196        {
9197          if (attribute_flag[0] == 0)
9198            argument_list[0].integer_reference=0;
9199          if (attribute_flag[1] != 0)
9200            channel=(ChannelType) argument_list[1].integer_reference;
9201          channel_mask=SetImageChannelMask(image,channel);
9202          (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9203            MagickTrue : MagickFalse,exception);
9204          (void) SetImageChannelMask(image,channel_mask);
9205          break;
9206        }
9207        case 45:  /* Normalize */
9208        {
9209          if (attribute_flag[0] != 0)
9210            channel=(ChannelType) argument_list[0].integer_reference;
9211          channel_mask=SetImageChannelMask(image,channel);
9212          NormalizeImage(image,exception);
9213          (void) SetImageChannelMask(image,channel_mask);
9214          break;
9215        }
9216        case 46:  /* NumberColors */
9217          break;
9218        case 47:  /* Opaque */
9219        {
9220          MagickBooleanType
9221            invert;
9222
9223          PixelInfo
9224            fill_color,
9225            target;
9226
9227          (void) QueryColorCompliance("none",AllCompliance,&target,
9228             exception);
9229          (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9230            exception);
9231          if (attribute_flag[0] != 0)
9232            (void) QueryColorCompliance(argument_list[0].string_reference,
9233              AllCompliance,&target,exception);
9234          if (attribute_flag[1] != 0)
9235            (void) QueryColorCompliance(argument_list[1].string_reference,
9236              AllCompliance,&fill_color,exception);
9237          if (attribute_flag[2] != 0)
9238            image->fuzz=StringToDoubleInterval(
9239              argument_list[2].string_reference,(double) QuantumRange+1.0);
9240          if (attribute_flag[3] != 0)
9241            channel=(ChannelType) argument_list[3].integer_reference;
9242          invert=MagickFalse;
9243          if (attribute_flag[4] != 0)
9244            invert=(MagickBooleanType) argument_list[4].integer_reference;
9245          channel_mask=SetImageChannelMask(image,channel);
9246          (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9247          (void) SetImageChannelMask(image,channel_mask);
9248          break;
9249        }
9250        case 48:  /* Quantize */
9251        {
9252          QuantizeInfo
9253            *quantize_info;
9254
9255          quantize_info=AcquireQuantizeInfo(info->image_info);
9256          if (attribute_flag[0] != 0)
9257            quantize_info->number_colors=(size_t)
9258              argument_list[0].integer_reference;
9259          if (attribute_flag[1] != 0)
9260            quantize_info->tree_depth=(size_t)
9261              argument_list[1].integer_reference;
9262          if (attribute_flag[2] != 0)
9263            quantize_info->colorspace=(ColorspaceType)
9264              argument_list[2].integer_reference;
9265          if (attribute_flag[3] != 0)
9266            quantize_info->dither_method=(DitherMethod)
9267              argument_list[3].integer_reference;
9268          if (attribute_flag[4] != 0)
9269            quantize_info->measure_error=
9270              argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9271          if (attribute_flag[6] != 0)
9272            (void) QueryColorCompliance(argument_list[6].string_reference,
9273              AllCompliance,&image->transparent_color,exception);
9274          if (attribute_flag[7] != 0)
9275            quantize_info->dither_method=(DitherMethod)
9276              argument_list[7].integer_reference;
9277          if (attribute_flag[5] && argument_list[5].integer_reference)
9278            (void) QuantizeImages(quantize_info,image,exception);
9279          else
9280            if ((image->storage_class == DirectClass) ||
9281               (image->colors > quantize_info->number_colors) ||
9282               (quantize_info->colorspace == GRAYColorspace))
9283             (void) QuantizeImage(quantize_info,image,exception);
9284           else
9285             CompressImageColormap(image,exception);
9286          quantize_info=DestroyQuantizeInfo(quantize_info);
9287          break;
9288        }
9289        case 49:  /* Raise */
9290        {
9291          if (attribute_flag[0] != 0)
9292            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9293              &geometry,exception);
9294          if (attribute_flag[1] != 0)
9295            geometry.width=argument_list[1].integer_reference;
9296          if (attribute_flag[2] != 0)
9297            geometry.height=argument_list[2].integer_reference;
9298          if (attribute_flag[3] == 0)
9299            argument_list[3].integer_reference=1;
9300          (void) RaiseImage(image,&geometry,
9301            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9302            exception);
9303          break;
9304        }
9305        case 50:  /* Segment */
9306        {
9307          ColorspaceType
9308            colorspace;
9309
9310          double
9311            cluster_threshold,
9312            smoothing_threshold;
9313
9314          MagickBooleanType
9315            verbose;
9316
9317          cluster_threshold=1.0;
9318          smoothing_threshold=1.5;
9319          colorspace=sRGBColorspace;
9320          verbose=MagickFalse;
9321          if (attribute_flag[0] != 0)
9322            {
9323              flags=ParseGeometry(argument_list[0].string_reference,
9324                &geometry_info);
9325              cluster_threshold=geometry_info.rho;
9326              if (flags & SigmaValue)
9327                smoothing_threshold=geometry_info.sigma;
9328            }
9329          if (attribute_flag[1] != 0)
9330            cluster_threshold=argument_list[1].real_reference;
9331          if (attribute_flag[2] != 0)
9332            smoothing_threshold=argument_list[2].real_reference;
9333          if (attribute_flag[3] != 0)
9334            colorspace=(ColorspaceType) argument_list[3].integer_reference;
9335          if (attribute_flag[4] != 0)
9336            verbose=argument_list[4].integer_reference != 0 ?
9337              MagickTrue : MagickFalse;
9338          (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9339            smoothing_threshold,exception);
9340          break;
9341        }
9342        case 51:  /* Signature */
9343        {
9344          (void) SignatureImage(image,exception);
9345          break;
9346        }
9347        case 52:  /* Solarize */
9348        {
9349          geometry_info.rho=QuantumRange/2.0;
9350          if (attribute_flag[0] != 0)
9351            flags=ParseGeometry(argument_list[0].string_reference,
9352              &geometry_info);
9353          if (attribute_flag[1] != 0)
9354            geometry_info.rho=StringToDoubleInterval(
9355              argument_list[1].string_reference,(double) QuantumRange+1.0);
9356          (void) SolarizeImage(image,geometry_info.rho,exception);
9357          break;
9358        }
9359        case 53:  /* Sync */
9360        {
9361          (void) SyncImage(image,exception);
9362          break;
9363        }
9364        case 54:  /* Texture */
9365        {
9366          if (attribute_flag[0] == 0)
9367            break;
9368          TextureImage(image,argument_list[0].image_reference,exception);
9369          break;
9370        }
9371        case 55:  /* Evalute */
9372        {
9373          MagickEvaluateOperator
9374            op;
9375
9376          op=SetEvaluateOperator;
9377          if (attribute_flag[0] == MagickFalse)
9378            argument_list[0].real_reference=0.0;
9379          if (attribute_flag[1] != MagickFalse)
9380            op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9381          if (attribute_flag[2] != MagickFalse)
9382            channel=(ChannelType) argument_list[2].integer_reference;
9383          channel_mask=SetImageChannelMask(image,channel);
9384          (void) EvaluateImage(image,op,argument_list[0].real_reference,
9385            exception);
9386          (void) SetImageChannelMask(image,channel_mask);
9387          break;
9388        }
9389        case 56:  /* Transparent */
9390        {
9391          double
9392            opacity;
9393
9394          MagickBooleanType
9395            invert;
9396
9397          PixelInfo
9398            target;
9399
9400          (void) QueryColorCompliance("none",AllCompliance,&target,
9401            exception);
9402          if (attribute_flag[0] != 0)
9403            (void) QueryColorCompliance(argument_list[0].string_reference,
9404              AllCompliance,&target,exception);
9405          opacity=TransparentAlpha;
9406          if (attribute_flag[1] != 0)
9407            opacity=StringToDoubleInterval(argument_list[1].string_reference,
9408              (double) QuantumRange+1.0);
9409          if (attribute_flag[2] != 0)
9410            image->fuzz=StringToDoubleInterval(
9411              argument_list[2].string_reference,(double) QuantumRange+1.0);
9412          if (attribute_flag[3] == 0)
9413            argument_list[3].integer_reference=0;
9414          invert=MagickFalse;
9415          if (attribute_flag[3] != 0)
9416            invert=(MagickBooleanType) argument_list[3].integer_reference;
9417          (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9418            invert,exception);
9419          break;
9420        }
9421        case 57:  /* Threshold */
9422        {
9423          double
9424            threshold;
9425
9426          if (attribute_flag[0] == 0)
9427            argument_list[0].string_reference="50%";
9428          if (attribute_flag[1] != 0)
9429            channel=(ChannelType) argument_list[1].integer_reference;
9430          threshold=StringToDoubleInterval(argument_list[0].string_reference,
9431            (double) QuantumRange+1.0);
9432          channel_mask=SetImageChannelMask(image,channel);
9433          (void) BilevelImage(image,threshold,exception);
9434          (void) SetImageChannelMask(image,channel_mask);
9435          break;
9436        }
9437        case 58:  /* Charcoal */
9438        {
9439          if (attribute_flag[0] != 0)
9440            {
9441              flags=ParseGeometry(argument_list[0].string_reference,
9442                &geometry_info);
9443              if ((flags & SigmaValue) == 0)
9444                geometry_info.sigma=1.0;
9445            }
9446          if (attribute_flag[1] != 0)
9447            geometry_info.rho=argument_list[1].real_reference;
9448          if (attribute_flag[2] != 0)
9449            geometry_info.sigma=argument_list[2].real_reference;
9450          image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9451            exception);
9452          break;
9453        }
9454        case 59:  /* Trim */
9455        {
9456          if (attribute_flag[0] != 0)
9457            image->fuzz=StringToDoubleInterval(
9458              argument_list[0].string_reference,(double) QuantumRange+1.0);
9459          image=TrimImage(image,exception);
9460          break;
9461        }
9462        case 60:  /* Wave */
9463        {
9464          PixelInterpolateMethod
9465            method;
9466
9467          if (attribute_flag[0] != 0)
9468            {
9469              flags=ParseGeometry(argument_list[0].string_reference,
9470                &geometry_info);
9471              if ((flags & SigmaValue) == 0)
9472                geometry_info.sigma=1.0;
9473            }
9474          if (attribute_flag[1] != 0)
9475            geometry_info.rho=argument_list[1].real_reference;
9476          if (attribute_flag[2] != 0)
9477            geometry_info.sigma=argument_list[2].real_reference;
9478          method=UndefinedInterpolatePixel;
9479          if (attribute_flag[3] != 0)
9480            method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9481          image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9482            method,exception);
9483          break;
9484        }
9485        case 61:  /* Separate */
9486        {
9487          if (attribute_flag[0] != 0)
9488            channel=(ChannelType) argument_list[0].integer_reference;
9489          image=SeparateImage(image,channel,exception);
9490          break;
9491        }
9492        case 63:  /* Stereo */
9493        {
9494          if (attribute_flag[0] == 0)
9495            {
9496              ThrowPerlException(exception,OptionError,"StereoImageRequired",
9497                PackageName);
9498              goto PerlException;
9499            }
9500          if (attribute_flag[1] != 0)
9501            geometry.x=argument_list[1].integer_reference;
9502          if (attribute_flag[2] != 0)
9503            geometry.y=argument_list[2].integer_reference;
9504          image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9505            geometry.x,geometry.y,exception);
9506          break;
9507        }
9508        case 64:  /* Stegano */
9509        {
9510          if (attribute_flag[0] == 0)
9511            {
9512              ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9513                PackageName);
9514              goto PerlException;
9515            }
9516          if (attribute_flag[1] == 0)
9517            argument_list[1].integer_reference=0;
9518          image->offset=argument_list[1].integer_reference;
9519          image=SteganoImage(image,argument_list[0].image_reference,exception);
9520          break;
9521        }
9522        case 65:  /* Deconstruct */
9523        {
9524          image=CompareImagesLayers(image,CompareAnyLayer,exception);
9525          break;
9526        }
9527        case 66:  /* GaussianBlur */
9528        {
9529          if (attribute_flag[0] != 0)
9530            {
9531              flags=ParseGeometry(argument_list[0].string_reference,
9532                &geometry_info);
9533              if ((flags & SigmaValue) == 0)
9534                geometry_info.sigma=1.0;
9535            }
9536          if (attribute_flag[1] != 0)
9537            geometry_info.rho=argument_list[1].real_reference;
9538          if (attribute_flag[2] != 0)
9539            geometry_info.sigma=argument_list[2].real_reference;
9540          if (attribute_flag[3] != 0)
9541            channel=(ChannelType) argument_list[3].integer_reference;
9542          channel_mask=SetImageChannelMask(image,channel);
9543          image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9544            exception);
9545          if (image != (Image *) NULL)
9546            (void) SetImageChannelMask(image,channel_mask);
9547          break;
9548        }
9549        case 67:  /* Convolve */
9550        {
9551          KernelInfo
9552            *kernel;
9553
9554          kernel=(KernelInfo *) NULL;
9555          if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9556            break;
9557          if (attribute_flag[0] != 0)
9558            {
9559              AV
9560                *av;
9561
9562              size_t
9563                order;
9564
9565              kernel=AcquireKernelInfo((const char *) NULL,exception);
9566              if (kernel == (KernelInfo *) NULL)
9567                break;
9568              av=(AV *) argument_list[0].array_reference;
9569              order=(size_t) sqrt(av_len(av)+1);
9570              kernel->width=order;
9571              kernel->height=order;
9572              kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9573                order*sizeof(*kernel->values));
9574              if (kernel->values == (MagickRealType *) NULL)
9575                {
9576                  kernel=DestroyKernelInfo(kernel);
9577                  ThrowPerlException(exception,ResourceLimitFatalError,
9578                    "MemoryAllocationFailed",PackageName);
9579                  goto PerlException;
9580                }
9581              for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9582                kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9583              for ( ; j < (ssize_t) (order*order); j++)
9584                kernel->values[j]=0.0;
9585            }
9586          if (attribute_flag[1] != 0)
9587            channel=(ChannelType) argument_list[1].integer_reference;
9588          if (attribute_flag[2] != 0)
9589            SetImageArtifact(image,"filter:blur",
9590              argument_list[2].string_reference);
9591          if (attribute_flag[3] != 0)
9592            {
9593              kernel=AcquireKernelInfo(argument_list[3].string_reference,
9594                exception);
9595              if (kernel == (KernelInfo *) NULL)
9596                break;
9597            }
9598          channel_mask=SetImageChannelMask(image,channel);
9599          image=ConvolveImage(image,kernel,exception);
9600          if (image != (Image *) NULL)
9601            (void) SetImageChannelMask(image,channel_mask);
9602          kernel=DestroyKernelInfo(kernel);
9603          break;
9604        }
9605        case 68:  /* Profile */
9606        {
9607          const char
9608            *name;
9609
9610          Image
9611            *profile_image;
9612
9613          ImageInfo
9614            *profile_info;
9615
9616          StringInfo
9617            *profile;
9618
9619          name="*";
9620          if (attribute_flag[0] != 0)
9621            name=argument_list[0].string_reference;
9622          if (attribute_flag[2] != 0)
9623            image->rendering_intent=(RenderingIntent)
9624              argument_list[2].integer_reference;
9625          if (attribute_flag[3] != 0)
9626            image->black_point_compensation=
9627              argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9628          if (attribute_flag[1] != 0)
9629            {
9630              if (argument_list[1].length == 0)
9631                {
9632                  /*
9633                    Remove a profile from the image.
9634                  */
9635                  (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9636                    exception);
9637                  break;
9638                }
9639              /*
9640                Associate user supplied profile with the image.
9641              */
9642              profile=AcquireStringInfo(argument_list[1].length);
9643              SetStringInfoDatum(profile,(const unsigned char *)
9644                argument_list[1].string_reference);
9645              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9646                (size_t) GetStringInfoLength(profile),exception);
9647              profile=DestroyStringInfo(profile);
9648              break;
9649            }
9650          /*
9651            Associate a profile with the image.
9652          */
9653          profile_info=CloneImageInfo(info ? info->image_info :
9654            (ImageInfo *) NULL);
9655          profile_image=ReadImages(profile_info,name,exception);
9656          if (profile_image == (Image *) NULL)
9657            break;
9658          ResetImageProfileIterator(profile_image);
9659          name=GetNextImageProfile(profile_image);
9660          while (name != (const char *) NULL)
9661          {
9662            const StringInfo
9663              *profile;
9664
9665            profile=GetImageProfile(profile_image,name);
9666            if (profile != (const StringInfo *) NULL)
9667              (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9668                (size_t) GetStringInfoLength(profile),exception);
9669            name=GetNextImageProfile(profile_image);
9670          }
9671          profile_image=DestroyImage(profile_image);
9672          profile_info=DestroyImageInfo(profile_info);
9673          break;
9674        }
9675        case 69:  /* UnsharpMask */
9676        {
9677          if (attribute_flag[0] != 0)
9678            {
9679              flags=ParseGeometry(argument_list[0].string_reference,
9680                &geometry_info);
9681              if ((flags & SigmaValue) == 0)
9682                geometry_info.sigma=1.0;
9683              if ((flags & XiValue) == 0)
9684                geometry_info.xi=1.0;
9685              if ((flags & PsiValue) == 0)
9686                geometry_info.psi=0.5;
9687            }
9688          if (attribute_flag[1] != 0)
9689            geometry_info.rho=argument_list[1].real_reference;
9690          if (attribute_flag[2] != 0)
9691            geometry_info.sigma=argument_list[2].real_reference;
9692          if (attribute_flag[3] != 0)
9693            geometry_info.xi=argument_list[3].real_reference;
9694          if (attribute_flag[4] != 0)
9695            geometry_info.psi=argument_list[4].real_reference;
9696          if (attribute_flag[5] != 0)
9697            channel=(ChannelType) argument_list[5].integer_reference;
9698          channel_mask=SetImageChannelMask(image,channel);
9699          image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9700            geometry_info.xi,geometry_info.psi,exception);
9701          if (image != (Image *) NULL)
9702            (void) SetImageChannelMask(image,channel_mask);
9703          break;
9704        }
9705        case 70:  /* MotionBlur */
9706        {
9707          if (attribute_flag[0] != 0)
9708            {
9709              flags=ParseGeometry(argument_list[0].string_reference,
9710                &geometry_info);
9711              if ((flags & SigmaValue) == 0)
9712                geometry_info.sigma=1.0;
9713              if ((flags & XiValue) == 0)
9714                geometry_info.xi=1.0;
9715            }
9716          if (attribute_flag[1] != 0)
9717            geometry_info.rho=argument_list[1].real_reference;
9718          if (attribute_flag[2] != 0)
9719            geometry_info.sigma=argument_list[2].real_reference;
9720          if (attribute_flag[3] != 0)
9721            geometry_info.xi=argument_list[3].real_reference;
9722          if (attribute_flag[4] != 0)
9723            channel=(ChannelType) argument_list[4].integer_reference;
9724          channel_mask=SetImageChannelMask(image,channel);
9725          image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9726            geometry_info.xi,exception);
9727          if (image != (Image *) NULL)
9728            (void) SetImageChannelMask(image,channel_mask);
9729          break;
9730        }
9731        case 71:  /* OrderedDither */
9732        {
9733          if (attribute_flag[0] == 0)
9734            argument_list[0].string_reference="o8x8";
9735          if (attribute_flag[1] != 0)
9736            channel=(ChannelType) argument_list[1].integer_reference;
9737          channel_mask=SetImageChannelMask(image,channel);
9738          (void) OrderedDitherImage(image,argument_list[0].string_reference,
9739            exception);
9740          (void) SetImageChannelMask(image,channel_mask);
9741          break;
9742        }
9743        case 72:  /* Shave */
9744        {
9745          if (attribute_flag[0] != 0)
9746            flags=ParsePageGeometry(image,argument_list[0].string_reference,
9747              &geometry,exception);
9748          if (attribute_flag[1] != 0)
9749            geometry.width=argument_list[1].integer_reference;
9750          if (attribute_flag[2] != 0)
9751            geometry.height=argument_list[2].integer_reference;
9752          image=ShaveImage(image,&geometry,exception);
9753          break;
9754        }
9755        case 73:  /* Level */
9756        {
9757          double
9758            black_point,
9759            gamma,
9760            white_point;
9761
9762          black_point=0.0;
9763          white_point=(double) image->columns*image->rows;
9764          gamma=1.0;
9765          if (attribute_flag[0] != 0)
9766            {
9767              flags=ParseGeometry(argument_list[0].string_reference,
9768                &geometry_info);
9769              black_point=geometry_info.rho;
9770              if ((flags & SigmaValue) != 0)
9771                white_point=geometry_info.sigma;
9772              if ((flags & XiValue) != 0)
9773                gamma=geometry_info.xi;
9774              if ((flags & PercentValue) != 0)
9775                {
9776                  black_point*=(double) (QuantumRange/100.0);
9777                  white_point*=(double) (QuantumRange/100.0);
9778                }
9779              if ((flags & SigmaValue) == 0)
9780                white_point=(double) QuantumRange-black_point;
9781            }
9782          if (attribute_flag[1] != 0)
9783            black_point=argument_list[1].real_reference;
9784          if (attribute_flag[2] != 0)
9785            white_point=argument_list[2].real_reference;
9786          if (attribute_flag[3] != 0)
9787            gamma=argument_list[3].real_reference;
9788          if (attribute_flag[4] != 0)
9789            channel=(ChannelType) argument_list[4].integer_reference;
9790          if (attribute_flag[5] != 0)
9791            {
9792              argument_list[0].real_reference=argument_list[5].real_reference;
9793              attribute_flag[0]=attribute_flag[5];
9794            }
9795          channel_mask=SetImageChannelMask(image,channel);
9796          (void) LevelImage(image,black_point,white_point,gamma,exception);
9797          (void) SetImageChannelMask(image,channel_mask);
9798          break;
9799        }
9800        case 74:  /* Clip */
9801        {
9802          if (attribute_flag[0] == 0)
9803            argument_list[0].string_reference="#1";
9804          if (attribute_flag[1] == 0)
9805            argument_list[1].integer_reference=MagickTrue;
9806          (void) ClipImagePath(image,argument_list[0].string_reference,
9807            argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9808            exception);
9809          break;
9810        }
9811        case 75:  /* AffineTransform */
9812        {
9813          DrawInfo
9814            *draw_info;
9815
9816          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9817            (DrawInfo *) NULL);
9818          if (attribute_flag[0] != 0)
9819            {
9820              AV
9821                *av;
9822
9823              av=(AV *) argument_list[0].array_reference;
9824              if ((av_len(av) != 3) && (av_len(av) != 5))
9825                {
9826                  ThrowPerlException(exception,OptionError,
9827                    "affine matrix must have 4 or 6 elements",PackageName);
9828                  goto PerlException;
9829                }
9830              draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9831              draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9832              draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9833              draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9834              if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9835                  draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9836                {
9837                  ThrowPerlException(exception,OptionError,
9838                    "affine matrix is singular",PackageName);
9839                   goto PerlException;
9840                }
9841              if (av_len(av) == 5)
9842                {
9843                  draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9844                  draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9845                }
9846            }
9847          for (j=1; j < 6; j++)
9848          {
9849            if (attribute_flag[j] == 0)
9850              continue;
9851            value=argument_list[j].string_reference;
9852            angle=argument_list[j].real_reference;
9853            current=draw_info->affine;
9854            GetAffineMatrix(&affine);
9855            switch (j)
9856            {
9857              case 1:
9858              {
9859                /*
9860                  Translate.
9861                */
9862                flags=ParseGeometry(value,&geometry_info);
9863                affine.tx=geometry_info.xi;
9864                affine.ty=geometry_info.psi;
9865                if ((flags & PsiValue) == 0)
9866                  affine.ty=affine.tx;
9867                break;
9868              }
9869              case 2:
9870              {
9871                /*
9872                  Scale.
9873                */
9874                flags=ParseGeometry(value,&geometry_info);
9875                affine.sx=geometry_info.rho;
9876                affine.sy=geometry_info.sigma;
9877                if ((flags & SigmaValue) == 0)
9878                  affine.sy=affine.sx;
9879                break;
9880              }
9881              case 3:
9882              {
9883                /*
9884                  Rotate.
9885                */
9886                if (angle == 0.0)
9887                  break;
9888                affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9889                affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9890                affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9891                affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9892                break;
9893              }
9894              case 4:
9895              {
9896                /*
9897                  SkewX.
9898                */
9899                affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9900                break;
9901              }
9902              case 5:
9903              {
9904                /*
9905                  SkewY.
9906                */
9907                affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9908                break;
9909              }
9910            }
9911            draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9912            draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9913            draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9914            draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9915            draw_info->affine.tx=
9916              current.sx*affine.tx+current.ry*affine.ty+current.tx;
9917            draw_info->affine.ty=
9918              current.rx*affine.tx+current.sy*affine.ty+current.ty;
9919          }
9920          if (attribute_flag[6] != 0)
9921            image->interpolate=(PixelInterpolateMethod)
9922              argument_list[6].integer_reference;
9923          if (attribute_flag[7] != 0)
9924            QueryColorCompliance(argument_list[7].string_reference,
9925              AllCompliance,&image->background_color,exception);
9926          image=AffineTransformImage(image,&draw_info->affine,exception);
9927          draw_info=DestroyDrawInfo(draw_info);
9928          break;
9929        }
9930        case 76:  /* Difference */
9931        {
9932          if (attribute_flag[0] == 0)
9933            {
9934              ThrowPerlException(exception,OptionError,
9935                "ReferenceImageRequired",PackageName);
9936              goto PerlException;
9937            }
9938          if (attribute_flag[1] != 0)
9939            image->fuzz=StringToDoubleInterval(
9940              argument_list[1].string_reference,(double) QuantumRange+1.0);
9941          (void) SetImageColorMetric(image,argument_list[0].image_reference,
9942            exception);
9943          break;
9944        }
9945        case 77:  /* AdaptiveThreshold */
9946        {
9947          if (attribute_flag[0] != 0)
9948            {
9949              flags=ParseGeometry(argument_list[0].string_reference,
9950                &geometry_info);
9951              if ((flags & PercentValue) != 0)
9952                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9953            }
9954          if (attribute_flag[1] != 0)
9955            geometry_info.rho=argument_list[1].integer_reference;
9956          if (attribute_flag[2] != 0)
9957            geometry_info.sigma=argument_list[2].integer_reference;
9958          if (attribute_flag[3] != 0)
9959            geometry_info.xi=argument_list[3].integer_reference;;
9960          image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9961            (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9962          break;
9963        }
9964        case 78:  /* Resample */
9965        {
9966          size_t
9967            height,
9968            width;
9969
9970          if (attribute_flag[0] != 0)
9971            {
9972              flags=ParseGeometry(argument_list[0].string_reference,
9973                &geometry_info);
9974              if ((flags & SigmaValue) == 0)
9975                geometry_info.sigma=geometry_info.rho;
9976            }
9977          if (attribute_flag[1] != 0)
9978            geometry_info.rho=argument_list[1].real_reference;
9979          if (attribute_flag[2] != 0)
9980            geometry_info.sigma=argument_list[2].real_reference;
9981          if (attribute_flag[3] == 0)
9982            argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9983          if (attribute_flag[4] == 0)
9984            SetImageArtifact(image,"filter:support",
9985              argument_list[4].string_reference);
9986          width=(size_t) (geometry_info.rho*image->columns/
9987            (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9988          height=(size_t) (geometry_info.sigma*image->rows/
9989            (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9990          image=ResizeImage(image,width,height,(FilterType)
9991            argument_list[3].integer_reference,exception);
9992          if (image != (Image *) NULL)
9993            {
9994              image->resolution.x=geometry_info.rho;
9995              image->resolution.y=geometry_info.sigma;
9996            }
9997          break;
9998        }
9999        case 79:  /* Describe */
10000        {
10001          if (attribute_flag[0] == 0)
10002            argument_list[0].file_reference=(FILE *) NULL;
10003          if (attribute_flag[1] != 0)
10004            (void) SetImageArtifact(image,"identify:features",
10005              argument_list[1].string_reference);
10006          (void) IdentifyImage(image,argument_list[0].file_reference,
10007            MagickTrue,exception);
10008          break;
10009        }
10010        case 80:  /* BlackThreshold */
10011        {
10012          if (attribute_flag[0] == 0)
10013            argument_list[0].string_reference="50%";
10014          if (attribute_flag[2] != 0)
10015            channel=(ChannelType) argument_list[2].integer_reference;
10016          channel_mask=SetImageChannelMask(image,channel);
10017          BlackThresholdImage(image,argument_list[0].string_reference,
10018            exception);
10019          (void) SetImageChannelMask(image,channel_mask);
10020          break;
10021        }
10022        case 81:  /* WhiteThreshold */
10023        {
10024          if (attribute_flag[0] == 0)
10025            argument_list[0].string_reference="50%";
10026          if (attribute_flag[2] != 0)
10027            channel=(ChannelType) argument_list[2].integer_reference;
10028          channel_mask=SetImageChannelMask(image,channel);
10029          WhiteThresholdImage(image,argument_list[0].string_reference,
10030            exception);
10031          (void) SetImageChannelMask(image,channel_mask);
10032          break;
10033        }
10034        case 82:  /* RotationalBlur */
10035        {
10036          if (attribute_flag[0] != 0)
10037            {
10038              flags=ParseGeometry(argument_list[0].string_reference,
10039                &geometry_info);
10040            }
10041          if (attribute_flag[1] != 0)
10042            geometry_info.rho=argument_list[1].real_reference;
10043          if (attribute_flag[2] != 0)
10044            channel=(ChannelType) argument_list[2].integer_reference;
10045          channel_mask=SetImageChannelMask(image,channel);
10046          image=RotationalBlurImage(image,geometry_info.rho,exception);
10047          if (image != (Image *) NULL)
10048            (void) SetImageChannelMask(image,channel_mask);
10049          break;
10050        }
10051        case 83:  /* Thumbnail */
10052        {
10053          if (attribute_flag[0] != 0)
10054            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10055              &geometry,exception);
10056          if (attribute_flag[1] != 0)
10057            geometry.width=argument_list[1].integer_reference;
10058          if (attribute_flag[2] != 0)
10059            geometry.height=argument_list[2].integer_reference;
10060          image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10061          break;
10062        }
10063        case 84:  /* Strip */
10064        {
10065          (void) StripImage(image,exception);
10066          break;
10067        }
10068        case 85:  /* Tint */
10069        {
10070          PixelInfo
10071            tint;
10072
10073          GetPixelInfo(image,&tint);
10074          if (attribute_flag[0] != 0)
10075            (void) QueryColorCompliance(argument_list[0].string_reference,
10076              AllCompliance,&tint,exception);
10077          if (attribute_flag[1] == 0)
10078            argument_list[1].string_reference="100";
10079          image=TintImage(image,argument_list[1].string_reference,&tint,
10080            exception);
10081          break;
10082        }
10083        case 86:  /* Channel */
10084        {
10085          if (attribute_flag[0] != 0)
10086            channel=(ChannelType) argument_list[0].integer_reference;
10087          image=SeparateImage(image,channel,exception);
10088          break;
10089        }
10090        case 87:  /* Splice */
10091        {
10092          if (attribute_flag[7] != 0)
10093            image->gravity=(GravityType) argument_list[7].integer_reference;
10094          if (attribute_flag[0] != 0)
10095            flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10096              &geometry,exception);
10097          if (attribute_flag[1] != 0)
10098            geometry.width=argument_list[1].integer_reference;
10099          if (attribute_flag[2] != 0)
10100            geometry.height=argument_list[2].integer_reference;
10101          if (attribute_flag[3] != 0)
10102            geometry.x=argument_list[3].integer_reference;
10103          if (attribute_flag[4] != 0)
10104            geometry.y=argument_list[4].integer_reference;
10105          if (attribute_flag[5] != 0)
10106            image->fuzz=StringToDoubleInterval(
10107              argument_list[5].string_reference,(double) QuantumRange+1.0);
10108          if (attribute_flag[6] != 0)
10109            (void) QueryColorCompliance(argument_list[6].string_reference,
10110              AllCompliance,&image->background_color,exception);
10111          image=SpliceImage(image,&geometry,exception);
10112          break;
10113        }
10114        case 88:  /* Posterize */
10115        {
10116          if (attribute_flag[0] == 0)
10117            argument_list[0].integer_reference=3;
10118          if (attribute_flag[1] == 0)
10119            argument_list[1].integer_reference=0;
10120          (void) PosterizeImage(image,argument_list[0].integer_reference,
10121            argument_list[1].integer_reference ? RiemersmaDitherMethod :
10122            NoDitherMethod,exception);
10123          break;
10124        }
10125        case 89:  /* Shadow */
10126        {
10127          if (attribute_flag[0] != 0)
10128            {
10129              flags=ParseGeometry(argument_list[0].string_reference,
10130                &geometry_info);
10131              if ((flags & SigmaValue) == 0)
10132                geometry_info.sigma=1.0;
10133              if ((flags & XiValue) == 0)
10134                geometry_info.xi=4.0;
10135              if ((flags & PsiValue) == 0)
10136                geometry_info.psi=4.0;
10137            }
10138          if (attribute_flag[1] != 0)
10139            geometry_info.rho=argument_list[1].real_reference;
10140          if (attribute_flag[2] != 0)
10141            geometry_info.sigma=argument_list[2].real_reference;
10142          if (attribute_flag[3] != 0)
10143            geometry_info.xi=argument_list[3].integer_reference;
10144          if (attribute_flag[4] != 0)
10145            geometry_info.psi=argument_list[4].integer_reference;
10146          image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10147            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10148            ceil(geometry_info.psi-0.5),exception);
10149          break;
10150        }
10151        case 90:  /* Identify */
10152        {
10153          if (attribute_flag[0] == 0)
10154            argument_list[0].file_reference=(FILE *) NULL;
10155          if (attribute_flag[1] != 0)
10156            (void) SetImageArtifact(image,"identify:features",
10157              argument_list[1].string_reference);
10158          if ((attribute_flag[2] != 0) &&
10159              (argument_list[2].integer_reference != 0))
10160            (void) SetImageArtifact(image,"identify:unique","true");
10161          (void) IdentifyImage(image,argument_list[0].file_reference,
10162            MagickTrue,exception);
10163          break;
10164        }
10165        case 91:  /* SepiaTone */
10166        {
10167          if (attribute_flag[0] == 0)
10168            argument_list[0].real_reference=80.0*QuantumRange/100.0;
10169          image=SepiaToneImage(image,argument_list[0].real_reference,
10170            exception);
10171          break;
10172        }
10173        case 92:  /* SigmoidalContrast */
10174        {
10175          MagickBooleanType
10176            sharpen;
10177
10178          if (attribute_flag[0] != 0)
10179            {
10180              flags=ParseGeometry(argument_list[0].string_reference,
10181                &geometry_info);
10182              if ((flags & SigmaValue) == 0)
10183                geometry_info.sigma=QuantumRange/2.0;
10184              if ((flags & PercentValue) != 0)
10185                geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10186            }
10187          if (attribute_flag[1] != 0)
10188            geometry_info.rho=argument_list[1].real_reference;
10189          if (attribute_flag[2] != 0)
10190            geometry_info.sigma=argument_list[2].real_reference;
10191          if (attribute_flag[3] != 0)
10192            channel=(ChannelType) argument_list[3].integer_reference;
10193          sharpen=MagickTrue;
10194          if (attribute_flag[4] != 0)
10195            sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10196              MagickFalse;
10197          channel_mask=SetImageChannelMask(image,channel);
10198          (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10199            geometry_info.sigma,exception);
10200          (void) SetImageChannelMask(image,channel_mask);
10201          break;
10202        }
10203        case 93:  /* Extent */
10204        {
10205          if (attribute_flag[7] != 0)
10206            image->gravity=(GravityType) argument_list[7].integer_reference;
10207          if (attribute_flag[0] != 0)
10208            {
10209              int
10210                flags;
10211
10212              flags=ParseGravityGeometry(image,
10213                argument_list[0].string_reference,&geometry,exception);
10214              (void) flags;
10215              if (geometry.width == 0)
10216                geometry.width=image->columns;
10217              if (geometry.height == 0)
10218                geometry.height=image->rows;
10219            }
10220          if (attribute_flag[1] != 0)
10221            geometry.width=argument_list[1].integer_reference;
10222          if (attribute_flag[2] != 0)
10223            geometry.height=argument_list[2].integer_reference;
10224          if (attribute_flag[3] != 0)
10225            geometry.x=argument_list[3].integer_reference;
10226          if (attribute_flag[4] != 0)
10227            geometry.y=argument_list[4].integer_reference;
10228          if (attribute_flag[5] != 0)
10229            image->fuzz=StringToDoubleInterval(
10230              argument_list[5].string_reference,(double) QuantumRange+1.0);
10231          if (attribute_flag[6] != 0)
10232            (void) QueryColorCompliance(argument_list[6].string_reference,
10233              AllCompliance,&image->background_color,exception);
10234          image=ExtentImage(image,&geometry,exception);
10235          break;
10236        }
10237        case 94:  /* Vignette */
10238        {
10239          if (attribute_flag[0] != 0)
10240            {
10241              flags=ParseGeometry(argument_list[0].string_reference,
10242                &geometry_info);
10243              if ((flags & SigmaValue) == 0)
10244                geometry_info.sigma=1.0;
10245              if ((flags & XiValue) == 0)
10246                geometry_info.xi=0.1*image->columns;
10247              if ((flags & PsiValue) == 0)
10248                geometry_info.psi=0.1*image->rows;
10249            }
10250          if (attribute_flag[1] != 0)
10251            geometry_info.rho=argument_list[1].real_reference;
10252          if (attribute_flag[2] != 0)
10253            geometry_info.sigma=argument_list[2].real_reference;
10254          if (attribute_flag[3] != 0)
10255            geometry_info.xi=argument_list[3].integer_reference;
10256          if (attribute_flag[4] != 0)
10257            geometry_info.psi=argument_list[4].integer_reference;
10258          if (attribute_flag[5] != 0)
10259            (void) QueryColorCompliance(argument_list[5].string_reference,
10260              AllCompliance,&image->background_color,exception);
10261          image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10262            (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10263            ceil(geometry_info.psi-0.5),exception);
10264          break;
10265        }
10266        case 95:  /* ContrastStretch */
10267        {
10268          double
10269            black_point,
10270            white_point;
10271
10272          black_point=0.0;
10273          white_point=(double) image->columns*image->rows;
10274          if (attribute_flag[0] != 0)
10275            {
10276              flags=ParseGeometry(argument_list[0].string_reference,
10277                &geometry_info);
10278              black_point=geometry_info.rho;
10279              white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10280                black_point;
10281              if ((flags & PercentValue) != 0)
10282                {
10283                  black_point*=(double) image->columns*image->rows/100.0;
10284                  white_point*=(double) image->columns*image->rows/100.0;
10285                }
10286              white_point=(double) image->columns*image->rows-
10287                white_point;
10288            }
10289          if (attribute_flag[1] != 0)
10290            black_point=argument_list[1].real_reference;
10291          if (attribute_flag[2] != 0)
10292            white_point=argument_list[2].real_reference;
10293          if (attribute_flag[4] != 0)
10294            channel=(ChannelType) argument_list[4].integer_reference;
10295          channel_mask=SetImageChannelMask(image,channel);
10296          (void) ContrastStretchImage(image,black_point,white_point,exception);
10297          (void) SetImageChannelMask(image,channel_mask);
10298          break;
10299        }
10300        case 96:  /* Sans0 */
10301        {
10302          break;
10303        }
10304        case 97:  /* Sans1 */
10305        {
10306          break;
10307        }
10308        case 98:  /* AdaptiveSharpen */
10309        {
10310          if (attribute_flag[0] != 0)
10311            {
10312              flags=ParseGeometry(argument_list[0].string_reference,
10313                &geometry_info);
10314              if ((flags & SigmaValue) == 0)
10315                geometry_info.sigma=1.0;
10316              if ((flags & XiValue) == 0)
10317                geometry_info.xi=0.0;
10318            }
10319          if (attribute_flag[1] != 0)
10320            geometry_info.rho=argument_list[1].real_reference;
10321          if (attribute_flag[2] != 0)
10322            geometry_info.sigma=argument_list[2].real_reference;
10323          if (attribute_flag[3] != 0)
10324            geometry_info.xi=argument_list[3].real_reference;
10325          if (attribute_flag[4] != 0)
10326            channel=(ChannelType) argument_list[4].integer_reference;
10327          channel_mask=SetImageChannelMask(image,channel);
10328          image=AdaptiveSharpenImage(image,geometry_info.rho,
10329            geometry_info.sigma,exception);
10330          if (image != (Image *) NULL)
10331            (void) SetImageChannelMask(image,channel_mask);
10332          break;
10333        }
10334        case 99:  /* Transpose */
10335        {
10336          image=TransposeImage(image,exception);
10337          break;
10338        }
10339        case 100:  /* Tranverse */
10340        {
10341          image=TransverseImage(image,exception);
10342          break;
10343        }
10344        case 101:  /* AutoOrient */
10345        {
10346          image=AutoOrientImage(image,image->orientation,exception);
10347          break;
10348        }
10349        case 102:  /* AdaptiveBlur */
10350        {
10351          if (attribute_flag[0] != 0)
10352            {
10353              flags=ParseGeometry(argument_list[0].string_reference,
10354                &geometry_info);
10355              if ((flags & SigmaValue) == 0)
10356                geometry_info.sigma=1.0;
10357              if ((flags & XiValue) == 0)
10358                geometry_info.xi=0.0;
10359            }
10360          if (attribute_flag[1] != 0)
10361            geometry_info.rho=argument_list[1].real_reference;
10362          if (attribute_flag[2] != 0)
10363            geometry_info.sigma=argument_list[2].real_reference;
10364          if (attribute_flag[3] != 0)
10365            channel=(ChannelType) argument_list[3].integer_reference;
10366          channel_mask=SetImageChannelMask(image,channel);
10367          image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10368            exception);
10369          if (image != (Image *) NULL)
10370            (void) SetImageChannelMask(image,channel_mask);
10371          break;
10372        }
10373        case 103:  /* Sketch */
10374        {
10375          if (attribute_flag[0] != 0)
10376            {
10377              flags=ParseGeometry(argument_list[0].string_reference,
10378                &geometry_info);
10379              if ((flags & SigmaValue) == 0)
10380                geometry_info.sigma=1.0;
10381              if ((flags & XiValue) == 0)
10382                geometry_info.xi=1.0;
10383            }
10384          if (attribute_flag[1] != 0)
10385            geometry_info.rho=argument_list[1].real_reference;
10386          if (attribute_flag[2] != 0)
10387            geometry_info.sigma=argument_list[2].real_reference;
10388          if (attribute_flag[3] != 0)
10389            geometry_info.xi=argument_list[3].real_reference;
10390          image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10391            geometry_info.xi,exception);
10392          break;
10393        }
10394        case 104:  /* UniqueColors */
10395        {
10396          image=UniqueImageColors(image,exception);
10397          break;
10398        }
10399        case 105:  /* AdaptiveResize */
10400        {
10401          if (attribute_flag[0] != 0)
10402            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10403              &geometry,exception);
10404          if (attribute_flag[1] != 0)
10405            geometry.width=argument_list[1].integer_reference;
10406          if (attribute_flag[2] != 0)
10407            geometry.height=argument_list[2].integer_reference;
10408          if (attribute_flag[3] != 0)
10409            image->filter=(FilterType) argument_list[4].integer_reference;
10410          if (attribute_flag[4] != 0)
10411            SetImageArtifact(image,"filter:support",
10412              argument_list[4].string_reference);
10413          image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10414            exception);
10415          break;
10416        }
10417        case 106:  /* ClipMask */
10418        {
10419          Image
10420            *mask_image;
10421
10422          if (attribute_flag[0] == 0)
10423            {
10424              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10425                PackageName);
10426              goto PerlException;
10427            }
10428          mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10429            exception);
10430          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10431          mask_image=DestroyImage(mask_image);
10432          break;
10433        }
10434        case 107:  /* LinearStretch */
10435        {
10436           double
10437             black_point,
10438             white_point;
10439
10440           black_point=0.0;
10441           white_point=(double) image->columns*image->rows;
10442           if (attribute_flag[0] != 0)
10443             {
10444               flags=ParseGeometry(argument_list[0].string_reference,
10445                 &geometry_info);
10446               if ((flags & SigmaValue) != 0)
10447                  white_point=geometry_info.sigma;
10448               if ((flags & PercentValue) != 0)
10449                 {
10450                   black_point*=(double) image->columns*image->rows/100.0;
10451                   white_point*=(double) image->columns*image->rows/100.0;
10452                 }
10453               if ((flags & SigmaValue) == 0)
10454                 white_point=(double) image->columns*image->rows-black_point;
10455             }
10456          if (attribute_flag[1] != 0)
10457            black_point=argument_list[1].real_reference;
10458          if (attribute_flag[2] != 0)
10459            white_point=argument_list[2].real_reference;
10460          (void) LinearStretchImage(image,black_point,white_point,exception);
10461          break;
10462        }
10463        case 108:  /* ColorMatrix */
10464        {
10465          AV
10466            *av;
10467
10468          double
10469            *color_matrix;
10470
10471          KernelInfo
10472            *kernel_info;
10473
10474          size_t
10475            order;
10476
10477          if (attribute_flag[0] == 0)
10478            break;
10479          av=(AV *) argument_list[0].array_reference;
10480          order=(size_t) sqrt(av_len(av)+1);
10481          color_matrix=(double *) AcquireQuantumMemory(order,order*
10482            sizeof(*color_matrix));
10483          if (color_matrix == (double *) NULL)
10484            {
10485              ThrowPerlException(exception,ResourceLimitFatalError,
10486                "MemoryAllocationFailed",PackageName);
10487              goto PerlException;
10488           }
10489          for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10490            color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10491          for ( ; j < (ssize_t) (order*order); j++)
10492            color_matrix[j]=0.0;
10493          kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10494          if (kernel_info == (KernelInfo *) NULL)
10495            break;
10496          kernel_info->width=order;
10497          kernel_info->height=order;
10498          kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10499            order*sizeof(*kernel_info->values));
10500          if (kernel_info->values != (MagickRealType *) NULL)
10501            {
10502              for (i=0; i < (ssize_t) (order*order); i++)
10503                kernel_info->values[i]=(MagickRealType) color_matrix[i];
10504              image=ColorMatrixImage(image,kernel_info,exception);
10505            }
10506          kernel_info=DestroyKernelInfo(kernel_info);
10507          color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10508          break;
10509        }
10510        case 109:  /* Mask */
10511        {
10512          Image
10513            *mask_image;
10514
10515          if (attribute_flag[0] == 0)
10516            {
10517              ThrowPerlException(exception,OptionError,"MaskImageRequired",
10518                PackageName);
10519              goto PerlException;
10520            }
10521          mask_image=CloneImage(argument_list[0].image_reference,0,0,
10522            MagickTrue,exception);
10523          (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10524          mask_image=DestroyImage(mask_image);
10525          break;
10526        }
10527        case 110:  /* Polaroid */
10528        {
10529          char
10530            *caption;
10531
10532          DrawInfo
10533            *draw_info;
10534
10535          double
10536            angle;
10537
10538          PixelInterpolateMethod
10539            method;
10540
10541          draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10542            (DrawInfo *) NULL);
10543          caption=(char *) NULL;
10544          if (attribute_flag[0] != 0)
10545            caption=InterpretImageProperties(info ? info->image_info :
10546              (ImageInfo *) NULL,image,argument_list[0].string_reference,
10547              exception);
10548          angle=0.0;
10549          if (attribute_flag[1] != 0)
10550            angle=argument_list[1].real_reference;
10551          if (attribute_flag[2] != 0)
10552            (void) CloneString(&draw_info->font,
10553              argument_list[2].string_reference);
10554          if (attribute_flag[3] != 0)
10555            (void) QueryColorCompliance(argument_list[3].string_reference,
10556              AllCompliance,&draw_info->stroke,exception);
10557          if (attribute_flag[4] != 0)
10558            (void) QueryColorCompliance(argument_list[4].string_reference,
10559              AllCompliance,&draw_info->fill,exception);
10560          if (attribute_flag[5] != 0)
10561            draw_info->stroke_width=argument_list[5].real_reference;
10562          if (attribute_flag[6] != 0)
10563            draw_info->pointsize=argument_list[6].real_reference;
10564          if (attribute_flag[7] != 0)
10565            draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10566          if (attribute_flag[8] != 0)
10567            (void) QueryColorCompliance(argument_list[8].string_reference,
10568              AllCompliance,&image->background_color,exception);
10569          method=UndefinedInterpolatePixel;
10570          if (attribute_flag[9] != 0)
10571            method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10572          image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10573          draw_info=DestroyDrawInfo(draw_info);
10574          if (caption != (char *) NULL)
10575            caption=DestroyString(caption);
10576          break;
10577        }
10578        case 111:  /* FloodfillPaint */
10579        {
10580          DrawInfo
10581            *draw_info;
10582
10583          MagickBooleanType
10584            invert;
10585
10586          PixelInfo
10587            target;
10588
10589          draw_info=CloneDrawInfo(info ? info->image_info :
10590            (ImageInfo *) NULL,(DrawInfo *) NULL);
10591          if (attribute_flag[0] != 0)
10592            flags=ParsePageGeometry(image,argument_list[0].string_reference,
10593              &geometry,exception);
10594          if (attribute_flag[1] != 0)
10595            geometry.x=argument_list[1].integer_reference;
10596          if (attribute_flag[2] != 0)
10597            geometry.y=argument_list[2].integer_reference;
10598          if (attribute_flag[3] != 0)
10599            (void) QueryColorCompliance(argument_list[3].string_reference,
10600              AllCompliance,&draw_info->fill,exception);
10601          (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10602            geometry.x,geometry.y,&target,exception);
10603          if (attribute_flag[4] != 0)
10604            QueryColorCompliance(argument_list[4].string_reference,
10605              AllCompliance,&target,exception);
10606          if (attribute_flag[5] != 0)
10607            image->fuzz=StringToDoubleInterval(
10608              argument_list[5].string_reference,(double) QuantumRange+1.0);
10609          if (attribute_flag[6] != 0)
10610            channel=(ChannelType) argument_list[6].integer_reference;
10611          invert=MagickFalse;
10612          if (attribute_flag[7] != 0)
10613            invert=(MagickBooleanType) argument_list[7].integer_reference;
10614          channel_mask=SetImageChannelMask(image,channel);
10615          (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10616            geometry.y,invert,exception);
10617          (void) SetImageChannelMask(image,channel_mask);
10618          draw_info=DestroyDrawInfo(draw_info);
10619          break;
10620        }
10621        case 112:  /* Distort */
10622        {
10623          AV
10624            *av;
10625
10626          double
10627            *coordinates;
10628
10629          DistortMethod
10630            method;
10631
10632          size_t
10633            number_coordinates;
10634
10635          VirtualPixelMethod
10636            virtual_pixel;
10637
10638          if (attribute_flag[0] == 0)
10639            break;
10640          method=UndefinedDistortion;
10641          if (attribute_flag[1] != 0)
10642            method=(DistortMethod) argument_list[1].integer_reference;
10643          av=(AV *) argument_list[0].array_reference;
10644          number_coordinates=(size_t) av_len(av)+1;
10645          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10646            sizeof(*coordinates));
10647          if (coordinates == (double *) NULL)
10648            {
10649              ThrowPerlException(exception,ResourceLimitFatalError,
10650                "MemoryAllocationFailed",PackageName);
10651              goto PerlException;
10652            }
10653          for (j=0; j < (ssize_t) number_coordinates; j++)
10654            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10655          virtual_pixel=UndefinedVirtualPixelMethod;
10656          if (attribute_flag[2] != 0)
10657            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10658              argument_list[2].integer_reference,exception);
10659          image=DistortImage(image,method,number_coordinates,coordinates,
10660            argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10661            exception);
10662          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10663            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10664              exception);
10665          coordinates=(double *) RelinquishMagickMemory(coordinates);
10666          break;
10667        }
10668        case 113:  /* Clut */
10669        {
10670          PixelInterpolateMethod
10671            method;
10672
10673          if (attribute_flag[0] == 0)
10674            {
10675              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10676                PackageName);
10677              goto PerlException;
10678            }
10679          method=UndefinedInterpolatePixel;
10680          if (attribute_flag[1] != 0)
10681            method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10682          if (attribute_flag[2] != 0)
10683            channel=(ChannelType) argument_list[2].integer_reference;
10684          channel_mask=SetImageChannelMask(image,channel);
10685          (void) ClutImage(image,argument_list[0].image_reference,method,
10686            exception);
10687          (void) SetImageChannelMask(image,channel_mask);
10688          break;
10689        }
10690        case 114:  /* LiquidRescale */
10691        {
10692          if (attribute_flag[0] != 0)
10693            flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10694              &geometry,exception);
10695          if (attribute_flag[1] != 0)
10696            geometry.width=argument_list[1].integer_reference;
10697          if (attribute_flag[2] != 0)
10698            geometry.height=argument_list[2].integer_reference;
10699          if (attribute_flag[3] == 0)
10700            argument_list[3].real_reference=1.0;
10701          if (attribute_flag[4] == 0)
10702            argument_list[4].real_reference=0.0;
10703          image=LiquidRescaleImage(image,geometry.width,geometry.height,
10704            argument_list[3].real_reference,argument_list[4].real_reference,
10705            exception);
10706          break;
10707        }
10708        case 115:  /* EncipherImage */
10709        {
10710          (void) EncipherImage(image,argument_list[0].string_reference,
10711            exception);
10712          break;
10713        }
10714        case 116:  /* DecipherImage */
10715        {
10716          (void) DecipherImage(image,argument_list[0].string_reference,
10717            exception);
10718          break;
10719        }
10720        case 117:  /* Deskew */
10721        {
10722          geometry_info.rho=QuantumRange/2.0;
10723          if (attribute_flag[0] != 0)
10724            flags=ParseGeometry(argument_list[0].string_reference,
10725              &geometry_info);
10726          if (attribute_flag[1] != 0)
10727            geometry_info.rho=StringToDoubleInterval(
10728              argument_list[1].string_reference,(double) QuantumRange+1.0);
10729          image=DeskewImage(image,geometry_info.rho,exception);
10730          break;
10731        }
10732        case 118:  /* Remap */
10733        {
10734          QuantizeInfo
10735            *quantize_info;
10736
10737          if (attribute_flag[0] == 0)
10738            {
10739              ThrowPerlException(exception,OptionError,"RemapImageRequired",
10740                PackageName);
10741              goto PerlException;
10742            }
10743          quantize_info=AcquireQuantizeInfo(info->image_info);
10744          if (attribute_flag[1] != 0)
10745            quantize_info->dither_method=(DitherMethod)
10746              argument_list[1].integer_reference;
10747          (void) RemapImages(quantize_info,image,
10748            argument_list[0].image_reference,exception);
10749          quantize_info=DestroyQuantizeInfo(quantize_info);
10750          break;
10751        }
10752        case 119:  /* SparseColor */
10753        {
10754          AV
10755            *av;
10756
10757          double
10758            *coordinates;
10759
10760          SparseColorMethod
10761            method;
10762
10763          size_t
10764            number_coordinates;
10765
10766          VirtualPixelMethod
10767            virtual_pixel;
10768
10769          if (attribute_flag[0] == 0)
10770            break;
10771          method=UndefinedColorInterpolate;
10772          if (attribute_flag[1] != 0)
10773            method=(SparseColorMethod) argument_list[1].integer_reference;
10774          av=(AV *) argument_list[0].array_reference;
10775          number_coordinates=(size_t) av_len(av)+1;
10776          coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10777            sizeof(*coordinates));
10778          if (coordinates == (double *) NULL)
10779            {
10780              ThrowPerlException(exception,ResourceLimitFatalError,
10781                "MemoryAllocationFailed",PackageName);
10782              goto PerlException;
10783            }
10784          for (j=0; j < (ssize_t) number_coordinates; j++)
10785            coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10786          virtual_pixel=UndefinedVirtualPixelMethod;
10787          if (attribute_flag[2] != 0)
10788            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10789              argument_list[2].integer_reference,exception);
10790          if (attribute_flag[3] != 0)
10791            channel=(ChannelType) argument_list[3].integer_reference;
10792          channel_mask=SetImageChannelMask(image,channel);
10793          image=SparseColorImage(image,method,number_coordinates,coordinates,
10794            exception);
10795          if (image != (Image *) NULL)
10796            (void) SetImageChannelMask(image,channel_mask);
10797          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10798            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10799              exception);
10800          coordinates=(double *) RelinquishMagickMemory(coordinates);
10801          break;
10802        }
10803        case 120:  /* Function */
10804        {
10805          AV
10806            *av;
10807
10808          double
10809            *parameters;
10810
10811          MagickFunction
10812            function;
10813
10814          size_t
10815            number_parameters;
10816
10817          VirtualPixelMethod
10818            virtual_pixel;
10819
10820          if (attribute_flag[0] == 0)
10821            break;
10822          function=UndefinedFunction;
10823          if (attribute_flag[1] != 0)
10824            function=(MagickFunction) argument_list[1].integer_reference;
10825          av=(AV *) argument_list[0].array_reference;
10826          number_parameters=(size_t) av_len(av)+1;
10827          parameters=(double *) AcquireQuantumMemory(number_parameters,
10828            sizeof(*parameters));
10829          if (parameters == (double *) NULL)
10830            {
10831              ThrowPerlException(exception,ResourceLimitFatalError,
10832                "MemoryAllocationFailed",PackageName);
10833              goto PerlException;
10834            }
10835          for (j=0; j < (ssize_t) number_parameters; j++)
10836            parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10837          virtual_pixel=UndefinedVirtualPixelMethod;
10838          if (attribute_flag[2] != 0)
10839            virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10840              argument_list[2].integer_reference,exception);
10841          (void) FunctionImage(image,function,number_parameters,parameters,
10842            exception);
10843          if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10844            virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10845              exception);
10846          parameters=(double *) RelinquishMagickMemory(parameters);
10847          break;
10848        }
10849        case 121:  /* SelectiveBlur */
10850        {
10851          if (attribute_flag[0] != 0)
10852            {
10853              flags=ParseGeometry(argument_list[0].string_reference,
10854                &geometry_info);
10855              if ((flags & SigmaValue) == 0)
10856                geometry_info.sigma=1.0;
10857              if ((flags & PercentValue) != 0)
10858                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10859            }
10860          if (attribute_flag[1] != 0)
10861            geometry_info.rho=argument_list[1].real_reference;
10862          if (attribute_flag[2] != 0)
10863            geometry_info.sigma=argument_list[2].real_reference;
10864          if (attribute_flag[3] != 0)
10865            geometry_info.xi=argument_list[3].integer_reference;;
10866          if (attribute_flag[5] != 0)
10867            channel=(ChannelType) argument_list[5].integer_reference;
10868          channel_mask=SetImageChannelMask(image,channel);
10869          image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10870            geometry_info.xi,exception);
10871          if (image != (Image *) NULL)
10872            (void) SetImageChannelMask(image,channel_mask);
10873          break;
10874        }
10875        case 122:  /* HaldClut */
10876        {
10877          if (attribute_flag[0] == 0)
10878            {
10879              ThrowPerlException(exception,OptionError,"ClutImageRequired",
10880                PackageName);
10881              goto PerlException;
10882            }
10883          if (attribute_flag[1] != 0)
10884            channel=(ChannelType) argument_list[1].integer_reference;
10885          channel_mask=SetImageChannelMask(image,channel);
10886          (void) HaldClutImage(image,argument_list[0].image_reference,
10887            exception);
10888          (void) SetImageChannelMask(image,channel_mask);
10889          break;
10890        }
10891        case 123:  /* BlueShift */
10892        {
10893          if (attribute_flag[0] != 0)
10894            (void) ParseGeometry(argument_list[0].string_reference,
10895              &geometry_info);
10896          image=BlueShiftImage(image,geometry_info.rho,exception);
10897          break;
10898        }
10899        case 124:  /* ForwardFourierTransformImage */
10900        {
10901          image=ForwardFourierTransformImage(image,
10902            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10903            exception);
10904          break;
10905        }
10906        case 125:  /* InverseFourierTransformImage */
10907        {
10908          image=InverseFourierTransformImage(image,image->next,
10909            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10910            exception);
10911          break;
10912        }
10913        case 126:  /* ColorDecisionList */
10914        {
10915          if (attribute_flag[0] == 0)
10916            argument_list[0].string_reference=(char *) NULL;
10917          (void) ColorDecisionListImage(image,
10918            argument_list[0].string_reference,exception);
10919          break;
10920        }
10921        case 127:  /* AutoGamma */
10922        {
10923          if (attribute_flag[0] != 0)
10924            channel=(ChannelType) argument_list[0].integer_reference;
10925          channel_mask=SetImageChannelMask(image,channel);
10926          (void) AutoGammaImage(image,exception);
10927          (void) SetImageChannelMask(image,channel_mask);
10928          break;
10929        }
10930        case 128:  /* AutoLevel */
10931        {
10932          if (attribute_flag[0] != 0)
10933            channel=(ChannelType) argument_list[0].integer_reference;
10934          channel_mask=SetImageChannelMask(image,channel);
10935          (void) AutoLevelImage(image,exception);
10936          (void) SetImageChannelMask(image,channel_mask);
10937          break;
10938        }
10939        case 129:  /* LevelColors */
10940        {
10941          PixelInfo
10942            black_point,
10943            white_point;
10944
10945          (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10946            exception);
10947          (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10948            exception);
10949          if (attribute_flag[1] != 0)
10950             (void) QueryColorCompliance(
10951               argument_list[1].string_reference,AllCompliance,&black_point,
10952               exception);
10953          if (attribute_flag[2] != 0)
10954             (void) QueryColorCompliance(
10955               argument_list[2].string_reference,AllCompliance,&white_point,
10956               exception);
10957          if (attribute_flag[3] != 0)
10958            channel=(ChannelType) argument_list[3].integer_reference;
10959          channel_mask=SetImageChannelMask(image,channel);
10960          (void) LevelImageColors(image,&black_point,&white_point,
10961            argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10962            exception);
10963          (void) SetImageChannelMask(image,channel_mask);
10964          break;
10965        }
10966        case 130:  /* Clamp */
10967        {
10968          if (attribute_flag[0] != 0)
10969            channel=(ChannelType) argument_list[0].integer_reference;
10970          channel_mask=SetImageChannelMask(image,channel);
10971          (void) ClampImage(image,exception);
10972          (void) SetImageChannelMask(image,channel_mask);
10973          break;
10974        }
10975        case 131:  /* BrightnessContrast */
10976        {
10977          double
10978            brightness,
10979            contrast;
10980
10981          brightness=0.0;
10982          contrast=0.0;
10983          if (attribute_flag[0] != 0)
10984            {
10985              flags=ParseGeometry(argument_list[0].string_reference,
10986                &geometry_info);
10987              brightness=geometry_info.rho;
10988              if ((flags & SigmaValue) == 0)
10989                contrast=geometry_info.sigma;
10990            }
10991          if (attribute_flag[1] != 0)
10992            brightness=argument_list[1].real_reference;
10993          if (attribute_flag[2] != 0)
10994            contrast=argument_list[2].real_reference;
10995          if (attribute_flag[4] != 0)
10996            channel=(ChannelType) argument_list[4].integer_reference;
10997          channel_mask=SetImageChannelMask(image,channel);
10998          (void) BrightnessContrastImage(image,brightness,contrast,exception);
10999          (void) SetImageChannelMask(image,channel_mask);
11000          break;
11001        }
11002        case 132:  /* Morphology */
11003        {
11004          KernelInfo
11005            *kernel;
11006
11007          MorphologyMethod
11008            method;
11009
11010          ssize_t
11011            iterations;
11012
11013          if (attribute_flag[0] == 0)
11014            break;
11015          kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11016          if (kernel == (KernelInfo *) NULL)
11017            break;
11018          if (attribute_flag[1] != 0)
11019            channel=(ChannelType) argument_list[1].integer_reference;
11020          method=UndefinedMorphology;
11021          if (attribute_flag[2] != 0)
11022            method=argument_list[2].integer_reference;
11023          iterations=1;
11024          if (attribute_flag[3] != 0)
11025            iterations=argument_list[3].integer_reference;
11026          channel_mask=SetImageChannelMask(image,channel);
11027          image=MorphologyImage(image,method,iterations,kernel,exception);
11028          if (image != (Image *) NULL)
11029            (void) SetImageChannelMask(image,channel_mask);
11030          kernel=DestroyKernelInfo(kernel);
11031          break;
11032        }
11033        case 133:  /* Mode */
11034        {
11035          if (attribute_flag[0] != 0)
11036            {
11037              flags=ParseGeometry(argument_list[0].string_reference,
11038                &geometry_info);
11039              if ((flags & SigmaValue) == 0)
11040                geometry_info.sigma=1.0;
11041            }
11042          if (attribute_flag[1] != 0)
11043            geometry_info.rho=argument_list[1].real_reference;
11044          if (attribute_flag[2] != 0)
11045            geometry_info.sigma=argument_list[2].real_reference;
11046          if (attribute_flag[3] != 0)
11047            channel=(ChannelType) argument_list[3].integer_reference;
11048          channel_mask=SetImageChannelMask(image,channel);
11049          image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11050            (size_t) geometry_info.sigma,exception);
11051          if (image != (Image *) NULL)
11052            (void) SetImageChannelMask(image,channel_mask);
11053          break;
11054        }
11055        case 134:  /* Statistic */
11056        {
11057          StatisticType
11058            statistic;
11059
11060          statistic=UndefinedStatistic;
11061          if (attribute_flag[0] != 0)
11062            {
11063              flags=ParseGeometry(argument_list[0].string_reference,
11064                &geometry_info);
11065              if ((flags & SigmaValue) == 0)
11066                geometry_info.sigma=1.0;
11067            }
11068          if (attribute_flag[1] != 0)
11069            geometry_info.rho=argument_list[1].real_reference;
11070          if (attribute_flag[2] != 0)
11071            geometry_info.sigma=argument_list[2].real_reference;
11072          if (attribute_flag[3] != 0)
11073            channel=(ChannelType) argument_list[3].integer_reference;
11074          if (attribute_flag[4] != 0)
11075            statistic=(StatisticType) argument_list[4].integer_reference;
11076          channel_mask=SetImageChannelMask(image,channel);
11077          image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11078            (size_t) geometry_info.sigma,exception);
11079          if (image != (Image *) NULL)
11080            (void) SetImageChannelMask(image,channel_mask);
11081          break;
11082        }
11083        case 135:  /* Perceptible */
11084        {
11085          double
11086            epsilon;
11087
11088          epsilon=MagickEpsilon;
11089          if (attribute_flag[0] != 0)
11090            epsilon=argument_list[0].real_reference;
11091          if (attribute_flag[1] != 0)
11092            channel=(ChannelType) argument_list[1].integer_reference;
11093          channel_mask=SetImageChannelMask(image,channel);
11094          (void) PerceptibleImage(image,epsilon,exception);
11095          (void) SetImageChannelMask(image,channel_mask);
11096          break;
11097        }
11098        case 136:  /* Poly */
11099        {
11100          AV
11101            *av;
11102
11103          double
11104            *terms;
11105
11106          size_t
11107            number_terms;
11108
11109          if (attribute_flag[0] == 0)
11110            break;
11111          if (attribute_flag[1] != 0)
11112            channel=(ChannelType) argument_list[1].integer_reference;
11113          av=(AV *) argument_list[0].array_reference;
11114          number_terms=(size_t) av_len(av);
11115          terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11116          if (terms == (double *) NULL)
11117            {
11118              ThrowPerlException(exception,ResourceLimitFatalError,
11119                "MemoryAllocationFailed",PackageName);
11120              goto PerlException;
11121            }
11122          for (j=0; j < av_len(av); j++)
11123            terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11124          image=PolynomialImage(image,number_terms >> 1,terms,exception);
11125          terms=(double *) RelinquishMagickMemory(terms);
11126          break;
11127        }
11128        case 137:  /* Grayscale */
11129        {
11130          PixelIntensityMethod
11131            method;
11132
11133          method=UndefinedPixelIntensityMethod;
11134          if (attribute_flag[0] != 0)
11135            method=(PixelIntensityMethod) argument_list[0].integer_reference;
11136          (void) GrayscaleImage(image,method,exception);
11137          break;
11138        }
11139        case 138:  /* Canny */
11140        {
11141          if (attribute_flag[0] != 0)
11142            {
11143              flags=ParseGeometry(argument_list[0].string_reference,
11144                &geometry_info);
11145              if ((flags & SigmaValue) == 0)
11146                geometry_info.sigma=1.0;
11147              if ((flags & XiValue) == 0)
11148                geometry_info.xi=0.10;
11149              if ((flags & PsiValue) == 0)
11150                geometry_info.psi=0.30;
11151              if ((flags & PercentValue) != 0)
11152                {
11153                  geometry_info.xi/=100.0;
11154                  geometry_info.psi/=100.0;
11155                }
11156            }
11157          if (attribute_flag[1] != 0)
11158            geometry_info.rho=argument_list[1].real_reference;
11159          if (attribute_flag[2] != 0)
11160            geometry_info.sigma=argument_list[2].real_reference;
11161          if (attribute_flag[3] != 0)
11162            geometry_info.xi=argument_list[3].real_reference;
11163          if (attribute_flag[4] != 0)
11164            geometry_info.psi=argument_list[4].real_reference;
11165          if (attribute_flag[5] != 0)
11166            channel=(ChannelType) argument_list[5].integer_reference;
11167          channel_mask=SetImageChannelMask(image,channel);
11168          image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11169            geometry_info.xi,geometry_info.psi,exception);
11170          if (image != (Image *) NULL)
11171            (void) SetImageChannelMask(image,channel_mask);
11172          break;
11173        }
11174        case 139:  /* HoughLine */
11175        {
11176          if (attribute_flag[0] != 0)
11177            {
11178              flags=ParseGeometry(argument_list[0].string_reference,
11179                &geometry_info);
11180              if ((flags & SigmaValue) == 0)
11181                geometry_info.sigma=geometry_info.rho;
11182              if ((flags & XiValue) == 0)
11183                geometry_info.xi=40;
11184            }
11185          if (attribute_flag[1] != 0)
11186            geometry_info.rho=(double) argument_list[1].integer_reference;
11187          if (attribute_flag[2] != 0)
11188            geometry_info.sigma=(double) argument_list[2].integer_reference;
11189          if (attribute_flag[3] != 0)
11190            geometry_info.xi=(double) argument_list[3].integer_reference;
11191          image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11192            geometry_info.sigma,(size_t) geometry_info.xi,exception);
11193          break;
11194        }
11195        case 140:  /* MeanShift */
11196        {
11197          if (attribute_flag[0] != 0)
11198            {
11199              flags=ParseGeometry(argument_list[0].string_reference,
11200                &geometry_info);
11201              if ((flags & SigmaValue) == 0)
11202                geometry_info.sigma=geometry_info.rho;
11203              if ((flags & XiValue) == 0)
11204                geometry_info.xi=0.10*QuantumRange;
11205              if ((flags & PercentValue) != 0)
11206                geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11207            }
11208          if (attribute_flag[1] != 0)
11209            geometry_info.rho=(double) argument_list[1].integer_reference;
11210          if (attribute_flag[2] != 0)
11211            geometry_info.sigma=(double) argument_list[2].integer_reference;
11212          if (attribute_flag[3] != 0)
11213            geometry_info.xi=(double) argument_list[3].integer_reference;
11214          image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11215            geometry_info.sigma,geometry_info.xi,exception);
11216          break;
11217        }
11218        case 141:  /* Kuwahara */
11219        {
11220          if (attribute_flag[0] != 0)
11221            {
11222              flags=ParseGeometry(argument_list[0].string_reference,
11223                &geometry_info);
11224              if ((flags & SigmaValue) == 0)
11225                geometry_info.sigma=geometry_info.rho-0.5;
11226            }
11227          if (attribute_flag[1] != 0)
11228            geometry_info.rho=argument_list[1].real_reference;
11229          if (attribute_flag[2] != 0)
11230            geometry_info.sigma=argument_list[2].real_reference;
11231          if (attribute_flag[3] != 0)
11232            channel=(ChannelType) argument_list[3].integer_reference;
11233          channel_mask=SetImageChannelMask(image,channel);
11234          image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11235            exception);
11236          if (image != (Image *) NULL)
11237            (void) SetImageChannelMask(image,channel_mask);
11238          break;
11239        }
11240        case 142:  /* ConnectedComponent */
11241        {
11242          size_t
11243            connectivity;
11244
11245          connectivity=4;
11246          if (attribute_flag[0] != 0)
11247            connectivity=argument_list[0].integer_reference;
11248          image=ConnectedComponentsImage(image,connectivity,
11249            (CCObjectInfo **) NULL,exception);
11250          break;
11251        }
11252        case 143:  /* Copy */
11253        {
11254          Image
11255            *source_image;
11256
11257          OffsetInfo
11258            offset;
11259
11260          RectangleInfo
11261            offset_geometry;
11262
11263          source_image=image;
11264          if (attribute_flag[0] != 0)
11265            source_image=argument_list[0].image_reference;
11266          SetGeometry(source_image,&geometry);
11267          if (attribute_flag[1] != 0)
11268            flags=ParseGravityGeometry(source_image,
11269              argument_list[1].string_reference,&geometry,exception);
11270          if (attribute_flag[2] != 0)
11271            geometry.width=argument_list[2].integer_reference;
11272          if (attribute_flag[3] != 0)
11273            geometry.height=argument_list[3].integer_reference;
11274          if (attribute_flag[4] != 0)
11275            geometry.x=argument_list[4].integer_reference;
11276          if (attribute_flag[5] != 0)
11277            geometry.y=argument_list[5].integer_reference;
11278          if (attribute_flag[6] != 0)
11279            image->gravity=(GravityType) argument_list[6].integer_reference;
11280          SetGeometry(image,&offset_geometry);
11281          if (attribute_flag[7] != 0)
11282            flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11283              &offset_geometry,exception);
11284          offset.x=offset_geometry.x;
11285          offset.y=offset_geometry.y;
11286          if (attribute_flag[8] != 0)
11287            offset.x=argument_list[8].integer_reference;
11288          if (attribute_flag[9] != 0)
11289            offset.y=argument_list[9].integer_reference;
11290          (void) CopyImagePixels(image,source_image,&geometry,&offset,
11291            exception);
11292          break;
11293        }
11294        case 144:  /* Color */
11295        {
11296          PixelInfo
11297            color;
11298
11299          (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11300          if (attribute_flag[0] != 0)
11301            (void) QueryColorCompliance(argument_list[0].string_reference,
11302              AllCompliance,&color,exception);
11303          (void) SetImageColor(image,&color,exception);
11304          break;
11305        }
11306        case 145:  /* WaveletDenoise */
11307        {
11308          if (attribute_flag[0] != 0)
11309            {
11310              flags=ParseGeometry(argument_list[0].string_reference,
11311                &geometry_info);
11312              if ((flags & PercentValue) != 0)
11313                {
11314                  geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11315                  geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11316                }
11317              if ((flags & SigmaValue) == 0)
11318                geometry_info.sigma=0.0;
11319            }
11320          if (attribute_flag[1] != 0)
11321            geometry_info.rho=argument_list[1].real_reference;
11322          if (attribute_flag[2] != 0)
11323            geometry_info.sigma=argument_list[2].real_reference;
11324          if (attribute_flag[3] != 0)
11325            channel=(ChannelType) argument_list[3].integer_reference;
11326          channel_mask=SetImageChannelMask(image,channel);
11327          image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11328            exception);
11329          if (image != (Image *) NULL)
11330            (void) SetImageChannelMask(image,channel_mask);
11331          break;
11332        }
11333      }
11334      if (next != (Image *) NULL)
11335        (void) CatchImageException(next);
11336      if (region_image != (Image *) NULL)
11337        {
11338          /*
11339            Composite region.
11340          */
11341          status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11342            region_info.x,region_info.y,exception);
11343          (void) status;
11344          (void) CatchImageException(region_image);
11345          image=DestroyImage(image);
11346          image=region_image;
11347        }
11348      if (image != (Image *) NULL)
11349        {
11350          number_images++;
11351          if (next && (next != image))
11352            {
11353              image->next=next->next;
11354              if (image->next != (Image *) NULL)
11355                image->next->previous=image;
11356              DeleteImageFromRegistry(*pv,next);
11357            }
11358          sv_setiv(*pv,PTR2IV(image));
11359          next=image;
11360        }
11361      if (*pv)
11362        pv++;
11363    }
11364
11365  PerlException:
11366    if (reference_vector)
11367      reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11368    InheritPerlException(exception,perl_exception);
11369    exception=DestroyExceptionInfo(exception);
11370    sv_setiv(perl_exception,(IV) number_images);
11371    SvPOK_on(perl_exception);
11372    ST(0)=sv_2mortal(perl_exception);
11373    XSRETURN(1);
11374  }
11375
11376#
11377###############################################################################
11378#                                                                             #
11379#                                                                             #
11380#                                                                             #
11381#   M o n t a g e                                                             #
11382#                                                                             #
11383#                                                                             #
11384#                                                                             #
11385###############################################################################
11386#
11387#
11388void
11389Montage(ref,...)
11390  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11391  ALIAS:
11392    MontageImage  = 1
11393    montage       = 2
11394    montageimage  = 3
11395  PPCODE:
11396  {
11397    AV
11398      *av;
11399
11400    char
11401      *attribute;
11402
11403    ExceptionInfo
11404      *exception;
11405
11406    HV
11407      *hv;
11408
11409    Image
11410      *image,
11411      *next;
11412
11413    PixelInfo
11414      transparent_color;
11415
11416    MontageInfo
11417      *montage_info;
11418
11419    register ssize_t
11420      i;
11421
11422    ssize_t
11423      sp;
11424
11425    struct PackageInfo
11426      *info;
11427
11428    SV
11429      *av_reference,
11430      *perl_exception,
11431      *reference,
11432      *rv,
11433      *sv;
11434
11435    PERL_UNUSED_VAR(ref);
11436    PERL_UNUSED_VAR(ix);
11437    exception=AcquireExceptionInfo();
11438    perl_exception=newSVpv("",0);
11439    sv=NULL;
11440    attribute=NULL;
11441    if (sv_isobject(ST(0)) == 0)
11442      {
11443        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11444          PackageName);
11445        goto PerlException;
11446      }
11447    reference=SvRV(ST(0));
11448    hv=SvSTASH(reference);
11449    av=newAV();
11450    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11451    SvREFCNT_dec(av);
11452    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11453    if (image == (Image *) NULL)
11454      {
11455        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11456          PackageName);
11457        goto PerlException;
11458      }
11459    /*
11460      Get options.
11461    */
11462    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11463    montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11464    (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11465      exception);
11466    for (i=2; i < items; i+=2)
11467    {
11468      attribute=(char *) SvPV(ST(i-1),na);
11469      switch (*attribute)
11470      {
11471        case 'B':
11472        case 'b':
11473        {
11474          if (LocaleCompare(attribute,"background") == 0)
11475            {
11476              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11477                &montage_info->background_color,exception);
11478              for (next=image; next; next=next->next)
11479                next->background_color=montage_info->background_color;
11480              break;
11481            }
11482          if (LocaleCompare(attribute,"border") == 0)
11483            {
11484              montage_info->border_width=SvIV(ST(i));
11485              break;
11486            }
11487          if (LocaleCompare(attribute,"bordercolor") == 0)
11488            {
11489              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11490                &montage_info->border_color,exception);
11491              for (next=image; next; next=next->next)
11492                next->border_color=montage_info->border_color;
11493              break;
11494            }
11495          if (LocaleCompare(attribute,"borderwidth") == 0)
11496            {
11497              montage_info->border_width=SvIV(ST(i));
11498              break;
11499            }
11500          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11501            attribute);
11502          break;
11503        }
11504        case 'C':
11505        case 'c':
11506        {
11507          if (LocaleCompare(attribute,"compose") == 0)
11508            {
11509              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11510                MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11511              if (sp < 0)
11512                {
11513                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11514                    SvPV(ST(i),na));
11515                  break;
11516                }
11517              for (next=image; next; next=next->next)
11518                next->compose=(CompositeOperator) sp;
11519              break;
11520            }
11521          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11522            attribute);
11523          break;
11524        }
11525        case 'F':
11526        case 'f':
11527        {
11528          if (LocaleCompare(attribute,"fill") == 0)
11529            {
11530              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11531                &montage_info->fill,exception);
11532              break;
11533            }
11534          if (LocaleCompare(attribute,"font") == 0)
11535            {
11536              (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11537              break;
11538            }
11539          if (LocaleCompare(attribute,"frame") == 0)
11540            {
11541              char
11542                *p;
11543
11544              p=SvPV(ST(i),na);
11545              if (IsGeometry(p) == MagickFalse)
11546                {
11547                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11548                    p);
11549                  break;
11550                }
11551              (void) CloneString(&montage_info->frame,p);
11552              if (*p == '\0')
11553                montage_info->frame=(char *) NULL;
11554              break;
11555            }
11556          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11557            attribute);
11558          break;
11559        }
11560        case 'G':
11561        case 'g':
11562        {
11563          if (LocaleCompare(attribute,"geometry") == 0)
11564            {
11565              char
11566                *p;
11567
11568              p=SvPV(ST(i),na);
11569              if (IsGeometry(p) == MagickFalse)
11570                {
11571                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11572                    p);
11573                  break;
11574                }
11575             (void) CloneString(&montage_info->geometry,p);
11576             if (*p == '\0')
11577               montage_info->geometry=(char *) NULL;
11578             break;
11579           }
11580         if (LocaleCompare(attribute,"gravity") == 0)
11581           {
11582             ssize_t
11583               in;
11584
11585             in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11586               MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11587             if (in < 0)
11588               {
11589                 ThrowPerlException(exception,OptionError,"UnrecognizedType",
11590                   SvPV(ST(i),na));
11591                 return;
11592               }
11593             montage_info->gravity=(GravityType) in;
11594             for (next=image; next; next=next->next)
11595               next->gravity=(GravityType) in;
11596             break;
11597           }
11598          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11599            attribute);
11600          break;
11601        }
11602        case 'L':
11603        case 'l':
11604        {
11605          if (LocaleCompare(attribute,"label") == 0)
11606            {
11607              for (next=image; next; next=next->next)
11608                (void) SetImageProperty(next,"label",InterpretImageProperties(
11609                  info ? info->image_info : (ImageInfo *) NULL,next,
11610                  SvPV(ST(i),na),exception),exception);
11611              break;
11612            }
11613          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11614            attribute);
11615          break;
11616        }
11617        case 'M':
11618        case 'm':
11619        {
11620          if (LocaleCompare(attribute,"mattecolor") == 0)
11621            {
11622              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11623                &montage_info->alpha_color,exception);
11624              for (next=image; next; next=next->next)
11625                next->alpha_color=montage_info->alpha_color;
11626              break;
11627            }
11628          if (LocaleCompare(attribute,"mode") == 0)
11629            {
11630              ssize_t
11631                in;
11632
11633              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11634                MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11635              switch (in)
11636              {
11637                default:
11638                {
11639                  ThrowPerlException(exception,OptionError,
11640                    "UnrecognizedModeType",SvPV(ST(i),na));
11641                  break;
11642                }
11643                case FrameMode:
11644                {
11645                  (void) CloneString(&montage_info->frame,"15x15+3+3");
11646                  montage_info->shadow=MagickTrue;
11647                  break;
11648                }
11649                case UnframeMode:
11650                {
11651                  montage_info->frame=(char *) NULL;
11652                  montage_info->shadow=MagickFalse;
11653                  montage_info->border_width=0;
11654                  break;
11655                }
11656                case ConcatenateMode:
11657                {
11658                  montage_info->frame=(char *) NULL;
11659                  montage_info->shadow=MagickFalse;
11660                  (void) CloneString(&montage_info->geometry,"+0+0");
11661                  montage_info->border_width=0;
11662                }
11663              }
11664              break;
11665            }
11666          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11667            attribute);
11668          break;
11669        }
11670        case 'P':
11671        case 'p':
11672        {
11673          if (LocaleCompare(attribute,"pointsize") == 0)
11674            {
11675              montage_info->pointsize=SvIV(ST(i));
11676              break;
11677            }
11678          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11679            attribute);
11680          break;
11681        }
11682        case 'S':
11683        case 's':
11684        {
11685          if (LocaleCompare(attribute,"shadow") == 0)
11686            {
11687              sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11688                MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11689              if (sp < 0)
11690                {
11691                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11692                    SvPV(ST(i),na));
11693                  break;
11694                }
11695             montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11696             break;
11697            }
11698          if (LocaleCompare(attribute,"stroke") == 0)
11699            {
11700              (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11701                &montage_info->stroke,exception);
11702              break;
11703            }
11704          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11705            attribute);
11706          break;
11707        }
11708        case 'T':
11709        case 't':
11710        {
11711          if (LocaleCompare(attribute,"texture") == 0)
11712            {
11713              (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11714              break;
11715            }
11716          if (LocaleCompare(attribute,"tile") == 0)
11717            {
11718              char *p=SvPV(ST(i),na);
11719              if (IsGeometry(p) == MagickFalse)
11720                {
11721                  ThrowPerlException(exception,OptionError,"MissingGeometry",
11722                    p);
11723                  break;
11724                }
11725              (void) CloneString(&montage_info->tile,p);
11726              if (*p == '\0')
11727                montage_info->tile=(char *) NULL;
11728              break;
11729            }
11730          if (LocaleCompare(attribute,"title") == 0)
11731            {
11732              (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11733              break;
11734            }
11735          if (LocaleCompare(attribute,"transparent") == 0)
11736            {
11737              PixelInfo
11738                transparent_color;
11739
11740              QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11741                &transparent_color,exception);
11742              for (next=image; next; next=next->next)
11743                (void) TransparentPaintImage(next,&transparent_color,
11744                  TransparentAlpha,MagickFalse,exception);
11745              break;
11746            }
11747          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11748            attribute);
11749          break;
11750        }
11751        default:
11752        {
11753          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11754            attribute);
11755          break;
11756        }
11757      }
11758    }
11759    image=MontageImageList(info->image_info,montage_info,image,exception);
11760    montage_info=DestroyMontageInfo(montage_info);
11761    if (image == (Image *) NULL)
11762      goto PerlException;
11763    if (transparent_color.alpha != TransparentAlpha)
11764      for (next=image; next; next=next->next)
11765        (void) TransparentPaintImage(next,&transparent_color,
11766          TransparentAlpha,MagickFalse,exception);
11767    for (  ; image; image=image->next)
11768    {
11769      AddImageToRegistry(sv,image);
11770      rv=newRV(sv);
11771      av_push(av,sv_bless(rv,hv));
11772      SvREFCNT_dec(sv);
11773    }
11774    exception=DestroyExceptionInfo(exception);
11775    ST(0)=av_reference;
11776    SvREFCNT_dec(perl_exception);
11777    XSRETURN(1);
11778
11779  PerlException:
11780    InheritPerlException(exception,perl_exception);
11781    exception=DestroyExceptionInfo(exception);
11782    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11783    SvPOK_on(perl_exception);
11784    ST(0)=sv_2mortal(perl_exception);
11785    XSRETURN(1);
11786  }
11787
11788#
11789###############################################################################
11790#                                                                             #
11791#                                                                             #
11792#                                                                             #
11793#   M o r p h                                                                 #
11794#                                                                             #
11795#                                                                             #
11796#                                                                             #
11797###############################################################################
11798#
11799#
11800void
11801Morph(ref,...)
11802  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11803  ALIAS:
11804    MorphImage  = 1
11805    morph       = 2
11806    morphimage  = 3
11807  PPCODE:
11808  {
11809    AV
11810      *av;
11811
11812    char
11813      *attribute;
11814
11815    ExceptionInfo
11816      *exception;
11817
11818    HV
11819      *hv;
11820
11821    Image
11822      *image;
11823
11824    register ssize_t
11825      i;
11826
11827    ssize_t
11828      number_frames;
11829
11830    struct PackageInfo
11831      *info;
11832
11833    SV
11834      *av_reference,
11835      *perl_exception,
11836      *reference,
11837      *rv,
11838      *sv;
11839
11840    PERL_UNUSED_VAR(ref);
11841    PERL_UNUSED_VAR(ix);
11842    exception=AcquireExceptionInfo();
11843    perl_exception=newSVpv("",0);
11844    sv=NULL;
11845    av=NULL;
11846    attribute=NULL;
11847    if (sv_isobject(ST(0)) == 0)
11848      {
11849        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11850          PackageName);
11851        goto PerlException;
11852      }
11853    reference=SvRV(ST(0));
11854    hv=SvSTASH(reference);
11855    av=newAV();
11856    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11857    SvREFCNT_dec(av);
11858    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11859    if (image == (Image *) NULL)
11860      {
11861        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11862          PackageName);
11863        goto PerlException;
11864      }
11865    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11866    /*
11867      Get attribute.
11868    */
11869    number_frames=30;
11870    for (i=2; i < items; i+=2)
11871    {
11872      attribute=(char *) SvPV(ST(i-1),na);
11873      switch (*attribute)
11874      {
11875        case 'F':
11876        case 'f':
11877        {
11878          if (LocaleCompare(attribute,"frames") == 0)
11879            {
11880              number_frames=SvIV(ST(i));
11881              break;
11882            }
11883          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11884            attribute);
11885          break;
11886        }
11887        default:
11888        {
11889          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11890            attribute);
11891          break;
11892        }
11893      }
11894    }
11895    image=MorphImages(image,number_frames,exception);
11896    if (image == (Image *) NULL)
11897      goto PerlException;
11898    for ( ; image; image=image->next)
11899    {
11900      AddImageToRegistry(sv,image);
11901      rv=newRV(sv);
11902      av_push(av,sv_bless(rv,hv));
11903      SvREFCNT_dec(sv);
11904    }
11905    exception=DestroyExceptionInfo(exception);
11906    ST(0)=av_reference;
11907    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11908    XSRETURN(1);
11909
11910  PerlException:
11911    InheritPerlException(exception,perl_exception);
11912    exception=DestroyExceptionInfo(exception);
11913    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11914    SvPOK_on(perl_exception);
11915    ST(0)=sv_2mortal(perl_exception);
11916    XSRETURN(1);
11917  }
11918
11919#
11920###############################################################################
11921#                                                                             #
11922#                                                                             #
11923#                                                                             #
11924#   M o s a i c                                                               #
11925#                                                                             #
11926#                                                                             #
11927#                                                                             #
11928###############################################################################
11929#
11930#
11931void
11932Mosaic(ref)
11933  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11934  ALIAS:
11935    MosaicImage   = 1
11936    mosaic        = 2
11937    mosaicimage   = 3
11938  PPCODE:
11939  {
11940    AV
11941      *av;
11942
11943    ExceptionInfo
11944      *exception;
11945
11946    HV
11947      *hv;
11948
11949    Image
11950      *image;
11951
11952    struct PackageInfo
11953      *info;
11954
11955    SV
11956      *perl_exception,
11957      *reference,
11958      *rv,
11959      *sv;
11960
11961    PERL_UNUSED_VAR(ref);
11962    PERL_UNUSED_VAR(ix);
11963    exception=AcquireExceptionInfo();
11964    perl_exception=newSVpv("",0);
11965    sv=NULL;
11966    if (sv_isobject(ST(0)) == 0)
11967      {
11968        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11969          PackageName);
11970        goto PerlException;
11971      }
11972    reference=SvRV(ST(0));
11973    hv=SvSTASH(reference);
11974    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11975    if (image == (Image *) NULL)
11976      {
11977        ThrowPerlException(exception,OptionError,"NoImagesDefined",
11978          PackageName);
11979        goto PerlException;
11980      }
11981    image=MergeImageLayers(image,MosaicLayer,exception);
11982    /*
11983      Create blessed Perl array for the returned image.
11984    */
11985    av=newAV();
11986    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11987    SvREFCNT_dec(av);
11988    AddImageToRegistry(sv,image);
11989    rv=newRV(sv);
11990    av_push(av,sv_bless(rv,hv));
11991    SvREFCNT_dec(sv);
11992    (void) CopyMagickString(info->image_info->filename,image->filename,
11993      MagickPathExtent);
11994    SetImageInfo(info->image_info,0,exception);
11995    exception=DestroyExceptionInfo(exception);
11996    SvREFCNT_dec(perl_exception);
11997    XSRETURN(1);
11998
11999  PerlException:
12000    InheritPerlException(exception,perl_exception);
12001    exception=DestroyExceptionInfo(exception);
12002    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12003    SvPOK_on(perl_exception);  /* return messages in string context */
12004    ST(0)=sv_2mortal(perl_exception);
12005    XSRETURN(1);
12006  }
12007
12008#
12009###############################################################################
12010#                                                                             #
12011#                                                                             #
12012#                                                                             #
12013#   P i n g                                                                   #
12014#                                                                             #
12015#                                                                             #
12016#                                                                             #
12017###############################################################################
12018#
12019#
12020void
12021Ping(ref,...)
12022  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12023  ALIAS:
12024    PingImage  = 1
12025    ping       = 2
12026    pingimage  = 3
12027  PPCODE:
12028  {
12029    AV
12030      *av;
12031
12032    char
12033      **keep,
12034      **list;
12035
12036    ExceptionInfo
12037      *exception;
12038
12039    Image
12040      *image,
12041      *next;
12042
12043    int
12044      n;
12045
12046    MagickBooleanType
12047      status;
12048
12049    register char
12050      **p;
12051
12052    register ssize_t
12053      i;
12054
12055    ssize_t
12056      ac;
12057
12058    STRLEN
12059      *length;
12060
12061    struct PackageInfo
12062      *info,
12063      *package_info;
12064
12065    SV
12066      *perl_exception,
12067      *reference;
12068
12069    size_t
12070      count;
12071
12072    PERL_UNUSED_VAR(ref);
12073    PERL_UNUSED_VAR(ix);
12074    exception=AcquireExceptionInfo();
12075    perl_exception=newSVpv("",0);
12076    package_info=(struct PackageInfo *) NULL;
12077    ac=(items < 2) ? 1 : items-1;
12078    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12079    keep=list;
12080    length=(STRLEN *) NULL;
12081    if (list == (char **) NULL)
12082      {
12083        ThrowPerlException(exception,ResourceLimitError,
12084          "MemoryAllocationFailed",PackageName);
12085        goto PerlException;
12086      }
12087    keep=list;
12088    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12089    if (length == (STRLEN *) NULL)
12090      {
12091        ThrowPerlException(exception,ResourceLimitError,
12092          "MemoryAllocationFailed",PackageName);
12093        goto PerlException;
12094      }
12095    if (sv_isobject(ST(0)) == 0)
12096      {
12097        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12098          PackageName);
12099        goto PerlException;
12100      }
12101    reference=SvRV(ST(0));
12102    if (SvTYPE(reference) != SVt_PVAV)
12103      {
12104        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12105          PackageName);
12106        goto PerlException;
12107      }
12108    av=(AV *) reference;
12109    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12110      exception);
12111    package_info=ClonePackageInfo(info,exception);
12112    n=1;
12113    if (items <= 1)
12114      *list=(char *) (*package_info->image_info->filename ?
12115        package_info->image_info->filename : "XC:black");
12116    else
12117      for (n=0, i=0; i < ac; i++)
12118      {
12119        list[n]=(char *) SvPV(ST(i+1),length[n]);
12120        if ((items >= 3) && strEQcase(list[n],"blob"))
12121          {
12122            void
12123              *blob;
12124
12125            i++;
12126            blob=(void *) (SvPV(ST(i+1),length[n]));
12127            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12128          }
12129        if ((items >= 3) && strEQcase(list[n],"filename"))
12130          continue;
12131        if ((items >= 3) && strEQcase(list[n],"file"))
12132          {
12133            FILE
12134              *file;
12135
12136            PerlIO
12137              *io_info;
12138
12139            i++;
12140            io_info=IoIFP(sv_2io(ST(i+1)));
12141            if (io_info == (PerlIO *) NULL)
12142              {
12143                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12144                  PackageName);
12145                continue;
12146              }
12147            file=PerlIO_findFILE(io_info);
12148            if (file == (FILE *) NULL)
12149              {
12150                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12151                  PackageName);
12152                continue;
12153              }
12154            SetImageInfoFile(package_info->image_info,file);
12155          }
12156        if ((items >= 3) && strEQcase(list[n],"magick"))
12157          continue;
12158        n++;
12159      }
12160    list[n]=(char *) NULL;
12161    keep=list;
12162    status=ExpandFilenames(&n,&list);
12163    if (status == MagickFalse)
12164      {
12165        ThrowPerlException(exception,ResourceLimitError,
12166          "MemoryAllocationFailed",PackageName);
12167        goto PerlException;
12168      }
12169    count=0;
12170    for (i=0; i < n; i++)
12171    {
12172      (void) CopyMagickString(package_info->image_info->filename,list[i],
12173        MagickPathExtent);
12174      image=PingImage(package_info->image_info,exception);
12175      if (image == (Image *) NULL)
12176        break;
12177      if ((package_info->image_info->file != (FILE *) NULL) ||
12178          (package_info->image_info->blob != (void *) NULL))
12179        DisassociateImageStream(image);
12180      count+=GetImageListLength(image);
12181      EXTEND(sp,4*count);
12182      for (next=image; next; next=next->next)
12183      {
12184        PUSHs(sv_2mortal(newSViv(next->columns)));
12185        PUSHs(sv_2mortal(newSViv(next->rows)));
12186        PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12187        PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12188      }
12189      image=DestroyImageList(image);
12190    }
12191    /*
12192      Free resources.
12193    */
12194    for (i=0; i < n; i++)
12195      if (list[i] != (char *) NULL)
12196        for (p=keep; list[i] != *p++; )
12197          if (*p == NULL)
12198            {
12199              list[i]=(char *) RelinquishMagickMemory(list[i]);
12200              break;
12201            }
12202
12203  PerlException:
12204    if (package_info != (struct PackageInfo *) NULL)
12205      DestroyPackageInfo(package_info);
12206    if (list && (list != keep))
12207      list=(char **) RelinquishMagickMemory(list);
12208    if (keep)
12209      keep=(char **) RelinquishMagickMemory(keep);
12210    if (length)
12211      length=(STRLEN *) RelinquishMagickMemory(length);
12212    InheritPerlException(exception,perl_exception);
12213    exception=DestroyExceptionInfo(exception);
12214    SvREFCNT_dec(perl_exception);  /* throw away all errors */
12215  }
12216
12217#
12218###############################################################################
12219#                                                                             #
12220#                                                                             #
12221#                                                                             #
12222#   P r e v i e w                                                             #
12223#                                                                             #
12224#                                                                             #
12225#                                                                             #
12226###############################################################################
12227#
12228#
12229void
12230Preview(ref,...)
12231  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12232  ALIAS:
12233    PreviewImage = 1
12234    preview      = 2
12235    previewimage = 3
12236  PPCODE:
12237  {
12238    AV
12239      *av;
12240
12241    ExceptionInfo
12242      *exception;
12243
12244    HV
12245      *hv;
12246
12247    Image
12248      *image,
12249      *preview_image;
12250
12251    PreviewType
12252      preview_type;
12253
12254    struct PackageInfo
12255      *info;
12256
12257    SV
12258      *av_reference,
12259      *perl_exception,
12260      *reference,
12261      *rv,
12262      *sv;
12263
12264    PERL_UNUSED_VAR(ref);
12265    PERL_UNUSED_VAR(ix);
12266    exception=AcquireExceptionInfo();
12267    perl_exception=newSVpv("",0);
12268    sv=NULL;
12269    av=NULL;
12270    if (sv_isobject(ST(0)) == 0)
12271      {
12272        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12273          PackageName);
12274        goto PerlException;
12275      }
12276    reference=SvRV(ST(0));
12277    hv=SvSTASH(reference);
12278    av=newAV();
12279    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12280    SvREFCNT_dec(av);
12281    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12282    if (image == (Image *) NULL)
12283      {
12284        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12285          PackageName);
12286        goto PerlException;
12287      }
12288    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12289    preview_type=GammaPreview;
12290    if (items > 1)
12291      preview_type=(PreviewType)
12292        ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12293    for ( ; image; image=image->next)
12294    {
12295      preview_image=PreviewImage(image,preview_type,exception);
12296      if (preview_image == (Image *) NULL)
12297        goto PerlException;
12298      AddImageToRegistry(sv,preview_image);
12299      rv=newRV(sv);
12300      av_push(av,sv_bless(rv,hv));
12301      SvREFCNT_dec(sv);
12302    }
12303    exception=DestroyExceptionInfo(exception);
12304    ST(0)=av_reference;
12305    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12306    XSRETURN(1);
12307
12308  PerlException:
12309    InheritPerlException(exception,perl_exception);
12310    exception=DestroyExceptionInfo(exception);
12311    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12312    SvPOK_on(perl_exception);
12313    ST(0)=sv_2mortal(perl_exception);
12314    XSRETURN(1);
12315  }
12316
12317#
12318###############################################################################
12319#                                                                             #
12320#                                                                             #
12321#                                                                             #
12322#   Q u e r y C o l o r                                                       #
12323#                                                                             #
12324#                                                                             #
12325#                                                                             #
12326###############################################################################
12327#
12328#
12329void
12330QueryColor(ref,...)
12331  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12332  ALIAS:
12333    querycolor = 1
12334  PPCODE:
12335  {
12336    char
12337      *name;
12338
12339    ExceptionInfo
12340      *exception;
12341
12342    PixelInfo
12343      color;
12344
12345    register ssize_t
12346      i;
12347
12348    SV
12349      *perl_exception;
12350
12351    PERL_UNUSED_VAR(ref);
12352    PERL_UNUSED_VAR(ix);
12353    exception=AcquireExceptionInfo();
12354    perl_exception=newSVpv("",0);
12355    if (items == 1)
12356      {
12357        const ColorInfo
12358          **colorlist;
12359
12360        size_t
12361          colors;
12362
12363        colorlist=GetColorInfoList("*",&colors,exception);
12364        EXTEND(sp,colors);
12365        for (i=0; i < (ssize_t) colors; i++)
12366        {
12367          PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12368        }
12369        colorlist=(const ColorInfo **)
12370          RelinquishMagickMemory((ColorInfo **) colorlist);
12371        goto PerlException;
12372      }
12373    EXTEND(sp,5*items);
12374    for (i=1; i < items; i++)
12375    {
12376      name=(char *) SvPV(ST(i),na);
12377      if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12378        {
12379          PUSHs(&sv_undef);
12380          continue;
12381        }
12382      PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12383      PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12384      PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12385      if (color.colorspace == CMYKColorspace)
12386        PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12387      if (color.alpha_trait != UndefinedPixelTrait)
12388        PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12389    }
12390
12391  PerlException:
12392    InheritPerlException(exception,perl_exception);
12393    exception=DestroyExceptionInfo(exception);
12394    SvREFCNT_dec(perl_exception);
12395  }
12396
12397#
12398###############################################################################
12399#                                                                             #
12400#                                                                             #
12401#                                                                             #
12402#   Q u e r y C o l o r N a m e                                               #
12403#                                                                             #
12404#                                                                             #
12405#                                                                             #
12406###############################################################################
12407#
12408#
12409void
12410QueryColorname(ref,...)
12411  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12412  ALIAS:
12413    querycolorname = 1
12414  PPCODE:
12415  {
12416    AV
12417      *av;
12418
12419    char
12420      message[MagickPathExtent];
12421
12422    ExceptionInfo
12423      *exception;
12424
12425    Image
12426      *image;
12427
12428    PixelInfo
12429      target_color;
12430
12431    register ssize_t
12432      i;
12433
12434    struct PackageInfo
12435      *info;
12436
12437    SV
12438      *perl_exception,
12439      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12440
12441    PERL_UNUSED_VAR(ref);
12442    PERL_UNUSED_VAR(ix);
12443    exception=AcquireExceptionInfo();
12444    perl_exception=newSVpv("",0);
12445    reference=SvRV(ST(0));
12446    av=(AV *) reference;
12447    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12448      exception);
12449    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12450    if (image == (Image *) NULL)
12451      {
12452        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12453          PackageName);
12454        goto PerlException;
12455      }
12456    EXTEND(sp,items);
12457    for (i=1; i < items; i++)
12458    {
12459      (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12460        exception);
12461      (void) QueryColorname(image,&target_color,SVGCompliance,message,
12462        exception);
12463      PUSHs(sv_2mortal(newSVpv(message,0)));
12464    }
12465
12466  PerlException:
12467    InheritPerlException(exception,perl_exception);
12468    exception=DestroyExceptionInfo(exception);
12469    SvREFCNT_dec(perl_exception);
12470  }
12471
12472#
12473###############################################################################
12474#                                                                             #
12475#                                                                             #
12476#                                                                             #
12477#   Q u e r y F o n t                                                         #
12478#                                                                             #
12479#                                                                             #
12480#                                                                             #
12481###############################################################################
12482#
12483#
12484void
12485QueryFont(ref,...)
12486  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12487  ALIAS:
12488    queryfont = 1
12489  PPCODE:
12490  {
12491    char
12492      *name,
12493      message[MagickPathExtent];
12494
12495    ExceptionInfo
12496      *exception;
12497
12498    register ssize_t
12499      i;
12500
12501    SV
12502      *perl_exception;
12503
12504    volatile const TypeInfo
12505      *type_info;
12506
12507    PERL_UNUSED_VAR(ref);
12508    PERL_UNUSED_VAR(ix);
12509    exception=AcquireExceptionInfo();
12510    perl_exception=newSVpv("",0);
12511    if (items == 1)
12512      {
12513        const TypeInfo
12514          **typelist;
12515
12516        size_t
12517          types;
12518
12519        typelist=GetTypeInfoList("*",&types,exception);
12520        EXTEND(sp,types);
12521        for (i=0; i < (ssize_t) types; i++)
12522        {
12523          PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12524        }
12525        typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12526          typelist);
12527        goto PerlException;
12528      }
12529    EXTEND(sp,10*items);
12530    for (i=1; i < items; i++)
12531    {
12532      name=(char *) SvPV(ST(i),na);
12533      type_info=GetTypeInfo(name,exception);
12534      if (type_info == (TypeInfo *) NULL)
12535        {
12536          PUSHs(&sv_undef);
12537          continue;
12538        }
12539      if (type_info->name == (char *) NULL)
12540        PUSHs(&sv_undef);
12541      else
12542        PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12543      if (type_info->description == (char *) NULL)
12544        PUSHs(&sv_undef);
12545      else
12546        PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12547      if (type_info->family == (char *) NULL)
12548        PUSHs(&sv_undef);
12549      else
12550        PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12551      if (type_info->style == UndefinedStyle)
12552        PUSHs(&sv_undef);
12553      else
12554        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12555          type_info->style),0)));
12556      if (type_info->stretch == UndefinedStretch)
12557        PUSHs(&sv_undef);
12558      else
12559        PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12560          type_info->stretch),0)));
12561      (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12562        type_info->weight);
12563      PUSHs(sv_2mortal(newSVpv(message,0)));
12564      if (type_info->encoding == (char *) NULL)
12565        PUSHs(&sv_undef);
12566      else
12567        PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12568      if (type_info->foundry == (char *) NULL)
12569        PUSHs(&sv_undef);
12570      else
12571        PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12572      if (type_info->format == (char *) NULL)
12573        PUSHs(&sv_undef);
12574      else
12575        PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12576      if (type_info->metrics == (char *) NULL)
12577        PUSHs(&sv_undef);
12578      else
12579        PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12580      if (type_info->glyphs == (char *) NULL)
12581        PUSHs(&sv_undef);
12582      else
12583        PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12584    }
12585
12586  PerlException:
12587    InheritPerlException(exception,perl_exception);
12588    exception=DestroyExceptionInfo(exception);
12589    SvREFCNT_dec(perl_exception);
12590  }
12591
12592#
12593###############################################################################
12594#                                                                             #
12595#                                                                             #
12596#                                                                             #
12597#   Q u e r y F o n t M e t r i c s                                           #
12598#                                                                             #
12599#                                                                             #
12600#                                                                             #
12601###############################################################################
12602#
12603#
12604void
12605QueryFontMetrics(ref,...)
12606  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12607  ALIAS:
12608    queryfontmetrics = 1
12609  PPCODE:
12610  {
12611    AffineMatrix
12612      affine,
12613      current;
12614
12615    AV
12616      *av;
12617
12618    char
12619      *attribute;
12620
12621    double
12622      x,
12623      y;
12624
12625    DrawInfo
12626      *draw_info;
12627
12628    ExceptionInfo
12629      *exception;
12630
12631    GeometryInfo
12632      geometry_info;
12633
12634    Image
12635      *image;
12636
12637    MagickBooleanType
12638      status;
12639
12640    MagickStatusType
12641      flags;
12642
12643    register ssize_t
12644      i;
12645
12646    ssize_t
12647      type;
12648
12649    struct PackageInfo
12650      *info,
12651      *package_info;
12652
12653    SV
12654      *perl_exception,
12655      *reference;  /* reference is the SV* of ref=SvIV(reference) */
12656
12657    TypeMetric
12658      metrics;
12659
12660    PERL_UNUSED_VAR(ref);
12661    PERL_UNUSED_VAR(ix);
12662    exception=AcquireExceptionInfo();
12663    package_info=(struct PackageInfo *) NULL;
12664    perl_exception=newSVpv("",0);
12665    reference=SvRV(ST(0));
12666    av=(AV *) reference;
12667    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12668      exception);
12669    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12670    if (image == (Image *) NULL)
12671      {
12672        ThrowPerlException(exception,OptionError,"NoImagesDefined",
12673          PackageName);
12674        goto PerlException;
12675      }
12676    package_info=ClonePackageInfo(info,exception);
12677    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12678    CloneString(&draw_info->text,"");
12679    current=draw_info->affine;
12680    GetAffineMatrix(&affine);
12681    x=0.0;
12682    y=0.0;
12683    EXTEND(sp,7*items);
12684    for (i=2; i < items; i+=2)
12685    {
12686      attribute=(char *) SvPV(ST(i-1),na);
12687      switch (*attribute)
12688      {
12689        case 'A':
12690        case 'a':
12691        {
12692          if (LocaleCompare(attribute,"antialias") == 0)
12693            {
12694              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12695                SvPV(ST(i),na));
12696              if (type < 0)
12697                {
12698                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12699                    SvPV(ST(i),na));
12700                  break;
12701                }
12702              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12703              break;
12704            }
12705          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12706            attribute);
12707          break;
12708        }
12709        case 'd':
12710        case 'D':
12711        {
12712          if (LocaleCompare(attribute,"density") == 0)
12713            {
12714              CloneString(&draw_info->density,SvPV(ST(i),na));
12715              break;
12716            }
12717          if (LocaleCompare(attribute,"direction") == 0)
12718            {
12719              draw_info->direction=(DirectionType) ParseCommandOption(
12720                MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12721              break;
12722            }
12723          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12724            attribute);
12725          break;
12726        }
12727        case 'e':
12728        case 'E':
12729        {
12730          if (LocaleCompare(attribute,"encoding") == 0)
12731            {
12732              CloneString(&draw_info->encoding,SvPV(ST(i),na));
12733              break;
12734            }
12735          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12736            attribute);
12737          break;
12738        }
12739        case 'f':
12740        case 'F':
12741        {
12742          if (LocaleCompare(attribute,"family") == 0)
12743            {
12744              CloneString(&draw_info->family,SvPV(ST(i),na));
12745              break;
12746            }
12747          if (LocaleCompare(attribute,"fill") == 0)
12748            {
12749              if (info)
12750                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12751                  &draw_info->fill,exception);
12752              break;
12753            }
12754          if (LocaleCompare(attribute,"font") == 0)
12755            {
12756              CloneString(&draw_info->font,SvPV(ST(i),na));
12757              break;
12758            }
12759          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12760            attribute);
12761          break;
12762        }
12763        case 'g':
12764        case 'G':
12765        {
12766          if (LocaleCompare(attribute,"geometry") == 0)
12767            {
12768              CloneString(&draw_info->geometry,SvPV(ST(i),na));
12769              break;
12770            }
12771          if (LocaleCompare(attribute,"gravity") == 0)
12772            {
12773              draw_info->gravity=(GravityType) ParseCommandOption(
12774                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12775              break;
12776            }
12777          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12778            attribute);
12779          break;
12780        }
12781        case 'i':
12782        case 'I':
12783        {
12784          if (LocaleCompare(attribute,"interline-spacing") == 0)
12785            {
12786              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12787              draw_info->interline_spacing=geometry_info.rho;
12788              break;
12789            }
12790          if (LocaleCompare(attribute,"interword-spacing") == 0)
12791            {
12792              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12793              draw_info->interword_spacing=geometry_info.rho;
12794              break;
12795            }
12796          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12797            attribute);
12798          break;
12799        }
12800        case 'k':
12801        case 'K':
12802        {
12803          if (LocaleCompare(attribute,"kerning") == 0)
12804            {
12805              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12806              draw_info->kerning=geometry_info.rho;
12807              break;
12808            }
12809          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12810            attribute);
12811          break;
12812        }
12813        case 'p':
12814        case 'P':
12815        {
12816          if (LocaleCompare(attribute,"pointsize") == 0)
12817            {
12818              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12819              draw_info->pointsize=geometry_info.rho;
12820              break;
12821            }
12822          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12823            attribute);
12824          break;
12825        }
12826        case 'r':
12827        case 'R':
12828        {
12829          if (LocaleCompare(attribute,"rotate") == 0)
12830            {
12831              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12832              affine.rx=geometry_info.rho;
12833              affine.ry=geometry_info.sigma;
12834              if ((flags & SigmaValue) == 0)
12835                affine.ry=affine.rx;
12836              break;
12837            }
12838          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12839            attribute);
12840          break;
12841        }
12842        case 's':
12843        case 'S':
12844        {
12845          if (LocaleCompare(attribute,"scale") == 0)
12846            {
12847              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12848              affine.sx=geometry_info.rho;
12849              affine.sy=geometry_info.sigma;
12850              if ((flags & SigmaValue) == 0)
12851                affine.sy=affine.sx;
12852              break;
12853            }
12854          if (LocaleCompare(attribute,"skew") == 0)
12855            {
12856              double
12857                x_angle,
12858                y_angle;
12859
12860              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12861              x_angle=geometry_info.rho;
12862              y_angle=geometry_info.sigma;
12863              if ((flags & SigmaValue) == 0)
12864                y_angle=x_angle;
12865              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12866              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12867              break;
12868            }
12869          if (LocaleCompare(attribute,"stroke") == 0)
12870            {
12871              if (info)
12872                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12873                  &draw_info->stroke,exception);
12874              break;
12875            }
12876          if (LocaleCompare(attribute,"style") == 0)
12877            {
12878              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12879                SvPV(ST(i),na));
12880              if (type < 0)
12881                {
12882                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
12883                    SvPV(ST(i),na));
12884                  break;
12885                }
12886              draw_info->style=(StyleType) type;
12887              break;
12888            }
12889          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12890            attribute);
12891          break;
12892        }
12893        case 't':
12894        case 'T':
12895        {
12896          if (LocaleCompare(attribute,"text") == 0)
12897            {
12898              CloneString(&draw_info->text,SvPV(ST(i),na));
12899              break;
12900            }
12901          if (LocaleCompare(attribute,"translate") == 0)
12902            {
12903              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12904              affine.tx=geometry_info.rho;
12905              affine.ty=geometry_info.sigma;
12906              if ((flags & SigmaValue) == 0)
12907                affine.ty=affine.tx;
12908              break;
12909            }
12910          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12911            attribute);
12912          break;
12913        }
12914        case 'w':
12915        case 'W':
12916        {
12917          if (LocaleCompare(attribute,"weight") == 0)
12918            {
12919              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12920              draw_info->weight=(size_t) geometry_info.rho;
12921              break;
12922            }
12923          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12924            attribute);
12925          break;
12926        }
12927        case 'x':
12928        case 'X':
12929        {
12930          if (LocaleCompare(attribute,"x") == 0)
12931            {
12932              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12933              x=geometry_info.rho;
12934              break;
12935            }
12936          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12937            attribute);
12938          break;
12939        }
12940        case 'y':
12941        case 'Y':
12942        {
12943          if (LocaleCompare(attribute,"y") == 0)
12944            {
12945              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12946              y=geometry_info.rho;
12947              break;
12948            }
12949          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12950            attribute);
12951          break;
12952        }
12953        default:
12954        {
12955          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12956            attribute);
12957          break;
12958        }
12959      }
12960    }
12961    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12962    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12963    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12964    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12965    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12966    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12967    if (draw_info->geometry == (char *) NULL)
12968      {
12969        draw_info->geometry=AcquireString((char *) NULL);
12970        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12971          "%.15g,%.15g",x,y);
12972      }
12973    status=GetTypeMetrics(image,draw_info,&metrics,exception);
12974    (void) CatchImageException(image);
12975    if (status == MagickFalse)
12976      PUSHs(&sv_undef);
12977    else
12978      {
12979        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12980        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12981        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12982        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12983        PUSHs(sv_2mortal(newSVnv(metrics.width)));
12984        PUSHs(sv_2mortal(newSVnv(metrics.height)));
12985        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12986        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12987        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12988        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12989        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12990        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12991        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12992      }
12993    draw_info=DestroyDrawInfo(draw_info);
12994
12995  PerlException:
12996    if (package_info != (struct PackageInfo *) NULL)
12997      DestroyPackageInfo(package_info);
12998    InheritPerlException(exception,perl_exception);
12999    exception=DestroyExceptionInfo(exception);
13000    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13001  }
13002
13003#
13004###############################################################################
13005#                                                                             #
13006#                                                                             #
13007#                                                                             #
13008#   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                         #
13009#                                                                             #
13010#                                                                             #
13011#                                                                             #
13012###############################################################################
13013#
13014#
13015void
13016QueryMultilineFontMetrics(ref,...)
13017  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13018  ALIAS:
13019    querymultilinefontmetrics = 1
13020  PPCODE:
13021  {
13022    AffineMatrix
13023      affine,
13024      current;
13025
13026    AV
13027      *av;
13028
13029    char
13030      *attribute;
13031
13032    double
13033      x,
13034      y;
13035
13036    DrawInfo
13037      *draw_info;
13038
13039    ExceptionInfo
13040      *exception;
13041
13042    GeometryInfo
13043      geometry_info;
13044
13045    Image
13046      *image;
13047
13048    MagickBooleanType
13049      status;
13050
13051    MagickStatusType
13052      flags;
13053
13054    register ssize_t
13055      i;
13056
13057    ssize_t
13058      type;
13059
13060    struct PackageInfo
13061      *info,
13062      *package_info;
13063
13064    SV
13065      *perl_exception,
13066      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13067
13068    TypeMetric
13069      metrics;
13070
13071    PERL_UNUSED_VAR(ref);
13072    PERL_UNUSED_VAR(ix);
13073    exception=AcquireExceptionInfo();
13074    package_info=(struct PackageInfo *) NULL;
13075    perl_exception=newSVpv("",0);
13076    reference=SvRV(ST(0));
13077    av=(AV *) reference;
13078    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13079      exception);
13080    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13081    if (image == (Image *) NULL)
13082      {
13083        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13084          PackageName);
13085        goto PerlException;
13086      }
13087    package_info=ClonePackageInfo(info,exception);
13088    draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13089    CloneString(&draw_info->text,"");
13090    current=draw_info->affine;
13091    GetAffineMatrix(&affine);
13092    x=0.0;
13093    y=0.0;
13094    EXTEND(sp,7*items);
13095    for (i=2; i < items; i+=2)
13096    {
13097      attribute=(char *) SvPV(ST(i-1),na);
13098      switch (*attribute)
13099      {
13100        case 'A':
13101        case 'a':
13102        {
13103          if (LocaleCompare(attribute,"antialias") == 0)
13104            {
13105              type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13106                SvPV(ST(i),na));
13107              if (type < 0)
13108                {
13109                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13110                    SvPV(ST(i),na));
13111                  break;
13112                }
13113              draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13114              break;
13115            }
13116          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13117            attribute);
13118          break;
13119        }
13120        case 'd':
13121        case 'D':
13122        {
13123          if (LocaleCompare(attribute,"density") == 0)
13124            {
13125              CloneString(&draw_info->density,SvPV(ST(i),na));
13126              break;
13127            }
13128          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13129            attribute);
13130          break;
13131        }
13132        case 'e':
13133        case 'E':
13134        {
13135          if (LocaleCompare(attribute,"encoding") == 0)
13136            {
13137              CloneString(&draw_info->encoding,SvPV(ST(i),na));
13138              break;
13139            }
13140          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13141            attribute);
13142          break;
13143        }
13144        case 'f':
13145        case 'F':
13146        {
13147          if (LocaleCompare(attribute,"family") == 0)
13148            {
13149              CloneString(&draw_info->family,SvPV(ST(i),na));
13150              break;
13151            }
13152          if (LocaleCompare(attribute,"fill") == 0)
13153            {
13154              if (info)
13155                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13156                  &draw_info->fill,exception);
13157              break;
13158            }
13159          if (LocaleCompare(attribute,"font") == 0)
13160            {
13161              CloneString(&draw_info->font,SvPV(ST(i),na));
13162              break;
13163            }
13164          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13165            attribute);
13166          break;
13167        }
13168        case 'g':
13169        case 'G':
13170        {
13171          if (LocaleCompare(attribute,"geometry") == 0)
13172            {
13173              CloneString(&draw_info->geometry,SvPV(ST(i),na));
13174              break;
13175            }
13176          if (LocaleCompare(attribute,"gravity") == 0)
13177            {
13178              draw_info->gravity=(GravityType) ParseCommandOption(
13179                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13180              break;
13181            }
13182          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13183            attribute);
13184          break;
13185        }
13186        case 'p':
13187        case 'P':
13188        {
13189          if (LocaleCompare(attribute,"pointsize") == 0)
13190            {
13191              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13192              draw_info->pointsize=geometry_info.rho;
13193              break;
13194            }
13195          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13196            attribute);
13197          break;
13198        }
13199        case 'r':
13200        case 'R':
13201        {
13202          if (LocaleCompare(attribute,"rotate") == 0)
13203            {
13204              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13205              affine.rx=geometry_info.rho;
13206              affine.ry=geometry_info.sigma;
13207              if ((flags & SigmaValue) == 0)
13208                affine.ry=affine.rx;
13209              break;
13210            }
13211          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13212            attribute);
13213          break;
13214        }
13215        case 's':
13216        case 'S':
13217        {
13218          if (LocaleCompare(attribute,"scale") == 0)
13219            {
13220              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13221              affine.sx=geometry_info.rho;
13222              affine.sy=geometry_info.sigma;
13223              if ((flags & SigmaValue) == 0)
13224                affine.sy=affine.sx;
13225              break;
13226            }
13227          if (LocaleCompare(attribute,"skew") == 0)
13228            {
13229              double
13230                x_angle,
13231                y_angle;
13232
13233              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13234              x_angle=geometry_info.rho;
13235              y_angle=geometry_info.sigma;
13236              if ((flags & SigmaValue) == 0)
13237                y_angle=x_angle;
13238              affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13239              affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13240              break;
13241            }
13242          if (LocaleCompare(attribute,"stroke") == 0)
13243            {
13244              if (info)
13245                (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13246                  &draw_info->stroke,exception);
13247              break;
13248            }
13249          if (LocaleCompare(attribute,"style") == 0)
13250            {
13251              type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13252                SvPV(ST(i),na));
13253              if (type < 0)
13254                {
13255                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13256                    SvPV(ST(i),na));
13257                  break;
13258                }
13259              draw_info->style=(StyleType) type;
13260              break;
13261            }
13262          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13263            attribute);
13264          break;
13265        }
13266        case 't':
13267        case 'T':
13268        {
13269          if (LocaleCompare(attribute,"text") == 0)
13270            {
13271              CloneString(&draw_info->text,SvPV(ST(i),na));
13272              break;
13273            }
13274          if (LocaleCompare(attribute,"translate") == 0)
13275            {
13276              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13277              affine.tx=geometry_info.rho;
13278              affine.ty=geometry_info.sigma;
13279              if ((flags & SigmaValue) == 0)
13280                affine.ty=affine.tx;
13281              break;
13282            }
13283          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13284            attribute);
13285          break;
13286        }
13287        case 'w':
13288        case 'W':
13289        {
13290          if (LocaleCompare(attribute,"weight") == 0)
13291            {
13292              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13293              draw_info->weight=(size_t) geometry_info.rho;
13294              break;
13295            }
13296          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13297            attribute);
13298          break;
13299        }
13300        case 'x':
13301        case 'X':
13302        {
13303          if (LocaleCompare(attribute,"x") == 0)
13304            {
13305              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13306              x=geometry_info.rho;
13307              break;
13308            }
13309          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13310            attribute);
13311          break;
13312        }
13313        case 'y':
13314        case 'Y':
13315        {
13316          if (LocaleCompare(attribute,"y") == 0)
13317            {
13318              flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13319              y=geometry_info.rho;
13320              break;
13321            }
13322          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13323            attribute);
13324          break;
13325        }
13326        default:
13327        {
13328          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13329            attribute);
13330          break;
13331        }
13332      }
13333    }
13334    draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13335    draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13336    draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13337    draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13338    draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13339    draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13340    if (draw_info->geometry == (char *) NULL)
13341      {
13342        draw_info->geometry=AcquireString((char *) NULL);
13343        (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13344          "%.15g,%.15g",x,y);
13345      }
13346    status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13347    (void) CatchException(exception);
13348    if (status == MagickFalse)
13349      PUSHs(&sv_undef);
13350    else
13351      {
13352        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13353        PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13354        PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13355        PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13356        PUSHs(sv_2mortal(newSVnv(metrics.width)));
13357        PUSHs(sv_2mortal(newSVnv(metrics.height)));
13358        PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13359        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13360        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13361        PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13362        PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13363        PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13364        PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13365      }
13366    draw_info=DestroyDrawInfo(draw_info);
13367
13368  PerlException:
13369    if (package_info != (struct PackageInfo *) NULL)
13370      DestroyPackageInfo(package_info);
13371    InheritPerlException(exception,perl_exception);
13372    exception=DestroyExceptionInfo(exception);
13373    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13374  }
13375
13376#
13377###############################################################################
13378#                                                                             #
13379#                                                                             #
13380#                                                                             #
13381#   Q u e r y F o r m a t                                                     #
13382#                                                                             #
13383#                                                                             #
13384#                                                                             #
13385###############################################################################
13386#
13387#
13388void
13389QueryFormat(ref,...)
13390  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13391  ALIAS:
13392    queryformat = 1
13393  PPCODE:
13394  {
13395    char
13396      *name;
13397
13398    ExceptionInfo
13399      *exception;
13400
13401    register ssize_t
13402      i;
13403
13404    SV
13405      *perl_exception;
13406
13407    volatile const MagickInfo
13408      *magick_info;
13409
13410    PERL_UNUSED_VAR(ref);
13411    PERL_UNUSED_VAR(ix);
13412    exception=AcquireExceptionInfo();
13413    perl_exception=newSVpv("",0);
13414    if (items == 1)
13415      {
13416        char
13417          format[MagickPathExtent];
13418
13419        const MagickInfo
13420          **format_list;
13421
13422        size_t
13423          types;
13424
13425        format_list=GetMagickInfoList("*",&types,exception);
13426        EXTEND(sp,types);
13427        for (i=0; i < (ssize_t) types; i++)
13428        {
13429          (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13430          LocaleLower(format);
13431          PUSHs(sv_2mortal(newSVpv(format,0)));
13432        }
13433        format_list=(const MagickInfo **)
13434          RelinquishMagickMemory((MagickInfo *) format_list);
13435        goto PerlException;
13436      }
13437    EXTEND(sp,8*items);
13438    for (i=1; i < items; i++)
13439    {
13440      name=(char *) SvPV(ST(i),na);
13441      magick_info=GetMagickInfo(name,exception);
13442      if (magick_info == (const MagickInfo *) NULL)
13443        {
13444          PUSHs(&sv_undef);
13445          continue;
13446        }
13447      if (magick_info->description == (char *) NULL)
13448        PUSHs(&sv_undef);
13449      else
13450        PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13451      if (magick_info->module == (char *) NULL)
13452        PUSHs(&sv_undef);
13453      else
13454        PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13455    }
13456
13457  PerlException:
13458    InheritPerlException(exception,perl_exception);
13459    exception=DestroyExceptionInfo(exception);
13460    SvREFCNT_dec(perl_exception);
13461  }
13462
13463#
13464###############################################################################
13465#                                                                             #
13466#                                                                             #
13467#                                                                             #
13468#   Q u e r y O p t i o n                                                     #
13469#                                                                             #
13470#                                                                             #
13471#                                                                             #
13472###############################################################################
13473#
13474#
13475void
13476QueryOption(ref,...)
13477  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13478  ALIAS:
13479    queryoption = 1
13480  PPCODE:
13481  {
13482    char
13483      **options;
13484
13485    ExceptionInfo
13486      *exception;
13487
13488    register ssize_t
13489      i;
13490
13491    ssize_t
13492      j,
13493      option;
13494
13495    SV
13496      *perl_exception;
13497
13498    PERL_UNUSED_VAR(ref);
13499    PERL_UNUSED_VAR(ix);
13500    exception=AcquireExceptionInfo();
13501    perl_exception=newSVpv("",0);
13502    EXTEND(sp,8*items);
13503    for (i=1; i < items; i++)
13504    {
13505      option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13506        SvPV(ST(i),na));
13507      options=GetCommandOptions((CommandOption) option);
13508      if (options == (char **) NULL)
13509        PUSHs(&sv_undef);
13510      else
13511        {
13512          for (j=0; options[j] != (char *) NULL; j++)
13513            PUSHs(sv_2mortal(newSVpv(options[j],0)));
13514          options=DestroyStringList(options);
13515        }
13516    }
13517
13518    InheritPerlException(exception,perl_exception);
13519    exception=DestroyExceptionInfo(exception);
13520    SvREFCNT_dec(perl_exception);
13521  }
13522
13523#
13524###############################################################################
13525#                                                                             #
13526#                                                                             #
13527#                                                                             #
13528#   R e a d                                                                   #
13529#                                                                             #
13530#                                                                             #
13531#                                                                             #
13532###############################################################################
13533#
13534#
13535void
13536Read(ref,...)
13537  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13538  ALIAS:
13539    ReadImage  = 1
13540    read       = 2
13541    readimage  = 3
13542  PPCODE:
13543  {
13544    AV
13545      *av;
13546
13547    char
13548      **keep,
13549      **list;
13550
13551    ExceptionInfo
13552      *exception;
13553
13554    HV
13555      *hv;
13556
13557    Image
13558      *image;
13559
13560    int
13561      n;
13562
13563    MagickBooleanType
13564      status;
13565
13566    register char
13567      **p;
13568
13569    register ssize_t
13570      i;
13571
13572    ssize_t
13573      ac,
13574      number_images;
13575
13576    STRLEN
13577      *length;
13578
13579    struct PackageInfo
13580      *info,
13581      *package_info;
13582
13583    SV
13584      *perl_exception,  /* Perl variable for storing messages */
13585      *reference,
13586      *rv,
13587      *sv;
13588
13589    PERL_UNUSED_VAR(ref);
13590    PERL_UNUSED_VAR(ix);
13591    exception=AcquireExceptionInfo();
13592    perl_exception=newSVpv("",0);
13593    sv=NULL;
13594    package_info=(struct PackageInfo *) NULL;
13595    number_images=0;
13596    ac=(items < 2) ? 1 : items-1;
13597    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13598    keep=list;
13599    length=(STRLEN *) NULL;
13600    if (list == (char **) NULL)
13601      {
13602        ThrowPerlException(exception,ResourceLimitError,
13603          "MemoryAllocationFailed",PackageName);
13604        goto PerlException;
13605      }
13606    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13607    if (length == (STRLEN *) NULL)
13608      {
13609        ThrowPerlException(exception,ResourceLimitError,
13610          "MemoryAllocationFailed",PackageName);
13611        goto PerlException;
13612      }
13613    if (sv_isobject(ST(0)) == 0)
13614      {
13615        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13616          PackageName);
13617        goto PerlException;
13618      }
13619    reference=SvRV(ST(0));
13620    hv=SvSTASH(reference);
13621    if (SvTYPE(reference) != SVt_PVAV)
13622      {
13623        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13624          PackageName);
13625        goto PerlException;
13626      }
13627    av=(AV *) reference;
13628    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13629      exception);
13630    package_info=ClonePackageInfo(info,exception);
13631    n=1;
13632    if (items <= 1)
13633      *list=(char *) (*package_info->image_info->filename ?
13634        package_info->image_info->filename : "XC:black");
13635    else
13636      for (n=0, i=0; i < ac; i++)
13637      {
13638        list[n]=(char *) SvPV(ST(i+1),length[n]);
13639        if ((items >= 3) && strEQcase(list[n],"blob"))
13640          {
13641            void
13642              *blob;
13643
13644            i++;
13645            blob=(void *) (SvPV(ST(i+1),length[n]));
13646            SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13647          }
13648        if ((items >= 3) && strEQcase(list[n],"filename"))
13649          continue;
13650        if ((items >= 3) && strEQcase(list[n],"file"))
13651          {
13652            FILE
13653              *file;
13654
13655            PerlIO
13656              *io_info;
13657
13658            i++;
13659            io_info=IoIFP(sv_2io(ST(i+1)));
13660            if (io_info == (PerlIO *) NULL)
13661              {
13662                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13663                  PackageName);
13664                continue;
13665              }
13666            file=PerlIO_findFILE(io_info);
13667            if (file == (FILE *) NULL)
13668              {
13669                ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13670                  PackageName);
13671                continue;
13672              }
13673            SetImageInfoFile(package_info->image_info,file);
13674          }
13675        if ((items >= 3) && strEQcase(list[n],"magick"))
13676          continue;
13677        n++;
13678      }
13679    list[n]=(char *) NULL;
13680    keep=list;
13681    status=ExpandFilenames(&n,&list);
13682    if (status == MagickFalse)
13683      {
13684        ThrowPerlException(exception,ResourceLimitError,
13685          "MemoryAllocationFailed",PackageName);
13686        goto PerlException;
13687      }
13688    number_images=0;
13689    for (i=0; i < n; i++)
13690    {
13691      if ((package_info->image_info->file == (FILE *) NULL) &&
13692          (package_info->image_info->blob == (void *) NULL))
13693        image=ReadImages(package_info->image_info,list[i],exception);
13694      else
13695        {
13696          image=ReadImages(package_info->image_info,
13697            package_info->image_info->filename,exception);
13698          if (image != (Image *) NULL)
13699            DisassociateImageStream(image);
13700        }
13701      if (image == (Image *) NULL)
13702        break;
13703      for ( ; image; image=image->next)
13704      {
13705        AddImageToRegistry(sv,image);
13706        rv=newRV(sv);
13707        av_push(av,sv_bless(rv,hv));
13708        SvREFCNT_dec(sv);
13709        number_images++;
13710      }
13711    }
13712    /*
13713      Free resources.
13714    */
13715    for (i=0; i < n; i++)
13716      if (list[i] != (char *) NULL)
13717        for (p=keep; list[i] != *p++; )
13718          if (*p == (char *) NULL)
13719            {
13720              list[i]=(char *) RelinquishMagickMemory(list[i]);
13721              break;
13722            }
13723
13724  PerlException:
13725    if (package_info != (struct PackageInfo *) NULL)
13726      DestroyPackageInfo(package_info);
13727    if (list && (list != keep))
13728      list=(char **) RelinquishMagickMemory(list);
13729    if (keep)
13730      keep=(char **) RelinquishMagickMemory(keep);
13731    if (length)
13732      length=(STRLEN *) RelinquishMagickMemory(length);
13733    InheritPerlException(exception,perl_exception);
13734    exception=DestroyExceptionInfo(exception);
13735    sv_setiv(perl_exception,(IV) number_images);
13736    SvPOK_on(perl_exception);
13737    ST(0)=sv_2mortal(perl_exception);
13738    XSRETURN(1);
13739  }
13740
13741#
13742###############################################################################
13743#                                                                             #
13744#                                                                             #
13745#                                                                             #
13746#   R e m o t e                                                               #
13747#                                                                             #
13748#                                                                             #
13749#                                                                             #
13750###############################################################################
13751#
13752#
13753void
13754Remote(ref,...)
13755  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13756  ALIAS:
13757    RemoteCommand  = 1
13758    remote         = 2
13759    remoteCommand  = 3
13760  PPCODE:
13761  {
13762    AV
13763      *av;
13764
13765    ExceptionInfo
13766      *exception;
13767
13768    register ssize_t
13769      i;
13770
13771    SV
13772      *perl_exception,
13773      *reference;
13774
13775    struct PackageInfo
13776      *info;
13777
13778    PERL_UNUSED_VAR(ref);
13779    PERL_UNUSED_VAR(ix);
13780    exception=AcquireExceptionInfo();
13781    perl_exception=newSVpv("",0);
13782    reference=SvRV(ST(0));
13783    av=(AV *) reference;
13784    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13785      exception);
13786    for (i=1; i < items; i++)
13787      (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13788        SvPV(ST(i),na),exception);
13789    InheritPerlException(exception,perl_exception);
13790    exception=DestroyExceptionInfo(exception);
13791    SvREFCNT_dec(perl_exception);    /* throw away all errors */
13792  }
13793
13794#
13795###############################################################################
13796#                                                                             #
13797#                                                                             #
13798#                                                                             #
13799#   S e t                                                                     #
13800#                                                                             #
13801#                                                                             #
13802#                                                                             #
13803###############################################################################
13804#
13805#
13806void
13807Set(ref,...)
13808  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13809  ALIAS:
13810    SetAttributes  = 1
13811    SetAttribute   = 2
13812    set            = 3
13813    setattributes  = 4
13814    setattribute   = 5
13815  PPCODE:
13816  {
13817    ExceptionInfo
13818      *exception;
13819
13820    Image
13821      *image;
13822
13823    register ssize_t
13824      i;
13825
13826    struct PackageInfo
13827      *info;
13828
13829    SV
13830      *perl_exception,
13831      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13832
13833    PERL_UNUSED_VAR(ref);
13834    PERL_UNUSED_VAR(ix);
13835    exception=AcquireExceptionInfo();
13836    perl_exception=newSVpv("",0);
13837    if (sv_isobject(ST(0)) == 0)
13838      {
13839        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13840          PackageName);
13841        goto PerlException;
13842      }
13843    reference=SvRV(ST(0));
13844    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13845    if (items == 2)
13846      SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13847    else
13848      for (i=2; i < items; i+=2)
13849        SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13850
13851  PerlException:
13852    InheritPerlException(exception,perl_exception);
13853    exception=DestroyExceptionInfo(exception);
13854    sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13855    SvPOK_on(perl_exception);
13856    ST(0)=sv_2mortal(perl_exception);
13857    XSRETURN(1);
13858  }
13859
13860#
13861###############################################################################
13862#                                                                             #
13863#                                                                             #
13864#                                                                             #
13865#   S e t P i x e l                                                           #
13866#                                                                             #
13867#                                                                             #
13868#                                                                             #
13869###############################################################################
13870#
13871#
13872void
13873SetPixel(ref,...)
13874  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13875  ALIAS:
13876    setpixel = 1
13877    setPixel = 2
13878  PPCODE:
13879  {
13880    AV
13881      *av;
13882
13883    char
13884      *attribute;
13885
13886    ChannelType
13887      channel,
13888      channel_mask;
13889
13890    ExceptionInfo
13891      *exception;
13892
13893    Image
13894      *image;
13895
13896    MagickBooleanType
13897      normalize;
13898
13899    RectangleInfo
13900      region;
13901
13902    register ssize_t
13903      i;
13904
13905    register Quantum
13906      *q;
13907
13908    ssize_t
13909      option;
13910
13911    struct PackageInfo
13912      *info;
13913
13914    SV
13915      *perl_exception,
13916      *reference;  /* reference is the SV* of ref=SvIV(reference) */
13917
13918    PERL_UNUSED_VAR(ref);
13919    PERL_UNUSED_VAR(ix);
13920    exception=AcquireExceptionInfo();
13921    perl_exception=newSVpv("",0);
13922    reference=SvRV(ST(0));
13923    av=(AV *) reference;
13924    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13925      exception);
13926    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13927    if (image == (Image *) NULL)
13928      {
13929        ThrowPerlException(exception,OptionError,"NoImagesDefined",
13930          PackageName);
13931        goto PerlException;
13932      }
13933    av=(AV *) NULL;
13934    normalize=MagickTrue;
13935    region.x=0;
13936    region.y=0;
13937    region.width=image->columns;
13938    region.height=1;
13939    if (items == 1)
13940      (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13941    channel=DefaultChannels;
13942    for (i=2; i < items; i+=2)
13943    {
13944      attribute=(char *) SvPV(ST(i-1),na);
13945      switch (*attribute)
13946      {
13947        case 'C':
13948        case 'c':
13949        {
13950          if (LocaleCompare(attribute,"channel") == 0)
13951            {
13952              ssize_t
13953                option;
13954
13955              option=ParseChannelOption(SvPV(ST(i),na));
13956              if (option < 0)
13957                {
13958                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13959                    SvPV(ST(i),na));
13960                  return;
13961                }
13962              channel=(ChannelType) option;
13963              break;
13964            }
13965          if (LocaleCompare(attribute,"color") == 0)
13966            {
13967              if (SvTYPE(ST(i)) != SVt_RV)
13968                {
13969                  char
13970                    message[MagickPathExtent];
13971
13972                  (void) FormatLocaleString(message,MagickPathExtent,
13973                    "invalid %.60s value",attribute);
13974                  ThrowPerlException(exception,OptionError,message,
13975                    SvPV(ST(i),na));
13976                }
13977              av=(AV *) SvRV(ST(i));
13978              break;
13979            }
13980          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13981            attribute);
13982          break;
13983        }
13984        case 'g':
13985        case 'G':
13986        {
13987          if (LocaleCompare(attribute,"geometry") == 0)
13988            {
13989              (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13990              break;
13991            }
13992          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13993            attribute);
13994          break;
13995        }
13996        case 'N':
13997        case 'n':
13998        {
13999          if (LocaleCompare(attribute,"normalize") == 0)
14000            {
14001              option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14002                SvPV(ST(i),na));
14003              if (option < 0)
14004                {
14005                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14006                    SvPV(ST(i),na));
14007                  break;
14008                }
14009             normalize=option != 0 ? MagickTrue : MagickFalse;
14010             break;
14011            }
14012          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14013            attribute);
14014          break;
14015        }
14016        case 'x':
14017        case 'X':
14018        {
14019          if (LocaleCompare(attribute,"x") == 0)
14020            {
14021              region.x=SvIV(ST(i));
14022              break;
14023            }
14024          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14025            attribute);
14026          break;
14027        }
14028        case 'y':
14029        case 'Y':
14030        {
14031          if (LocaleCompare(attribute,"y") == 0)
14032            {
14033              region.y=SvIV(ST(i));
14034              break;
14035            }
14036          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14037            attribute);
14038          break;
14039        }
14040        default:
14041        {
14042          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14043            attribute);
14044          break;
14045        }
14046      }
14047    }
14048    (void) SetImageStorageClass(image,DirectClass,exception);
14049    channel_mask=SetImageChannelMask(image,channel);
14050    q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14051    if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14052        (SvTYPE(av) != SVt_PVAV))
14053      PUSHs(&sv_undef);
14054    else
14055      {
14056        double
14057          scale;
14058
14059        register ssize_t
14060          i;
14061
14062        i=0;
14063        scale=1.0;
14064        if (normalize != MagickFalse)
14065          scale=QuantumRange;
14066        if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14067            (i <= av_len(av)))
14068          {
14069            SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14070              av_fetch(av,i,0)))),q);
14071            i++;
14072          }
14073        if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14074            (i <= av_len(av)))
14075          {
14076            SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14077              av_fetch(av,i,0)))),q);
14078            i++;
14079          }
14080        if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14081            (i <= av_len(av)))
14082          {
14083            SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14084              av_fetch(av,i,0)))),q);
14085            i++;
14086          }
14087        if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14088            (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14089          {
14090            SetPixelBlack(image,ClampToQuantum(scale*
14091              SvNV(*(av_fetch(av,i,0)))),q);
14092            i++;
14093          }
14094        if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14095            (i <= av_len(av)))
14096          {
14097            SetPixelAlpha(image,ClampToQuantum(scale*
14098              SvNV(*(av_fetch(av,i,0)))),q);
14099            i++;
14100          }
14101        (void) SyncAuthenticPixels(image,exception);
14102      }
14103    (void) SetImageChannelMask(image,channel_mask);
14104
14105  PerlException:
14106    InheritPerlException(exception,perl_exception);
14107    exception=DestroyExceptionInfo(exception);
14108    SvREFCNT_dec(perl_exception);
14109  }
14110
14111#
14112###############################################################################
14113#                                                                             #
14114#                                                                             #
14115#                                                                             #
14116#   S m u s h                                                                 #
14117#                                                                             #
14118#                                                                             #
14119#                                                                             #
14120###############################################################################
14121#
14122#
14123void
14124Smush(ref,...)
14125  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14126  ALIAS:
14127    SmushImage  = 1
14128    smush       = 2
14129    smushimage  = 3
14130  PPCODE:
14131  {
14132    AV
14133      *av;
14134
14135    char
14136      *attribute;
14137
14138    ExceptionInfo
14139      *exception;
14140
14141    HV
14142      *hv;
14143
14144    Image
14145      *image;
14146
14147    register ssize_t
14148      i;
14149
14150    ssize_t
14151      offset,
14152      stack;
14153
14154    struct PackageInfo
14155      *info;
14156
14157    SV
14158      *av_reference,
14159      *perl_exception,
14160      *reference,
14161      *rv,
14162      *sv;
14163
14164    PERL_UNUSED_VAR(ref);
14165    PERL_UNUSED_VAR(ix);
14166    exception=AcquireExceptionInfo();
14167    perl_exception=newSVpv("",0);
14168    sv=NULL;
14169    attribute=NULL;
14170    av=NULL;
14171    if (sv_isobject(ST(0)) == 0)
14172      {
14173        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14174          PackageName);
14175        goto PerlException;
14176      }
14177    reference=SvRV(ST(0));
14178    hv=SvSTASH(reference);
14179    av=newAV();
14180    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14181    SvREFCNT_dec(av);
14182    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14183    if (image == (Image *) NULL)
14184      {
14185        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14186          PackageName);
14187        goto PerlException;
14188      }
14189    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14190    /*
14191      Get options.
14192    */
14193    offset=0;
14194    stack=MagickTrue;
14195    for (i=2; i < items; i+=2)
14196    {
14197      attribute=(char *) SvPV(ST(i-1),na);
14198      switch (*attribute)
14199      {
14200        case 'O':
14201        case 'o':
14202        {
14203          if (LocaleCompare(attribute,"offset") == 0)
14204            {
14205              offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14206              break;
14207            }
14208          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14209            attribute);
14210          break;
14211        }
14212        case 'S':
14213        case 's':
14214        {
14215          if (LocaleCompare(attribute,"stack") == 0)
14216            {
14217              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14218                SvPV(ST(i),na));
14219              if (stack < 0)
14220                {
14221                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14222                    SvPV(ST(i),na));
14223                  return;
14224                }
14225              break;
14226            }
14227          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14228            attribute);
14229          break;
14230        }
14231        default:
14232        {
14233          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14234            attribute);
14235          break;
14236        }
14237      }
14238    }
14239    image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14240      exception);
14241    if (image == (Image *) NULL)
14242      goto PerlException;
14243    for ( ; image; image=image->next)
14244    {
14245      AddImageToRegistry(sv,image);
14246      rv=newRV(sv);
14247      av_push(av,sv_bless(rv,hv));
14248      SvREFCNT_dec(sv);
14249    }
14250    exception=DestroyExceptionInfo(exception);
14251    ST(0)=av_reference;
14252    SvREFCNT_dec(perl_exception);
14253    XSRETURN(1);
14254
14255  PerlException:
14256    InheritPerlException(exception,perl_exception);
14257    exception=DestroyExceptionInfo(exception);
14258    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14259    SvPOK_on(perl_exception);
14260    ST(0)=sv_2mortal(perl_exception);
14261    XSRETURN(1);
14262  }
14263
14264#
14265###############################################################################
14266#                                                                             #
14267#                                                                             #
14268#                                                                             #
14269#   S t a t i s t i c s                                                       #
14270#                                                                             #
14271#                                                                             #
14272#                                                                             #
14273###############################################################################
14274#
14275#
14276void
14277Statistics(ref,...)
14278  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14279  ALIAS:
14280    StatisticsImage = 1
14281    statistics      = 2
14282    statisticsimage = 3
14283  PPCODE:
14284  {
14285#define ChannelStatistics(channel) \
14286{ \
14287  (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14288    (double) channel_statistics[channel].depth); \
14289  PUSHs(sv_2mortal(newSVpv(message,0))); \
14290  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14291    channel_statistics[channel].minima/scale); \
14292  PUSHs(sv_2mortal(newSVpv(message,0))); \
14293  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14294    channel_statistics[channel].maxima/scale); \
14295  PUSHs(sv_2mortal(newSVpv(message,0))); \
14296  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14297    channel_statistics[channel].mean/scale); \
14298  PUSHs(sv_2mortal(newSVpv(message,0))); \
14299  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14300    channel_statistics[channel].standard_deviation/scale); \
14301  PUSHs(sv_2mortal(newSVpv(message,0))); \
14302  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14303    channel_statistics[channel].kurtosis); \
14304  PUSHs(sv_2mortal(newSVpv(message,0))); \
14305  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14306    channel_statistics[channel].skewness); \
14307  PUSHs(sv_2mortal(newSVpv(message,0))); \
14308  (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14309    channel_statistics[channel].entropy); \
14310  PUSHs(sv_2mortal(newSVpv(message,0))); \
14311}
14312
14313    AV
14314      *av;
14315
14316    char
14317      message[MagickPathExtent];
14318
14319    ChannelStatistics
14320      *channel_statistics;
14321
14322    double
14323      scale;
14324
14325    ExceptionInfo
14326      *exception;
14327
14328    Image
14329      *image;
14330
14331    ssize_t
14332      count;
14333
14334    struct PackageInfo
14335      *info;
14336
14337    SV
14338      *perl_exception,
14339      *reference;
14340
14341    PERL_UNUSED_VAR(ref);
14342    PERL_UNUSED_VAR(ix);
14343    exception=AcquireExceptionInfo();
14344    perl_exception=newSVpv("",0);
14345    av=NULL;
14346    if (sv_isobject(ST(0)) == 0)
14347      {
14348        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14349          PackageName);
14350        goto PerlException;
14351      }
14352    reference=SvRV(ST(0));
14353    av=newAV();
14354    SvREFCNT_dec(av);
14355    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14356    if (image == (Image *) NULL)
14357      {
14358        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14359          PackageName);
14360        goto PerlException;
14361      }
14362    count=0;
14363    for ( ; image; image=image->next)
14364    {
14365      channel_statistics=GetImageStatistics(image,exception);
14366      if (channel_statistics == (ChannelStatistics *) NULL)
14367        continue;
14368      count++;
14369      EXTEND(sp,35*count);
14370      scale=(double) QuantumRange;
14371      ChannelStatistics(RedChannel);
14372      ChannelStatistics(GreenChannel);
14373      ChannelStatistics(BlueChannel);
14374      if (image->colorspace == CMYKColorspace)
14375        ChannelStatistics(BlackChannel);
14376      if (image->alpha_trait != UndefinedPixelTrait)
14377        ChannelStatistics(AlphaChannel);
14378      channel_statistics=(ChannelStatistics *)
14379        RelinquishMagickMemory(channel_statistics);
14380    }
14381
14382  PerlException:
14383    InheritPerlException(exception,perl_exception);
14384    exception=DestroyExceptionInfo(exception);
14385    SvREFCNT_dec(perl_exception);
14386  }
14387
14388#
14389###############################################################################
14390#                                                                             #
14391#                                                                             #
14392#                                                                             #
14393#   S y n c A u t h e n t i c P i x e l s                                     #
14394#                                                                             #
14395#                                                                             #
14396#                                                                             #
14397###############################################################################
14398#
14399#
14400void
14401SyncAuthenticPixels(ref,...)
14402  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14403  ALIAS:
14404    Syncauthenticpixels = 1
14405    SyncImagePixels = 2
14406    syncimagepixels = 3
14407  CODE:
14408  {
14409    ExceptionInfo
14410      *exception;
14411
14412    Image
14413      *image;
14414
14415    MagickBooleanType
14416      status;
14417
14418    struct PackageInfo
14419      *info;
14420
14421    SV
14422      *perl_exception,
14423      *reference;
14424
14425    PERL_UNUSED_VAR(ref);
14426    PERL_UNUSED_VAR(ix);
14427    exception=AcquireExceptionInfo();
14428    perl_exception=newSVpv("",0);
14429    if (sv_isobject(ST(0)) == 0)
14430      {
14431        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14432          PackageName);
14433        goto PerlException;
14434      }
14435
14436    reference=SvRV(ST(0));
14437    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14438    if (image == (Image *) NULL)
14439      {
14440        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14441          PackageName);
14442        goto PerlException;
14443      }
14444
14445    status=SyncAuthenticPixels(image,exception);
14446    if (status != MagickFalse)
14447      return;
14448
14449  PerlException:
14450    InheritPerlException(exception,perl_exception);
14451    exception=DestroyExceptionInfo(exception);
14452    SvREFCNT_dec(perl_exception);  /* throw away all errors */
14453  }
14454
14455
14456#
14457###############################################################################
14458#                                                                             #
14459#                                                                             #
14460#                                                                             #
14461#   W r i t e                                                                 #
14462#                                                                             #
14463#                                                                             #
14464#                                                                             #
14465###############################################################################
14466#
14467#
14468void
14469Write(ref,...)
14470  Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14471  ALIAS:
14472    WriteImage    = 1
14473    write         = 2
14474    writeimage    = 3
14475  PPCODE:
14476  {
14477    char
14478      filename[MagickPathExtent];
14479
14480    ExceptionInfo
14481      *exception;
14482
14483    Image
14484      *image,
14485      *next;
14486
14487    register ssize_t
14488      i;
14489
14490    ssize_t
14491      number_images,
14492      scene;
14493
14494    struct PackageInfo
14495      *info,
14496      *package_info;
14497
14498    SV
14499      *perl_exception,
14500      *reference;
14501
14502    PERL_UNUSED_VAR(ref);
14503    PERL_UNUSED_VAR(ix);
14504    exception=AcquireExceptionInfo();
14505    perl_exception=newSVpv("",0);
14506    number_images=0;
14507    package_info=(struct PackageInfo *) NULL;
14508    if (sv_isobject(ST(0)) == 0)
14509      {
14510        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14511          PackageName);
14512        goto PerlException;
14513      }
14514    reference=SvRV(ST(0));
14515    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14516    if (image == (Image *) NULL)
14517      {
14518        ThrowPerlException(exception,OptionError,"NoImagesDefined",
14519          PackageName);
14520        goto PerlException;
14521      }
14522    package_info=ClonePackageInfo(info,exception);
14523    if (items == 2)
14524      SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14525    else
14526      if (items > 2)
14527        for (i=2; i < items; i+=2)
14528          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14529            exception);
14530    (void) CopyMagickString(filename,package_info->image_info->filename,
14531      MagickPathExtent);
14532    scene=0;
14533    for (next=image; next; next=next->next)
14534    {
14535      (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14536      next->scene=scene++;
14537    }
14538    *package_info->image_info->magick='\0';
14539    SetImageInfo(package_info->image_info,(unsigned int)
14540      GetImageListLength(image),exception);
14541    for (next=image; next; next=next->next)
14542    {
14543      (void) WriteImage(package_info->image_info,next,exception);
14544      number_images++;
14545      if (package_info->image_info->adjoin)
14546        break;
14547    }
14548
14549  PerlException:
14550    if (package_info != (struct PackageInfo *) NULL)
14551      DestroyPackageInfo(package_info);
14552    InheritPerlException(exception,perl_exception);
14553    exception=DestroyExceptionInfo(exception);
14554    sv_setiv(perl_exception,(IV) number_images);
14555    SvPOK_on(perl_exception);
14556    ST(0)=sv_2mortal(perl_exception);
14557    XSRETURN(1);
14558  }
14559