]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/resize.c
(no commit message)
[imagemagick] / MagickCore / resize.c
index 2258f78ae30d4f55b53c88a82383b6857bc33e8a..83d0452b2f313c7f8a027daf1a79f063ec751af2 100644 (file)
@@ -17,7 +17,7 @@
 %                                 July 1992                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2012 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  %
@@ -59,8 +59,9 @@
 #include "MagickCore/property.h"
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
-#include "MagickCore/pixel.h"
 #include "MagickCore/option.h"
+#include "MagickCore/pixel.h"
+#include "MagickCore/quantum-private.h"
 #include "MagickCore/resample.h"
 #include "MagickCore/resample-private.h"
 #include "MagickCore/resize.h"
@@ -68,7 +69,9 @@
 #include "MagickCore/string_.h"
 #include "MagickCore/string-private.h"
 #include "MagickCore/thread-private.h"
+#include "MagickCore/token.h"
 #include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
 #include "MagickCore/version.h"
 #if defined(MAGICKCORE_LQR_DELEGATE)
 #include <lqr.h>
@@ -136,33 +139,18 @@ static MagickRealType
 
 #define MagickPIL ((MagickRealType) 3.14159265358979323846264338327950288420L)
 
-static MagickRealType Jinc(const MagickRealType x,
-  const ResizeFilter *magick_unused(resize_filter))
-{
-  /*
-    See Pratt "Digital Image Processing" p.97 for Jinc/Bessel functions.
-    http://mathworld.wolfram.com/JincFunction.html and page 11 of
-    http://www.ph.ed.ac.uk/%7ewjh/teaching/mo/slides/lens/lens.pdf
-
-    The original "zoom" program by Paul Heckbert called this "Bessel".
-    But really it is more accurately named "Jinc".
-  */
-  if (x == 0.0)
-    return(0.5*MagickPIL);
-  return(BesselOrderOne(MagickPIL*x)/x);
-}
-
 static MagickRealType Blackman(const MagickRealType x,
   const ResizeFilter *magick_unused(resize_filter))
 {
   /*
     Blackman: 2nd order cosine windowing function:
       0.42 + 0.5 cos(pi x) + 0.08 cos(2pi x)
-    Refactored by Chantal Racette and Nicolas Robidoux to one trig
-    call and five flops.
+
+    Refactored by Chantal Racette and Nicolas Robidoux to one trig call and
+    five flops.
   */
-  const MagickRealType cospix = cos((double) (MagickPIL*x));
-  return(0.34+cospix*(0.5+cospix*0.16));
+  const MagickRealType cosine=cos((double) (MagickPIL*x));
+  return(0.34+cosine*(0.5+cosine*0.16));
 }
 
 static MagickRealType Bohman(const MagickRealType x,
@@ -171,22 +159,23 @@ static MagickRealType Bohman(const MagickRealType x,
   /*
     Bohman: 2rd Order cosine windowing function:
       (1-x) cos(pi x) + sin(pi x) / pi.
-    Refactored by Nicolas Robidoux to one trig call, one sqrt call,
-    and 7 flops, taking advantage of the fact that the support of
-    Bohman is 1 (so that we know that sin(pi x) >= 0).
+
+    Refactored by Nicolas Robidoux to one trig call, one sqrt call, and 7 flops,
+    taking advantage of the fact that the support of Bohman is 1.0 (so that we
+    know that sin(pi x) >= 0).
   */
-  const double cospix = cos((double) (MagickPIL*x));
-  const double sinpix = sqrt(1.0-cospix*cospix);
-  return((1.0-x)*cospix+(1.0/MagickPIL)*sinpix);
+  const MagickRealType cosine=cos((double) (MagickPIL*x));
+  const MagickRealType sine=sqrt(1.0-cosine*cosine);
+  return((1.0-x)*cosine+(1.0/MagickPIL)*sine);
 }
 
 static MagickRealType Box(const MagickRealType magick_unused(x),
   const ResizeFilter *magick_unused(resize_filter))
 {
   /*
-    A Box filter is a equal weighting function (all weights equal).
-    DO NOT LIMIT results by support or resize point sampling will work
-    as it requests points beyond its normal 0.0 support size.
+    A Box filter is a equal weighting function (all weights equal).  DO NOT
+    LIMIT results by support or resize point sampling will work as it requests
+    points beyond its normal 0.0 support size.
   */
   return(1.0);
 }
@@ -221,12 +210,11 @@ static MagickRealType CubicBC(const MagickRealType x,
        P0 + P1*x + P2*x^2 + P3*x^3      0 <= x < 1
        Q0 + Q1*x + Q2*x^2 + Q3*x^3      1 <= x < 2
 
-    which ensures function is continuous in value and derivative
-    (slope).
+    which ensures function is continuous in value and derivative (slope).
   */
   if (x < 1.0)
-    return(resize_filter->coefficient[0]+x*(x*
-      (resize_filter->coefficient[1]+x*resize_filter->coefficient[2])));
+    return(resize_filter->coefficient[0]+x*(x*(resize_filter->coefficient[1]+x*
+      resize_filter->coefficient[2])));
   if (x < 2.0)
     return(resize_filter->coefficient[3]+x*(resize_filter->coefficient[4]+x*
       (resize_filter->coefficient[5]+x*resize_filter->coefficient[6])));
@@ -240,20 +228,22 @@ static MagickRealType Gaussian(const MagickRealType x,
     Gaussian with a fixed sigma = 1/2
 
     Gaussian Formula (1D) ...
-        exp( -(x^2)/((2.0*sigma^2) ) / sqrt(2*PI)sigma^2))
+       exp( -(x^2)/((2.0*sigma^2) ) / sqrt(2*PI)sigma^2))
+
     The constants are pre-calculated...
-        exp( -coeff[0]*(x^2)) ) * coeff[1]
+       exp( -coeff[0]*(x^2)) ) * coeff[1]
+
     However the multiplier coefficent (1) is not needed and not used.
 
     Gaussian Formula (2D) ...
-        exp( -(x^2)/((2.0*sigma^2) ) / (PI*sigma^2) )
-    Note that it is only a change in the normalization multiplier
-    which is not needed or used when gausian is used as a filter.
+       exp( -(x^2)/((2.0*sigma^2) ) / (PI*sigma^2) )
+
+    Note that it is only a change in the normalization multiplier which is
+    not needed or used when gausian is used as a filter.
 
     This separates the gaussian 'sigma' value from the 'blur/support'
     settings allowing for its use in special 'small sigma' gaussians,
-    without the filter 'missing' pixels because the support becomes too
-    small.
+    without the filter 'missing' pixels because the support becomes too small.
   */
   return(exp((double)(-resize_filter->coefficient[0]*x*x)));
 }
@@ -263,10 +253,10 @@ static MagickRealType Hanning(const MagickRealType x,
 {
   /*
     Cosine window function:
-      .5+.5cos(pi x).
+      0.5+0.5*cos(pi*x).
   */
-  const MagickRealType cospix = cos((double) (MagickPIL*x));
-  return(0.5+0.5*cospix);
+  const MagickRealType cosine=cos((double) (MagickPIL*x));
+  return(0.5+0.5*cosine);
 }
 
 static MagickRealType Hamming(const MagickRealType x,
@@ -276,22 +266,36 @@ static MagickRealType Hamming(const MagickRealType x,
     Offset cosine window function:
      .54 + .46 cos(pi x).
   */
-  const MagickRealType cospix = cos((double) (MagickPIL*x));
-  return(0.54+0.46*cospix);
+  const MagickRealType cosine=cos((double) (MagickPIL*x));
+  return(0.54+0.46*cosine);
 }
 
-static MagickRealType Kaiser(const MagickRealType x,
+static MagickRealType Jinc(const MagickRealType x,
   const ResizeFilter *magick_unused(resize_filter))
 {
-#define Alpha  6.5
-#define I0A  (1.0/I0(Alpha))
+  /*
+    See Pratt "Digital Image Processing" p.97 for Jinc/Bessel functions.
+    http://mathworld.wolfram.com/JincFunction.html and page 11 of
+    http://www.ph.ed.ac.uk/%7ewjh/teaching/mo/slides/lens/lens.pdf
+
+    The original "zoom" program by Paul Heckbert called this "Bessel".  But
+    really it is more accurately named "Jinc".
+  */
+  if (x == 0.0)
+    return(0.5*MagickPIL);
+  return(BesselOrderOne(MagickPIL*x)/x);
+}
 
+static MagickRealType Kaiser(const MagickRealType x,
+  const ResizeFilter *resize_filter)
+{
   /*
-    Kaiser Windowing Function (bessel windowing): Alpha is a free
-    value from 5 to 8 (currently hardcoded to 6.5).
-    Future: make alpha the IOA pre-calculation, an 'expert' setting.
+    Kaiser Windowing Function (bessel windowing)
+    Alpha (c[0]) is a free value from 5 to 8 (defaults to 6.5).
+    A scaling factor (c[1]) is not needed as filter is normalized
   */
-  return(I0A*I0(Alpha*sqrt((double) (1.0-x*x))));
+  return(resize_filter->coefficient[1]*
+              I0(resize_filter->coefficient[0]*sqrt((double) (1.0-x*x))));
 }
 
 static MagickRealType Lagrange(const MagickRealType x,
@@ -308,22 +312,19 @@ static MagickRealType Lagrange(const MagickRealType x,
     order;
 
   /*
-    Lagrange piecewise polynomial fit of sinc: N is the 'order' of the
-    lagrange function and depends on the overall support window size
-    of the filter. That is: for a support of 2, it gives a lagrange-4
-    (piecewise cubic function).
+    Lagrange piecewise polynomial fit of sinc: N is the 'order' of the lagrange
+    function and depends on the overall support window size of the filter. That
+    is: for a support of 2, it gives a lagrange-4 (piecewise cubic function).
 
     "n" identifies the piece of the piecewise polynomial.
 
-    See Survey: Interpolation Methods, IEEE Transactions on Medical
-    Imaging, Vol 18, No 11, November 1999, p1049-1075, -- Equation 27
-    on p1064.
+    See Survey: Interpolation Methods, IEEE Transactions on Medical Imaging,
+    Vol 18, No 11, November 1999, p1049-1075, -- Equation 27 on p1064.
   */
   if (x > resize_filter->support)
     return(0.0);
   order=(ssize_t) (2.0*resize_filter->window_support);  /* number of pieces */
-  /*n=(ssize_t)((1.0*order)/2.0+x);   --  which piece does x belong to */
-  n = (ssize_t)(resize_filter->window_support + x);
+  n=(ssize_t) (resize_filter->window_support+x);
   value=1.0f;
   for (i=0; i < order; i++)
     if (i != n)
@@ -352,10 +353,10 @@ static MagickRealType Sinc(const MagickRealType x,
       sinc(x) == sin(pi x)/(pi x).
   */
   if (x != 0.0)
-  {
-    const MagickRealType pix = (MagickRealType) (MagickPIL*x);
-    return(sin((double) pix)/pix);
-  }
+    {
+      const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+      return(sin((double) alpha)/alpha);
+    }
   return((MagickRealType) 1.0);
 }
 
@@ -363,43 +364,37 @@ static MagickRealType SincFast(const MagickRealType x,
   const ResizeFilter *magick_unused(resize_filter))
 {
   /*
-    Approximations of the sinc function sin(pi x)/(pi x) over the
-    interval [-4,4] constructed by Nicolas Robidoux and Chantal
-    Racette with funding from the Natural Sciences and Engineering
-    Research Council of Canada.
+    Approximations of the sinc function sin(pi x)/(pi x) over the interval
+    [-4,4] constructed by Nicolas Robidoux and Chantal Racette with funding
+    from the Natural Sciences and Engineering Research Council of Canada.
 
     Although the approximations are polynomials (for low order of
     approximation) and quotients of polynomials (for higher order of
-    approximation) and consequently are similar in form to Taylor
-    polynomials/Pade approximants, the approximations are computed
-    with a completely different technique.
-
-    Summary: These approximations are "the best" in terms of bang
-    (accuracy) for the buck (flops). More specifically: Among the
-    polynomial quotients that can be computed using a fixed number of
-    flops (with a given "+ - * / budget"), the chosen polynomial
-    quotient is the one closest to the approximated function with
-    respect to maximum absolute relative error over the given
-    interval.
-
-    The Remez algorithm, as implemented in the boost library's minimax
-    package, is the key to the construction:
-    http://www.boost.org/doc/libs/1_36_0/libs/math/doc/...
-    ...sf_and_dist/html/math_toolkit/backgrounders/remez.html
-  */
-  /*
-    If outside of the interval of approximation, use the standard trig
-    formula.
+    approximation) and consequently are similar in form to Taylor polynomials /
+    Pade approximants, the approximations are computed with a completely
+    different technique.
+
+    Summary: These approximations are "the best" in terms of bang (accuracy)
+    for the buck (flops). More specifically: Among the polynomial quotients
+    that can be computed using a fixed number of flops (with a given "+ - * /
+    budget"), the chosen polynomial quotient is the one closest to the
+    approximated function with respect to maximum absolute relative error over
+    the given interval.
+
+    The Remez algorithm, as implemented in the boost library's minimax package,
+    is the key to the construction: http://www.boost.org/doc/libs/1_36_0/libs/
+    math/doc/sf_and_dist/html/math_toolkit/backgrounders/remez.html
+
+    If outside of the interval of approximation, use the standard trig formula.
   */
   if (x > 4.0)
     {
-      const MagickRealType pix = (MagickRealType) (MagickPIL*x);
-      return(sin((double) pix)/pix);
+      const MagickRealType alpha=(MagickRealType) (MagickPIL*x);
+      return(sin((double) alpha)/alpha);
     }
   {
     /*
-      The approximations only depend on x^2 (sinc is an even
-      function).
+      The approximations only depend on x^2 (sinc is an even function).
     */
     const MagickRealType xx = x*x;
 #if MAGICKCORE_QUANTUM_DEPTH <= 8
@@ -463,9 +458,9 @@ static MagickRealType Triangle(const MagickRealType x,
   const ResizeFilter *magick_unused(resize_filter))
 {
   /*
-    1st order (linear) B-Spline, bilinear interpolation, Tent 1D
-    filter, or a Bartlett 2D Cone filter.  Also used as a
-    Bartlett Windowing function for Sinc().
+    1st order (linear) B-Spline, bilinear interpolation, Tent 1D filter, or
+    a Bartlett 2D Cone filter.  Also used as a Bartlett Windowing function
+    for Sinc().
   */
   if (x < 1.0)
     return(1.0-x);
@@ -498,19 +493,16 @@ static MagickRealType Welsh(const MagickRealType x,
 %  these filters:
 %
 %  FIR (Finite impulse Response) Filters
-%      Box         Triangle   Quadratic
-%      Cubic       Hermite    Catrom
-%      Mitchell
+%      Box  Triangle Quadratic  Cubic  Hermite  Catrom  Mitchell
 %
 %  IIR (Infinite impulse Response) Filters
-%      Gaussian     Sinc        Jinc (Bessel)
+%      Gaussian  Sinc  Jinc (Bessel)
 %
 %  Windowed Sinc/Jinc Filters
-%      Blackman     Hanning     Hamming
-%      Kaiser       Lanczos
+%      Blackman  Hanning  Hamming  Kaiser Lanczos
 %
 %  Special purpose Filters
-%      SincFast  LanczosSharp  Lanczos2D Lanczos2DSharp  Robidoux
+%      SincFast  LanczosSharp  Lanczos2D  Lanczos2DSharp  Robidoux
 %
 %  The users "-filter" selection is used to lookup the default 'expert'
 %  settings for that filter from a internal table.  However any provided
@@ -638,7 +630,7 @@ static MagickRealType Welsh(const MagickRealType x,
 %  The format of the AcquireResizeFilter method is:
 %
 %      ResizeFilter *AcquireResizeFilter(const Image *image,
-%        const FilterTypes filter_type, const MagickBooleanType radial,
+%        const FilterTypes filter_type,const MagickBooleanType radial,
 %        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
@@ -658,9 +650,9 @@ static MagickRealType Welsh(const MagickRealType x,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
-  const FilterTypes filter,const MagickRealType blur,
-  const MagickBooleanType cylindrical,ExceptionInfo *exception)
+MagickPrivate ResizeFilter *AcquireResizeFilter(const Image *image,
+  const FilterTypes filter,const MagickBooleanType cylindrical,
+  ExceptionInfo *exception)
 {
   const char
     *artifact;
@@ -672,13 +664,13 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   MagickRealType
     B,
     C,
-    sigma;
+    value;
 
   register ResizeFilter
     *resize_filter;
 
   /*
-    Table Mapping given Filter, into Weighting and Windowing functions.  A
+    Table Mapping given Filter, into Weighting and Windowing functions. A
     'Box' windowing function means its a simble non-windowed filter.  An
     'SincFast' filter function could be upgraded to a 'Jinc' filter if a
     "cylindrical", unless a 'Sinc' or 'SincFast' filter was specifically
@@ -697,33 +689,33 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
       window;
   } const mapping[SentinelFilter] =
   {
-    { UndefinedFilter,    BoxFilter      }, /* Undefined (default to Box)   */
-    { PointFilter,        BoxFilter      }, /* SPECIAL: Nearest neighbour   */
-    { BoxFilter,          BoxFilter      }, /* Box averaging filter         */
-    { TriangleFilter,     BoxFilter      }, /* Linear interpolation filter  */
-    { HermiteFilter,      BoxFilter      }, /* Hermite interpolation filter */
-    { SincFastFilter,     HanningFilter  }, /* Hanning -- cosine-sinc       */
-    { SincFastFilter,     HammingFilter  }, /* Hamming --      '' variation */
-    { SincFastFilter,     BlackmanFilter }, /* Blackman -- 2*cosine-sinc    */
-    { GaussianFilter,     BoxFilter      }, /* Gaussian blur filter         */
-    { QuadraticFilter,    BoxFilter      }, /* Quadratic Gaussian approx    */
-    { CubicFilter,        BoxFilter      }, /* Cubic B-Spline               */
-    { CatromFilter,       BoxFilter      }, /* Cubic-Keys interpolator      */
-    { MitchellFilter,     BoxFilter      }, /* 'Ideal' Cubic-Keys filter    */
-    { JincFilter,         BoxFilter      }, /* Raw 3-lobed Jinc function    */
-    { SincFilter,         BoxFilter      }, /* Raw 4-lobed Sinc function    */
-    { SincFastFilter,     BoxFilter      }, /* Raw fast sinc ("Pade"-type)  */
-    { SincFastFilter,     KaiserFilter   }, /* Kaiser -- square root-sinc   */
-    { SincFastFilter,     WelshFilter    }, /* Welsh -- parabolic-sinc      */
-    { SincFastFilter,     CubicFilter    }, /* Parzen -- cubic-sinc         */
-    { SincFastFilter,     BohmanFilter   }, /* Bohman -- 2*cosine-sinc      */
-    { SincFastFilter,     TriangleFilter }, /* Bartlett -- triangle-sinc    */
-    { LagrangeFilter,     BoxFilter      }, /* Lagrange self-windowing      */
-    { LanczosFilter,      LanczosFilter  }, /* Lanczos Sinc-Sinc filters    */
-    { LanczosSharpFilter, LanczosSharpFilter }, /* | these require */
-    { Lanczos2Filter,     Lanczos2Filter },     /* | special handling */
-    { Lanczos2SharpFilter,Lanczos2SharpFilter },
-    { RobidouxFilter,     BoxFilter      }, /* Cubic Keys tuned for EWA     */
+    { UndefinedFilter,     BoxFilter      },  /* Undefined (default to Box)   */
+    { PointFilter,         BoxFilter      },  /* SPECIAL: Nearest neighbour   */
+    { BoxFilter,           BoxFilter      },  /* Box averaging filter         */
+    { TriangleFilter,      BoxFilter      },  /* Linear interpolation filter  */
+    { HermiteFilter,       BoxFilter      },  /* Hermite interpolation filter */
+    { SincFastFilter,      HanningFilter  },  /* Hanning -- cosine-sinc       */
+    { SincFastFilter,      HammingFilter  },  /* Hamming --      '' variation */
+    { SincFastFilter,      BlackmanFilter },  /* Blackman -- 2*cosine-sinc    */
+    { GaussianFilter,      BoxFilter      },  /* Gaussian blur filter         */
+    { QuadraticFilter,     BoxFilter      },  /* Quadratic Gaussian approx    */
+    { CubicFilter,         BoxFilter      },  /* Cubic B-Spline               */
+    { CatromFilter,        BoxFilter      },  /* Cubic-Keys interpolator      */
+    { MitchellFilter,      BoxFilter      },  /* 'Ideal' Cubic-Keys filter    */
+    { JincFilter,          BoxFilter      },  /* Raw 3-lobed Jinc function    */
+    { SincFilter,          BoxFilter      },  /* Raw 4-lobed Sinc function    */
+    { SincFastFilter,      BoxFilter      },  /* Raw fast sinc ("Pade"-type)  */
+    { SincFastFilter,      KaiserFilter   },  /* Kaiser -- square root-sinc   */
+    { SincFastFilter,      WelshFilter    },  /* Welsh -- parabolic-sinc      */
+    { SincFastFilter,      CubicFilter    },  /* Parzen -- cubic-sinc         */
+    { SincFastFilter,      BohmanFilter   },  /* Bohman -- 2*cosine-sinc      */
+    { SincFastFilter,      TriangleFilter },  /* Bartlett -- triangle-sinc    */
+    { LagrangeFilter,      BoxFilter      },  /* Lagrange self-windowing      */
+    { LanczosFilter,       LanczosFilter  },  /* Lanczos Sinc-Sinc filters    */
+    { LanczosSharpFilter,  LanczosSharpFilter }, /* | these require */
+    { Lanczos2Filter,      Lanczos2Filter },     /* | special handling */
+    { Lanczos2SharpFilter, Lanczos2SharpFilter },
+    { RobidouxFilter,      BoxFilter      },  /* Cubic Keys tuned for EWA     */
   };
   /*
     Table mapping the filter/window from the above table to an actual function.
@@ -739,42 +731,42 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   static struct
   {
     MagickRealType
-      (*function)(const MagickRealType, const ResizeFilter*),
-      lobes, /* Default lobes/support size of the weighting filter. */
+      (*function)(const MagickRealType,const ResizeFilter*),
+      lobes,  /* Default lobes/support size of the weighting filter. */
       scale, /* Support when function used as a windowing function
                 Typically equal to the location of the first zero crossing. */
       B,C;   /* BC-spline coefficients, ignored if not a CubicBC filter. */
   } const filters[SentinelFilter] =
   {
-    { Box,       0.5, 0.5,     0.0, 0.0 }, /* Undefined (default to Box)  */
-    { Box,       0.0, 0.5,     0.0, 0.0 }, /* Point (special handling)    */
-    { Box,       0.5, 0.5,     0.0, 0.0 }, /* Box                         */
-    { Triangle,  1.0, 1.0,     0.0, 0.0 }, /* Triangle                    */
-    { CubicBC,   1.0, 1.0,     0.0, 0.0 }, /* Hermite (cubic  B=C=0)      */
-    { Hanning,   1.0, 1.0,     0.0, 0.0 }, /* Hanning, cosine window      */
-    { Hamming,   1.0, 1.0,     0.0, 0.0 }, /* Hamming, '' variation       */
-    { Blackman,  1.0, 1.0,     0.0, 0.0 }, /* Blackman, 2*cosine window   */
-    { Gaussian,  2.0, 1.5,     0.0, 0.0 }, /* Gaussian                    */
-    { Quadratic, 1.5, 1.5,     0.0, 0.0 }, /* Quadratic gaussian          */
-    { CubicBC,   2.0, 2.0,     1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0)    */
-    { CubicBC,   2.0, 1.0,     0.0, 0.5 }, /* Catmull-Rom    (B=0,C=1/2)  */
+    { Box,       0.5, 0.5, 0.0, 0.0 }, /* Undefined (default to Box)  */
+    { Box,       0.0, 0.5, 0.0, 0.0 }, /* Point (special handling)    */
+    { Box,       0.5, 0.5, 0.0, 0.0 }, /* Box                         */
+    { Triangle,  1.0, 1.0, 0.0, 0.0 }, /* Triangle                    */
+    { CubicBC,   1.0, 1.0, 0.0, 0.0 }, /* Hermite (cubic  B=C=0)      */
+    { Hanning,   1.0, 1.0, 0.0, 0.0 }, /* Hanning, cosine window      */
+    { Hamming,   1.0, 1.0, 0.0, 0.0 }, /* Hamming, '' variation       */
+    { Blackman,  1.0, 1.0, 0.0, 0.0 }, /* Blackman, 2*cosine window   */
+    { Gaussian,  2.0, 1.5, 0.0, 0.0 }, /* Gaussian                    */
+    { Quadratic, 1.5, 1.5, 0.0, 0.0 }, /* Quadratic gaussian          */
+    { CubicBC,   2.0, 2.0, 1.0, 0.0 }, /* Cubic B-Spline (B=1,C=0)    */
+    { CubicBC,   2.0, 1.0, 0.0, 0.5 }, /* Catmull-Rom    (B=0,C=1/2)  */
     { CubicBC,   2.0, 8.0/7.0, 1./3., 1./3. }, /* Mitchell   (B=C=1/3)    */
     { Jinc,      3.0, 1.2196698912665045, 0.0, 0.0 }, /* Raw 3-lobed Jinc */
-    { Sinc,      4.0, 1.0,     0.0, 0.0 }, /* Raw 4-lobed Sinc            */
-    { SincFast,  4.0, 1.0,     0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
-    { Kaiser,    1.0, 1.0,     0.0, 0.0 }, /* Kaiser (square root window) */
-    { Welsh,     1.0, 1.0,     0.0, 0.0 }, /* Welsh (parabolic window)    */
-    { CubicBC,   2.0, 2.0,     1.0, 0.0 }, /* Parzen (B-Spline window)    */
-    { Bohman,    1.0, 1.0,     0.0, 0.0 }, /* Bohman, 2*Cosine window     */
-    { Triangle,  1.0, 1.0,     0.0, 0.0 }, /* Bartlett (triangle window)  */
-    { Lagrange,  2.0, 1.0,     0.0, 0.0 }, /* Lagrange sinc approximation */
-    { SincFast,  3.0, 1.0,     0.0, 0.0 }, /* Lanczos, 3-lobed Sinc-Sinc  */
-    { SincFast,  3.0, 1.0,     0.0, 0.0 }, /* lanczos, Sharpened          */
-    { SincFast,  2.0, 1.0,     0.0, 0.0 }, /* Lanczos, 2-lobed            */
-    { SincFast,  2.0, 1.0,     0.0, 0.0 }, /* Lanczos2, sharpened         */
-    { CubicBC,   2.0, 1.1685777620836932,
-                              0.37821575509399867, 0.31089212245300067 }
-                     /* Robidoux: Keys cubic close to Lanczos2D sharpened */
+    { Sinc,      4.0, 1.0, 0.0, 0.0 }, /* Raw 4-lobed Sinc            */
+    { SincFast,  4.0, 1.0, 0.0, 0.0 }, /* Raw fast sinc ("Pade"-type) */
+    { Kaiser,    1.0, 1.0, 0.0, 0.0 }, /* Kaiser (square root window) */
+    { Welsh,     1.0, 1.0, 0.0, 0.0 }, /* Welsh (parabolic window)    */
+    { CubicBC,   2.0, 2.0, 1.0, 0.0 }, /* Parzen (B-Spline window)    */
+    { Bohman,    1.0, 1.0, 0.0, 0.0 }, /* Bohman, 2*Cosine window     */
+    { Triangle,  1.0, 1.0, 0.0, 0.0 }, /* Bartlett (triangle window)  */
+    { Lagrange,  2.0, 1.0, 0.0, 0.0 }, /* Lagrange sinc approximation */
+    { SincFast,  3.0, 1.0, 0.0, 0.0 }, /* Lanczos, 3-lobed Sinc-Sinc  */
+    { SincFast,  3.0, 1.0, 0.0, 0.0 }, /* lanczos, Sharpened          */
+    { SincFast,  2.0, 1.0, 0.0, 0.0 }, /* Lanczos, 2-lobed            */
+    { SincFast,  2.0, 1.0, 0.0, 0.0 }, /* Lanczos2, sharpened         */
+    { CubicBC,   2.0, 1.1685777620836932, 0.37821575509399867,
+                 0.31089212245300067 }
+                 /* Robidoux: Keys cubic close to Lanczos2D sharpened */
   };
   /*
     The known zero crossings of the Jinc() or more accurately the Jinc(x*PI)
@@ -783,9 +775,8 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
     users do not have to deal with the highly irrational lobe sizes of the Jinc
     filter.
 
-    Values taken from
-    http://cose.math.bas.bg/webMathematica/webComputing/BesselZeros.jsp using
-    Jv-function with v=1, then dividing by PI.
+    Values taken from http://cose.math.bas.bg/webMathematica/webComputing/
+    BesselZeros.jsp using Jv-function with v=1, then dividing by PI.
   */
   static MagickRealType
     jinc_zeros[16] =
@@ -796,7 +787,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
       4.2410628637960699,
       5.2427643768701817,
       6.2439216898644877,
-      7.244759868719957,
+      7.2447598687199570,
       8.2453949139520427,
       9.2458926849494673,
       10.246293348754916,
@@ -804,7 +795,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
       12.246898461138105,
       13.247132522181061,
       14.247333735806849,
-      15.2475085630373,
+      15.247508563037300,
       16.247661874700962
    };
 
@@ -813,7 +804,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   */
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(UndefinedFilter < filter && filter < SentinelFilter);
   assert(exception != (ExceptionInfo *) NULL);
@@ -821,18 +812,17 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   resize_filter=(ResizeFilter *) AcquireMagickMemory(sizeof(*resize_filter));
   if (resize_filter == (ResizeFilter *) NULL)
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+  (void) ResetMagickMemory(resize_filter,0,sizeof(*resize_filter));
+  resize_filter->blur=1.0;
   /*
     Defaults for the requested filter.
   */
   filter_type=mapping[filter].filter;
   window_type=mapping[filter].window;
-  resize_filter->blur = blur;   /* function argument blur factor */
-  sigma = 0.5;    /* guassian sigma of half a pixel by default */
   /* Promote 1D Windowed Sinc Filters to a 2D Windowed Jinc filters */
-  if (cylindrical != MagickFalse && filter_type == SincFastFilter
-       && filter != SincFastFilter )
-    filter_type=JincFilter;
-
+  if( IfMagickTrue(cylindrical) && (filter_type == SincFastFilter) &&
+      (filter != SincFastFilter))
+    filter_type=JincFilter;  /* 1D Windowed Sinc => 2D Windowed Jinc filters */
   /* Expert filter setting override */
   artifact=GetImageArtifact(image,"filter:filter");
   if (artifact != (const char *) NULL)
@@ -842,11 +832,16 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
 
       option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
       if ((UndefinedFilter < option) && (option < SentinelFilter))
-        { /* Raw filter request - no window function. */
+        {
+          /*
+            Raw filter request - no window function.
+          */
           filter_type=(FilterTypes) option;
           window_type=BoxFilter;
         }
-      /* Filter override with a specific window function. */
+      /*
+        Filter override with a specific window function.
+      */
       artifact=GetImageArtifact(image,"filter:window");
       if (artifact != (const char *) NULL)
         {
@@ -857,83 +852,109 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
     }
   else
     {
-      /* Window specified, but no filter function?  Assume Sinc/Jinc. */
+      /*
+        Window specified, but no filter function?  Assume Sinc/Jinc.
+      */
       artifact=GetImageArtifact(image,"filter:window");
       if (artifact != (const char *) NULL)
         {
           ssize_t
             option;
 
-          option=ParseCommandOption(MagickFilterOptions,MagickFalse,
-            artifact);
+          option=ParseCommandOption(MagickFilterOptions,MagickFalse,artifact);
           if ((UndefinedFilter < option) && (option < SentinelFilter))
             {
-              filter_type=cylindrical != MagickFalse ?
-                         JincFilter : SincFastFilter;
+              filter_type= IfMagickTrue(cylindrical) ? JincFilter
+                                                     : SincFastFilter;
               window_type=(FilterTypes) option;
             }
         }
     }
-
-  /* Assign the real functions to use for the filters selected. */
+  /*
+    Assign the real functions to use for the filters selected.
+  */
   resize_filter->filter=filters[filter_type].function;
   resize_filter->support=filters[filter_type].lobes;
   resize_filter->window=filters[window_type].function;
   resize_filter->scale=filters[window_type].scale;
   resize_filter->signature=MagickSignature;
-
-  /* Filter Modifications for orthogonal/cylindrical usage */
-  if (cylindrical != MagickFalse)
+  /*
+    Filter Modifications for orthogonal/cylindrical usage.
+  */
+  if( IfMagickTrue(cylindrical) )
     switch (filter_type)
     {
       case BoxFilter:
-        /* Support for Cylindrical Box should be sqrt(2)/2 */
+      {
+        /*
+          Support for Cylindrical Box should be sqrt(2)/2.
+        */
         resize_filter->support=(MagickRealType) MagickSQ1_2;
         break;
+      }
       case LanczosFilter:
       case LanczosSharpFilter:
       case Lanczos2Filter:
       case Lanczos2SharpFilter:
+      {
+        /*
+          Number of lobes (support window size) remain unchanged.
+        */
         resize_filter->filter=filters[JincFilter].function;
         resize_filter->window=filters[JincFilter].function;
         resize_filter->scale=filters[JincFilter].scale;
-        /* number of lobes (support window size) remain unchanged */
         break;
+      }
       default:
         break;
     }
-  /* Global Sharpening (regardless of orthoginal/cylindrical) */
+  /*
+    Global Sharpening (regardless of orthoginal/cylindrical).
+  */
   switch (filter_type)
   {
     case LanczosSharpFilter:
-      resize_filter->blur *= 0.9812505644269356;
+    {
+      resize_filter->blur*=0.9812505644269356;
       break;
+    }
     case Lanczos2SharpFilter:
-      resize_filter->blur *= 0.9549963639785485;
+    {
+      resize_filter->blur*=0.9549963639785485;
       break;
+    }
     default:
       break;
   }
-
   /*
-  ** Other Expert Option Modifications
+    Expert Option Modifications.
   */
-
-  /* User Sigma Override - no support change */
+  /* User Gaussian Sigma Override - no support change */
+  value=0.5;    /* guassian sigma default, half pixel */
+  if ( GaussianFilter ) {
   artifact=GetImageArtifact(image,"filter:sigma");
   if (artifact != (const char *) NULL)
-    sigma=InterpretLocaleValue(artifact,(char **) NULL);
-  /* Define coefficents for Gaussian */
-  if ( GaussianFilter ) {
-    resize_filter->coefficient[0]=1.0/(2.0*sigma*sigma);
-    resize_filter->coefficient[1]=(MagickRealType) (1.0/(Magick2PI*sigma*
-      sigma)); /* Normalization Multiplier - unneeded for filters */
+      value=StringToDouble(artifact,(char **) NULL);
+    /* Define coefficents for Gaussian */
+    resize_filter->coefficient[0]=1.0/(2.0*value*value); /* X scaling */
+    resize_filter->coefficient[1]=(MagickRealType) (1.0/(Magick2PI*value*
+      value)); /* normalization */
+  }
+  /* User Kaiser Alpha Override - no support change */
+  if ( KaiserFilter ) {
+    value=6.5; /* default alpha value for Kaiser bessel windowing function */
+    artifact=GetImageArtifact(image,"filter:alpha");
+    if (artifact != (const char *) NULL)
+      value=StringToDouble(artifact,(char **) NULL);
+    /* Define coefficents for Kaiser Windowing Function */
+    resize_filter->coefficient[0]=value;         /* X scaling */
+    resize_filter->coefficient[1]=1.0/I0(value); /* normalization */
   }
 
   /* Blur Override */
   artifact=GetImageArtifact(image,"filter:blur");
   if (artifact != (const char *) NULL)
-    resize_filter->blur *= InterpretLocaleValue(artifact,(char **) NULL);
+    resize_filter->blur*=StringToDouble(artifact,(char **) NULL);
   if (resize_filter->blur < MagickEpsilon)
     resize_filter->blur=(MagickRealType) MagickEpsilon;
 
@@ -955,12 +976,12 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
       if (resize_filter->support > 16)
         resize_filter->support=jinc_zeros[15];  /* largest entry in table */
       else
-        resize_filter->support = jinc_zeros[((long)resize_filter->support)-1];
+        resize_filter->support=jinc_zeros[((long)resize_filter->support)-1];
     }
   /* expert override of the support setting */
   artifact=GetImageArtifact(image,"filter:support");
   if (artifact != (const char *) NULL)
-    resize_filter->support=fabs(InterpretLocaleValue(artifact,(char **) NULL));
+    resize_filter->support=fabs(StringToDouble(artifact,(char **) NULL));
   /*
     Scale windowing function separately to the support 'clipping'
     window that calling operator is planning to actually use. (Expert
@@ -969,12 +990,12 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   resize_filter->window_support=resize_filter->support; /* default */
   artifact=GetImageArtifact(image,"filter:win-support");
   if (artifact != (const char *) NULL)
-    resize_filter->window_support=fabs(InterpretLocaleValue(artifact,(char **) NULL));
+    resize_filter->window_support=fabs(StringToDouble(artifact,(char **) NULL));
   /*
     Adjust window function scaling to match windowing support for
     weighting function.  This avoids a division on every filter call.
   */
-  resize_filter->scale /= resize_filter->window_support;
+  resize_filter->scale/=resize_filter->window_support;
 
   /*
    * Set Cubic Spline B,C values, calculate Cubic coefficients.
@@ -994,32 +1015,35 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
       artifact=GetImageArtifact(image,"filter:b");
       if (artifact != (const char *) NULL)
         {
-          B=InterpretLocaleValue(artifact,(char **) NULL);
+          B=StringToDouble(artifact,(char **) NULL);
           C=(1.0-B)/2.0; /* Calculate C to get a Keys cubic filter. */
           artifact=GetImageArtifact(image,"filter:c"); /* user C override */
           if (artifact != (const char *) NULL)
-            C=InterpretLocaleValue(artifact,(char **) NULL);
+            C=StringToDouble(artifact,(char **) NULL);
         }
       else
         {
           artifact=GetImageArtifact(image,"filter:c");
           if (artifact != (const char *) NULL)
             {
-              C=InterpretLocaleValue(artifact,(char **) NULL);
+              C=StringToDouble(artifact,(char **) NULL);
               B=1.0-2.0*C; /* Calculate B to get a Keys cubic filter. */
             }
         }
       /* Convert B,C values into Cubic Coefficents. See CubicBC(). */
-      {
-        const double twoB = B+B;
+     {
+        double
+          B_squared;
+
+        B_squared=B+B;
         resize_filter->coefficient[0]=1.0-(1.0/3.0)*B;
-        resize_filter->coefficient[1]=-3.0+twoB+C;
+        resize_filter->coefficient[1]=-3.0+B_squared+C;
         resize_filter->coefficient[2]=2.0-1.5*B-C;
         resize_filter->coefficient[3]=(4.0/3.0)*B+4.0*C;
-        resize_filter->coefficient[4]=-8.0*C-twoB;
+        resize_filter->coefficient[4]=-8.0*C-B_squared;
         resize_filter->coefficient[5]=B+5.0*C;
         resize_filter->coefficient[6]=(-1.0/6.0)*B-C;
-      }
+     }
     }
 
   /*
@@ -1029,8 +1053,7 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
   #pragma omp master
   {
 #endif
-    artifact=GetImageArtifact(image,"filter:verbose");
-    if (IsMagickTrue(artifact))
+    if (IfMagickTrue(GetImageArtifact(image,"filter:verbose")))
       {
         double
           support,
@@ -1055,34 +1078,38 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
         /*
           Report Filter Details.
         */
-        support=GetResizeFilterSupport(resize_filter); /* practical_support */
+        support=GetResizeFilterSupport(resize_filter);  /* practical_support */
         (void) FormatLocaleFile(stdout,"# Resize Filter (for graphing)\n#\n");
         (void) FormatLocaleFile(stdout,"# filter = %s\n",
-             CommandOptionToMnemonic(MagickFilterOptions,filter_type));
+          CommandOptionToMnemonic(MagickFilterOptions,filter_type));
         (void) FormatLocaleFile(stdout,"# window = %s\n",
-             CommandOptionToMnemonic(MagickFilterOptions, window_type));
+          CommandOptionToMnemonic(MagickFilterOptions, window_type));
         (void) FormatLocaleFile(stdout,"# support = %.*g\n",
-             GetMagickPrecision(),(double) resize_filter->support);
+          GetMagickPrecision(),(double) resize_filter->support);
         (void) FormatLocaleFile(stdout,"# win-support = %.*g\n",
-             GetMagickPrecision(),(double) resize_filter->window_support);
+          GetMagickPrecision(),(double) resize_filter->window_support);
         (void) FormatLocaleFile(stdout,"# scale_blur = %.*g\n",
-             GetMagickPrecision(), (double)resize_filter->blur);
-        if ( filter_type == GaussianFilter )
+          GetMagickPrecision(), (double)resize_filter->blur);
+        if (filter_type == GaussianFilter)
           (void) FormatLocaleFile(stdout,"# gaussian_sigma = %.*g\n",
-               GetMagickPrecision(), (double)sigma);
+            GetMagickPrecision(), (double)value);
+        if ( filter_type == KaiserFilter )
+          (void) FormatLocaleFile(stdout,"# kaiser_alpha = %.*g\n",
+            GetMagickPrecision(), (double)value);
         (void) FormatLocaleFile(stdout,"# practical_support = %.*g\n",
-             GetMagickPrecision(), (double)support);
+           GetMagickPrecision(), (double)support);
         if ( filter_type == CubicFilter || window_type == CubicFilter )
           (void) FormatLocaleFile(stdout,"# B,C = %.*g,%.*g\n",
-               GetMagickPrecision(),(double)B, GetMagickPrecision(),(double)C);
+            GetMagickPrecision(),(double)B, GetMagickPrecision(),(double)C);
         (void) FormatLocaleFile(stdout,"\n");
         /*
           Output values of resulting filter graph -- for graphing
           filter result.
         */
         for (x=0.0; x <= support; x+=0.01f)
-          (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,GetMagickPrecision(),
-            (double) GetResizeFilterWeight(resize_filter,x));
+          (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",x,
+            GetMagickPrecision(),(double) GetResizeFilterWeight(resize_filter,
+            x));
         /* A final value so gnuplot can graph the 'stop' properly. */
         (void) FormatLocaleFile(stdout,"%5.2lf\t%.*g\n",support,
           GetMagickPrecision(),0.0);
@@ -1108,10 +1135,15 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
 %
 %  AdaptiveResizeImage() adaptively resize image with pixel resampling.
 %
+%  This is shortcut function for a fast interpolative resize using mesh
+%  interpolation.  It works well for small resizes of less than +/- 50%
+%  of the original image size.  For larger resizing on images a full
+%  filtered and slower resize function should be used instead.
+%
 %  The format of the AdaptiveResizeImage method is:
 %
 %      Image *AdaptiveResizeImage(const Image *image,const size_t columns,
-%        const size_t rows,ExceptionInfo *exception)
+%        const size_t rows, ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -1127,103 +1159,11 @@ MagickExport ResizeFilter *AcquireResizeFilter(const Image *image,
 MagickExport Image *AdaptiveResizeImage(const Image *image,
   const size_t columns,const size_t rows,ExceptionInfo *exception)
 {
-#define AdaptiveResizeImageTag  "Resize/Image"
-
-  CacheView
-    *image_view,
-    *resize_view;
-
   Image
     *resize_image;
 
-  MagickBooleanType
-    status;
-
-  MagickOffsetType
-    progress;
-
-  ssize_t
-    y;
-
-  /*
-    Adaptively resize image.
-  */
-  assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  if ((columns == 0) || (rows == 0))
-    return((Image *) NULL);
-  if ((columns == image->columns) && (rows == image->rows))
-    return(CloneImage(image,0,0,MagickTrue,exception));
-  resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
-  if (resize_image == (Image *) NULL)
-    return((Image *) NULL);
-  if (SetImageStorageClass(resize_image,DirectClass) == MagickFalse)
-    {
-      InheritException(exception,&resize_image->exception);
-      resize_image=DestroyImage(resize_image);
-      return((Image *) NULL);
-    }
-  status=MagickTrue;
-  progress=0;
-  image_view=AcquireCacheView(image);
-  resize_view=AcquireCacheView(resize_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1)
-#endif
-  for (y=0; y < (ssize_t) resize_image->rows; y++)
-  {
-    PixelInfo
-      pixel;
-
-    PointInfo
-      offset;
-
-    register Quantum
-      *restrict q;
-
-    register ssize_t
-      x;
-
-    if (status == MagickFalse)
-      continue;
-    q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
-      exception);
-    if (q == (const Quantum *) NULL)
-      continue;
-    offset.y=((MagickRealType) (y+0.5)*image->rows/resize_image->rows);
-    GetPixelInfo(image,&pixel);
-    for (x=0; x < (ssize_t) resize_image->columns; x++)
-    {
-      offset.x=((MagickRealType) (x+0.5)*image->columns/resize_image->columns);
-      (void) InterpolatePixelInfo(image,image_view,
-        MeshInterpolatePixel,offset.x-0.5,offset.y-0.5,&pixel,exception);
-      SetPixelPixelInfo(resize_image,&pixel,q);
-      q+=GetPixelComponents(resize_image);
-    }
-    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
-      continue;
-    if (image->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT) 
-  #pragma omp critical (MagickCore_AdaptiveResizeImage)
-#endif
-        proceed=SetImageProgress(image,AdaptiveResizeImageTag,progress++,
-          image->rows);
-        if (proceed == MagickFalse)
-          status=MagickFalse;
-      }
-  }
-  resize_view=DestroyCacheView(resize_view);
-  image_view=DestroyCacheView(image_view);
-  if (status == MagickFalse)
-    resize_image=DestroyImage(resize_image);
+  resize_image=InterpolativeResizeImage(image,columns,rows,MeshInterpolatePixel,
+    exception);
   return(resize_image);
 }
 \f
@@ -1460,7 +1400,7 @@ static MagickRealType BesselOrderOne(MagickRealType x)
 %    o resize_filter: the resize filter.
 %
 */
-MagickExport ResizeFilter *DestroyResizeFilter(ResizeFilter *resize_filter)
+MagickPrivate ResizeFilter *DestroyResizeFilter(ResizeFilter *resize_filter)
 {
   assert(resize_filter != (ResizeFilter *) NULL);
   assert(resize_filter->signature == MagickSignature);
@@ -1492,7 +1432,7 @@ MagickExport ResizeFilter *DestroyResizeFilter(ResizeFilter *resize_filter)
 %    o filter: Image filter to use.
 %
 */
-MagickExport MagickRealType GetResizeFilterSupport(
+MagickPrivate MagickRealType GetResizeFilterSupport(
   const ResizeFilter *resize_filter)
 {
   assert(resize_filter != (ResizeFilter *) NULL);
@@ -1527,7 +1467,7 @@ MagickExport MagickRealType GetResizeFilterSupport(
 %    o x: the point.
 %
 */
-MagickExport MagickRealType GetResizeFilterWeight(
+MagickPrivate MagickRealType GetResizeFilterWeight(
   const ResizeFilter *resize_filter,const MagickRealType x)
 {
   MagickRealType
@@ -1558,171 +1498,180 @@ MagickExport MagickRealType GetResizeFilterWeight(
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   M a g n i f y I m a g e                                                   %
+%   I n t e r p o l a t i v e R e s i z e I m a g e                           %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  MagnifyImage() is a convenience method that scales an image proportionally
-%  to twice its size.
+%  InterpolativeResizeImage() resizes an image using the specified
+%  interpolation method.
 %
-%  The format of the MagnifyImage method is:
+%  The format of the InterpolativeResizeImage method is:
 %
-%      Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+%      Image *InterpolativeResizeImage(const Image *image,const size_t columns,
+%        const size_t rows,const PixelInterpolateMethod method,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
+%    o columns: the number of columns in the resized image.
+%
+%    o rows: the number of rows in the resized image.
+%
+%    o method: the pixel interpolation method.
+%
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+MagickExport Image *InterpolativeResizeImage(const Image *image,
+  const size_t columns,const size_t rows,const PixelInterpolateMethod method,
+  ExceptionInfo *exception)
 {
+#define InterpolativeResizeImageTag  "Resize/Image"
+
+  CacheView
+    *image_view,
+    *resize_view;
+
   Image
-    *magnify_image;
+    *resize_image;
 
-  assert(image != (Image *) NULL);
+  MagickBooleanType
+    status;
+
+  MagickOffsetType
+    progress;
+
+  PointInfo
+    scale;
+
+  ssize_t
+    y;
+
+  /*
+    Interpolatively resize image.
+  */
+  assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  magnify_image=ResizeImage(image,2*image->columns,2*image->rows,CubicFilter,
-    1.0,exception);
-  return(magnify_image);
+  if ((columns == 0) || (rows == 0))
+    return((Image *) NULL);
+  if ((columns == image->columns) && (rows == image->rows))
+    return(CloneImage(image,0,0,MagickTrue,exception));
+  resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
+  if (resize_image == (Image *) NULL)
+    return((Image *) NULL);
+  if( IfMagickFalse(SetImageStorageClass(resize_image,DirectClass,exception)) )
+    {
+      resize_image=DestroyImage(resize_image);
+      return((Image *) NULL);
+    }
+  status=MagickTrue;
+  progress=0;
+  image_view=AcquireCacheView(image);
+  resize_view=AcquireCacheView(resize_image);
+  scale.x=(double) image->columns/resize_image->columns;
+  scale.y=(double) image->rows/resize_image->rows;
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(static) shared(progress,status)
+#endif
+  for (y=0; y < (ssize_t) resize_image->rows; y++)
+  {
+    PointInfo
+      offset;
+
+    register Quantum
+      *restrict q;
+
+    register ssize_t
+      x;
+
+    if( IfMagickFalse(status) )
+      continue;
+    q=QueueCacheViewAuthenticPixels(resize_view,0,y,resize_image->columns,1,
+      exception);
+    if (q == (Quantum *) NULL)
+      continue;
+    offset.y=((MagickRealType) y+0.5)*scale.y-0.5;
+    for (x=0; x < (ssize_t) resize_image->columns; x++)
+    {
+      register ssize_t
+        i;
+
+      if (GetPixelMask(resize_image,q) != 0)
+        {
+          q+=GetPixelChannels(resize_image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+      {
+        PixelChannel
+          channel;
+
+        PixelTrait
+          resize_traits,
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (resize_traits == UndefinedPixelTrait))
+          continue;
+        offset.x=((MagickRealType) x+0.5)*scale.x-0.5;
+        status=InterpolatePixelChannels(image,image_view,resize_image,method,
+          offset.x,offset.y,q,exception);
+      }
+      q+=GetPixelChannels(resize_image);
+    }
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
+      continue;
+    if (image->progress_monitor != (MagickProgressMonitor) NULL)
+      {
+        MagickBooleanType
+          proceed;
+
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp critical (MagickCore_InterpolativeResizeImage)
+#endif
+        proceed=SetImageProgress(image,InterpolativeResizeImageTag,progress++,
+          image->rows);
+        if( IfMagickFalse(proceed) )
+          status=MagickFalse;
+      }
+  }
+  resize_view=DestroyCacheView(resize_view);
+  image_view=DestroyCacheView(image_view);
+  if( IfMagickFalse(status) )
+    resize_image=DestroyImage(resize_image);
+  return(resize_image);
 }
+#if defined(MAGICKCORE_LQR_DELEGATE)
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   M i n i f y I m a g e                                                     %
+%   L i q u i d R e s c a l e I m a g e                                       %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  MinifyImage() is a convenience method that scales an image proportionally
-%  to half its size.
-%
-%  The format of the MinifyImage method is:
-%
-%      Image *MinifyImage(const Image *image,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception)
-{
-  Image
-    *minify_image;
-
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter,1.0,
-    exception);
-  return(minify_image);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%   R e s a m p l e I m a g e                                                 %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  ResampleImage() resize image in terms of its pixel size, so that when
-%  displayed at the given resolution it will be the same size in terms of
-%  real world units as the original image at the original resolution.
-%
-%  The format of the ResampleImage method is:
-%
-%      Image *ResampleImage(Image *image,const double x_resolution,
-%        const double y_resolution,const FilterTypes filter,const double blur,
-%        ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image to be resized to fit the given resolution.
-%
-%    o x_resolution: the new image x resolution.
-%
-%    o y_resolution: the new image y resolution.
-%
-%    o filter: Image filter to use.
-%
-%    o blur: the blur factor where > 1 is blurry, < 1 is sharp.
-%
-*/
-MagickExport Image *ResampleImage(const Image *image,const double x_resolution,
-  const double y_resolution,const FilterTypes filter,const double blur,
-  ExceptionInfo *exception)
-{
-#define ResampleImageTag  "Resample/Image"
-
-  Image
-    *resample_image;
-
-  size_t
-    height,
-    width;
-
-  /*
-    Initialize sampled image attributes.
-  */
-  assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  width=(size_t) (x_resolution*image->columns/(image->x_resolution == 0.0 ?
-    72.0 : image->x_resolution)+0.5);
-  height=(size_t) (y_resolution*image->rows/(image->y_resolution == 0.0 ?
-    72.0 : image->y_resolution)+0.5);
-  resample_image=ResizeImage(image,width,height,filter,blur,exception);
-  if (resample_image != (Image *) NULL)
-    {
-      resample_image->x_resolution=x_resolution;
-      resample_image->y_resolution=y_resolution;
-    }
-  return(resample_image);
-}
-#if defined(MAGICKCORE_LQR_DELEGATE)
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%   L i q u i d R e s c a l e I m a g e                                       %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  LiquidRescaleImage() rescales image with seam carving.
+%  LiquidRescaleImage() rescales image with seam carving.
 %
 %  The format of the LiquidRescaleImage method is:
 %
-%      Image *LiquidRescaleImage(const Image *image,
-%        const size_t columns,const size_t rows,
-%        const double delta_x,const double rigidity,ExceptionInfo *exception)
+%      Image *LiquidRescaleImage(const Image *image,const size_t columns,
+%        const size_t rows,const double delta_x,const double rigidity,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -1746,20 +1695,19 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
 #define LiquidRescaleImageTag  "Rescale/Image"
 
   CacheView
+    *image_view,
     *rescale_view;
 
-  const char
-    *map;
-
-  guchar
-    *packet;
+  gfloat
+    *packet,
+    *pixels;
 
   Image
     *rescale_image;
 
   int
-    x,
-    y;
+    x_offset,
+    y_offset;
 
   LqrCarver
     *carver;
@@ -1770,18 +1718,18 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
   MagickBooleanType
     status;
 
-  PixelInfo
-    pixel;
+  register gfloat
+    *q;
 
-  unsigned char
-    *pixels;
+  ssize_t
+    y;
 
   /*
     Liquid rescale image.
   */
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
@@ -1790,7 +1738,7 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
   if ((columns == image->columns) && (rows == image->rows))
     return(CloneImage(image,0,0,MagickTrue,exception));
   if ((columns <= 2) || (rows <= 2))
-    return(ResizeImage(image,columns,rows,image->filter,image->blur,exception));
+    return(ResizeImage(image,columns,rows,image->filter,exception));
   if ((columns >= (2*image->columns)) || (rows >= (2*image->rows)))
     {
       Image
@@ -1805,8 +1753,7 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
       */
       for (width=image->columns; columns >= (2*width-1); width*=2);
       for (height=image->rows; rows >= (2*height-1); height*=2);
-      resize_image=ResizeImage(image,width,height,image->filter,image->blur,
-        exception);
+      resize_image=ResizeImage(image,width,height,image->filter,exception);
       if (resize_image == (Image *) NULL)
         return((Image *) NULL);
       rescale_image=LiquidRescaleImage(resize_image,columns,rows,delta_x,
@@ -1814,30 +1761,45 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
       resize_image=DestroyImage(resize_image);
       return(rescale_image);
     }
-  map="RGB";
-  if (image->matte == MagickFalse)
-    map="RGBA";
-  if (image->colorspace == CMYKColorspace)
-    {
-      map="CMYK";
-      if (image->matte == MagickFalse)
-        map="CMYKA";
-    }
-  pixels=(unsigned char *) AcquireQuantumMemory(image->columns,image->rows*
-    strlen(map)*sizeof(*pixels));
-  if (pixels == (unsigned char *) NULL)
+  pixels=(gfloat *) AcquireQuantumMemory(image->columns,image->rows*
+    GetPixelChannels(image)*sizeof(*pixels));
+  if (pixels == (gfloat *) NULL)
     return((Image *) NULL);
-  status=ExportImagePixels(image,0,0,image->columns,image->rows,map,CharPixel,
-    pixels,exception);
-  if (status == MagickFalse)
+  status=MagickTrue;
+  q=pixels;
+  image_view=AcquireCacheView(image);
+  for (y=0; y < (ssize_t) image->rows; y++)
+  {
+    register const Quantum
+      *restrict p;
+
+    register ssize_t
+      x;
+
+    if( IfMagickFalse(status) )
+      continue;
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    if (p == (const Quantum *) NULL)
+      {
+        status=MagickFalse;
+        continue;
+      }
+    for (x=0; x < (ssize_t) image->columns; x++)
     {
-      pixels=(unsigned char *) RelinquishMagickMemory(pixels);
-      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
+      register ssize_t
+        i;
+
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+        *q++=QuantumScale*p[i];
+      p+=GetPixelChannels(image);
     }
-  carver=lqr_carver_new(pixels,image->columns,image->rows,strlen(map));
+  }
+  image_view=DestroyCacheView(image_view);
+  carver=lqr_carver_new_ext(pixels,image->columns,image->rows,
+    GetPixelChannels(image),LQR_COLDEPTH_32F);
   if (carver == (LqrCarver *) NULL)
     {
-      pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+      pixels=(gfloat *) RelinquishMagickMemory(pixels);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
     }
   lqr_status=lqr_carver_init(carver,(int) delta_x,rigidity);
@@ -1847,48 +1809,51 @@ MagickExport Image *LiquidRescaleImage(const Image *image,const size_t columns,
     lqr_carver_get_height(carver),MagickTrue,exception);
   if (rescale_image == (Image *) NULL)
     {
-      pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+      pixels=(gfloat *) RelinquishMagickMemory(pixels);
       return((Image *) NULL);
     }
-  if (SetImageStorageClass(rescale_image,DirectClass) == MagickFalse)
+  if( IfMagickFalse(SetImageStorageClass(rescale_image,DirectClass,exception)) )
     {
-      InheritException(exception,&rescale_image->exception);
+      pixels=(gfloat *) RelinquishMagickMemory(pixels);
       rescale_image=DestroyImage(rescale_image);
       return((Image *) NULL);
     }
-  GetPixelInfo(rescale_image,&pixel);
-  (void) lqr_carver_scan_reset(carver);
   rescale_view=AcquireCacheView(rescale_image);
-  while (lqr_carver_scan(carver,&x,&y,&packet) != 0)
+  (void) lqr_carver_scan_reset(carver);
+  while (lqr_carver_scan_ext(carver,&x_offset,&y_offset,(void **) &packet) != 0)
   {
     register Quantum
       *restrict q;
 
-    q=QueueCacheViewAuthenticPixels(rescale_view,x,y,1,1,exception);
-    if (q == (const Quantum *) NULL)
+    register ssize_t
+      i;
+
+    q=QueueCacheViewAuthenticPixels(rescale_view,x_offset,y_offset,1,1,
+      exception);
+    if (q == (Quantum *) NULL)
       break;
-    pixel.red=QuantumRange*(packet[0]/255.0);
-    pixel.green=QuantumRange*(packet[1]/255.0);
-    pixel.blue=QuantumRange*(packet[2]/255.0);
-    if (image->colorspace != CMYKColorspace)
-      {
-        if (image->matte == MagickFalse)
-          pixel.alpha=QuantumRange*(packet[3]/255.0);
-      }
-    else
-      {
-        pixel.black=QuantumRange*(packet[3]/255.0);
-        if (image->matte == MagickFalse)
-          pixel.alpha=QuantumRange*(packet[4]/255.0);
-      }
-    SetPixelPixelInfo(rescale_image,&pixel,q);
-    if (SyncCacheViewAuthenticPixels(rescale_view,exception) == MagickFalse)
+    for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+    {
+      PixelChannel
+        channel;
+
+      PixelTrait
+        rescale_traits,
+        traits;
+
+      channel=GetPixelChannelMapChannel(image,i);
+      traits=GetPixelChannelMapTraits(image,channel);
+      rescale_traits=GetPixelChannelMapTraits(rescale_image,channel);
+      if ((traits == UndefinedPixelTrait) ||
+          (rescale_traits == UndefinedPixelTrait))
+        continue;
+      SetPixelChannel(rescale_image,channel,ClampToQuantum(QuantumRange*
+        packet[i]),q);
+    }
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(rescale_view,exception)) )
       break;
   }
   rescale_view=DestroyCacheView(rescale_view);
-  /*
-    Relinquish resources.
-  */
   lqr_carver_destroy(carver);
   return(rescale_image);
 }
@@ -1900,7 +1865,7 @@ MagickExport Image *LiquidRescaleImage(const Image *image,
 {
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
@@ -1915,6 +1880,156 @@ MagickExport Image *LiquidRescaleImage(const Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   M a g n i f y I m a g e                                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MagnifyImage() is a convenience method that scales an image proportionally
+%  to twice its size.
+%
+%  The format of the MagnifyImage method is:
+%
+%      Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MagnifyImage(const Image *image,ExceptionInfo *exception)
+{
+  Image
+    *magnify_image;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if( IfMagickTrue(image->debug) )
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  magnify_image=ResizeImage(image,2*image->columns,2*image->rows,CubicFilter,
+    exception);
+  return(magnify_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   M i n i f y I m a g e                                                     %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  MinifyImage() is a convenience method that scales an image proportionally to
+%  half its size.
+%
+%  The format of the MinifyImage method is:
+%
+%      Image *MinifyImage(const Image *image,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *MinifyImage(const Image *image,ExceptionInfo *exception)
+{
+  Image
+    *minify_image;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if( IfMagickTrue(image->debug) )
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  minify_image=ResizeImage(image,image->columns/2,image->rows/2,CubicFilter,
+    exception);
+  return(minify_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   R e s a m p l e I m a g e                                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  ResampleImage() resize image in terms of its pixel size, so that when
+%  displayed at the given resolution it will be the same size in terms of
+%  real world units as the original image at the original resolution.
+%
+%  The format of the ResampleImage method is:
+%
+%      Image *ResampleImage(Image *image,const double x_resolution,
+%        const double y_resolution,const FilterTypes filter,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image to be resized to fit the given resolution.
+%
+%    o x_resolution: the new image x resolution.
+%
+%    o y_resolution: the new image y resolution.
+%
+%    o filter: Image filter to use.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *ResampleImage(const Image *image,const double x_resolution,
+  const double y_resolution,const FilterTypes filter,ExceptionInfo *exception)
+{
+#define ResampleImageTag  "Resample/Image"
+
+  Image
+    *resample_image;
+
+  size_t
+    height,
+    width;
+
+  /*
+    Initialize sampled image attributes.
+  */
+  assert(image != (const Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if( IfMagickTrue(image->debug) )
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  width=(size_t) (x_resolution*image->columns/(image->resolution.x == 0.0 ?
+    72.0 : image->resolution.x)+0.5);
+  height=(size_t) (y_resolution*image->rows/(image->resolution.y == 0.0 ?
+    72.0 : image->resolution.y)+0.5);
+  resample_image=ResizeImage(image,width,height,filter,exception);
+  if (resample_image != (Image *) NULL)
+    {
+      resample_image->resolution.x=x_resolution;
+      resample_image->resolution.y=y_resolution;
+    }
+  return(resample_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   R e s i z e I m a g e                                                     %
 %                                                                             %
 %                                                                             %
@@ -1971,7 +2086,7 @@ static ContributionInfo **DestroyContributionThreadSet(
   assert(contribution != (ContributionInfo **) NULL);
   for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
     if (contribution[i] != (ContributionInfo *) NULL)
-      contribution[i]=(ContributionInfo *) RelinquishMagickMemory(
+      contribution[i]=(ContributionInfo *) RelinquishAlignedMemory(
         contribution[i]);
   contribution=(ContributionInfo **) RelinquishMagickMemory(contribution);
   return(contribution);
@@ -1996,7 +2111,7 @@ static ContributionInfo **AcquireContributionThreadSet(const size_t count)
   (void) ResetMagickMemory(contribution,0,number_threads*sizeof(*contribution));
   for (i=0; i < (ssize_t) number_threads; i++)
   {
-    contribution[i]=(ContributionInfo *) AcquireQuantumMemory(count,
+    contribution[i]=(ContributionInfo *) AcquireAlignedMemory(count,
       sizeof(**contribution));
     if (contribution[i] == (ContributionInfo *) NULL)
       return(DestroyContributionThreadSet(contribution));
@@ -2037,9 +2152,6 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
   MagickBooleanType
     status;
 
-  PixelInfo
-    zero;
-
   MagickRealType
     scale,
     support;
@@ -2053,16 +2165,12 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
   scale=MagickMax(1.0/x_factor+MagickEpsilon,1.0);
   support=scale*GetResizeFilterSupport(resize_filter);
   storage_class=support > 0.5 ? DirectClass : image->storage_class;
-  if (SetImageStorageClass(resize_image,storage_class) == MagickFalse)
-    {
-      InheritException(exception,&resize_image->exception);
-      return(MagickFalse);
-    }
+  if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
+    return(MagickFalse);
   if (support < 0.5)
     {
       /*
-        Support too small even for nearest neighbour: Reduce to point
-        sampling.
+        Support too small even for nearest neighbour: Reduce to point sampling.
       */
       support=(MagickRealType) 0.5;
       scale=1.0;
@@ -2076,19 +2184,17 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
     }
   status=MagickTrue;
   scale=1.0/scale;
-  (void) ResetMagickMemory(&zero,0,sizeof(zero));
   image_view=AcquireCacheView(image);
   resize_view=AcquireCacheView(resize_image);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for shared(status)
+  #pragma omp parallel for schedule(static,4) shared(status)
 #endif
   for (x=0; x < (ssize_t) resize_image->columns; x++)
   {
     MagickRealType
-      center,
+      bisect,
       density;
 
-
     register const Quantum
       *restrict p;
 
@@ -2106,18 +2212,18 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
       start,
       stop;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
-    center=(MagickRealType) (x+0.5)/x_factor;
-    start=(ssize_t) MagickMax(center-support+0.5,0.0);
-    stop=(ssize_t) MagickMin(center+support+0.5,(double) image->columns);
+    bisect=(MagickRealType) (x+0.5)/x_factor+MagickEpsilon;
+    start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
+    stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->columns);
     density=0.0;
     contribution=contributions[GetOpenMPThreadId()];
     for (n=0; n < (stop-start); n++)
     {
       contribution[n].pixel=start+n;
       contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
-        ((MagickRealType) (start+n)-center+0.5));
+        ((MagickRealType) (start+n)-bisect+0.5));
       density+=contribution[n].weight;
     }
     if ((density != 0.0) && (density != 1.0))
@@ -2143,95 +2249,85 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
       }
     for (y=0; y < (ssize_t) resize_image->rows; y++)
     {
-      PixelInfo
-        pixel;
-
-      MagickRealType
-        alpha;
-
       register ssize_t
         i;
 
-      ssize_t
-        j;
-
-      pixel=zero;
-      if (image->matte == MagickFalse)
+      if (GetPixelMask(resize_image,q) != 0)
         {
-          for (i=0; i < n; i++)
-          {
-            j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
-              (contribution[i].pixel-contribution[0].pixel);
-            alpha=contribution[i].weight;
-            pixel.red+=alpha*GetPixelRed(image,p+j*
-              GetPixelComponents(image));
-            pixel.green+=alpha*GetPixelGreen(image,p+j*
-              GetPixelComponents(image));
-            pixel.blue+=alpha*GetPixelBlue(image,p+j*
-              GetPixelComponents(image));
-            if ((image->colorspace == CMYKColorspace) &&
-                (resize_image->colorspace == CMYKColorspace))
-              pixel.black+=alpha*GetPixelBlue(image,p+j*
-                GetPixelComponents(image));
-            pixel.alpha+=alpha*GetPixelAlpha(image,p+j*
-              GetPixelComponents(image));
-          }
-          SetPixelRed(resize_image,ClampToQuantum(pixel.red),q);
-          SetPixelGreen(resize_image,ClampToQuantum(pixel.green),q);
-          SetPixelBlue(resize_image,ClampToQuantum(pixel.blue),q);
-          if ((image->colorspace == CMYKColorspace) &&
-              (resize_image->colorspace == CMYKColorspace))
-            SetPixelBlack(resize_image,ClampToQuantum(pixel.black),q);
-          SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
+          q+=GetPixelChannels(resize_image);
+          continue;
         }
-      else
-        {
-          MagickRealType
-            gamma;
+      for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+      {
+        MagickRealType
+          alpha,
+          gamma,
+          pixel;
+
+        PixelChannel
+          channel;
 
-          gamma=0.0;
-          for (i=0; i < n; i++)
+        PixelTrait
+          resize_traits,
+          traits;
+
+        register ssize_t
+          j;
+
+        ssize_t
+          k;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (resize_traits == UndefinedPixelTrait))
+          continue;
+        if ((resize_traits & CopyPixelTrait) != 0)
           {
-            j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
-              (contribution[i].pixel-contribution[0].pixel);
-            alpha=contribution[i].weight*QuantumScale*
-              GetPixelAlpha(image,p+j*GetPixelComponents(image));
-            pixel.red+=alpha*GetPixelRed(image,p+j*
-              GetPixelComponents(image));
-            pixel.green+=alpha*GetPixelGreen(image,p+j*
-              GetPixelComponents(image));
-            pixel.blue+=alpha*GetPixelBlue(image,p+j*
-              GetPixelComponents(image));
-            if ((image->colorspace == CMYKColorspace) &&
-                (resize_image->colorspace == CMYKColorspace))
-              pixel.black+=alpha*GetPixelBlack(image,p+j*
-                GetPixelComponents(image));
-            pixel.alpha+=contribution[i].weight*
-              GetPixelAlpha(image,p+j*GetPixelComponents(image));
-            gamma+=alpha;
+            j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
+              stop-1.0)+0.5);
+            k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
+              (contribution[j-start].pixel-contribution[0].pixel);
+            SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+              q);
+            continue;
           }
-          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
-          SetPixelRed(resize_image,ClampToQuantum(gamma*pixel.red),q);
-          SetPixelGreen(resize_image,ClampToQuantum(gamma*pixel.green),q);
-          SetPixelBlue(resize_image,ClampToQuantum(gamma*pixel.blue),q);
-          if ((image->colorspace == CMYKColorspace) &&
-              (resize_image->colorspace == CMYKColorspace))
-            SetPixelBlack(resize_image,ClampToQuantum(gamma*pixel.black),q);
-          SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
-        }
-      if ((resize_image->storage_class == PseudoClass) &&
-          (image->storage_class == PseudoClass))
+        pixel=0.0;
+        if ((resize_traits & BlendPixelTrait) == 0)
+          {
+            /*
+              No alpha blending.
+            */
+            for (j=0; j < n; j++)
+            {
+              k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
+                (contribution[j].pixel-contribution[0].pixel);
+              alpha=contribution[j].weight;
+              pixel+=alpha*p[k*GetPixelChannels(image)+i];
+            }
+            SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
+            continue;
+          }
+        /*
+          Alpha blending.
+        */
+        gamma=0.0;
+        for (j=0; j < n; j++)
         {
-          i=(ssize_t) (MagickMin(MagickMax(center,(double) start),(double) stop-
-            1.0)+0.5);
-          j=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
-            (contribution[i-start].pixel-contribution[0].pixel);
-          SetPixelIndex(resize_image,GetPixelIndex(image,p+j*
-            GetPixelComponents(image)),q);
+          k=y*(contribution[n-1].pixel-contribution[0].pixel+1)+
+            (contribution[j].pixel-contribution[0].pixel);
+          alpha=contribution[j].weight*QuantumScale*
+            GetPixelAlpha(image,p+k*GetPixelChannels(image));
+          pixel+=alpha*p[k*GetPixelChannels(image)+i];
+          gamma+=alpha;
         }
-      q+=GetPixelComponents(resize_image);
+        gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+        SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
+      }
+      q+=GetPixelChannels(resize_image);
     }
-    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2242,7 +2338,7 @@ static MagickBooleanType HorizontalFilter(const ResizeFilter *resize_filter,
   #pragma omp critical (MagickCore_HorizontalFilter)
 #endif
         proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -2285,16 +2381,12 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
   scale=MagickMax(1.0/y_factor+MagickEpsilon,1.0);
   support=scale*GetResizeFilterSupport(resize_filter);
   storage_class=support > 0.5 ? DirectClass : image->storage_class;
-  if (SetImageStorageClass(resize_image,storage_class) == MagickFalse)
-    {
-      InheritException(exception,&resize_image->exception);
-      return(MagickFalse);
-    }
+  if( IfMagickFalse(SetImageStorageClass(resize_image,storage_class,exception)) )
+    return(MagickFalse);
   if (support < 0.5)
     {
       /*
-        Support too small even for nearest neighbour: Reduce to point
-        sampling.
+        Support too small even for nearest neighbour: Reduce to point sampling.
       */
       support=(MagickRealType) 0.5;
       scale=1.0;
@@ -2312,12 +2404,12 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
   image_view=AcquireCacheView(image);
   resize_view=AcquireCacheView(resize_image);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for shared(status)
+  #pragma omp parallel for schedule(static,4) shared(status)
 #endif
   for (y=0; y < (ssize_t) resize_image->rows; y++)
   {
     MagickRealType
-      center,
+      bisect,
       density;
 
     register const Quantum
@@ -2337,18 +2429,18 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
       start,
       stop;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
-    center=(MagickRealType) (y+0.5)/y_factor;
-    start=(ssize_t) MagickMax(center-support+0.5,0.0);
-    stop=(ssize_t) MagickMin(center+support+0.5,(double) image->rows);
+    bisect=(MagickRealType) (y+0.5)/y_factor+MagickEpsilon;
+    start=(ssize_t) MagickMax(bisect-support+0.5,0.0);
+    stop=(ssize_t) MagickMin(bisect+support+0.5,(double) image->rows);
     density=0.0;
     contribution=contributions[GetOpenMPThreadId()];
     for (n=0; n < (stop-start); n++)
     {
       contribution[n].pixel=start+n;
       contribution[n].weight=GetResizeFilterWeight(resize_filter,scale*
-        ((MagickRealType) (start+n)-center+0.5));
+        ((MagickRealType) (start+n)-bisect+0.5));
       density+=contribution[n].weight;
     }
     if ((density != 0.0) && (density != 1.0))
@@ -2375,95 +2467,82 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
       }
     for (x=0; x < (ssize_t) resize_image->columns; x++)
     {
-      PixelInfo
-        pixel;
-
-      MagickRealType
-        alpha;
-
       register ssize_t
         i;
 
-      ssize_t
-        j;
-
-      pixel=zero;
-      if (image->matte == MagickFalse)
+      if (GetPixelMask(resize_image,q) != 0)
         {
-          for (i=0; i < n; i++)
-          {
-            j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
-              image->columns+x);
-            alpha=contribution[i].weight;
-            pixel.red+=alpha*GetPixelRed(image,p+j*
-              GetPixelComponents(image));
-            pixel.green+=alpha*GetPixelGreen(image,p+j*
-              GetPixelComponents(image));
-            pixel.blue+=alpha*GetPixelBlue(image,p+j*
-              GetPixelComponents(image));
-            if ((image->colorspace == CMYKColorspace) &&
-                (resize_image->colorspace == CMYKColorspace))
-              pixel.black+=alpha*GetPixelBlack(image,p+j*
-                GetPixelComponents(image));
-            pixel.alpha+=alpha*GetPixelAlpha(image,p+j*
-              GetPixelComponents(image));
-          }
-          SetPixelRed(resize_image,ClampToQuantum(pixel.red),q);
-          SetPixelGreen(resize_image,ClampToQuantum(pixel.green),q);
-          SetPixelBlue(resize_image,ClampToQuantum(pixel.blue),q);
-          if ((image->colorspace == CMYKColorspace) &&
-              (resize_image->colorspace == CMYKColorspace))
-            SetPixelBlack(resize_image,ClampToQuantum(pixel.black),q);
-          SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
+          q+=GetPixelChannels(resize_image);
+          continue;
         }
-      else
-        {
-          MagickRealType
-            gamma;
+      for (i=0; i < (ssize_t) GetPixelChannels(resize_image); i++)
+      {
+        MagickRealType
+          alpha,
+          gamma,
+          pixel;
+
+        PixelChannel
+          channel;
+
+        PixelTrait
+          resize_traits,
+          traits;
 
-          gamma=0.0;
-          for (i=0; i < n; i++)
+        register ssize_t
+          j;
+
+        ssize_t
+          k;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        resize_traits=GetPixelChannelMapTraits(resize_image,channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (resize_traits == UndefinedPixelTrait))
+          continue;
+        if ((resize_traits & CopyPixelTrait) != 0)
           {
-            j=(ssize_t) ((contribution[i].pixel-contribution[0].pixel)*
+            j=(ssize_t) (MagickMin(MagickMax(bisect,(double) start),(double)
+              stop-1.0)+0.5);
+            k=(ssize_t) ((contribution[j-start].pixel-contribution[0].pixel)*
               image->columns+x);
-            alpha=contribution[i].weight*QuantumScale*
-              GetPixelAlpha(image,p+j*GetPixelComponents(image));
-            pixel.red+=alpha*GetPixelRed(image,p+j*
-              GetPixelComponents(image));
-            pixel.green+=alpha*GetPixelGreen(image,p+j*
-              GetPixelComponents(image));
-            pixel.blue+=alpha*GetPixelBlue(image,p+j*
-              GetPixelComponents(image));
-            if ((image->colorspace == CMYKColorspace) &&
-                (resize_image->colorspace == CMYKColorspace))
-              pixel.black+=alpha*GetPixelBlack(image,p+j*
-                GetPixelComponents(image));
-            pixel.alpha+=contribution[i].weight*GetPixelAlpha(image,p+j*
-             GetPixelComponents(image));
-            gamma+=alpha;
+            SetPixelChannel(resize_image,channel,p[k*GetPixelChannels(image)+i],
+              q);
+            continue;
           }
-          gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
-          SetPixelRed(resize_image,ClampToQuantum(gamma*pixel.red),q);
-          SetPixelGreen(resize_image,ClampToQuantum(gamma*pixel.green),q);
-          SetPixelBlue(resize_image,ClampToQuantum(gamma*pixel.blue),q);
-          if ((image->colorspace == CMYKColorspace) &&
-              (resize_image->colorspace == CMYKColorspace))
-            SetPixelBlack(resize_image,ClampToQuantum(gamma*pixel.black),q);
-          SetPixelAlpha(resize_image,ClampToQuantum(pixel.alpha),q);
-        }
-      if ((resize_image->storage_class == PseudoClass) &&
-          (image->storage_class == PseudoClass))
+        pixel=0.0;
+        if ((resize_traits & BlendPixelTrait) == 0)
+          {
+            /*
+              No alpha blending.
+            */
+            for (j=0; j < n; j++)
+            {
+              k=(ssize_t) ((contribution[j].pixel-contribution[0].pixel)*
+                image->columns+x);
+              alpha=contribution[j].weight;
+              pixel+=alpha*p[k*GetPixelChannels(image)+i];
+            }
+            SetPixelChannel(resize_image,channel,ClampToQuantum(pixel),q);
+            continue;
+          }
+        gamma=0.0;
+        for (j=0; j < n; j++)
         {
-          i=(ssize_t) (MagickMin(MagickMax(center,(double) start),(double) stop-
-            1.0)+0.5);
-          j=(ssize_t) ((contribution[i-start].pixel-contribution[0].pixel)*
+          k=(ssize_t) ((contribution[j].pixel-contribution[0].pixel)*
             image->columns+x);
-          SetPixelIndex(resize_image,GetPixelIndex(image,p+j*
-            GetPixelComponents(image)),q);
+          alpha=contribution[j].weight*QuantumScale*
+            GetPixelAlpha(image,p+k*GetPixelChannels(image));
+          pixel+=alpha*p[k*GetPixelChannels(image)+i];
+          gamma+=alpha;
         }
-      q+=GetPixelComponents(resize_image);
+        gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+        SetPixelChannel(resize_image,channel,ClampToQuantum(gamma*pixel),q);
+      }
+      q+=GetPixelChannels(resize_image);
     }
-    if (SyncCacheViewAuthenticPixels(resize_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(resize_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2474,7 +2553,7 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
   #pragma omp critical (MagickCore_VerticalFilter)
 #endif
         proceed=SetImageProgress(image,ResizeImageTag,(*offset)++,span);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -2485,8 +2564,7 @@ static MagickBooleanType VerticalFilter(const ResizeFilter *resize_filter,
 }
 
 MagickExport Image *ResizeImage(const Image *image,const size_t columns,
-  const size_t rows,const FilterTypes filter,const double blur,
-  ExceptionInfo *exception)
+  const size_t rows,const FilterTypes filter,ExceptionInfo *exception)
 {
 #define WorkLoadFactor  0.265
 
@@ -2518,14 +2596,14 @@ MagickExport Image *ResizeImage(const Image *image,const size_t columns,
   */
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
   if ((columns == 0) || (rows == 0))
     ThrowImageException(ImageError,"NegativeOrZeroImageSize");
   if ((columns == image->columns) && (rows == image->rows) &&
-      (filter == UndefinedFilter) && (blur == 1.0))
+      (filter == UndefinedFilter))
     return(CloneImage(image,0,0,MagickTrue,exception));
   resize_image=CloneImage(image,columns,rows,MagickTrue,exception);
   if (resize_image == (Image *) NULL)
@@ -2549,10 +2627,10 @@ MagickExport Image *ResizeImage(const Image *image,const size_t columns,
       filter_type=PointFilter;
     else
       if ((image->storage_class == PseudoClass) ||
-          (image->matte != MagickFalse) || ((x_factor*y_factor) > 1.0))
+          IfMagickTrue(image->matte) ||
+          ((x_factor*y_factor) > 1.0))
         filter_type=MitchellFilter;
-  resize_filter=AcquireResizeFilter(image,filter_type,blur,MagickFalse,
-    exception);
+  resize_filter=AcquireResizeFilter(image,filter_type,MagickFalse,exception);
   /*
     Resize image.
   */
@@ -2578,8 +2656,11 @@ MagickExport Image *ResizeImage(const Image *image,const size_t columns,
   */
   filter_image=DestroyImage(filter_image);
   resize_filter=DestroyResizeFilter(resize_filter);
-  if ((status == MagickFalse) || (resize_image == (Image *) NULL))
-    return((Image *) NULL);
+  if( IfMagickFalse(status) )
+    {
+      resize_image=DestroyImage(resize_image);
+      return((Image *) NULL);
+    }
   resize_image->type=image->type;
   return(resize_image);
 }
@@ -2645,7 +2726,7 @@ MagickExport Image *SampleImage(const Image *image,const size_t columns,
   */
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
@@ -2677,7 +2758,7 @@ MagickExport Image *SampleImage(const Image *image,const size_t columns,
   image_view=AcquireCacheView(image);
   sample_view=AcquireCacheView(sample_image);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+  #pragma omp parallel for schedule(static) shared(progress,status)
 #endif
   for (y=0; y < (ssize_t) sample_image->rows; y++)
   {
@@ -2693,7 +2774,7 @@ MagickExport Image *SampleImage(const Image *image,const size_t columns,
     ssize_t
       y_offset;
 
-    if (status == MagickFalse)
+    if( IfMagickFalse(status) )
       continue;
     y_offset=(ssize_t) (((MagickRealType) y+0.5)*image->rows/
       sample_image->rows);
@@ -2711,24 +2792,35 @@ MagickExport Image *SampleImage(const Image *image,const size_t columns,
     */
     for (x=0; x < (ssize_t) sample_image->columns; x++)
     {
-      SetPixelRed(sample_image,GetPixelRed(image,p+x_offset[x]*
-        GetPixelComponents(image)),q);
-      SetPixelGreen(sample_image,GetPixelGreen(image,p+x_offset[x]*
-        GetPixelComponents(image)),q);
-      SetPixelBlue(sample_image,GetPixelBlue(image,p+x_offset[x]*
-        GetPixelComponents(image)),q);
-      if (image->colorspace == CMYKColorspace)
-        SetPixelBlack(sample_image,GetPixelBlack(image,p+x_offset[x]*
-          GetPixelComponents(image)),q);
-      if (image->matte != MagickFalse)
-        SetPixelAlpha(sample_image,GetPixelAlpha(image,p+x_offset[x]*
-          GetPixelComponents(image)),q);
-      if (image->storage_class == PseudoClass)
-        SetPixelIndex(sample_image,GetPixelIndex(image,p+x_offset[x]*
-          GetPixelComponents(image)),q);
-      q+=GetPixelComponents(sample_image);
+      register ssize_t
+        i;
+
+      if (GetPixelMask(sample_image,q) != 0)
+        {
+          q+=GetPixelChannels(sample_image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(sample_image); i++)
+      {
+        PixelChannel
+          channel;
+
+        PixelTrait
+          sample_traits,
+          traits;
+
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
+        sample_traits=GetPixelChannelMapTraits(sample_image,channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (sample_traits == UndefinedPixelTrait))
+          continue;
+        SetPixelChannel(sample_image,channel,p[x_offset[x]*GetPixelChannels(
+          image)+i],q);
+      }
+      q+=GetPixelChannels(sample_image);
     }
-    if (SyncCacheViewAuthenticPixels(sample_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(sample_view,exception)) )
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -2739,7 +2831,7 @@ MagickExport Image *SampleImage(const Image *image,const size_t columns,
         #pragma omp critical (MagickCore_SampleImage)
 #endif
         proceed=SetImageProgress(image,SampleImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
+        if( IfMagickFalse(proceed) )
           status=MagickFalse;
       }
   }
@@ -2796,16 +2888,21 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
     next_row,
     proceed;
 
-  PixelInfo
-    pixel,
+  MagickRealType
+    alpha,
+    gamma,
+    pixel[CompositePixelChannel],
     *scale_scanline,
     *scanline,
     *x_vector,
-    *y_vector,
-    zero;
+    *y_vector;
 
-  MagickRealType
-    alpha;
+  PixelChannel
+    channel;
+
+  PixelTrait
+    scale_traits,
+    traits;
 
   PointInfo
     scale,
@@ -2815,6 +2912,7 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
     i;
 
   ssize_t
+    n,
     number_rows,
     y;
 
@@ -2823,7 +2921,7 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
   */
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
@@ -2834,29 +2932,28 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
   scale_image=CloneImage(image,columns,rows,MagickTrue,exception);
   if (scale_image == (Image *) NULL)
     return((Image *) NULL);
-  if (SetImageStorageClass(scale_image,DirectClass) == MagickFalse)
+  if( IfMagickFalse(SetImageStorageClass(scale_image,DirectClass,exception)) )
     {
-      InheritException(exception,&scale_image->exception);
       scale_image=DestroyImage(scale_image);
       return((Image *) NULL);
     }
   /*
     Allocate memory.
   */
-  x_vector=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
-    sizeof(*x_vector));
+  x_vector=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+    GetPixelChannels(image)*sizeof(*x_vector));
   scanline=x_vector;
   if (image->rows != scale_image->rows)
-    scanline=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
-      sizeof(*scanline));
-  scale_scanline=(PixelInfo *) AcquireQuantumMemory((size_t)
-    scale_image->columns,sizeof(*scale_scanline));
-  y_vector=(PixelInfo *) AcquireQuantumMemory((size_t) image->columns,
-    sizeof(*y_vector));
-  if ((scanline == (PixelInfo *) NULL) ||
-      (scale_scanline == (PixelInfo *) NULL) ||
-      (x_vector == (PixelInfo *) NULL) ||
-      (y_vector == (PixelInfo *) NULL))
+    scanline=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+      GetPixelChannels(image)*sizeof(*scanline));
+  scale_scanline=(MagickRealType *) AcquireQuantumMemory((size_t)
+    scale_image->columns,MaxPixelChannels*sizeof(*scale_scanline));
+  y_vector=(MagickRealType *) AcquireQuantumMemory((size_t) image->columns,
+    GetPixelChannels(image)*sizeof(*y_vector));
+  if ((scanline == (MagickRealType *) NULL) ||
+      (scale_scanline == (MagickRealType *) NULL) ||
+      (x_vector == (MagickRealType *) NULL) ||
+      (y_vector == (MagickRealType *) NULL))
     {
       scale_image=DestroyImage(scale_image);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -2868,11 +2965,9 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
   next_row=MagickTrue;
   span.y=1.0;
   scale.y=(double) scale_image->rows/(double) image->rows;
-  (void) ResetMagickMemory(y_vector,0,(size_t) image->columns*
-    sizeof(*y_vector));
-  GetPixelInfo(image,&pixel);
-  (void) ResetMagickMemory(&zero,0,sizeof(zero));
-  i=0;
+  for (i=0; i < (ssize_t) (GetPixelChannels(image)*image->columns); i++)
+    y_vector[i]=0.0;
+  n=0;
   image_view=AcquireCacheView(image);
   scale_view=AcquireCacheView(scale_image);
   for (y=0; y < (ssize_t) scale_image->rows; y++)
@@ -2880,10 +2975,6 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
     register const Quantum
       *restrict p;
 
-    register PixelInfo
-      *restrict s,
-      *restrict t;
-
     register Quantum
       *restrict q;
 
@@ -2892,7 +2983,7 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
 
     q=QueueCacheViewAuthenticPixels(scale_view,0,y,scale_image->columns,1,
       exception);
-    if (q == (const Quantum *) NULL)
+    if (q == (Quantum *) NULL)
       break;
     alpha=1.0;
     if (scale_image->rows == image->rows)
@@ -2900,22 +2991,36 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
         /*
           Read a new scanline.
         */
-        p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+        p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
           exception);
         if (p == (const Quantum *) NULL)
           break;
         for (x=0; x < (ssize_t) image->columns; x++)
         {
-          if (image->matte != MagickFalse)
+          if (GetPixelMask(image,p) != 0)
+            {
+              p+=GetPixelChannels(image);
+              continue;
+            }
+          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+          {
+            PixelChannel
+              channel;
+
+            PixelTrait
+              traits;
+
+            channel=GetPixelChannelMapChannel(image,i);
+            traits=GetPixelChannelMapTraits(image,channel);
+            if ((traits & BlendPixelTrait) == 0)
+              {
+                x_vector[x*GetPixelChannels(image)+i]=(MagickRealType) p[i];
+                continue;
+              }
             alpha=QuantumScale*GetPixelAlpha(image,p);
-          x_vector[x].red=(MagickRealType) (alpha*GetPixelRed(image,p));
-          x_vector[x].green=(MagickRealType) (alpha*GetPixelGreen(image,p));
-          x_vector[x].blue=(MagickRealType) (alpha*GetPixelBlue(image,p));
-          if (image->matte != MagickFalse)
-            x_vector[x].alpha=(MagickRealType) GetPixelAlpha(image,p);
-          if (image->colorspace == CMYKColorspace)
-            x_vector[x].black=(MagickRealType) (alpha*GetPixelBlack(image,p));
-          p+=GetPixelComponents(image);
+            x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+          }
+          p+=GetPixelChannels(image);
         }
       }
     else
@@ -2925,96 +3030,102 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
         */
         while (scale.y < span.y)
         {
-          if ((next_row != MagickFalse) &&
-              (number_rows < (ssize_t) image->rows))
+          if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
             {
               /*
                 Read a new scanline.
               */
-              p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+              p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
                 exception);
               if (p == (const Quantum *) NULL)
                 break;
               for (x=0; x < (ssize_t) image->columns; x++)
               {
-                if (image->matte != MagickFalse)
-                  alpha=QuantumScale*
-                    GetPixelAlpha(image,p);
-                x_vector[x].red=(MagickRealType) (alpha*
-                  GetPixelRed(image,p));
-                x_vector[x].green=(MagickRealType) (alpha*
-                  GetPixelGreen(image,p));
-                x_vector[x].blue=(MagickRealType) (alpha*
-                  GetPixelBlue(image,p));
-                if (image->colorspace == CMYKColorspace)
-                  x_vector[x].black=(MagickRealType) (alpha*
-                    GetPixelBlack(image,p));
-                if (image->matte != MagickFalse)
-                  x_vector[x].alpha=(MagickRealType)
-                    GetPixelAlpha(image,p);
-                p+=GetPixelComponents(image);
+                if (GetPixelMask(image,p) != 0)
+                  {
+                    p+=GetPixelChannels(image);
+                    continue;
+                  }
+                for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+                {
+                  PixelChannel
+                    channel;
+
+                  PixelTrait
+                    traits;
+
+                  channel=GetPixelChannelMapChannel(image,i);
+                  traits=GetPixelChannelMapTraits(image,channel);
+                  if ((traits & BlendPixelTrait) == 0)
+                    {
+                      x_vector[x*GetPixelChannels(image)+i]=(MagickRealType)
+                        p[i];
+                      continue;
+                    }
+                  alpha=QuantumScale*GetPixelAlpha(image,p);
+                  x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+                }
+                p+=GetPixelChannels(image);
               }
               number_rows++;
             }
           for (x=0; x < (ssize_t) image->columns; x++)
-          {
-            y_vector[x].red+=scale.y*x_vector[x].red;
-            y_vector[x].green+=scale.y*x_vector[x].green;
-            y_vector[x].blue+=scale.y*x_vector[x].blue;
-            if (scale_image->colorspace == CMYKColorspace)
-              y_vector[x].black+=scale.y*x_vector[x].black;
-            if (scale_image->matte != MagickFalse)
-              y_vector[x].alpha+=scale.y*x_vector[x].alpha;
-          }
+            for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+              y_vector[x*GetPixelChannels(image)+i]+=scale.y*
+                x_vector[x*GetPixelChannels(image)+i];
           span.y-=scale.y;
           scale.y=(double) scale_image->rows/(double) image->rows;
           next_row=MagickTrue;
         }
-        if ((next_row != MagickFalse) && (number_rows < (ssize_t) image->rows))
+        if( IfMagickTrue(next_row) && (number_rows < (ssize_t) image->rows))
           {
             /*
               Read a new scanline.
             */
-            p=GetCacheViewVirtualPixels(image_view,0,i++,image->columns,1,
+            p=GetCacheViewVirtualPixels(image_view,0,n++,image->columns,1,
               exception);
             if (p == (const Quantum *) NULL)
               break;
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              if (image->matte != MagickFalse)
+              if (GetPixelMask(image,p) != 0)
+                {
+                  p+=GetPixelChannels(image);
+                  continue;
+                }
+              for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+              {
+                PixelChannel
+                  channel;
+
+                PixelTrait
+                  traits;
+
+                channel=GetPixelChannelMapChannel(image,i);
+                traits=GetPixelChannelMapTraits(image,channel);
+                if ((traits & BlendPixelTrait) == 0)
+                  {
+                    x_vector[x*GetPixelChannels(image)+i]=(MagickRealType)
+                      p[i];
+                    continue;
+                  }
                 alpha=QuantumScale*GetPixelAlpha(image,p);
-              x_vector[x].red=(MagickRealType) (alpha*GetPixelRed(image,p));
-              x_vector[x].green=(MagickRealType) (alpha*GetPixelGreen(image,p));
-              x_vector[x].blue=(MagickRealType) (alpha*GetPixelBlue(image,p));
-              if (image->colorspace == CMYKColorspace)
-                x_vector[x].black=(MagickRealType) (alpha*
-                  GetPixelBlack(image,p));
-              if (image->matte != MagickFalse)
-                x_vector[x].alpha=(MagickRealType) GetPixelAlpha(image,p);
-              p+=GetPixelComponents(image);
+                x_vector[x*GetPixelChannels(image)+i]=alpha*p[i];
+              }
+              p+=GetPixelChannels(image);
             }
             number_rows++;
             next_row=MagickFalse;
           }
-        s=scanline;
         for (x=0; x < (ssize_t) image->columns; x++)
         {
-          pixel.red=y_vector[x].red+span.y*x_vector[x].red;
-          pixel.green=y_vector[x].green+span.y*x_vector[x].green;
-          pixel.blue=y_vector[x].blue+span.y*x_vector[x].blue;
-          if (image->colorspace == CMYKColorspace)
-            pixel.black=y_vector[x].black+span.y*x_vector[x].black;
-          if (image->matte != MagickFalse)
-            pixel.alpha=y_vector[x].alpha+span.y*x_vector[x].alpha;
-          s->red=pixel.red;
-          s->green=pixel.green;
-          s->blue=pixel.blue;
-          if (scale_image->colorspace == CMYKColorspace)
-            s->black=pixel.black;
-          if (scale_image->matte != MagickFalse)
-            s->alpha=pixel.alpha;
-          s++;
-          y_vector[x]=zero;
+          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+          {
+            pixel[i]=y_vector[x*GetPixelChannels(image)+i]+span.y*
+              x_vector[x*GetPixelChannels(image)+i];
+            scanline[x*GetPixelChannels(image)+i]=pixel[i];
+            y_vector[x*GetPixelChannels(image)+i]=0.0;
+          }
         }
         scale.y-=span.y;
         if (scale.y <= 0)
@@ -3029,127 +3140,147 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
         /*
           Transfer scanline to scaled image.
         */
-        s=scanline;
         for (x=0; x < (ssize_t) scale_image->columns; x++)
         {
-          if (scale_image->matte != MagickFalse)
-            alpha=QuantumScale*s->alpha;
-          alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
-          SetPixelRed(scale_image,ClampToQuantum(alpha*s->red),q);
-          SetPixelGreen(scale_image,ClampToQuantum(alpha*s->green),q);
-          SetPixelBlue(scale_image,ClampToQuantum(alpha*s->blue),q);
-          if (scale_image->colorspace == CMYKColorspace)
-            SetPixelBlack(scale_image,ClampToQuantum(alpha*s->black),q);
-          if (scale_image->matte != MagickFalse)
-            SetPixelAlpha(scale_image,ClampToQuantum(s->alpha),q);
-          q+=GetPixelComponents(scale_image);
-          s++;
+          if (GetPixelMask(scale_image,q) != 0)
+            {
+              q+=GetPixelChannels(scale_image);
+              continue;
+            }
+          for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+          {
+            ssize_t
+              offset;
+
+            channel=GetPixelChannelMapChannel(scale_image,i);
+            traits=GetPixelChannelMapTraits(image,channel);
+            scale_traits=GetPixelChannelMapTraits(scale_image,channel);
+            if ((traits == UndefinedPixelTrait) ||
+                (scale_traits == UndefinedPixelTrait))
+              continue;
+            offset=GetPixelChannelMapOffset(image,channel);
+            if ((traits & BlendPixelTrait) == 0)
+              {
+                SetPixelChannel(scale_image,channel,ClampToQuantum(
+                  scanline[x*GetPixelChannels(image)+offset]),q);
+                continue;
+              }
+            alpha=QuantumScale*scanline[x*GetPixelChannels(image)+
+              GetPixelChannelMapChannel(image,AlphaPixelChannel)];
+            gamma=1.0/(fabs((double) alpha) <= MagickEpsilon ? 1.0 : alpha);
+            SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*scanline[
+              x*GetPixelChannels(image)+offset]),q);
+          }
+          q+=GetPixelChannels(scale_image);
         }
       }
     else
       {
+        ssize_t
+          n;
+
         /*
           Scale X direction.
         */
-        pixel=zero;
         next_column=MagickFalse;
+        n=0;
         span.x=1.0;
-        s=scanline;
-        t=scale_scanline;
+        for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+          pixel[i]=0.0;
         for (x=0; x < (ssize_t) image->columns; x++)
         {
           scale.x=(double) scale_image->columns/(double) image->columns;
           while (scale.x >= span.x)
           {
-            if (next_column != MagickFalse)
+            if( IfMagickTrue(next_column) )
               {
-                pixel=zero;
-                t++;
+                for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+                  pixel[i]=0.0;
+                n++;
               }
-            pixel.red+=span.x*s->red;
-            pixel.green+=span.x*s->green;
-            pixel.blue+=span.x*s->blue;
-            if (scale_image->colorspace == CMYKColorspace)
-              pixel.black+=span.x*s->black;
-            if (image->matte != MagickFalse)
-              pixel.alpha+=span.x*s->alpha;
-            t->red=pixel.red;
-            t->green=pixel.green;
-            t->blue=pixel.blue;
-            if (scale_image->colorspace == CMYKColorspace)
-              t->black=pixel.black;
-            if (scale_image->matte != MagickFalse)
-              t->alpha=pixel.alpha;
+            for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+            {
+              PixelChannel
+                channel;
+
+              PixelTrait
+                traits;
+
+              channel=GetPixelChannelMapChannel(image,i);
+              traits=GetPixelChannelMapTraits(image,channel);
+              if (traits == UndefinedPixelTrait)
+                continue;
+              pixel[i]+=span.x*scanline[x*GetPixelChannels(image)+i];
+              scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
+            }
             scale.x-=span.x;
             span.x=1.0;
             next_column=MagickTrue;
           }
         if (scale.x > 0)
           {
-            if (next_column != MagickFalse)
+            if( IfMagickTrue(next_column) )
               {
-                pixel=zero;
+                for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+                  pixel[i]=0.0;
+                n++;
                 next_column=MagickFalse;
-                t++;
               }
-            pixel.red+=scale.x*s->red;
-            pixel.green+=scale.x*s->green;
-            pixel.blue+=scale.x*s->blue;
-            if (scale_image->colorspace == CMYKColorspace)
-              pixel.black+=scale.x*s->black;
-            if (scale_image->matte != MagickFalse)
-              pixel.alpha+=scale.x*s->alpha;
+            for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+              pixel[i]+=scale.x*scanline[x*GetPixelChannels(image)+i];
             span.x-=scale.x;
           }
-        s++;
       }
       if (span.x > 0)
         {
-          s--;
-          pixel.red+=span.x*s->red;
-          pixel.green+=span.x*s->green;
-          pixel.blue+=span.x*s->blue;
-          if (scale_image->colorspace == CMYKColorspace)
-            pixel.black+=span.x*s->black;
-          if (scale_image->matte != MagickFalse)
-            pixel.alpha+=span.x*s->alpha;
+          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+            pixel[i]+=span.x*scanline[(x-1)*GetPixelChannels(image)+i];
         }
-      if ((next_column == MagickFalse) &&
-          ((ssize_t) (t-scale_scanline) < (ssize_t) scale_image->columns))
+      if( IfMagickFalse(next_column) &&
+          ((ssize_t) n < (ssize_t) scale_image->columns))
+        for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
         {
-          t->red=pixel.red;
-          t->green=pixel.green;
-          t->blue=pixel.blue;
-          if (scale_image->colorspace == CMYKColorspace)
-            t->black=pixel.black;
-          if (scale_image->matte != MagickFalse)
-            t->alpha=pixel.alpha;
+          channel=GetPixelChannelMapChannel(image,i);
+          scale_scanline[n*MaxPixelChannels+channel]=pixel[i];
         }
       /*
         Transfer scanline to scaled image.
       */
-      t=scale_scanline;
       for (x=0; x < (ssize_t) scale_image->columns; x++)
       {
-        if (scale_image->matte != MagickFalse)
-          alpha=QuantumScale*s->alpha;
-        alpha=1.0/(fabs(alpha) <= MagickEpsilon ? 1.0 : alpha);
-        SetPixelRed(scale_image,ClampToQuantum(alpha*t->red),q);
-        SetPixelGreen(scale_image,ClampToQuantum(alpha*t->green),q);
-        SetPixelBlue(scale_image,ClampToQuantum(alpha*t->blue),q);
-        if (scale_image->colorspace == CMYKColorspace)
-          SetPixelBlack(scale_image,ClampToQuantum(alpha*t->black),q);
-        if (scale_image->matte != MagickFalse)
-          SetPixelAlpha(scale_image,ClampToQuantum(t->alpha),q);
-        t++;
-        q+=GetPixelComponents(scale_image);
+        if (GetPixelMask(scale_image,q) != 0)
+          {
+            q+=GetPixelChannels(scale_image);
+            continue;
+          }
+        for (i=0; i < (ssize_t) GetPixelChannels(scale_image); i++)
+        {
+          channel=GetPixelChannelMapChannel(scale_image,i);
+          traits=GetPixelChannelMapTraits(image,channel);
+          scale_traits=GetPixelChannelMapTraits(scale_image,channel);
+          if ((traits == UndefinedPixelTrait) ||
+              (scale_traits == UndefinedPixelTrait))
+            continue;
+          if ((traits & BlendPixelTrait) == 0)
+            {
+              SetPixelChannel(scale_image,channel,ClampToQuantum(
+                scale_scanline[x*MaxPixelChannels+channel]),q);
+              continue;
+            }
+          alpha=QuantumScale*scanline[x*GetPixelChannels(image)+
+            GetPixelChannelMapChannel(image,AlphaPixelChannel)];
+          gamma=1.0/(fabs((double) alpha) <= MagickEpsilon ? 1.0 : alpha);
+          SetPixelChannel(scale_image,channel,ClampToQuantum(gamma*
+            scale_scanline[x*MaxPixelChannels+channel]),q);
+        }
+        q+=GetPixelChannels(scale_image);
       }
     }
-    if (SyncCacheViewAuthenticPixels(scale_view,exception) == MagickFalse)
+    if( IfMagickFalse(SyncCacheViewAuthenticPixels(scale_view,exception)) )
       break;
     proceed=SetImageProgress(image,ScaleImageTag,(MagickOffsetType) y,
       image->rows);
-    if (proceed == MagickFalse)
+    if( IfMagickFalse(proceed) )
       break;
   }
   scale_view=DestroyCacheView(scale_view);
@@ -3157,11 +3288,11 @@ MagickExport Image *ScaleImage(const Image *image,const size_t columns,
   /*
     Free allocated memory.
   */
-  y_vector=(PixelInfo *) RelinquishMagickMemory(y_vector);
-  scale_scanline=(PixelInfo *) RelinquishMagickMemory(scale_scanline);
+  y_vector=(MagickRealType *) RelinquishMagickMemory(y_vector);
+  scale_scanline=(MagickRealType *) RelinquishMagickMemory(scale_scanline);
   if (scale_image->rows != image->rows)
-    scanline=(PixelInfo *) RelinquishMagickMemory(scanline);
-  x_vector=(PixelInfo *) RelinquishMagickMemory(x_vector);
+    scanline=(MagickRealType *) RelinquishMagickMemory(scanline);
+  x_vector=(MagickRealType *) RelinquishMagickMemory(x_vector);
   scale_image->type=image->type;
   return(scale_image);
 }
@@ -3223,19 +3354,17 @@ MagickExport Image *ThumbnailImage(const Image *image,const size_t columns,
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
+  if( IfMagickTrue(image->debug) )
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
   x_factor=(MagickRealType) columns/(MagickRealType) image->columns;
   y_factor=(MagickRealType) rows/(MagickRealType) image->rows;
   if ((x_factor*y_factor) > 0.1)
-    thumbnail_image=ResizeImage(image,columns,rows,image->filter,image->blur,
-      exception);
+    thumbnail_image=ResizeImage(image,columns,rows,image->filter,exception);
   else
     if (((SampleFactor*columns) < 128) || ((SampleFactor*rows) < 128))
-      thumbnail_image=ResizeImage(image,columns,rows,image->filter,
-        image->blur,exception);
+      thumbnail_image=ResizeImage(image,columns,rows,image->filter,exception);
     else
       {
         Image
@@ -3246,14 +3375,14 @@ MagickExport Image *ThumbnailImage(const Image *image,const size_t columns,
         if (sample_image == (Image *) NULL)
           return((Image *) NULL);
         thumbnail_image=ResizeImage(sample_image,columns,rows,image->filter,
-          image->blur,exception);
+          exception);
         sample_image=DestroyImage(sample_image);
       }
   if (thumbnail_image == (Image *) NULL)
     return(thumbnail_image);
   (void) ParseAbsoluteGeometry("0x0+0+0",&thumbnail_image->page);
-  if (thumbnail_image->matte == MagickFalse)
-    (void) SetImageAlphaChannel(thumbnail_image,OpaqueAlphaChannel);
+  if( IfMagickFalse(thumbnail_image->matte) )
+    (void) SetImageAlphaChannel(thumbnail_image,OpaqueAlphaChannel,exception);
   thumbnail_image->depth=8;
   thumbnail_image->interlace=NoInterlace;
   /*
@@ -3274,32 +3403,35 @@ MagickExport Image *ThumbnailImage(const Image *image,const size_t columns,
   if (strstr(image->magick_filename,"//") == (char *) NULL)
     (void) FormatLocaleString(value,MaxTextExtent,"file://%s",
       image->magick_filename);
-  (void) SetImageProperty(thumbnail_image,"Thumb::URI",value);
+  (void) SetImageProperty(thumbnail_image,"Thumb::URI",value,exception);
   (void) CopyMagickString(value,image->magick_filename,MaxTextExtent);
-  if (GetPathAttributes(image->filename,&attributes) != MagickFalse)
+  if( IfMagickTrue(GetPathAttributes(image->filename,&attributes)) )
     {
       (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
         attributes.st_mtime);
-      (void) SetImageProperty(thumbnail_image,"Thumb::MTime",value);
+      (void) SetImageProperty(thumbnail_image,"Thumb::MTime",value,exception);
     }
   (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
     attributes.st_mtime);
   (void) FormatMagickSize(GetBlobSize(image),MagickFalse,value);
   (void) ConcatenateMagickString(value,"B",MaxTextExtent);
-  (void) SetImageProperty(thumbnail_image,"Thumb::Size",value);
+  (void) SetImageProperty(thumbnail_image,"Thumb::Size",value,exception);
   (void) FormatLocaleString(value,MaxTextExtent,"image/%s",image->magick);
   LocaleLower(value);
-  (void) SetImageProperty(thumbnail_image,"Thumb::Mimetype",value);
-  (void) SetImageProperty(thumbnail_image,"software",
-    GetMagickVersion(&version));
+  (void) SetImageProperty(thumbnail_image,"Thumb::Mimetype",value,exception);
+  (void) SetImageProperty(thumbnail_image,"software",GetMagickVersion(&version),
+    exception);
   (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
     image->magick_columns);
-  (void) SetImageProperty(thumbnail_image,"Thumb::Image::Width",value);
+  (void) SetImageProperty(thumbnail_image,"Thumb::Image::Width",value,
+    exception);
   (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
     image->magick_rows);
-  (void) SetImageProperty(thumbnail_image,"Thumb::Image::height",value);
+  (void) SetImageProperty(thumbnail_image,"Thumb::Image::Height",value,
+    exception);
   (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
     GetImageListLength(image));
-  (void) SetImageProperty(thumbnail_image,"Thumb::Document::Pages",value);
+  (void) SetImageProperty(thumbnail_image,"Thumb::Document::Pages",value,
+    exception);
   return(thumbnail_image);
 }