[packages/ImageMagick/ImageMagick-6] - restore perlMagick from 6.9.6-6

baggins baggins at pld-linux.org
Tue Dec 27 00:23:23 CET 2016


commit 6b7c141d26d924fce2313c0ab86c1f2a3b3bf020
Author: Jan Rękorajski <baggins at pld-linux.org>
Date:   Tue Dec 27 00:22:44 2016 +0100

    - restore perlMagick from 6.9.6-6

 ImageMagick.spec |     6 +-
 perlmagick.patch | 14602 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 14606 insertions(+), 2 deletions(-)
---
diff --git a/ImageMagick.spec b/ImageMagick.spec
index 94384c7..7d42f5c 100644
--- a/ImageMagick.spec
+++ b/ImageMagick.spec
@@ -46,6 +46,7 @@ Patch1:		%{name}-link.patch
 Patch2:		%{name}-libpath.patch
 Patch3:		%{name}-ldflags.patch
 Patch4:		%{name}-lt.patch
+Patch5:		perlmagick.patch
 URL:		http://www.imagemagick.org/
 %{?with_opencl:BuildRequires:	OpenCL-devel}
 BuildRequires:	OpenEXR-devel >= 1.0.6
@@ -669,6 +670,7 @@ Moduł kodera dla plików WMF.
 %patch2 -p1
 %patch3 -p1
 %patch4 -p1
+%patch5 -p1
 
 find -type f | xargs grep -l '/usr/local/bin/perl' | xargs %{__sed} -i -e 's=!/usr/local/bin/perl=!%{__perl}='
 
@@ -1165,8 +1167,8 @@ rm -rf $RPM_BUILD_ROOT
 %dir %{perl_vendorarch}/Image/Magick
 %{perl_vendorarch}/Image/Magick/%{abisuf}.pm
 %dir %{perl_vendorarch}/auto/Image/Magick
-#%{perl_vendorarch}/auto/Image/Magick/autosplit.ix
-#%attr(755,root,root) %{perl_vendorarch}/auto/Image/Magick/Magick.so
+%{perl_vendorarch}/auto/Image/Magick/autosplit.ix
+%attr(755,root,root) %{perl_vendorarch}/auto/Image/Magick/Magick.so
 %dir %{perl_vendorarch}/auto/Image/Magick/%{abisuf}
 %{perl_vendorarch}/auto/Image/Magick/%{abisuf}/autosplit.ix
 %attr(755,root,root) %{perl_vendorarch}/auto/Image/Magick/%{abisuf}/%{abisuf}.so
diff --git a/perlmagick.patch b/perlmagick.patch
new file mode 100644
index 0000000..7d56b68
--- /dev/null
+++ b/perlmagick.patch
@@ -0,0 +1,14602 @@
+diff -urN ImageMagick-6.9.7-0/PerlMagick/Magick.pm ImageMagick-6.9.6-6/PerlMagick/Magick.pm
+--- ImageMagick-6.9.7-0/PerlMagick/Magick.pm	1970-01-01 01:00:00.000000000 +0100
++++ ImageMagick-6.9.6-6/PerlMagick/Magick.pm	2016-11-25 16:58:55.000000000 +0100
+@@ -0,0 +1,144 @@
++package Image::Magick;
++
++#  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization
++#  dedicated to making software imaging solutions freely available.
++#
++#  You may not use this file except in compliance with the License.  You may
++#  obtain a copy of the License at
++#
++#    http://www.imagemagick.org/script/license.php
++#
++#  Unless required by applicable law or agreed to in writing, software
++#  distributed under the License is distributed on an "AS IS" BASIS,
++#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++#  See the License for the specific language governing permissions and
++#  limitations under the License.
++#
++#  Initial version, written by Kyle Shorter.
++
++use strict;
++use Carp;
++use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);
++
++require 5.002;
++require Exporter;
++require DynaLoader;
++require AutoLoader;
++
++ at ISA = qw(Exporter DynaLoader);
++# Items to export into callers namespace by default. Note: do not export
++# names by default without a very good reason. Use EXPORT_OK instead.
++# Do not simply export all your public functions/methods/constants.
++ at EXPORT =
++  qw(
++      Success Transparent Opaque QuantumDepth QuantumRange MaxRGB
++      WarningException ResourceLimitWarning TypeWarning OptionWarning
++      DelegateWarning MissingDelegateWarning CorruptImageWarning
++      FileOpenWarning BlobWarning StreamWarning CacheWarning CoderWarning
++      ModuleWarning DrawWarning ImageWarning XServerWarning RegistryWarning
++      ConfigureWarning ErrorException ResourceLimitError TypeError
++      OptionError DelegateError MissingDelegateError CorruptImageError
++      FileOpenError BlobError StreamError CacheError CoderError
++      ModuleError DrawError ImageError XServerError RegistryError
++      ConfigureError FatalErrorException
++    );
++
++$VERSION = '6.96';
++
++sub AUTOLOAD {
++    # This AUTOLOAD is used to 'autoload' constants from the constant()
++    # XS function.  If a constant is not found then control is passed
++    # to the AUTOLOAD in AutoLoader.
++
++    my $constname;
++    ($constname = $AUTOLOAD) =~ s/.*:://;
++    die "&${AUTOLOAD} not defined. The required ImageMagick libraries are not installed or not installed properly.\n" if $constname eq 'constant';
++    my $val = constant($constname, @_ ? $_[0] : 0);
++    if ($! != 0) {
++    	if ($! =~ /Invalid/) {
++	        $AutoLoader::AUTOLOAD = $AUTOLOAD;
++	        goto &AutoLoader::AUTOLOAD;
++    	}
++    	else {
++	        my($pack,$file,$line) = caller;
++	        die "Your vendor has not defined PerlMagick macro $pack\:\:$constname, used at $file line $line.\n";
++    	}
++    }
++    eval "sub $AUTOLOAD { $val }";
++    goto &$AUTOLOAD;
++}
++
++bootstrap Image::Magick $VERSION;
++
++# Preloaded methods go here.
++
++sub new
++{
++    my $this = shift;
++    my $class = ref($this) || $this || "Image::Magick";
++    my $self = [ ];
++    bless $self, $class;
++    $self->set(@_) if @_;
++    return $self;
++}
++
++sub New
++{
++    my $this = shift;
++    my $class = ref($this) || $this || "Image::Magick";
++    my $self = [ ];
++    bless $self, $class;
++    $self->set(@_) if @_;
++    return $self;
++}
++
++# Autoload methods go after =cut, and are processed by the autosplit program.
++
++END { UNLOAD () };
++
++1;
++__END__
++
++=head1 NAME
++
++Image::Magick - objected-oriented Perl interface to ImageMagick. Use it to create, edit, compose, or convert bitmap images from within a Perl script.
++
++=head1 SYNOPSIS
++
++  use Image::Magick;
++  $p = new Image::Magick;
++  $p->Read("imagefile");
++  $p->Set(attribute => value, ...)
++  ($a, ...) = $p->Get("attribute", ...)
++  $p->routine(parameter => value, ...)
++  $p->Mogrify("Routine", parameter => value, ...)
++  $p->Write("filename");
++
++=head1 DESCRIPTION
++
++This Perl extension allows the reading, manipulation and writing of
++a large number of image file formats using the ImageMagick library.
++It was originally developed to be used by CGI scripts for Web pages.
++
++A web page has been set up for this extension. See:
++
++	 file:///usr/share/doc/ImageMagick-6.8.0/www/perl-magick.html
++	 http://www.imagemagick.org/script/perl-magick.php
++
++If you have problems, go to
++
++   http://www.imagemagick.org/discourse-server/viewforum.php?f=7
++
++=head1 AUTHOR
++
++Kyle Shorter	magick-users at imagemagick.org
++
++=head1 BUGS
++
++Has all the bugs of ImageMagick and much, much more!
++
++=head1 SEE ALSO
++
++perl(1).
++
++=cut
+diff -urN ImageMagick-6.9.7-0/PerlMagick/Magick.xs ImageMagick-6.9.6-6/PerlMagick/Magick.xs
+--- ImageMagick-6.9.7-0/PerlMagick/Magick.xs	1970-01-01 01:00:00.000000000 +0100
++++ ImageMagick-6.9.6-6/PerlMagick/Magick.xs	2016-11-25 16:58:55.000000000 +0100
+@@ -0,0 +1,14450 @@
++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                         PPPP   EEEEE  RRRR   L                              %
++%                         P   P  E      R   R  L                              %
++%                         PPPP   EEE    RRRR   L                              %
++%                         P      E      R  R   L                              %
++%                         P      EEEEE  R   R  LLLLL                          %
++%                                                                             %
++%                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
++%                  MM MM  A   A  G        I    C      K  K                    %
++%                  M M M  AAAAA  G GGG    I    C      KKK                     %
++%                  M   M  A   A  G   G    I    C      K  K                    %
++%                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
++%                                                                             %
++%                                                                             %
++%                Object-oriented Perl interface to ImageMagick                %
++%                                                                             %
++%                            Software Design                                  %
++%                              Kyle Shorter                                   %
++%                                 Cristy                                      %
++%                             February 1997                                   %
++%                                                                             %
++%                                                                             %
++%  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
++%  dedicated to making software imaging solutions freely available.           %
++%                                                                             %
++%  You may not use this file except in compliance with the License.  You may  %
++%  obtain a copy of the License at                                            %
++%                                                                             %
++%    http://www.imagemagick.org/script/license.php                            %
++%                                                                             %
++%  Unless required by applicable law or agreed to in writing, software        %
++%  distributed under the License is distributed on an "AS IS" BASIS,          %
++%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
++%  See the License for the specific language governing permissions and        %
++%  limitations under the License.                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
++%  the module to read, manipulate, or write an image or image sequence from
++%  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
++%
++*/
++

++/*
++  Include declarations.
++*/
++#if defined(__cplusplus) || defined(c_plusplus)
++extern "C" {
++#endif
++
++#define PERL_NO_GET_CONTEXT
++#include "EXTERN.h"
++#include "perl.h"
++#include "XSUB.h"
++#include <math.h>
++#include <magick/MagickCore.h>
++#undef tainted
++
++#if defined(__cplusplus) || defined(c_plusplus)
++}
++#endif
++

++/*
++  Define declarations.
++*/
++#ifndef aTHX_
++#define aTHX_
++#define pTHX_
++#define dTHX
++#endif
++#define DegreesToRadians(x)  (MagickPI*(x)/180.0)
++#define EndOf(array)  (&array[NumberOf(array)])
++#define MagickPI  3.14159265358979323846264338327950288419716939937510
++#define MaxArguments  33
++#ifndef na
++#define na  PL_na
++#endif
++#define NumberOf(array)  (sizeof(array)/sizeof(*array))
++#define PackageName   "Image::Magick"
++#if PERL_VERSION <= 6
++#define PerlIO  FILE
++#define PerlIO_importFILE(f, fl)  (f)
++#define PerlIO_findFILE(f)  NULL
++#endif
++#ifndef sv_undef
++#define sv_undef  PL_sv_undef
++#endif
++
++#define AddImageToRegistry(sv,image) \
++{ \
++  if (magick_registry != (SplayTreeInfo *) NULL) \
++    { \
++      (void) AddValueToSplayTree(magick_registry,image,image); \
++      (sv)=newSViv(PTR2IV(image)); \
++    } \
++}
++
++#define DeleteImageFromRegistry(reference,image) \
++{ \
++  if (magick_registry != (SplayTreeInfo *) NULL) \
++    { \
++      if (GetImageReferenceCount(image) == 1) \
++       (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
++      image=DestroyImage(image); \
++      sv_setiv(reference,0); \
++    } \
++}
++
++#define InheritPerlException(exception,perl_exception) \
++{ \
++  char \
++    message[MaxTextExtent]; \
++ \
++  if ((exception)->severity != UndefinedException) \
++    { \
++      (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
++        (exception)->severity, (exception)->reason ? \
++        GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
++        "Unknown", (exception)->description ? " (" : "", \
++        (exception)->description ? GetLocaleExceptionMessage( \
++        (exception)->severity,(exception)->description) : "", \
++        (exception)->description ? ")" : ""); \
++      if ((perl_exception) != (SV *) NULL) \
++        { \
++          if (SvCUR(perl_exception)) \
++            sv_catpv(perl_exception,"\n"); \
++          sv_catpv(perl_exception,message); \
++        } \
++    } \
++}
++
++#define ThrowPerlException(exception,severity,tag,reason) \
++  (void) ThrowMagickException(exception,GetMagickModule(),severity, \
++    tag,"`%s'",reason); \
++

++/*
++  Typedef and structure declarations.
++*/
++typedef enum
++{
++  ArrayReference = (~0),
++  RealReference = (~0)-1,
++  FileReference = (~0)-2,
++  ImageReference = (~0)-3,
++  IntegerReference = (~0)-4,
++  StringReference = (~0)-5
++} MagickReference;
++
++typedef struct _Arguments
++{
++  const char
++    *method;
++
++  ssize_t
++    type;
++} Arguments;
++
++struct ArgumentList
++{
++  ssize_t
++    integer_reference;
++
++  MagickRealType
++    real_reference;
++
++  const char
++    *string_reference;
++
++  Image
++    *image_reference;
++
++  SV
++    *array_reference;
++
++  FILE
++    *file_reference;
++
++  size_t
++    length;
++};
++
++struct PackageInfo
++{
++  ImageInfo
++    *image_info;
++};
++
++typedef void
++  *Image__Magick;  /* data type for the Image::Magick package */
++

++/*
++  Static declarations.
++*/
++static struct
++  Methods
++  {
++    const char
++      *name;
++
++    Arguments
++      arguments[MaxArguments];
++  } Methods[] =
++  {
++    { "Comment", { {"comment", StringReference} } },
++    { "Label", { {"label", StringReference} } },
++    { "AddNoise", { {"noise", MagickNoiseOptions},
++      {"channel", MagickChannelOptions} } },
++    { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
++    { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"fill", StringReference},
++      {"bordercolor", StringReference}, {"color", StringReference},
++      {"compose", MagickComposeOptions} } },
++    { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
++    { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"x", IntegerReference},
++      {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
++    { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"x", IntegerReference},
++      {"y", IntegerReference}, {"fuzz", StringReference},
++      {"gravity", MagickGravityOptions} } },
++    { "Despeckle", },
++    { "Edge", { {"radius", RealReference} } },
++    { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference} } },
++    { "Enhance", },
++    { "Flip", },
++    { "Flop", },
++    { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"inner", IntegerReference},
++      {"outer", IntegerReference}, {"fill", StringReference},
++      {"color", StringReference}, {"compose", MagickComposeOptions} } },
++    { "Implode", { {"amount", RealReference},
++      {"interpolate", MagickInterpolateOptions} } },
++    { "Magnify", },
++    { "MedianFilter", { {"geometry", StringReference},
++      {"width", IntegerReference},{"height", IntegerReference},
++      {"channel", MagickChannelOptions} } },
++    { "Minify", },
++    { "OilPaint", { {"radius", RealReference} } },
++    { "ReduceNoise", { {"geometry", StringReference},
++      {"width", IntegerReference},{"height", IntegerReference},
++      {"channel", MagickChannelOptions} } },
++    { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
++      {"y", IntegerReference} } },
++    { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
++      {"color", StringReference}, {"background", StringReference} } },
++    { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference} } },
++    { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference} } },
++    { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
++      {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
++    { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
++    { "Shear", { {"geometry", StringReference}, {"x", RealReference},
++      {"y", RealReference}, { "fill", StringReference},
++      {"color", StringReference} } },
++    { "Spread", { {"radius", RealReference},
++      {"interpolate", MagickInterpolateOptions} } },
++    { "Swirl", { {"degrees", RealReference},
++      {"interpolate", MagickInterpolateOptions} } },
++    { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"filter", MagickFilterOptions},
++      {"support", StringReference }, {"blur", RealReference } } },
++    { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"filter", MagickFilterOptions},
++      {"support", RealReference }, {"blur", RealReference } } },
++    { "Annotate", { {"text", StringReference}, {"font", StringReference},
++      {"pointsize", RealReference}, {"density", StringReference},
++      {"undercolor", StringReference}, {"stroke", StringReference},
++      {"fill", StringReference}, {"geometry", StringReference},
++      {"pen", StringReference}, {"x", RealReference},
++      {"y", RealReference}, {"gravity", MagickGravityOptions},
++      {"translate", StringReference}, {"scale", StringReference},
++      {"rotate", RealReference}, {"skewX", RealReference},
++      {"skewY", RealReference}, {"strokewidth", RealReference},
++      {"antialias", MagickBooleanOptions}, {"family", StringReference},
++      {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
++      {"weight", IntegerReference}, {"align", MagickAlignOptions},
++      {"encoding", StringReference}, {"affine", ArrayReference},
++      {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
++      {"tile", ImageReference}, {"kerning", RealReference},
++      {"interline-spacing", RealReference},
++      {"interword-spacing", RealReference},
++      {"direction", MagickDirectionOptions} } },
++    { "ColorFloodfill", { {"geometry", StringReference},
++      {"x", IntegerReference}, {"y", IntegerReference},
++      {"fill", StringReference}, {"bordercolor", StringReference},
++      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
++    { "Composite", { {"image", ImageReference},
++      {"compose", MagickComposeOptions}, {"geometry", StringReference},
++      {"x", IntegerReference}, {"y", IntegerReference},
++      {"gravity", MagickGravityOptions}, {"opacity", StringReference},
++      {"tile", MagickBooleanOptions}, {"rotate", RealReference},
++      {"color", StringReference}, {"mask", ImageReference},
++      {"channel", MagickChannelOptions},
++      {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
++      {"blend", StringReference} } },
++    { "Contrast", { {"sharpen", MagickBooleanOptions} } },
++    { "CycleColormap", { {"display", IntegerReference} } },
++    { "Draw", { {"primitive", MagickPrimitiveOptions},
++      {"points", StringReference}, {"method", MagickMethodOptions},
++      {"stroke", StringReference}, {"fill", StringReference},
++      {"strokewidth", RealReference}, {"font", StringReference},
++      {"bordercolor", StringReference}, {"x", RealReference},
++      {"y", RealReference}, {"translate", StringReference},
++      {"scale", StringReference}, {"rotate", RealReference},
++      {"skewX", RealReference}, {"skewY", RealReference},
++      {"tile", ImageReference}, {"pointsize", RealReference},
++      {"antialias", MagickBooleanOptions}, {"density", StringReference},
++      {"linewidth", RealReference}, {"affine", ArrayReference},
++      {"stroke-dashoffset", RealReference},
++      {"stroke-dasharray", ArrayReference},
++      {"interpolate", MagickInterpolateOptions},
++      {"origin", StringReference}, {"text", StringReference},
++      {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
++      {"vector-graphics", StringReference}, {"kerning", RealReference},
++      {"interline-spacing", RealReference},
++      {"interword-spacing", RealReference},
++      {"direction", MagickDirectionOptions} } },
++    { "Equalize", { {"channel", MagickChannelOptions} } },
++    { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
++      {"red", RealReference}, {"green", RealReference},
++      {"blue", RealReference} } },
++    { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
++      {"dither-method", MagickDitherOptions} } },
++    { "MatteFloodfill", { {"geometry", StringReference},
++      {"x", IntegerReference}, {"y", IntegerReference},
++      {"opacity", StringReference}, {"bordercolor", StringReference},
++      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
++    { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
++      {"saturation", RealReference}, {"whiteness", RealReference},
++      {"brightness", RealReference}, {"lightness", RealReference},
++      {"blackness", RealReference} } },
++    { "Negate", { {"gray", MagickBooleanOptions},
++      {"channel", MagickChannelOptions} } },
++    { "Normalize", { {"channel", MagickChannelOptions} } },
++    { "NumberColors", },
++    { "Opaque", { {"color", StringReference}, {"fill", StringReference},
++      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
++      {"invert", MagickBooleanOptions} } },
++    { "Quantize", { {"colors", IntegerReference},
++      {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
++      {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
++      {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
++      {"dither-method", MagickDitherOptions} } },
++    { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
++    { "Segment", { {"geometry", StringReference},
++      {"cluster-threshold", RealReference},
++      {"smoothing-threshold", RealReference},
++      {"colorspace", MagickColorspaceOptions},
++      {"verbose", MagickBooleanOptions} } },
++    { "Signature", },
++    { "Solarize", { {"geometry", StringReference},
++      {"threshold", StringReference}, {"channel", MagickChannelOptions} } },
++    { "Sync", },
++    { "Texture", { {"texture", ImageReference} } },
++    { "Evaluate", { {"value", RealReference},
++      {"operator", MagickEvaluateOptions},
++      {"channel", MagickChannelOptions} } },
++    { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
++      {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
++    { "Threshold", { {"threshold", StringReference},
++      {"channel", MagickChannelOptions} } },
++    { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference} } },
++    { "Trim", { {"fuzz", StringReference} } },
++    { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
++      {"wavelength", RealReference},
++      {"interpolate", MagickInterpolateOptions} } },
++    { "Separate", { {"channel", MagickChannelOptions} } },
++    { "Condense", },
++    { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
++      {"y", IntegerReference} } },
++    { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
++    { "Deconstruct", },
++    { "GaussianBlur", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Convolve", { {"coefficients", ArrayReference},
++      {"channel", MagickChannelOptions}, {"bias", StringReference} } },
++    { "Profile", { {"name", StringReference}, {"profile", StringReference},
++      { "rendering-intent", MagickIntentOptions},
++      { "black-point-compensation", MagickBooleanOptions} } },
++    { "UnsharpMask", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"amount", RealReference}, {"threshold", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "MotionBlur", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
++    { "OrderedDither", { {"threshold", StringReference},
++      {"channel", MagickChannelOptions} } },
++    { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference} } },
++    { "Level", { {"levels", StringReference}, {"black-point", RealReference},
++      {"white-point", RealReference}, {"gamma", RealReference},
++      {"channel", MagickChannelOptions}, {"level", StringReference} } },
++    { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
++    { "AffineTransform", { {"affine", ArrayReference},
++      {"translate", StringReference}, {"scale", StringReference},
++      {"rotate", RealReference}, {"skewX", RealReference},
++      {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
++      {"background", StringReference} } },
++    { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
++    { "AdaptiveThreshold", { {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"offset", IntegerReference} } },
++    { "Resample", { {"density", StringReference}, {"x", RealReference},
++      {"y", RealReference}, {"filter", MagickFilterOptions},
++      {"support", RealReference }, {"blur", RealReference } } },
++    { "Describe", { {"file", FileReference} } },
++    { "BlackThreshold", { {"threshold", StringReference},
++      {"channel", MagickChannelOptions} } },
++    { "WhiteThreshold", { {"threshold", StringReference},
++      {"channel", MagickChannelOptions} } },
++    { "RotationalBlur", { {"geometry", StringReference},
++      {"angle", RealReference}, {"channel", MagickChannelOptions} } },
++    { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference} } },
++    { "Strip", },
++    { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
++    { "Channel", { {"channel", MagickChannelOptions} } },
++    { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"x", IntegerReference},
++      {"y", IntegerReference}, {"fuzz", StringReference},
++      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
++    { "Posterize", { {"levels", IntegerReference},
++      {"dither", MagickBooleanOptions} } },
++    { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
++      {"sigma", RealReference}, {"x", IntegerReference},
++      {"y", IntegerReference} } },
++    { "Identify", { {"file", FileReference}, {"features", StringReference},
++      {"unique", MagickBooleanOptions} } },
++    { "SepiaTone", { {"threshold", RealReference} } },
++    { "SigmoidalContrast", { {"geometry", StringReference},
++      {"contrast", RealReference}, {"mid-point", RealReference},
++      {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
++    { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
++      {"height", IntegerReference}, {"x", IntegerReference},
++      {"y", IntegerReference}, {"fuzz", StringReference},
++      {"background", StringReference}, {"gravity", MagickGravityOptions} } },
++    { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference}, {"x", IntegerReference},
++      {"y", IntegerReference}, {"background", StringReference} } },
++    { "ContrastStretch", { {"levels", StringReference},
++      {"black-point", RealReference},{"white-point", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Sans0", },
++    { "Sans1", },
++    { "AdaptiveSharpen", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Transpose", },
++    { "Transverse", },
++    { "AutoOrient", },
++    { "AdaptiveBlur", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Sketch", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"angle", RealReference} } },
++    { "UniqueColors", },
++    { "AdaptiveResize", { {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"filter", MagickFilterOptions}, {"support", StringReference },
++      {"blur", RealReference } } },
++    { "ClipMask", { {"mask", ImageReference} } },
++    { "LinearStretch", { {"levels", StringReference},
++      {"black-point", RealReference},{"white-point", RealReference} } },
++    { "Recolor", { {"matrix", ArrayReference} } },
++    { "Mask", { {"mask", ImageReference} } },
++    { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
++      {"font", StringReference}, {"stroke", StringReference},
++      {"fill", StringReference}, {"strokewidth", RealReference},
++      {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
++      {"background", StringReference} } },
++    { "FloodfillPaint", { {"geometry", StringReference},
++      {"x", IntegerReference}, {"y", IntegerReference},
++      {"fill", StringReference}, {"bordercolor", StringReference},
++      {"fuzz", StringReference}, {"channel", MagickChannelOptions},
++      {"invert", MagickBooleanOptions} } },
++    { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
++      {"virtual-pixel", MagickVirtualPixelOptions},
++      {"best-fit", MagickBooleanOptions} } },
++    { "Clut", { {"image", ImageReference},
++      {"channel", MagickChannelOptions} } },
++    { "LiquidRescale", { {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"delta-x", RealReference}, {"rigidity", RealReference } } },
++    { "Encipher", { {"passphrase", StringReference} } },
++    { "Decipher", { {"passphrase", StringReference} } },
++    { "Deskew", { {"geometry", StringReference},
++      {"threshold", StringReference} } },
++    { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
++      {"dither-method", MagickDitherOptions} } },
++    { "SparseColor", { {"points", ArrayReference},
++      {"method", MagickSparseColorOptions},
++      {"virtual-pixel", MagickVirtualPixelOptions},
++      {"channel", MagickChannelOptions} } },
++    { "Function", { {"parameters", ArrayReference},
++      {"function", MagickFunctionOptions},
++      {"virtual-pixel", MagickVirtualPixelOptions} } },
++    { "SelectiveBlur", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
++    { "HaldClut", { {"image", ImageReference},
++      {"channel", MagickChannelOptions} } },
++    { "BlueShift", { {"factor", StringReference} } },
++    { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
++    { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
++    { "ColorDecisionList", {
++      {"color-correction-collection", StringReference} } },
++    { "AutoGamma", { {"channel", MagickChannelOptions} } },
++    { "AutoLevel", { {"channel", MagickChannelOptions} } },
++    { "LevelColors", { {"invert", MagickBooleanOptions},
++      {"black-point", StringReference}, {"white-point", StringReference},
++      {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
++    { "Clamp", { {"channel", MagickChannelOptions} } },
++    { "Filter", { {"kernel", StringReference},
++      {"channel", MagickChannelOptions}, {"bias", StringReference} } },
++    { "BrightnessContrast", { {"levels", StringReference},
++      {"brightness", RealReference},{"contrast", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Morphology", { {"kernel", StringReference},
++      {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
++      {"iterations", IntegerReference} } },
++    { "ColorMatrix", { {"matrix", ArrayReference} } },
++    { "Color", { {"color", StringReference} } },
++    { "Mode", { {"geometry", StringReference},
++      {"width", IntegerReference},{"height", IntegerReference},
++      {"channel", MagickChannelOptions} } },
++    { "Statistic", { {"geometry", StringReference},
++      {"width", IntegerReference},{"height", IntegerReference},
++      {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
++    { "Perceptible", { {"epsilon", RealReference},
++      {"channel", MagickChannelOptions} } },
++    { "Poly", { {"terms", ArrayReference},
++      {"channel", MagickChannelOptions} } },
++    { "Grayscale", { {"method", MagickPixelIntensityOptions} } },
++    { "CannyEdge", { {"geometry", StringReference},
++      {"radius", RealReference}, {"sigma", RealReference},
++      {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
++    { "HoughLine", { {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"threshold", IntegerReference} } },
++    { "MeanShift", { {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"distance", RealReference} } },
++    { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
++      {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
++    { "ConnectedComponents", { {"connectivity", IntegerReference} } },
++    { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
++      {"width", IntegerReference}, {"height", IntegerReference},
++      {"x", IntegerReference}, {"y", IntegerReference},
++      {"gravity", MagickGravityOptions}, {"offset", StringReference},
++      {"dx", IntegerReference}, {"dy", IntegerReference} } },
++    { "WaveletDenoise", {  {"geometry", StringReference},
++      {"threshold", RealReference}, {"softness", RealReference} } },
++  };
++
++static SplayTreeInfo
++  *magick_registry = (SplayTreeInfo *) NULL;
++

++/*
++  Forward declarations.
++*/
++static Image
++  *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
++
++static ssize_t
++  strEQcase(const char *,const char *);
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   C l o n e P a c k a g e I n f o                                           %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
++%  a new one.
++%
++%  The format of the ClonePackageInfo routine is:
++%
++%      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
++%        exception)
++%
++%  A description of each parameter follows:
++%
++%    o info: a structure of type info.
++%
++%    o exception: Return any errors or warnings in this structure.
++%
++*/
++static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
++  ExceptionInfo *exception)
++{
++  struct PackageInfo
++    *clone_info;
++
++  clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
++  if (clone_info == (struct PackageInfo *) NULL)
++    {
++      ThrowPerlException(exception,ResourceLimitError,
++        "UnableToClonePackageInfo",PackageName);
++      return((struct PackageInfo *) NULL);
++    }
++  if (info == (struct PackageInfo *) NULL)
++    {
++      clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
++      return(clone_info);
++    }
++  *clone_info=(*info);
++  clone_info->image_info=CloneImageInfo(info->image_info);
++  return(clone_info);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   c o n s t a n t                                                           %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  constant() returns a double value for the specified name.
++%
++%  The format of the constant routine is:
++%
++%      double constant(char *name,ssize_t sans)
++%
++%  A description of each parameter follows:
++%
++%    o value: Method constant returns a double value for the specified name.
++%
++%    o name: The name of the constant.
++%
++%    o sans: This integer value is not used.
++%
++*/
++static double constant(char *name,ssize_t sans)
++{
++  (void) sans;
++  errno=0;
++  switch (*name)
++  {
++    case 'B':
++    {
++      if (strEQ(name,"BlobError"))
++        return(BlobError);
++      if (strEQ(name,"BlobWarning"))
++        return(BlobWarning);
++      break;
++    }
++    case 'C':
++    {
++      if (strEQ(name,"CacheError"))
++        return(CacheError);
++      if (strEQ(name,"CacheWarning"))
++        return(CacheWarning);
++      if (strEQ(name,"CoderError"))
++        return(CoderError);
++      if (strEQ(name,"CoderWarning"))
++        return(CoderWarning);
++      if (strEQ(name,"ConfigureError"))
++        return(ConfigureError);
++      if (strEQ(name,"ConfigureWarning"))
++        return(ConfigureWarning);
++      if (strEQ(name,"CorruptImageError"))
++        return(CorruptImageError);
++      if (strEQ(name,"CorruptImageWarning"))
++        return(CorruptImageWarning);
++      break;
++    }
++    case 'D':
++    {
++      if (strEQ(name,"DelegateError"))
++        return(DelegateError);
++      if (strEQ(name,"DelegateWarning"))
++        return(DelegateWarning);
++      if (strEQ(name,"DrawError"))
++        return(DrawError);
++      if (strEQ(name,"DrawWarning"))
++        return(DrawWarning);
++      break;
++    }
++    case 'E':
++    {
++      if (strEQ(name,"ErrorException"))
++        return(ErrorException);
++      if (strEQ(name,"ExceptionError"))
++        return(CoderError);
++      if (strEQ(name,"ExceptionWarning"))
++        return(CoderWarning);
++      break;
++    }
++    case 'F':
++    {
++      if (strEQ(name,"FatalErrorException"))
++        return(FatalErrorException);
++      if (strEQ(name,"FileOpenError"))
++        return(FileOpenError);
++      if (strEQ(name,"FileOpenWarning"))
++        return(FileOpenWarning);
++      break;
++    }
++    case 'I':
++    {
++      if (strEQ(name,"ImageError"))
++        return(ImageError);
++      if (strEQ(name,"ImageWarning"))
++        return(ImageWarning);
++      break;
++    }
++    case 'M':
++    {
++      if (strEQ(name,"MaxRGB"))
++        return(QuantumRange);
++      if (strEQ(name,"MissingDelegateError"))
++        return(MissingDelegateError);
++      if (strEQ(name,"MissingDelegateWarning"))
++        return(MissingDelegateWarning);
++      if (strEQ(name,"ModuleError"))
++        return(ModuleError);
++      if (strEQ(name,"ModuleWarning"))
++        return(ModuleWarning);
++      break;
++    }
++    case 'O':
++    {
++      if (strEQ(name,"Opaque"))
++        return(OpaqueOpacity);
++      if (strEQ(name,"OptionError"))
++        return(OptionError);
++      if (strEQ(name,"OptionWarning"))
++        return(OptionWarning);
++      break;
++    }
++    case 'Q':
++    {
++      if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
++        return(MAGICKCORE_QUANTUM_DEPTH);
++      if (strEQ(name,"QuantumDepth"))
++        return(MAGICKCORE_QUANTUM_DEPTH);
++      if (strEQ(name,"QuantumRange"))
++        return(QuantumRange);
++      break;
++    }
++    case 'R':
++    {
++      if (strEQ(name,"ResourceLimitError"))
++        return(ResourceLimitError);
++      if (strEQ(name,"ResourceLimitWarning"))
++        return(ResourceLimitWarning);
++      if (strEQ(name,"RegistryError"))
++        return(RegistryError);
++      if (strEQ(name,"RegistryWarning"))
++        return(RegistryWarning);
++      break;
++    }
++    case 'S':
++    {
++      if (strEQ(name,"StreamError"))
++        return(StreamError);
++      if (strEQ(name,"StreamWarning"))
++        return(StreamWarning);
++      if (strEQ(name,"Success"))
++        return(0);
++      break;
++    }
++    case 'T':
++    {
++      if (strEQ(name,"Transparent"))
++        return(TransparentOpacity);
++      if (strEQ(name,"TypeError"))
++        return(TypeError);
++      if (strEQ(name,"TypeWarning"))
++        return(TypeWarning);
++      break;
++    }
++    case 'W':
++    {
++      if (strEQ(name,"WarningException"))
++        return(WarningException);
++      break;
++    }
++    case 'X':
++    {
++      if (strEQ(name,"XServerError"))
++        return(XServerError);
++      if (strEQ(name,"XServerWarning"))
++        return(XServerWarning);
++      break;
++    }
++  }
++  errno=EINVAL;
++  return(0);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   D e s t r o y P a c k a g e I n f o                                       %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  Method DestroyPackageInfo frees a previously created info structure.
++%
++%  The format of the DestroyPackageInfo routine is:
++%
++%      DestroyPackageInfo(struct PackageInfo *info)
++%
++%  A description of each parameter follows:
++%
++%    o info: a structure of type info.
++%
++*/
++static void DestroyPackageInfo(struct PackageInfo *info)
++{
++  info->image_info=DestroyImageInfo(info->image_info);
++  info=(struct PackageInfo *) RelinquishMagickMemory(info);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   G e t L i s t                                                             %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  Method GetList is recursively called by SetupList to traverse the
++%  Image__Magick reference.  If building an reference_vector (see SetupList),
++%  *current is the current position in *reference_vector and *last is the final
++%  entry in *reference_vector.
++%
++%  The format of the GetList routine is:
++%
++%      GetList(info)
++%
++%  A description of each parameter follows:
++%
++%    o info: a structure of type info.
++%
++*/
++static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
++  ssize_t *current,ssize_t *last,ExceptionInfo *exception)
++{
++  Image
++    *image;
++
++  if (reference == (SV *) NULL)
++    return(NULL);
++  switch (SvTYPE(reference))
++  {
++    case SVt_PVAV:
++    {
++      AV
++        *av;
++
++      Image
++        *head,
++        *previous;
++
++      register ssize_t
++        i;
++
++      ssize_t
++        n;
++
++      /*
++        Array of images.
++      */
++      previous=(Image *) NULL;
++      head=(Image *) NULL;
++      av=(AV *) reference;
++      n=av_len(av);
++      for (i=0; i <= n; i++)
++      {
++        SV
++          **rv;
++
++        rv=av_fetch(av,i,0);
++        if (rv && *rv && sv_isobject(*rv))
++          {
++            image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
++              exception);
++            if (image == (Image *) NULL)
++              continue;
++            if (image == previous)
++              {
++                image=CloneImage(image,0,0,MagickTrue,exception);
++                if (image == (Image *) NULL)
++                  return(NULL);
++              }
++            image->previous=previous;
++            *(previous ? &previous->next : &head)=image;
++            for (previous=image; previous->next; previous=previous->next) ;
++          }
++      }
++      return(head);
++    }
++    case SVt_PVMG:
++    {
++      /*
++        Blessed scalar, one image.
++      */
++      image=INT2PTR(Image *,SvIV(reference));
++      if (image == (Image *) NULL)
++        return(NULL);
++      image->previous=(Image *) NULL;
++      image->next=(Image *) NULL;
++      if (reference_vector)
++        {
++          if (*current == *last)
++            {
++              *last+=256;
++              if (*reference_vector == (SV **) NULL)
++                *reference_vector=(SV **) AcquireQuantumMemory(*last,
++                  sizeof(*reference_vector));
++              else
++                *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
++                  *last,sizeof(*reference_vector));
++            }
++          if (*reference_vector == (SV **) NULL)
++            {
++              ThrowPerlException(exception,ResourceLimitError,
++                "MemoryAllocationFailed",PackageName);
++              return((Image *) NULL);
++            }
++          (*reference_vector)[*current]=reference;
++          (*reference_vector)[++(*current)]=NULL;
++        }
++      return(image);
++    }
++    default:
++      break;
++  }
++  (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
++    (double) SvTYPE(reference));
++  return((Image *) NULL);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   G e t P a c k a g e I n f o                                               %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  Method GetPackageInfo looks up or creates an info structure for the given
++%  Image__Magick reference.  If it does create a new one, the information in
++%  package_info is used to initialize it.
++%
++%  The format of the GetPackageInfo routine is:
++%
++%      struct PackageInfo *GetPackageInfo(void *reference,
++%        struct PackageInfo *package_info,ExceptionInfo *exception)
++%
++%  A description of each parameter follows:
++%
++%    o info: a structure of type info.
++%
++%    o exception: Return any errors or warnings in this structure.
++%
++*/
++static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
++  struct PackageInfo *package_info,ExceptionInfo *exception)
++{
++  char
++    message[MaxTextExtent];
++
++  struct PackageInfo
++    *clone_info;
++
++  SV
++    *sv;
++
++  (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
++    PackageName,XS_VERSION,reference);
++  sv=perl_get_sv(message,(TRUE | 0x02));
++  if (sv == (SV *) NULL)
++    {
++      ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
++        message);
++      return(package_info);
++    }
++  if (SvREFCNT(sv) == 0)
++    (void) SvREFCNT_inc(sv);
++  if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
++    return(clone_info);
++  clone_info=ClonePackageInfo(package_info,exception);
++  sv_setiv(sv,PTR2IV(clone_info));
++  return(clone_info);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   S e t A t t r i b u t e                                                   %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  SetAttribute() sets the attribute to the value in sval.  This can change
++%  either or both of image or info.
++%
++%  The format of the SetAttribute routine is:
++%
++%      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
++%        SV *sval,ExceptionInfo *exception)
++%
++%  A description of each parameter follows:
++%
++%    o list: a list of strings.
++%
++%    o string: a character string.
++%
++*/
++
++static double SiPrefixToDoubleInterval(const char *string,const double interval)
++{
++  char
++    *q;
++
++  double
++    value;
++
++  value=InterpretSiPrefixValue(string,&q);
++  if (*q == '%')
++    value*=interval/100.0;
++  return(value);
++}
++
++static inline double StringToDouble(const char *string,char **sentinal)
++{
++  return(InterpretLocaleValue(string,sentinal));
++}
++
++static double StringToDoubleInterval(const char *string,const double interval)
++{
++  char
++    *q;
++
++  double
++    value;
++
++  value=InterpretLocaleValue(string,&q);
++  if (*q == '%')
++    value*=interval/100.0;
++  return(value);
++}
++
++static inline ssize_t StringToLong(const char *value)
++{
++  return(strtol(value,(char **) NULL,10));
++}
++
++static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
++  const char *attribute,SV *sval,ExceptionInfo *exception)
++{
++  GeometryInfo
++    geometry_info;
++
++  long
++    x,
++    y;
++
++  MagickPixelPacket
++    pixel;
++
++  MagickStatusType
++    flags;
++
++  PixelPacket
++    *color,
++    target_color;
++
++  ssize_t
++    sp;
++
++  switch (*attribute)
++  {
++    case 'A':
++    case 'a':
++    {
++      if (LocaleCompare(attribute,"adjoin") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
++          break;
++        }
++      if (LocaleCompare(attribute,"alpha") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          for ( ; image; image=image->next)
++            (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
++          break;
++        }
++      if (LocaleCompare(attribute,"antialias") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
++          break;
++        }
++      if (LocaleCompare(attribute,"area-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(AreaResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"attenuate") == 0)
++        {
++          if (info)
++            (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"authenticate") == 0)
++        {
++          if (info)
++            (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'B':
++    case 'b':
++    {
++      if (LocaleCompare(attribute,"background") == 0)
++        {
++          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
++          if (info)
++            info->image_info->background_color=target_color;
++          for ( ; image; image=image->next)
++            image->background_color=target_color;
++          break;
++        }
++      if (LocaleCompare(attribute,"bias") == 0)
++        {
++          for ( ; image; image=image->next)
++            image->bias=StringToDoubleInterval(SvPV(sval,na),(double)
++              QuantumRange+1.0);
++          break;
++        }
++      if (LocaleCompare(attribute,"blue-primary") == 0)
++        {
++          for ( ; image; image=image->next)
++          {
++            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++            image->chromaticity.blue_primary.x=geometry_info.rho;
++            image->chromaticity.blue_primary.y=geometry_info.sigma;
++            if ((flags & SigmaValue) == 0)
++              image->chromaticity.blue_primary.y=
++                image->chromaticity.blue_primary.x;
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"bordercolor") == 0)
++        {
++          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
++          if (info)
++            info->image_info->border_color=target_color;
++          for ( ; image; image=image->next)
++            image->border_color=target_color;
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'C':
++    case 'c':
++    {
++      if (LocaleCompare(attribute,"cache-threshold") == 0)
++        {
++          (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
++            SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
++          (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
++            (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
++          break;
++        }
++      if (LocaleCompare(attribute,"clip-mask") == 0)
++        {
++          Image
++            *clip_mask;
++
++          clip_mask=(Image *) NULL;
++          if (SvPOK(sval))
++            clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
++          for ( ; image; image=image->next)
++            SetImageClipMask(image,clip_mask);
++          break;
++        }
++      if (LocaleNCompare(attribute,"colormap",8) == 0)
++        {
++          for ( ; image; image=image->next)
++          {
++            int
++              items;
++
++            long
++              i;
++
++            if (image->storage_class == DirectClass)
++              continue;
++            i=0;
++            items=sscanf(attribute,"%*[^[][%ld",&i);
++            (void) items;
++            if (i > (ssize_t) image->colors)
++              i%=image->colors;
++            if ((strchr(SvPV(sval,na),',') == 0) ||
++                (strchr(SvPV(sval,na),')') != 0))
++              QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
++            else
++              {
++                color=image->colormap+i;
++                pixel.red=color->red;
++                pixel.green=color->green;
++                pixel.blue=color->blue;
++                flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++                pixel.red=geometry_info.rho;
++                pixel.green=geometry_info.sigma;
++                pixel.blue=geometry_info.xi;
++                color->red=ClampToQuantum(pixel.red);
++                color->green=ClampToQuantum(pixel.green);
++                color->blue=ClampToQuantum(pixel.blue);
++              }
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"colorspace") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
++                SvPV(sval,na));
++              break;
++            }
++          for ( ; image; image=image->next)
++            (void) TransformImageColorspace(image,(ColorspaceType) sp);
++          break;
++        }
++      if (LocaleCompare(attribute,"comment") == 0)
++        {
++          for ( ; image; image=image->next)
++            (void) SetImageProperty(image,"Comment",InterpretImageProperties(
++              info ? info->image_info : (ImageInfo *) NULL,image,
++              SvPV(sval,na)));
++          break;
++        }
++      if (LocaleCompare(attribute,"compression") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedImageCompression",SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->compression=(CompressionType) sp;
++          for ( ; image; image=image->next)
++            image->compression=(CompressionType) sp;
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'D':
++    case 'd':
++    {
++      if (LocaleCompare(attribute,"debug") == 0)
++        {
++          SetLogEventMask(SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"delay") == 0)
++        {
++          flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++          for ( ; image; image=image->next)
++          {
++            image->delay=(size_t) floor(geometry_info.rho+0.5);
++            if ((flags & SigmaValue) != 0)
++              image->ticks_per_second=(ssize_t)
++                floor(geometry_info.sigma+0.5);
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"disk-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(DiskResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"density") == 0)
++        {
++          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
++            {
++              ThrowPerlException(exception,OptionError,"MissingGeometry",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            (void) CloneString(&info->image_info->density,SvPV(sval,na));
++          for ( ; image; image=image->next)
++          {
++            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++            image->x_resolution=geometry_info.rho;
++            image->y_resolution=geometry_info.sigma;
++            if ((flags & SigmaValue) == 0)
++              image->y_resolution=image->x_resolution;
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"depth") == 0)
++        {
++          if (info)
++            info->image_info->depth=SvIV(sval);
++          for ( ; image; image=image->next)
++            (void) SetImageDepth(image,SvIV(sval));
++          break;
++        }
++      if (LocaleCompare(attribute,"dispose") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedDisposeMethod",SvPV(sval,na));
++              break;
++            }
++          for ( ; image; image=image->next)
++            image->dispose=(DisposeType) sp;
++          break;
++        }
++      if (LocaleCompare(attribute,"dither") == 0)
++        {
++          if (info)
++            {
++              sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
++                MagickFalse,SvPV(sval,na)) : SvIV(sval);
++              if (sp < 0)
++                {
++                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                    SvPV(sval,na));
++                  break;
++                }
++              info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
++            }
++          break;
++        }
++      if (LocaleCompare(attribute,"display") == 0)
++        {
++          display:
++          if (info)
++            (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'E':
++    case 'e':
++    {
++      if (LocaleCompare(attribute,"endian") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->endian=(EndianType) sp;
++          for ( ; image; image=image->next)
++            image->endian=(EndianType) sp;
++          break;
++        }
++      if (LocaleCompare(attribute,"extract") == 0)
++        {
++          /*
++            Set image extract geometry.
++          */
++          (void) CloneString(&info->image_info->extract,SvPV(sval,na));
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'F':
++    case 'f':
++    {
++      if (LocaleCompare(attribute,"filename") == 0)
++        {
++          if (info)
++            (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
++              MaxTextExtent);
++          for ( ; image; image=image->next)
++            (void) CopyMagickString(image->filename,SvPV(sval,na),
++              MaxTextExtent);
++          break;
++        }
++      if (LocaleCompare(attribute,"file") == 0)
++        {
++          FILE
++            *file;
++
++          PerlIO
++            *io_info;
++
++          if (info == (struct PackageInfo *) NULL)
++            break;
++          io_info=IoIFP(sv_2io(sval));
++          if (io_info == (PerlIO *) NULL)
++            {
++              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
++                PackageName);
++              break;
++            }
++          file=PerlIO_findFILE(io_info);
++          if (file == (FILE *) NULL)
++            {
++              ThrowPerlException(exception,BlobError,"UnableToOpenFile",
++                PackageName);
++              break;
++            }
++          SetImageInfoFile(info->image_info,file);
++          break;
++        }
++      if (LocaleCompare(attribute,"fill") == 0)
++        {
++          if (info)
++            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"font") == 0)
++        {
++          if (info)
++            (void) CloneString(&info->image_info->font,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"foreground") == 0)
++        break;
++      if (LocaleCompare(attribute,"fuzz") == 0)
++        {
++          if (info)
++            info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
++              QuantumRange+1.0);
++          for ( ; image; image=image->next)
++            image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
++              QuantumRange+1.0);
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'G':
++    case 'g':
++    {
++      if (LocaleCompare(attribute,"gamma") == 0)
++        {
++          for ( ; image; image=image->next)
++            image->gamma=SvNV(sval);
++          break;
++        }
++      if (LocaleCompare(attribute,"gravity") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedGravityType",SvPV(sval,na));
++              break;
++            }
++          if (info)
++            SetImageOption(info->image_info,attribute,SvPV(sval,na));
++          for ( ; image; image=image->next)
++            image->gravity=(GravityType) sp;
++          break;
++        }
++      if (LocaleCompare(attribute,"green-primary") == 0)
++        {
++          for ( ; image; image=image->next)
++          {
++            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++            image->chromaticity.green_primary.x=geometry_info.rho;
++            image->chromaticity.green_primary.y=geometry_info.sigma;
++            if ((flags & SigmaValue) == 0)
++              image->chromaticity.green_primary.y=
++                image->chromaticity.green_primary.x;
++          }
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'I':
++    case 'i':
++    {
++      if (LocaleNCompare(attribute,"index",5) == 0)
++        {
++          IndexPacket
++            *indexes;
++
++          int
++            items;
++
++          long
++            index;
++
++          register PixelPacket
++            *p;
++
++          CacheView
++            *image_view;
++
++          for ( ; image; image=image->next)
++          {
++            if (image->storage_class != PseudoClass)
++              continue;
++            x=0;
++            y=0;
++            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
++            (void) items;
++            image_view=AcquireAuthenticCacheView(image,exception);
++            p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
++            if (p != (PixelPacket *) NULL)
++              {
++                indexes=GetCacheViewAuthenticIndexQueue(image_view);
++                items=sscanf(SvPV(sval,na),"%ld",&index);
++                if ((index >= 0) && (index < (ssize_t) image->colors))
++                  SetPixelIndex(indexes,index);
++                (void) SyncCacheViewAuthenticPixels(image_view,exception);
++              }
++            image_view=DestroyCacheView(image_view);
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"iterations") == 0)
++        {
++  iterations:
++          for ( ; image; image=image->next)
++            image->iterations=SvIV(sval);
++          break;
++        }
++      if (LocaleCompare(attribute,"interlace") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedInterlaceType",SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->interlace=(InterlaceType) sp;
++          for ( ; image; image=image->next)
++            image->interlace=(InterlaceType) sp;
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'L':
++    case 'l':
++    {
++      if (LocaleCompare(attribute,"label") == 0)
++        {
++          for ( ; image; image=image->next)
++            (void) SetImageProperty(image,"label",InterpretImageProperties(
++              info ? info->image_info : (ImageInfo *) NULL,image,
++              SvPV(sval,na)));
++          break;
++        }
++      if (LocaleCompare(attribute,"loop") == 0)
++        goto iterations;
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'M':
++    case 'm':
++    {
++      if (LocaleCompare(attribute,"magick") == 0)
++        {
++          if (info)
++            (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
++              "%s:",SvPV(sval,na));
++          for ( ; image; image=image->next)
++            (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
++          break;
++        }
++      if (LocaleCompare(attribute,"map-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(MapResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"mask") == 0)
++        {
++          Image
++            *mask;
++
++          mask=(Image *) NULL;
++          if (SvPOK(sval))
++            mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
++          for ( ; image; image=image->next)
++            SetImageMask(image,mask);
++          break;
++        }
++      if (LocaleCompare(attribute,"mattecolor") == 0)
++        {
++          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
++          if (info)
++            info->image_info->matte_color=target_color;
++          for ( ; image; image=image->next)
++            image->matte_color=target_color;
++          break;
++        }
++      if (LocaleCompare(attribute,"matte") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          for ( ; image; image=image->next)
++            image->matte=sp != 0 ? MagickTrue : MagickFalse;
++          break;
++        }
++      if (LocaleCompare(attribute,"memory-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(MemoryResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"monochrome") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
++          for ( ; image; image=image->next)
++            (void) SetImageType(image,BilevelType);
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'O':
++    case 'o':
++    {
++      if (LocaleCompare(attribute,"option") == 0)
++        {
++          if (info)
++            DefineImageOption(info->image_info,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"orientation") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedOrientationType",SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->orientation=(OrientationType) sp;
++          for ( ; image; image=image->next)
++            image->orientation=(OrientationType) sp;
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'P':
++    case 'p':
++    {
++      if (LocaleCompare(attribute,"page") == 0)
++        {
++          char
++            *geometry;
++
++          geometry=GetPageGeometry(SvPV(sval,na));
++          if (info)
++            (void) CloneString(&info->image_info->page,geometry);
++          for ( ; image; image=image->next)
++            (void) ParsePageGeometry(image,geometry,&image->page,exception);
++          geometry=(char *) RelinquishMagickMemory(geometry);
++          break;
++        }
++      if (LocaleCompare(attribute,"pen") == 0)
++        {
++          if (info)
++            (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
++          break;
++        }
++      if (LocaleNCompare(attribute,"pixel",5) == 0)
++        {
++          int
++            items;
++
++          MagickPixelPacket
++            pixel;
++
++          register IndexPacket
++            *indexes;
++
++          register PixelPacket
++            *q;
++
++          CacheView
++            *image_view;
++
++          for ( ; image; image=image->next)
++          {
++            if (SetImageStorageClass(image,DirectClass) == MagickFalse)
++              break;
++            x=0;
++            y=0;
++            items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
++            (void) items;
++            image_view=AcquireAuthenticCacheView(image,exception);
++            q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
++            indexes=GetCacheViewAuthenticIndexQueue(image_view);
++            if (q != (PixelPacket *) NULL)
++              {
++                if ((strchr(SvPV(sval,na),',') == 0) ||
++                    (strchr(SvPV(sval,na),')') != 0))
++                  QueryMagickColor(SvPV(sval,na),&pixel,exception);
++                else
++                  {
++                    GetMagickPixelPacket(image,&pixel);
++                    flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++                    pixel.red=geometry_info.rho;
++                    if ((flags & SigmaValue) != 0)
++                      pixel.green=geometry_info.sigma;
++                    if ((flags & XiValue) != 0)
++                      pixel.blue=geometry_info.xi;
++                    if ((flags & PsiValue) != 0)
++                      pixel.opacity=geometry_info.psi;
++                    if ((flags & ChiValue) != 0)
++                      pixel.index=geometry_info.chi;
++                  }
++                SetPixelRed(q,ClampToQuantum(pixel.red));
++                SetPixelGreen(q,ClampToQuantum(pixel.green));
++                SetPixelBlue(q,ClampToQuantum(pixel.blue));
++                SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
++                if (((image->colorspace == CMYKColorspace) ||
++                     (image->storage_class == PseudoClass)) &&
++                    (indexes != (IndexPacket *) NULL))
++                  SetPixelIndex(indexes,ClampToQuantum(pixel.index));
++                (void) SyncCacheViewAuthenticPixels(image_view,exception);
++              }
++            image_view=DestroyCacheView(image_view);
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"pointsize") == 0)
++        {
++          if (info)
++            {
++              (void) ParseGeometry(SvPV(sval,na),&geometry_info);
++              info->image_info->pointsize=geometry_info.rho;
++            }
++          break;
++        }
++      if (LocaleCompare(attribute,"preview") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->preview_type=(PreviewType) sp;
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'Q':
++    case 'q':
++    {
++      if (LocaleCompare(attribute,"quality") == 0)
++        {
++          if (info)
++            info->image_info->quality=SvIV(sval);
++          for ( ; image; image=image->next)
++            image->quality=SvIV(sval);
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'R':
++    case 'r':
++    {
++      if (LocaleCompare(attribute,"red-primary") == 0)
++        {
++          for ( ; image; image=image->next)
++          {
++            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++            image->chromaticity.red_primary.x=geometry_info.rho;
++            image->chromaticity.red_primary.y=geometry_info.sigma;
++            if ((flags & SigmaValue) == 0)
++              image->chromaticity.red_primary.y=
++                image->chromaticity.red_primary.x;
++          }
++          break;
++        }
++      if (LocaleCompare(attribute,"render") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
++                SvPV(sval,na));
++              break;
++            }
++         for ( ; image; image=image->next)
++           image->rendering_intent=(RenderingIntent) sp;
++         break;
++       }
++      if (LocaleCompare(attribute,"repage") == 0)
++        {
++          RectangleInfo
++            geometry;
++
++          for ( ; image; image=image->next)
++          {
++            flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
++            if ((flags & WidthValue) != 0)
++              {
++                if ((flags & HeightValue) == 0)
++                  geometry.height=geometry.width;
++                image->page.width=geometry.width;
++                image->page.height=geometry.height;
++              }
++            if ((flags & AspectValue) != 0)
++              {
++                if ((flags & XValue) != 0)
++                  image->page.x+=geometry.x;
++                if ((flags & YValue) != 0)
++                  image->page.y+=geometry.y;
++              }
++            else
++              {
++                if ((flags & XValue) != 0)
++                  {
++                    image->page.x=geometry.x;
++                    if (((flags & WidthValue) != 0) && (geometry.x > 0))
++                      image->page.width=image->columns+geometry.x;
++                  }
++                if ((flags & YValue) != 0)
++                  {
++                    image->page.y=geometry.y;
++                    if (((flags & HeightValue) != 0) && (geometry.y > 0))
++                      image->page.height=image->rows+geometry.y;
++                  }
++              }
++          }
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'S':
++    case 's':
++    {
++      if (LocaleCompare(attribute,"sampling-factor") == 0)
++        {
++          if (IsGeometry(SvPV(sval,na)) == MagickFalse)
++            {
++              ThrowPerlException(exception,OptionError,"MissingGeometry",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            (void) CloneString(&info->image_info->sampling_factor,
++              SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"scene") == 0)
++        {
++          for ( ; image; image=image->next)
++            image->scene=SvIV(sval);
++          break;
++        }
++      if (LocaleCompare(attribute,"subimage") == 0)
++        {
++          if (info)
++            info->image_info->subimage=SvIV(sval);
++          break;
++        }
++      if (LocaleCompare(attribute,"subrange") == 0)
++        {
++          if (info)
++            info->image_info->subrange=SvIV(sval);
++          break;
++        }
++      if (LocaleCompare(attribute,"server") == 0)
++        goto display;
++      if (LocaleCompare(attribute,"size") == 0)
++        {
++          if (info)
++            {
++              if (IsGeometry(SvPV(sval,na)) == MagickFalse)
++                {
++                  ThrowPerlException(exception,OptionError,"MissingGeometry",
++                    SvPV(sval,na));
++                  break;
++                }
++              (void) CloneString(&info->image_info->size,SvPV(sval,na));
++            }
++          break;
++        }
++      if (LocaleCompare(attribute,"stroke") == 0)
++        {
++          if (info)
++            (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'T':
++    case 't':
++    {
++      if (LocaleCompare(attribute,"texture") == 0)
++        {
++          if (info)
++            (void) CloneString(&info->image_info->texture,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"thread-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(ThreadResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"tile") == 0)
++        {
++          if (info)
++            (void) CloneString(&info->image_info->tile,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"tile-offset") == 0)
++        {
++          char
++            *geometry;
++
++          geometry=GetPageGeometry(SvPV(sval,na));
++          if (info)
++            (void) CloneString(&info->image_info->page,geometry);
++          for ( ; image; image=image->next)
++            (void) ParsePageGeometry(image,geometry,&image->tile_offset,
++              exception);
++          geometry=(char *) RelinquishMagickMemory(geometry);
++          break;
++        }
++      if (LocaleCompare(attribute,"time-limit") == 0)
++        {
++          MagickSizeType
++            limit;
++
++          limit=MagickResourceInfinity;
++          if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
++            limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
++              100.0);
++          (void) SetMagickResourceLimit(TimeResource,limit);
++          break;
++        }
++      if (LocaleCompare(attribute,"transparent-color") == 0)
++        {
++          (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
++          if (info)
++            info->image_info->transparent_color=target_color;
++          for ( ; image; image=image->next)
++            image->transparent_color=target_color;
++          break;
++        }
++      if (LocaleCompare(attribute,"type") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->type=(ImageType) sp;
++          for ( ; image; image=image->next)
++            SetImageType(image,(ImageType) sp);
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'U':
++    case 'u':
++    {
++      if (LocaleCompare(attribute,"units") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->units=(ResolutionType) sp;
++          for ( ; image; image=image->next)
++          {
++            ResolutionType
++              units;
++
++            units=(ResolutionType) sp;
++            if (image->units != units)
++              switch (image->units)
++              {
++                case UndefinedResolution:
++                case PixelsPerInchResolution:
++                {
++                  if (units == PixelsPerCentimeterResolution)
++                    {
++                      image->x_resolution*=2.54;
++                      image->y_resolution*=2.54;
++                    }
++                  break;
++                }
++                case PixelsPerCentimeterResolution:
++                {
++                  if (units == PixelsPerInchResolution)
++                    {
++                      image->x_resolution/=2.54;
++                      image->y_resolution/=2.54;
++                    }
++                  break;
++                }
++              }
++            image->units=units;
++          }
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'V':
++    case 'v':
++    {
++      if (LocaleCompare(attribute,"verbose") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
++            SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
++          break;
++        }
++      if (LocaleCompare(attribute,"view") == 0)
++        {
++          if (info)
++            (void) CloneString(&info->image_info->view,SvPV(sval,na));
++          break;
++        }
++      if (LocaleCompare(attribute,"virtual-pixel") == 0)
++        {
++          sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
++            MagickFalse,SvPV(sval,na)) : SvIV(sval);
++          if (sp < 0)
++            {
++              ThrowPerlException(exception,OptionError,
++                "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
++              break;
++            }
++          if (info)
++            info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
++          for ( ; image; image=image->next)
++            SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    case 'W':
++    case 'w':
++    {
++      if (LocaleCompare(attribute,"white-point") == 0)
++        {
++          for ( ; image; image=image->next)
++          {
++            flags=ParseGeometry(SvPV(sval,na),&geometry_info);
++            image->chromaticity.white_point.x=geometry_info.rho;
++            image->chromaticity.white_point.y=geometry_info.sigma;
++            if ((flags & SigmaValue) == 0)
++              image->chromaticity.white_point.y=
++                image->chromaticity.white_point.x;
++          }
++          break;
++        }
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++    default:
++    {
++      if (info)
++        SetImageOption(info->image_info,attribute,SvPV(sval,na));
++      for ( ; image; image=image->next)
++        SetImageProperty(image,attribute,SvPV(sval,na));
++      break;
++    }
++  }
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   S e t u p L i s t                                                         %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  Method SetupList returns the list of all the images linked by their
++%  image->next and image->previous link lists for use with ImageMagick.  If
++%  info is non-NULL, an info structure is returned in *info.  If
++%  reference_vector is non-NULL,an array of SV* are returned in
++%  *reference_vector.  Reference_vector is used when the images are going to be
++%  replaced with new Image*'s.
++%
++%  The format of the SetupList routine is:
++%
++%      Image *SetupList(SV *reference,struct PackageInfo **info,
++%        SV ***reference_vector,ExceptionInfo *exception)
++%
++%  A description of each parameter follows:
++%
++%    o list: a list of strings.
++%
++%    o string: a character string.
++%
++%    o exception: Return any errors or warnings in this structure.
++%
++*/
++static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
++  SV ***reference_vector,ExceptionInfo *exception)
++{
++  Image
++    *image;
++
++  ssize_t
++    current,
++    last;
++
++  if (reference_vector)
++    *reference_vector=NULL;
++  if (info)
++    *info=NULL;
++  current=0;
++  last=0;
++  image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
++  if (info && (SvTYPE(reference) == SVt_PVAV))
++    *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
++      exception);
++  return(image);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   s t r E Q c a s e                                                         %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%  strEQcase() compares two strings and returns 0 if they are the
++%  same or if the second string runs out first.  The comparison is case
++%  insensitive.
++%
++%  The format of the strEQcase routine is:
++%
++%      ssize_t strEQcase(const char *p,const char *q)
++%
++%  A description of each parameter follows:
++%
++%    o p: a character string.
++%
++%    o q: a character string.
++%
++%
++*/
++static ssize_t strEQcase(const char *p,const char *q)
++{
++  char
++    c;
++
++  register ssize_t
++    i;
++
++  for (i=0 ; (c=(*q)) != 0; i++)
++  {
++    if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
++        (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
++      return(0);
++    p++;
++    q++;
++  }
++  return(((*q == 0) && (*p == 0)) ? i : 0);
++}
++

++/*
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%   I m a g e : : M a g i c k                                                 %
++%                                                                             %
++%                                                                             %
++%                                                                             %
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%
++%
++*/
++MODULE = Image::Magick PACKAGE = Image::Magick
++
++PROTOTYPES: ENABLE
++
++BOOT:
++  MagickCoreGenesis("PerlMagick",MagickFalse);
++  SetWarningHandler(NULL);
++  SetErrorHandler(NULL);
++  magick_registry=NewSplayTree((int (*)(const void *,const void *))
++    NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
++
++void
++UNLOAD()
++  PPCODE:
++  {
++    if (magick_registry != (SplayTreeInfo *) NULL)
++      magick_registry=DestroySplayTree(magick_registry);
++    MagickCoreTerminus();
++  }
++
++double
++constant(name,argument)
++  char *name
++  ssize_t argument
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   A n i m a t e                                                             #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Animate(ref,...)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    AnimateImage  = 1
++    animate       = 2
++    animateimage  = 3
++  PPCODE:
++  {
++    ExceptionInfo
++      *exception;
++
++    Image
++      *image;
++
++    register ssize_t
++      i;
++
++    struct PackageInfo
++      *info,
++      *package_info;
++
++    SV
++      *perl_exception,
++      *reference;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    package_info=(struct PackageInfo *) NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    package_info=ClonePackageInfo(info,exception);
++    if (items == 2)
++      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
++    else
++      if (items > 2)
++        for (i=2; i < items; i+=2)
++          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
++            exception);
++    (void) AnimateImages(package_info->image_info,image);
++    (void) CatchImageException(image);
++    InheritException(exception,&image->exception);
++
++  PerlException:
++    if (package_info != (struct PackageInfo *) NULL)
++      DestroyPackageInfo(package_info);
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   A p p e n d                                                               #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Append(ref,...)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    AppendImage  = 1
++    append       = 2
++    appendimage  = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      *attribute;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    register ssize_t
++      i;
++
++    ssize_t
++      stack;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *av_reference,
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    attribute=NULL;
++    av=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    av=newAV();
++    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
++    /*
++      Get options.
++    */
++    stack=MagickTrue;
++    for (i=2; i < items; i+=2)
++    {
++      attribute=(char *) SvPV(ST(i-1),na);
++      switch (*attribute)
++      {
++        case 'S':
++        case 's':
++        {
++          if (LocaleCompare(attribute,"stack") == 0)
++            {
++              stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
++                SvPV(ST(i),na));
++              if (stack < 0)
++                {
++                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                    SvPV(ST(i),na));
++                  return;
++                }
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        default:
++        {
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++      }
++    }
++    image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
++    if (image == (Image *) NULL)
++      goto PerlException;
++    for ( ; image; image=image->next)
++    {
++      AddImageToRegistry(sv,image);
++      rv=newRV(sv);
++      av_push(av,sv_bless(rv,hv));
++      SvREFCNT_dec(sv);
++    }
++    exception=DestroyExceptionInfo(exception);
++    ST(0)=av_reference;
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   A v e r a g e                                                             #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Average(ref)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    AverageImage   = 1
++    average        = 2
++    averageimage   = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      *p;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    image=EvaluateImages(image,MeanEvaluateOperator,exception);
++    if (image == (Image *) NULL)
++      goto PerlException;
++    /*
++      Create blessed Perl array for the returned image.
++    */
++    av=newAV();
++    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    AddImageToRegistry(sv,image);
++    rv=newRV(sv);
++    av_push(av,sv_bless(rv,hv));
++    SvREFCNT_dec(sv);
++    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
++    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
++      "average-%.*s",(int) (MaxTextExtent-9),
++      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
++    (void) CopyMagickString(image->filename,info->image_info->filename,
++      MaxTextExtent);
++    SetImageInfo(info->image_info,0,exception);
++    exception=DestroyExceptionInfo(exception);
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   B l o b T o I m a g e                                                     #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++BlobToImage(ref,...)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    BlobToImage  = 1
++    blobtoimage  = 2
++    blobto       = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      **keep,
++      **list;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    register char
++      **p;
++
++    register ssize_t
++      i;
++
++    ssize_t
++      ac,
++      n,
++      number_images;
++
++    STRLEN
++      *length;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    number_images=0;
++    ac=(items < 2) ? 1 : items-1;
++    length=(STRLEN *) NULL;
++    list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
++    if (list == (char **) NULL)
++      {
++        ThrowPerlException(exception,ResourceLimitError,
++          "MemoryAllocationFailed",PackageName);
++        goto PerlException;
++      }
++    length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
++    if (length == (STRLEN *) NULL)
++      {
++        ThrowPerlException(exception,ResourceLimitError,
++          "MemoryAllocationFailed",PackageName);
++        goto PerlException;
++      }
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    if (SvTYPE(reference) != SVt_PVAV)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    av=(AV *) reference;
++    info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
++      exception);
++    n=1;
++    if (items <= 1)
++      {
++        ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
++        goto PerlException;
++      }
++    for (n=0, i=0; i < ac; i++)
++    {
++      list[n]=(char *) (SvPV(ST(i+1),length[n]));
++      if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
++        {
++          list[n]=(char *) (SvPV(ST(i+2),length[n]));
++          continue;
++        }
++      n++;
++    }
++    list[n]=(char *) NULL;
++    keep=list;
++    for (i=number_images=0; i < n; i++)
++    {
++      image=BlobToImage(info->image_info,list[i],length[i],exception);
++      if (image == (Image *) NULL)
++        break;
++      for ( ; image; image=image->next)
++      {
++        AddImageToRegistry(sv,image);
++        rv=newRV(sv);
++        av_push(av,sv_bless(rv,hv));
++        SvREFCNT_dec(sv);
++        number_images++;
++      }
++    }
++    /*
++      Free resources.
++    */
++    for (i=0; i < n; i++)
++      if (list[i] != (char *) NULL)
++        for (p=keep; list[i] != *p++; )
++          if (*p == (char *) NULL)
++            {
++              list[i]=(char *) RelinquishMagickMemory(list[i]);
++              break;
++            }
++
++  PerlException:
++    if (list)
++      list=(char **) RelinquishMagickMemory(list);
++    if (length)
++      length=(STRLEN *) RelinquishMagickMemory(length);
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) number_images);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C l o n e                                                                 #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Clone(ref)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    CopyImage   = 1
++    copy        = 2
++    copyimage   = 3
++    CloneImage  = 4
++    clone       = 5
++    cloneimage  = 6
++    Clone       = 7
++  PPCODE:
++  {
++    AV
++      *av;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *clone,
++      *image;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    /*
++      Create blessed Perl array for the returned image.
++    */
++    av=newAV();
++    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    for ( ; image; image=image->next)
++    {
++      clone=CloneImage(image,0,0,MagickTrue,exception);
++      if (clone == (Image *) NULL)
++        break;
++      AddImageToRegistry(sv,clone);
++      rv=newRV(sv);
++      av_push(av,sv_bless(rv,hv));
++      SvREFCNT_dec(sv);
++    }
++    exception=DestroyExceptionInfo(exception);
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C L O N E                                                                 #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++CLONE(ref,...)
++  SV *ref;
++  CODE:
++  {
++    PERL_UNUSED_VAR(ref);
++    if (magick_registry != (SplayTreeInfo *) NULL)
++      {
++        register Image
++          *p;
++
++        ResetSplayTreeIterator(magick_registry);
++        p=(Image *) GetNextKeyInSplayTree(magick_registry);
++        while (p != (Image *) NULL)
++        {
++          ReferenceImage(p);
++          p=(Image *) GetNextKeyInSplayTree(magick_registry);
++        }
++      }
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C o a l e s c e                                                           #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Coalesce(ref)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    CoalesceImage   = 1
++    coalesce        = 2
++    coalesceimage   = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *av_reference,
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    av=newAV();
++    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    image=CoalesceImages(image,exception);
++    if (image == (Image *) NULL)
++      goto PerlException;
++    for ( ; image; image=image->next)
++    {
++      AddImageToRegistry(sv,image);
++      rv=newRV(sv);
++      av_push(av,sv_bless(rv,hv));
++      SvREFCNT_dec(sv);
++    }
++    exception=DestroyExceptionInfo(exception);
++    ST(0)=av_reference;
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C o m p a r e                                                             #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Compare(ref,...)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    CompareImage = 1
++    compare      = 2
++    compareimage = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      *attribute;
++
++    ChannelType
++      channel;
++
++    double
++      distortion;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *difference_image,
++      *image,
++      *reconstruct_image;
++
++    MetricType
++      metric;
++
++    register ssize_t
++      i;
++
++    ssize_t
++      option;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *av_reference,
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    av=NULL;
++    attribute=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    av=newAV();
++    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
++    /*
++      Get attribute.
++    */
++    channel=DefaultChannels;
++    reconstruct_image=image;
++    metric=RootMeanSquaredErrorMetric;
++    for (i=2; i < items; i+=2)
++    {
++      attribute=(char *) SvPV(ST(i-1),na);
++      switch (*attribute)
++      {
++        case 'C':
++        case 'c':
++        {
++          if (LocaleCompare(attribute,"channel") == 0)
++            {
++              ssize_t
++                option;
++
++              option=ParseChannelOption(SvPV(ST(i),na));
++              if (option < 0)
++                {
++                  ThrowPerlException(exception,OptionError,
++                    "UnrecognizedType",SvPV(ST(i),na));
++                  return;
++                }
++              channel=(ChannelType) option;
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        case 'F':
++        case 'f':
++        {
++          if (LocaleCompare(attribute,"fuzz") == 0)
++            {
++              image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        case 'I':
++        case 'i':
++        {
++          if (LocaleCompare(attribute,"image") == 0)
++            {
++              reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
++                (struct PackageInfo **) NULL,(SV ***) NULL,exception);
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        case 'M':
++        case 'm':
++        {
++          if (LocaleCompare(attribute,"metric") == 0)
++            {
++              option=ParseCommandOption(MagickMetricOptions,MagickFalse,
++                SvPV(ST(i),na));
++              if (option < 0)
++                {
++                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                    SvPV(ST(i),na));
++                  break;
++                }
++              metric=(MetricType) option;
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        default:
++        {
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++      }
++    }
++    difference_image=CompareImageChannels(image,reconstruct_image,channel,
++      metric,&distortion,exception);
++    if (difference_image != (Image *) NULL)
++      {
++        difference_image->error.mean_error_per_pixel=distortion;
++        AddImageToRegistry(sv,difference_image);
++        rv=newRV(sv);
++        av_push(av,sv_bless(rv,hv));
++        SvREFCNT_dec(sv);
++      }
++    exception=DestroyExceptionInfo(exception);
++    ST(0)=av_reference;
++    SvREFCNT_dec(perl_exception);  /* can't return warning messages */
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C o m p a r e L a y e r s                                                 #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++CompareLayers(ref)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    CompareImageLayers   = 1
++    comparelayers        = 2
++    compareimagelayers   = 3
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      *attribute;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    ImageLayerMethod
++      method;
++
++    register ssize_t
++      i;
++
++    ssize_t
++      option;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *av_reference,
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    av=newAV();
++    av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    method=CompareAnyLayer;
++    for (i=2; i < items; i+=2)
++    {
++      attribute=(char *) SvPV(ST(i-1),na);
++      switch (*attribute)
++      {
++        case 'M':
++        case 'm':
++        {
++          if (LocaleCompare(attribute,"method") == 0)
++            {
++              option=ParseCommandOption(MagickLayerOptions,MagickFalse,
++                SvPV(ST(i),na));
++              if (option < 0)
++                {
++                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                    SvPV(ST(i),na));
++                  break;
++                }
++               method=(ImageLayerMethod) option;
++              break;
++            }
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++        default:
++        {
++          ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++            attribute);
++          break;
++        }
++      }
++    }
++    image=CompareImageLayers(image,method,exception);
++    if (image == (Image *) NULL)
++      goto PerlException;
++    for ( ; image; image=image->next)
++    {
++      AddImageToRegistry(sv,image);
++      rv=newRV(sv);
++      av_push(av,sv_bless(rv,hv));
++      SvREFCNT_dec(sv);
++    }
++    exception=DestroyExceptionInfo(exception);
++    ST(0)=av_reference;
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   C o m p l e x I m a g e s                                                 #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++ComplexImages(ref)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    ComplexImages   = 1
++    compleximages   = 2
++  PPCODE:
++  {
++    AV
++      *av;
++
++    char
++      *attribute,
++      *p;
++
++    ExceptionInfo
++      *exception;
++
++    HV
++      *hv;
++
++    Image
++      *image;
++
++    ComplexOperator
++      op;
++
++    register ssize_t
++      i;
++
++    struct PackageInfo
++      *info;
++
++    SV
++      *perl_exception,
++      *reference,
++      *rv,
++      *sv;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    sv=NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    hv=SvSTASH(reference);
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    op=UndefinedComplexOperator;
++    if (items == 2)
++      {
++        ssize_t
++          in;
++
++        in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
++          SvPV(ST(1),na));
++        if (in < 0)
++          {
++            ThrowPerlException(exception,OptionError,"UnrecognizedType",
++              SvPV(ST(1),na));
++            return;
++          }
++        op=(ComplexOperator) in;
++      }
++    else
++      for (i=2; i < items; i+=2)
++      {
++        attribute=(char *) SvPV(ST(i-1),na);
++        switch (*attribute)
++        {
++          case 'O':
++          case 'o':
++          {
++            if (LocaleCompare(attribute,"operator") == 0)
++              {
++                ssize_t
++                  in;
++
++                in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
++                  MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
++                if (in < 0)
++                  {
++                    ThrowPerlException(exception,OptionError,"UnrecognizedType",
++                      SvPV(ST(i),na));
++                    return;
++                  }
++                op=(ComplexOperator) in;
++                break;
++              }
++            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++              attribute);
++            break;
++          }
++          default:
++          {
++            ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
++              attribute);
++            break;
++          }
++        }
++      }
++    image=ComplexImages(image,op,exception);
++    if (image == (Image *) NULL)
++      goto PerlException;
++    /*
++      Create blessed Perl array for the returned image.
++    */
++    av=newAV();
++    ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
++    SvREFCNT_dec(av);
++    AddImageToRegistry(sv,image);
++    rv=newRV(sv);
++    av_push(av,sv_bless(rv,hv));
++    SvREFCNT_dec(sv);
++    info=GetPackageInfo(aTHX_ (void *) av,info,exception);
++    (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
++      "complex-%.*s",(int) (MaxTextExtent-9),
++      ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
++    (void) CopyMagickString(image->filename,info->image_info->filename,
++      MaxTextExtent);
++    SetImageInfo(info->image_info,0,exception);
++    exception=DestroyExceptionInfo(exception);
++    SvREFCNT_dec(perl_exception);
++    XSRETURN(1);
++
++  PerlException:
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   D e s t r o y                                                             #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++DESTROY(ref)
++  Image::Magick ref = NO_INIT
++  PPCODE:
++  {
++    SV
++      *reference;
++
++    PERL_UNUSED_VAR(ref);
++    if (sv_isobject(ST(0)) == 0)
++      croak("ReferenceIsNotMyType");
++    reference=SvRV(ST(0));
++    switch (SvTYPE(reference))
++    {
++      case SVt_PVAV:
++      {
++        char
++          message[MaxTextExtent];
++
++        const SV
++          *key;
++
++        HV
++          *hv;
++
++        GV
++          **gvp;
++
++        struct PackageInfo
++          *info;
++
++        SV
++          *sv;
++
++        /*
++          Array (AV *) reference
++        */
++        (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
++          XS_VERSION,reference);
++        hv=gv_stashpv(PackageName, FALSE);
++        if (!hv)
++          break;
++        gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
++        if (!gvp)
++          break;
++        sv=GvSV(*gvp);
++        if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
++          {
++            info=INT2PTR(struct PackageInfo *,SvIV(sv));
++            DestroyPackageInfo(info);
++          }
++        key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
++        (void) key;
++        break;
++      }
++      case SVt_PVMG:
++      {
++        Image
++          *image;
++
++        /*
++          Blessed scalar = (Image *) SvIV(reference)
++        */
++        image=INT2PTR(Image *,SvIV(reference));
++        if (image != (Image *) NULL)
++          DeleteImageFromRegistry(reference,image);
++        break;
++      }
++      default:
++        break;
++    }
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   D i s p l a y                                                             #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++Display(ref,...)
++  Image::Magick ref = NO_INIT
++  ALIAS:
++    DisplayImage  = 1
++    display       = 2
++    displayimage  = 3
++  PPCODE:
++  {
++    ExceptionInfo
++      *exception;
++
++    Image
++      *image;
++
++    register ssize_t
++      i;
++
++    struct PackageInfo
++      *info,
++      *package_info;
++
++    SV
++      *perl_exception,
++      *reference;
++
++    PERL_UNUSED_VAR(ref);
++    PERL_UNUSED_VAR(ix);
++    exception=AcquireExceptionInfo();
++    perl_exception=newSVpv("",0);
++    package_info=(struct PackageInfo *) NULL;
++    if (sv_isobject(ST(0)) == 0)
++      {
++        ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
++          PackageName);
++        goto PerlException;
++      }
++    reference=SvRV(ST(0));
++    image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
++    if (image == (Image *) NULL)
++      {
++        ThrowPerlException(exception,OptionError,"NoImagesDefined",
++          PackageName);
++        goto PerlException;
++      }
++    package_info=ClonePackageInfo(info,exception);
++    if (items == 2)
++      SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
++    else
++      if (items > 2)
++        for (i=2; i < items; i+=2)
++          SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
++            exception);
++    (void) DisplayImages(package_info->image_info,image);
++    (void) CatchImageException(image);
++    InheritException(exception,&image->exception);
++
++  PerlException:
++    if (package_info != (struct PackageInfo *) NULL)
++      DestroyPackageInfo(package_info);
++    InheritPerlException(exception,perl_exception);
++    exception=DestroyExceptionInfo(exception);
++    sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
++    SvPOK_on(perl_exception);
++    ST(0)=sv_2mortal(perl_exception);
++    XSRETURN(1);
++  }
++

++#
++###############################################################################
++#                                                                             #
++#                                                                             #
++#                                                                             #
++#   E v a l u a t e I m a g e s                                               #
++#                                                                             #
++#                                                                             #
++#                                                                             #
++###############################################################################
++#
++#
++void
++EvaluateImages(ref)
<Skipped 10664 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/ImageMagick.git/commitdiff/6b7c141d26d924fce2313c0ab86c1f2a3b3bf020




More information about the pld-cvs-commit mailing list