]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/pixel.c
(no commit message)
[imagemagick] / MagickCore / pixel.c
index e14f7c9bbce046854352082988ff276aeb936dc8..fbf27e31d28cb584945c093aeff0390ccc994a7a 100644 (file)
 %                  MagickCore Methods to Import/Export Pixels                 %
 %                                                                             %
 %                             Software Design                                 %
-%                               John Cristy                                   %
+%                                  Cristy                                     %
 %                               October 1998                                  %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 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  %
@@ -42,6 +42,7 @@
 #include "MagickCore/property.h"
 #include "MagickCore/blob.h"
 #include "MagickCore/blob-private.h"
+#include "MagickCore/cache-private.h"
 #include "MagickCore/color-private.h"
 #include "MagickCore/draw.h"
 #include "MagickCore/exception.h"
@@ -58,6 +59,7 @@
 #include "MagickCore/option.h"
 #include "MagickCore/pixel.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
 #include "MagickCore/quantum.h"
 #include "MagickCore/quantum-private.h"
 #include "MagickCore/resource_.h"
 #include "MagickCore/transform.h"
 #include "MagickCore/utility.h"
 \f
-#define LogPixelChannels(image) \
-{ \
-  register ssize_t \
-    i; \
- \
-  (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]", \
-    image->filename,(double) image->number_channels); \
-  for (i=0; i < (ssize_t) image->number_channels; i++) \
-  { \
-    char \
-      traits[MaxTextExtent]; \
- \
-    const char \
-      *name; \
- \
-    PixelChannel \
-      channel; \
- \
-    switch (GetPixelChannelMapChannel(image,i)) \
-    { \
-      case RedPixelChannel: \
-      { \
-        name="red"; \
-        if (image->colorspace == CMYKColorspace) \
-          name="cyan"; \
-        if (image->colorspace == GRAYColorspace) \
-          name="gray"; \
-        break; \
-      } \
-      case GreenPixelChannel: \
-      { \
-        name="green"; \
-        if (image->colorspace == CMYKColorspace) \
-          name="magenta"; \
-        break; \
-      } \
-      case BluePixelChannel: \
-      { \
-        name="blue"; \
-        if (image->colorspace == CMYKColorspace) \
-          name="yellow"; \
-        break; \
-      } \
-      case BlackPixelChannel: \
-      { \
-        name="black"; \
-        if (image->storage_class == PseudoClass) \
-          name="index"; \
-        break; \
-      } \
-      case IndexPixelChannel: \
-      { \
-        name="index"; \
-        break; \
-      } \
-      case AlphaPixelChannel: \
-      { \
-        name="alpha"; \
-        break; \
-      } \
-      case MaskPixelChannel: \
-      { \
-        name="mask"; \
-        break; \
-      } \
-      case MetaPixelChannel: \
-      { \
-        name="meta"; \
-        break; \
-      } \
-      default: \
-        name="undefined"; \
-    } \
-    channel=GetPixelChannelMapChannel(image,i); \
-    *traits='\0'; \
-    if ((GetPixelChannelMapTraits(image,channel) & UpdatePixelTrait) != 0) \
-      (void) ConcatenateMagickString(traits,"update,",MaxTextExtent); \
-    if ((GetPixelChannelMapTraits(image,channel) & BlendPixelTrait) != 0) \
-      (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent); \
-    if ((GetPixelChannelMapTraits(image,channel) & CopyPixelTrait) != 0) \
-      (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent); \
-    if (*traits == '\0') \
-      (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent); \
-    traits[strlen(traits)-1]='\0'; \
-    (void) LogMagickEvent(PixelEvent,GetMagickModule(),"  %.20g: %s (%s)", \
-      (double) i,name,traits); \
-  } \
-}
-\f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %                                                                             %
@@ -269,6 +182,95 @@ MagickExport PixelInfo *ClonePixelInfo(const PixelInfo *pixel)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   D e c o d e P i x e l G a m m a                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  DecodePixelGamma() applies the expansive power-law nonlinearity to the pixel.
+%
+%  The format of the DecodePixelGamma method is:
+%
+%      double DecodePixelGamma(const MagickRealType pixel)
+%
+%  A description of each parameter follows:
+%
+%    o pixel: the pixel.
+%
+*/
+
+static inline double DecodeGamma(const double x)
+{
+  div_t
+    quotient;
+
+  double
+    p,
+    term[9];
+
+  int
+    exponent;
+
+  static const double coefficient[] =  /* terms for x^(7/5), x=1.5 */
+  {
+    1.7917488588043277509,
+    0.82045614371976854984,
+    0.027694100686325412819,
+    -0.00094244335181762134018,
+    0.000064355540911469709545,
+    -5.7224404636060757485e-06,
+    5.8767669437311184313e-07,
+    -6.6139920053589721168e-08,
+    7.9323242696227458163e-09
+  };
+
+  static const double powers_of_two[] =  /* (2^x)^(7/5) */
+  {
+    1.0,
+    2.6390158215457883983,
+    6.9644045063689921093,
+    1.8379173679952558018e+01,
+    4.8502930128332728543e+01
+  };
+
+  /*
+    Compute x^2.4 == x*x^(7/5) == pow(x,2.4).
+  */
+  term[0]=1.0;
+  term[1]=4.0*frexp(x,&exponent)-3.0;
+  term[2]=2.0*term[1]*term[1]-term[0];
+  term[3]=2.0*term[1]*term[2]-term[1];
+  term[4]=2.0*term[1]*term[3]-term[2];
+  term[5]=2.0*term[1]*term[4]-term[3];
+  term[6]=2.0*term[1]*term[5]-term[4];
+  term[7]=2.0*term[1]*term[6]-term[5];
+  term[8]=2.0*term[1]*term[7]-term[6];
+  p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
+    coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
+    coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
+  quotient=div(exponent-1,5);
+  if (quotient.rem < 0)
+    {
+      quotient.quot-=1;
+      quotient.rem+=5;
+    }
+  return(x*ldexp(powers_of_two[quotient.rem]*p,7*quotient.quot));
+}
+
+MagickExport MagickRealType DecodePixelGamma(const MagickRealType pixel)
+{
+  if (pixel <= (0.0404482362771076*QuantumRange))
+    return(pixel/12.92f);
+  return((MagickRealType) (QuantumRange*DecodeGamma((double) (QuantumScale*
+    pixel+0.055)/1.055)));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 +   D e s t r o y P i x e l C h a n n e l M a p                               %
 %                                                                             %
 %                                                                             %
@@ -300,6 +302,102 @@ MagickExport PixelChannelMap *DestroyPixelChannelMap(
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   E n c o d e P i x e l G a m m a                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  EncodePixelGamma() cancels any nonlinearity in the pixel.
+%
+%  The format of the EncodePixelGamma method is:
+%
+%      MagickRealType EncodePixelGamma(const double MagickRealType)
+%
+%  A description of each parameter follows:
+%
+%    o pixel: the pixel.
+%
+*/
+
+static inline double EncodeGamma(const double x)
+{
+  div_t
+    quotient;
+
+  double
+    p,
+    term[9];
+
+  int
+    exponent;
+
+  static const double coefficient[] =  /* Chebychevi poly: x^(5/12), x=1.5 */
+  {
+    1.1758200232996901923,
+    0.16665763094889061230,
+    -0.0083154894939042125035,
+    0.00075187976780420279038,
+    -0.000083240178519391795367,
+    0.000010229209410070008679,
+    -1.3400466409860246e-06,
+    1.8333422241635376682e-07,
+    -2.5878596761348859722e-08
+  };
+
+  static const double powers_of_two[] =  /* (2^N)^(5/12) */
+  {
+    1.0,
+    1.3348398541700343678,
+    1.7817974362806785482,
+    2.3784142300054420538,
+    3.1748021039363991669,
+    4.2378523774371812394,
+    5.6568542494923805819,
+    7.5509945014535482244,
+    1.0079368399158985525e1,
+    1.3454342644059433809e1,
+    1.7959392772949968275e1,
+    2.3972913230026907883e1
+  };
+
+  /*
+    Compute x^(1/2.4) == x^(5/12) == pow(x,1.0/2.4).
+  */
+  term[0]=1.0;
+  term[1]=4.0*frexp(x,&exponent)-3.0;
+  term[2]=2.0*term[1]*term[1]-term[0];
+  term[3]=2.0*term[1]*term[2]-term[1];
+  term[4]=2.0*term[1]*term[3]-term[2];
+  term[5]=2.0*term[1]*term[4]-term[3];
+  term[6]=2.0*term[1]*term[5]-term[4];
+  term[7]=2.0*term[1]*term[6]-term[5];
+  term[8]=2.0*term[1]*term[7]-term[6];
+  p=coefficient[0]*term[0]+coefficient[1]*term[1]+coefficient[2]*term[2]+
+    coefficient[3]*term[3]+coefficient[4]*term[4]+coefficient[5]*term[5]+
+    coefficient[6]*term[6]+coefficient[7]*term[7]+coefficient[8]*term[8];
+  quotient=div(exponent-1,12);
+  if (quotient.rem < 0)
+    {
+      quotient.quot-=1;
+      quotient.rem+=12;
+    }
+  return(ldexp(powers_of_two[quotient.rem]*p,5*quotient.quot));
+}
+
+MagickExport MagickRealType EncodePixelGamma(const MagickRealType pixel)
+{
+  if (pixel <= (0.0031306684425005883*QuantumRange))
+    return(12.92f*pixel);
+  return((MagickRealType) QuantumRange*(1.055*EncodeGamma((double) QuantumScale*
+    pixel)-0.055));
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   E x p o r t I m a g e P i x e l s                                         %
 %                                                                             %
 %                                                                             %
@@ -308,8 +406,8 @@ MagickExport PixelChannelMap *DestroyPixelChannelMap(
 %
 %  ExportImagePixels() extracts pixel data from an image and returns it to you.
 %  The method returns MagickTrue on success otherwise MagickFalse if an error is
-%  encountered.  The data is returned as char, short int, int, ssize_t, float,
-%  or double in the order specified by map.
+%  encountered.  The data is returned as char, short int, Quantum, unsigned int,
+%  unsigned long long, float, or double in the order specified by map.
 %
 %  Suppose you want to extract the first scanline of a 640x480 image as
 %  character data in red-green-blue order:
@@ -318,16 +416,16 @@ MagickExport PixelChannelMap *DestroyPixelChannelMap(
 %
 %  The format of the ExportImagePixels method is:
 %
-%      MagickBooleanType ExportImagePixels(const Image *image,
-%        const ssize_t x_offset,const ssize_t y_offset,const size_t columns,
-%        const size_t rows,const char *map,const StorageType type,
-%        void *pixels,ExceptionInfo *exception)
+%      MagickBooleanType ExportImagePixels(const Image *image,const ssize_t x,
+%        const ssize_t y,const size_t width,const size_t height,
+%        const char *map,const StorageType type,void *pixels,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o x_offset,y_offset,columns,rows:  These values define the perimeter
+%    o x,y,width,height:  These values define the perimeter
 %      of a region of pixels you want to extract.
 %
 %    o map:  This string reflects the expected ordering of the pixel array.
@@ -338,8 +436,9 @@ MagickExport PixelChannelMap *DestroyPixelChannelMap(
 %
 %    o type: Define the data type of the pixels.  Float and double types are
 %      normalized to [0..1] otherwise [0..QuantumRange].  Choose from these
-%      types: CharPixel, DoublePixel, FloatPixel, IntegerPixel, LongPixel,
-%      QuantumPixel, or ShortPixel.
+%      types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
+%      LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
+%      QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
 %
 %    o pixels: This array of values contain the pixel components as defined by
 %      map and type.  You must preallocate this array where the expected
@@ -349,10 +448,9 @@ MagickExport PixelChannelMap *DestroyPixelChannelMap(
 %
 */
 
-static void ExportCharPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportCharPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
@@ -361,20 +459,23 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     x;
 
   register unsigned char
-    *q;
+    *restrict q;
+
+  size_t
+    length;
 
   ssize_t
     y;
 
-  q=pixels;
+  q=(unsigned char *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -386,12 +487,12 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -404,12 +505,12 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -422,14 +523,14 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToChar(GetPixelIntensity(image,p));
+          *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
           p+=GetPixelChannels(image);
         }
       }
@@ -437,12 +538,12 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -454,12 +555,12 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -472,12 +573,12 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
@@ -488,17 +589,18 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -539,7 +641,7 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
           }
           case IndexQuantum:
           {
-            *q=ScaleQuantumToChar(GetPixelIntensity(image,p));
+            *q=ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity(image,p)));
             break;
           }
           default:
@@ -552,32 +654,34 @@ static void ExportCharPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportDoublePixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
 
   register double
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   q=(double *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -589,12 +693,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -607,12 +711,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelBlue(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -625,12 +729,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelIntensity(image,p));
           p+=GetPixelChannels(image);
@@ -640,12 +744,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelRed(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -657,12 +761,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelRed(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -675,12 +779,12 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(double) (QuantumScale*GetPixelRed(image,p));
           *q++=(double) (QuantumScale*GetPixelGreen(image,p));
@@ -691,17 +795,18 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -756,32 +861,34 @@ static void ExportDoublePixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportFloatPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
 
   register float
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   q=(float *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -793,12 +900,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -811,12 +918,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelBlue(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -829,12 +936,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelIntensity(image,p));
           p+=GetPixelChannels(image);
@@ -844,12 +951,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelRed(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -861,12 +968,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelRed(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -879,12 +986,12 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=(float) (QuantumScale*GetPixelRed(image,p));
           *q++=(float) (QuantumScale*GetPixelGreen(image,p));
@@ -895,17 +1002,18 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -959,10 +1067,9 @@ static void ExportFloatPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportLongPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
@@ -971,7 +1078,10 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     x;
 
   register unsigned int
-    *q;
+    *restrict q;
+
+  size_t
+    length;
 
   ssize_t
     y;
@@ -979,16 +1089,16 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
   q=(unsigned int *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -996,17 +1106,17 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelAlpha(image,p));
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1014,17 +1124,17 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=0U;
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=0;
           p+=GetPixelChannels(image);
         }
       }
@@ -1032,15 +1142,14 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(
-            GetPixelIntensity(image,p));
+          *q++=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
           p+=GetPixelChannels(image);
         }
       }
@@ -1048,16 +1157,16 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1065,17 +1174,17 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelAlpha(image,p));
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1083,33 +1192,34 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=0U;
+          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=0;
           p+=GetPixelChannels(image);
         }
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -1117,45 +1227,44 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
           case RedQuantum:
           case CyanQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(GetPixelRed(image,p));
+            *q=ScaleQuantumToLong(GetPixelRed(image,p));
             break;
           }
           case GreenQuantum:
           case MagentaQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(GetPixelGreen(image,p));
+            *q=ScaleQuantumToLong(GetPixelGreen(image,p));
             break;
           }
           case BlueQuantum:
           case YellowQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(GetPixelBlue(image,p));
+            *q=ScaleQuantumToLong(GetPixelBlue(image,p));
             break;
           }
           case AlphaQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(GetPixelAlpha(image,p));
+            *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
             break;
           }
           case OpacityQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(GetPixelAlpha(image,p));
+            *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
             break;
           }
           case BlackQuantum:
           {
             if (image->colorspace == CMYKColorspace)
-              *q=(unsigned int) ScaleQuantumToLong(GetPixelBlack(image,p));
+              *q=ScaleQuantumToLong(GetPixelBlack(image,p));
             break;
           }
           case IndexQuantum:
           {
-            *q=(unsigned int) ScaleQuantumToLong(
-              GetPixelIntensity(image,p));
+            *q=ScaleQuantumToLong(ClampToQuantum(GetPixelIntensity(image,p)));
             break;
           }
           default:
-            *q=0;
+            break;
         }
         q++;
       }
@@ -1164,10 +1273,9 @@ static void ExportIntegerPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportLongPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportLongLongPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
@@ -1175,25 +1283,28 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
   register ssize_t
     x;
 
-  register unsigned long
-    *q;
+  register MagickSizeType
+    *restrict q;
+
+  size_t
+    length;
 
   ssize_t
     y;
 
-  q=(unsigned long *) pixels;
+  q=(MagickSizeType *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1201,17 +1312,17 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1219,16 +1330,16 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
           *q++=0;
           p+=GetPixelChannels(image);
         }
@@ -1237,14 +1348,14 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelIntensity(image,p));
+          *q++=ScaleQuantumToLongLong(ClampToQuantum(GetPixelIntensity(image,p)));
           p+=GetPixelChannels(image);
         }
       }
@@ -1252,16 +1363,16 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1269,17 +1380,17 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
-          *q++=ScaleQuantumToLong(GetPixelAlpha(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1287,33 +1398,34 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToLong(GetPixelRed(image,p));
-          *q++=ScaleQuantumToLong(GetPixelGreen(image,p));
-          *q++=ScaleQuantumToLong(GetPixelBlue(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelRed(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelGreen(image,p));
+          *q++=ScaleQuantumToLongLong(GetPixelBlue(image,p));
           *q++=0;
           p+=GetPixelChannels(image);
         }
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -1321,40 +1433,41 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
           case RedQuantum:
           case CyanQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelRed(image,p));
+            *q=ScaleQuantumToLongLong(GetPixelRed(image,p));
             break;
           }
           case GreenQuantum:
           case MagentaQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelGreen(image,p));
+            *q=ScaleQuantumToLongLong(GetPixelGreen(image,p));
             break;
           }
           case BlueQuantum:
           case YellowQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelBlue(image,p));
+            *q=ScaleQuantumToLongLong(GetPixelBlue(image,p));
             break;
           }
           case AlphaQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
+            *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
             break;
           }
           case OpacityQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelAlpha(image,p));
+            *q=ScaleQuantumToLongLong(GetPixelAlpha(image,p));
             break;
           }
           case BlackQuantum:
           {
             if (image->colorspace == CMYKColorspace)
-              *q=ScaleQuantumToLong(GetPixelBlack(image,p));
+              *q=ScaleQuantumToLongLong(GetPixelBlack(image,p));
             break;
           }
           case IndexQuantum:
           {
-            *q=ScaleQuantumToLong(GetPixelIntensity(image,p));
+            *q=ScaleQuantumToLongLong(ClampToQuantum(
+              GetPixelIntensity(image,p)));
             break;
           }
           default:
@@ -1367,32 +1480,34 @@ static void ExportLongPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportQuantumPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   q=(Quantum *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelBlue(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1404,12 +1519,12 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelBlue(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1422,12 +1537,12 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelBlue(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1440,14 +1555,14 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=GetPixelIntensity(image,p);
+          *q++=ClampToQuantum(GetPixelIntensity(image,p));
           p+=GetPixelChannels(image);
         }
       }
@@ -1455,12 +1570,12 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelRed(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1472,12 +1587,12 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelRed(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1490,12 +1605,12 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=GetPixelRed(image,p);
           *q++=GetPixelGreen(image,p);
@@ -1506,17 +1621,18 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=(Quantum) 0;
         switch (quantum_map[i])
@@ -1557,7 +1673,7 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
           }
           case IndexQuantum:
           {
-            *q=(GetPixelIntensity(image,p));
+            *q=ClampToQuantum(GetPixelIntensity(image,p));
             break;
           }
           default:
@@ -1573,10 +1689,9 @@ static void ExportQuantumPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-static void ExportShortPixel(const Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ExportShortPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
@@ -1584,21 +1699,24 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
   register ssize_t
     x;
 
+  register unsigned short
+    *restrict q;
+
+  size_t
+    length;
+
   ssize_t
     y;
 
-  register unsigned short
-    *q;
-
   q=(unsigned short *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1610,12 +1728,12 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1628,12 +1746,12 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelBlue(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1646,14 +1764,14 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          *q++=ScaleQuantumToShort(GetPixelIntensity(image,p));
+          *q++=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
           p+=GetPixelChannels(image);
         }
       }
@@ -1661,12 +1779,12 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1678,12 +1796,12 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1696,12 +1814,12 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+        p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (p == (const Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           *q++=ScaleQuantumToShort(GetPixelRed(image,p));
           *q++=ScaleQuantumToShort(GetPixelGreen(image,p));
@@ -1712,17 +1830,18 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    p=GetVirtualPixels(image,x_offset,y_offset+y,columns,1,exception);
+    p=GetVirtualPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (p == (const Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         *q=0;
         switch (quantum_map[i])
@@ -1763,7 +1882,7 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
           }
           case IndexQuantum:
           {
-            *q=ScaleQuantumToShort(GetPixelIntensity(image,p));
+            *q=ScaleQuantumToShort(ClampToQuantum(GetPixelIntensity(image,p)));
             break;
           }
           default:
@@ -1776,30 +1895,35 @@ static void ExportShortPixel(const Image *image,const ssize_t x_offset,
   }
 }
 
-MagickExport MagickBooleanType ExportImagePixels(const Image *image,
-  const ssize_t x_offset,const ssize_t y_offset,const size_t columns,
-  const size_t rows,const char *map,const StorageType type,void *pixels,
-  ExceptionInfo *exception)
+MagickExport MagickBooleanType ExportImagePixels(Image *image,const ssize_t x,
+  const ssize_t y,const size_t width,const size_t height,const char *map,
+  const StorageType type,void *pixels,ExceptionInfo *exception)
 {
   QuantumType
     *quantum_map;
 
+  RectangleInfo
+    roi;
+
   register ssize_t
     i;
 
+  size_t
+    length;
+
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  quantum_map=(QuantumType *) AcquireQuantumMemory(strlen(map),
-    sizeof(*quantum_map));
+  length=strlen(map);
+  quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
   if (quantum_map == (QuantumType *) NULL)
     {
       (void) ThrowMagickException(exception,GetMagickModule(),
         ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
       return(MagickFalse);
     }
-  for (i=0; i < (ssize_t) strlen(map); i++)
+  for (i=0; i < (ssize_t) length; i++)
   {
     switch (map[i])
     {
@@ -1898,48 +2022,45 @@ MagickExport MagickBooleanType ExportImagePixels(const Image *image,
       }
     }
   }
+  roi.width=width;
+  roi.height=height;
+  roi.x=x;
+  roi.y=y;
   switch (type)
   {
     case CharPixel:
     {
-      ExportCharPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportCharPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case DoublePixel:
     {
-      ExportDoublePixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case FloatPixel:
     {
-      ExportFloatPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
-    case IntegerPixel:
+    case LongPixel:
     {
-      ExportIntegerPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportLongPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
-    case LongPixel:
+    case LongLongPixel:
     {
-      ExportLongPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case QuantumPixel:
     {
-      ExportQuantumPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case ShortPixel:
     {
-      ExportShortPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ExportShortPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     default:
@@ -1973,7 +2094,7 @@ MagickExport MagickBooleanType ExportImagePixels(const Image *image,
 %
 %  A description of each parameter follows:
 %
-%    o image: the image.
+%    o image: the image. (optional - may be NULL)
 %
 %    o pixel: Specifies a pointer to a PixelInfo structure.
 %
@@ -1981,21 +2102,21 @@ MagickExport MagickBooleanType ExportImagePixels(const Image *image,
 MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 {
   pixel->storage_class=DirectClass;
-  pixel->colorspace=RGBColorspace;
-  pixel->matte=MagickFalse;
+  pixel->colorspace=sRGBColorspace;
+  pixel->alpha_trait=UndefinedPixelTrait;
   pixel->fuzz=0.0;
   pixel->depth=MAGICKCORE_QUANTUM_DEPTH;
   pixel->red=0.0;
   pixel->green=0.0;
   pixel->blue=0.0;
   pixel->black=0.0;
-  pixel->alpha=(MagickRealType) OpaqueAlpha;
+  pixel->alpha=(double) OpaqueAlpha;
   pixel->index=0.0;
   if (image == (const Image *) NULL)
     return;
   pixel->storage_class=image->storage_class;
   pixel->colorspace=image->colorspace;
-  pixel->matte=image->matte;
+  pixel->alpha_trait=image->alpha_trait;
   pixel->depth=image->depth;
   pixel->fuzz=image->fuzz;
 }
@@ -2005,6 +2126,153 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   G e t P i x e l I n t e n s i t y                                         %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetPixelIntensity() returns a single sample intensity value from the red,
+%  green, and blue components of a pixel based on the selected method:
+%
+%    Rec601Luma       0.298839R' + 0.586811G' + 0.114350B'
+%    Rec601Luminance  0.298839R + 0.586811G + 0.114350B
+%    Rec709Luma       0.212656R' + 0.715158G' + 0.072186B'
+%    Rec709Luminance  0.212656R + 0.715158G + 0.072186B
+%    Brightness       max(R', G', B')
+%    Lightness        (min(R', G', B') + max(R', G', B')) / 2.0
+% 
+%    MS               (R^2 + G^2 + B^2) / 3.0
+%    RMS              sqrt((R^2 + G^2 + B^2) / 3.0
+%    Average          (R + G + B') / 3.0
+%
+%  The format of the GetPixelIntensity method is:
+%
+%      MagickRealType GetPixelIntensity(const Image *image,
+%        const Quantum *pixel)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o pixel: Specifies a pointer to a Quantum structure.
+%
+*/
+
+static inline MagickRealType MagickMax(const MagickRealType x,
+  const MagickRealType y)
+{
+  if (x > y)
+    return(x);
+  return(y);
+}
+
+static inline MagickRealType MagickMin(const MagickRealType x,
+  const MagickRealType y)
+{
+  if (x < y)
+    return(x);
+  return(y);
+}
+
+MagickExport MagickRealType GetPixelIntensity(const Image *restrict image,
+  const Quantum *restrict pixel)
+{
+  MagickRealType
+    blue,
+    green,
+    red,
+    intensity;
+
+  if (image->colorspace == GRAYColorspace)
+    return((MagickRealType) GetPixelGray(image,pixel));
+  red=(MagickRealType) GetPixelRed(image,pixel);
+  green=(MagickRealType) GetPixelGreen(image,pixel);
+  blue=(MagickRealType) GetPixelBlue(image,pixel);
+  switch (image->intensity)
+  {
+    case AveragePixelIntensityMethod:
+    {
+      intensity=(red+green+blue)/3.0;
+      break;
+    }
+    case BrightnessPixelIntensityMethod:
+    {
+      intensity=MagickMax(MagickMax(red,green),blue);
+      break;
+    }
+    case LightnessPixelIntensityMethod:
+    {
+      intensity=(MagickMin(MagickMin(red,green),blue)+
+        MagickMax(MagickMax(red,green),blue))/2.0;
+      break;
+    }
+    case MSPixelIntensityMethod:
+    {
+      intensity=(MagickRealType) (((double) red*red+green*green+blue*blue)/
+        (3.0*QuantumRange));
+      break;
+    }
+    case Rec601LumaPixelIntensityMethod:
+    {
+      if (image->colorspace == RGBColorspace)
+        {
+          red=EncodePixelGamma(red);
+          green=EncodePixelGamma(green);
+          blue=EncodePixelGamma(blue);
+        }
+      intensity=0.298839*red+0.586811*green+0.114350*blue;
+      break;
+    }
+    case Rec601LuminancePixelIntensityMethod:
+    {
+      if (image->colorspace == sRGBColorspace)
+        {
+          red=DecodePixelGamma(red);
+          green=DecodePixelGamma(green);
+          blue=DecodePixelGamma(blue);
+        }
+      intensity=0.298839*red+0.586811*green+0.114350*blue;
+      break;
+    }
+    case Rec709LumaPixelIntensityMethod:
+    default:
+    {
+      if (image->colorspace == RGBColorspace)
+        {
+          red=EncodePixelGamma(red);
+          green=EncodePixelGamma(green);
+          blue=EncodePixelGamma(blue);
+        }
+      intensity=0.212656*red+0.715158*green+0.072186*blue;
+      break;
+    }
+    case Rec709LuminancePixelIntensityMethod:
+    {
+      if (image->colorspace == sRGBColorspace)
+        {
+          red=DecodePixelGamma(red);
+          green=DecodePixelGamma(green);
+          blue=DecodePixelGamma(blue);
+        }
+      intensity=0.212656*red+0.715158*green+0.072186*blue;
+      break;
+    }
+    case RMSPixelIntensityMethod:
+    {
+      intensity=(MagickRealType) (sqrt((double) red*red+green*green+blue*blue)/
+        sqrt(3.0));
+      break;
+    }
+  }
+  return(intensity);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   I m p o r t I m a g e P i x e l s                                         %
 %                                                                             %
 %                                                                             %
@@ -2014,7 +2282,8 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 %  ImportImagePixels() accepts pixel data and stores in the image at the
 %  location you specify.  The method returns MagickTrue on success otherwise
 %  MagickFalse if an error is encountered.  The pixel data can be either char,
-%  short int, int, ssize_t, float, or double in the order specified by map.
+%  Quantum, short int, unsigned int, unsigned long long, float, or double in
+%  the order specified by map.
 %
 %  Suppose your want to upload the first scanline of a 640x480 image from
 %  character data in red-green-blue order:
@@ -2023,16 +2292,16 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 %
 %  The format of the ImportImagePixels method is:
 %
-%      MagickBooleanType ImportImagePixels(Image *image,const ssize_t x_offset,
-%        const ssize_t y_offset,const size_t columns,
-%        const size_t rows,const char *map,const StorageType type,
-%        const void *pixels,ExceptionInfo *exception)
+%      MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
+%        const ssize_t y,const size_t width,const size_t height,
+%        const char *map,const StorageType type,const void *pixels,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o x_offset,y_offset,columns,rows:  These values define the perimeter
+%    o x,y,width,height:  These values define the perimeter
 %      of a region of pixels you want to define.
 %
 %    o map:  This string reflects the expected ordering of the pixel array.
@@ -2043,8 +2312,9 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 %
 %    o type: Define the data type of the pixels.  Float and double types are
 %      normalized to [0..1] otherwise [0..QuantumRange].  Choose from these
-%      types: CharPixel, ShortPixel, IntegerPixel, LongPixel, FloatPixel, or
-%      DoublePixel.
+%      types: CharPixel (char *), DoublePixel (double *), FloatPixel (float *),
+%      LongPixel (unsigned int *), LongLongPixel (unsigned long long *),
+%      QuantumPixel (Quantum *), or ShortPixel (unsigned short *).
 %
 %    o pixels: This array of values contain the pixel components as defined by
 %      map and type.  You must preallocate this array where the expected
@@ -2054,32 +2324,34 @@ MagickExport void GetPixelInfo(const Image *image,PixelInfo *pixel)
 %
 */
 
-static void ImportCharPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportCharPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const unsigned char
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const unsigned char *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2093,12 +2365,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2113,12 +2385,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRO") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2133,12 +2405,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2153,12 +2425,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelGray(image,ScaleCharToQuantum(*p++),q);
           q+=GetPixelChannels(image);
@@ -2170,12 +2442,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2189,12 +2461,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2209,12 +2481,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBO") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2229,12 +2501,12 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
@@ -2247,17 +2519,18 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
@@ -2311,41 +2584,40 @@ static void ImportCharPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportDoublePixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportDoublePixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const double
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const double *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2356,24 +2628,20 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelAlpha(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2384,21 +2652,18 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           p++;
           q+=GetPixelChannels(image);
@@ -2410,15 +2675,14 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelGray(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2429,21 +2693,18 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2454,24 +2715,20 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelAlpha(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2482,21 +2739,18 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2505,63 +2759,57 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+   length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
           case RedQuantum:
           case CyanQuantum:
           {
-            SetPixelRed(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case GreenQuantum:
           case MagentaQuantum:
           {
-            SetPixelGreen(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case BlueQuantum:
           case YellowQuantum:
           {
-            SetPixelBlue(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case AlphaQuantum:
           {
-            SetPixelAlpha(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case OpacityQuantum:
           {
-            SetPixelAlpha(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case BlackQuantum:
           {
-            SetPixelBlack(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case IndexQuantum:
           {
-            SetPixelGray(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           default:
@@ -2576,41 +2824,40 @@ static void ImportDoublePixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportFloatPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportFloatPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const float
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const float *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2621,24 +2868,20 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelAlpha(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2649,21 +2892,18 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           p++;
           q+=GetPixelChannels(image);
@@ -2675,15 +2915,14 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelGray(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2694,21 +2933,18 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2719,24 +2955,20 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType)
-            QuantumRange*(*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelAlpha(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2747,21 +2979,18 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelGreen(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
-          SetPixelBlue(image,ClampToQuantum((MagickRealType) QuantumRange*
-            (*p)),q);
+          SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -2770,63 +2999,57 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
           case RedQuantum:
           case CyanQuantum:
           {
-            SetPixelRed(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelRed(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case GreenQuantum:
           case MagentaQuantum:
           {
-            SetPixelGreen(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelGreen(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case BlueQuantum:
           case YellowQuantum:
           {
-            SetPixelBlue(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelBlue(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case AlphaQuantum:
           {
-            SetPixelAlpha(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case OpacityQuantum:
           {
-            SetPixelAlpha(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelAlpha(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case BlackQuantum:
           {
-            SetPixelBlack(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelBlack(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           case IndexQuantum:
           {
-            SetPixelGray(image,ClampToQuantum((MagickRealType)
-              QuantumRange*(*p)),q);
+            SetPixelGray(image,ClampToQuantum(QuantumRange*(*p)),q);
             break;
           }
           default:
@@ -2841,32 +3064,34 @@ static void ImportFloatPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportLongPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const unsigned int
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const unsigned int *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2880,12 +3105,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2900,12 +3125,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2920,12 +3145,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelGray(image,ScaleLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
@@ -2937,12 +3162,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2956,12 +3181,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2976,12 +3201,12 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleLongToQuantum(*p++),q);
           SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
@@ -2994,17 +3219,18 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
@@ -3058,36 +3284,38 @@ static void ImportIntegerPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportLongPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportLongLongPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
-  register const unsigned long
+  register const MagickSizeType
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
-  p=(const unsigned long *) pixels;
+  p=(const MagickSizeType *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -3097,17 +3325,17 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
-          SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -3117,16 +3345,16 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -3137,14 +3365,14 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelGray(image,ScaleLongToQuantum(*p++),q);
+          SetPixelGray(image,ScaleLongLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -3154,16 +3382,16 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -3173,17 +3401,17 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
-          SetPixelAlpha(image,ScaleLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelAlpha(image,ScaleLongLongToQuantum(*p++),q);
           q+=GetPixelChannels(image);
         }
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -3193,16 +3421,16 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
-          SetPixelRed(image,ScaleLongToQuantum(*p++),q);
-          SetPixelGreen(image,ScaleLongToQuantum(*p++),q);
-          SetPixelBlue(image,ScaleLongToQuantum(*p++),q);
+          SetPixelRed(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelGreen(image,ScaleLongLongToQuantum(*p++),q);
+          SetPixelBlue(image,ScaleLongLongToQuantum(*p++),q);
           p++;
           q+=GetPixelChannels(image);
         }
@@ -3211,56 +3439,57 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
           case RedQuantum:
           case CyanQuantum:
           {
-            SetPixelRed(image,ScaleLongToQuantum(*p),q);
+            SetPixelRed(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case GreenQuantum:
           case MagentaQuantum:
           {
-            SetPixelGreen(image,ScaleLongToQuantum(*p),q);
+            SetPixelGreen(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case BlueQuantum:
           case YellowQuantum:
           {
-            SetPixelBlue(image,ScaleLongToQuantum(*p),q);
+            SetPixelBlue(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case AlphaQuantum:
           {
-            SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
+            SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case OpacityQuantum:
           {
-            SetPixelAlpha(image,ScaleLongToQuantum(*p),q);
+            SetPixelAlpha(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case BlackQuantum:
           {
-            SetPixelBlack(image,ScaleLongToQuantum(*p),q);
+            SetPixelBlack(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           case IndexQuantum:
           {
-            SetPixelGray(image,ScaleLongToQuantum(*p),q);
+            SetPixelGray(image,ScaleLongLongToQuantum(*p),q);
             break;
           }
           default:
@@ -3275,32 +3504,34 @@ static void ImportLongPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportQuantumPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const Quantum
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const Quantum *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3314,12 +3545,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3334,12 +3565,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3354,12 +3585,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelGray(image,*p++,q);
           q+=GetPixelChannels(image);
@@ -3371,12 +3602,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3390,12 +3621,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3410,12 +3641,12 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,*p++,q);
           SetPixelGreen(image,*p++,q);
@@ -3428,17 +3659,18 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
@@ -3492,32 +3724,34 @@ static void ImportQuantumPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-static void ImportShortPixel(Image *image,const ssize_t x_offset,
-  const ssize_t y_offset,const size_t columns,const size_t rows,
-  const char *restrict map,const QuantumType *quantum_map,
-  const unsigned char *restrict pixels,ExceptionInfo *exception)
+static void ImportShortPixel(Image *image,const RectangleInfo *roi,
+  const char *restrict map,const QuantumType *quantum_map,const void *pixels,
+  ExceptionInfo *exception)
 {
   register const unsigned short
     *restrict p;
 
   register Quantum
-    *q;
+    *restrict q;
 
   register ssize_t
     x;
 
+  size_t
+    length;
+
   ssize_t
     y;
 
   p=(const unsigned short *) pixels;
   if (LocaleCompare(map,"BGR") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3531,12 +3765,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3551,12 +3785,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"BGRP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelBlue(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3571,12 +3805,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"I") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelGray(image,ScaleShortToQuantum(*p++),q);
           q+=GetPixelChannels(image);
@@ -3588,12 +3822,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGB") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3607,12 +3841,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBA") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3627,12 +3861,12 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
     }
   if (LocaleCompare(map,"RGBP") == 0)
     {
-      for (y=0; y < (ssize_t) rows; y++)
+      for (y=0; y < (ssize_t) roi->height; y++)
       {
-        q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+        q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
         if (q == (Quantum *) NULL)
           break;
-        for (x=0; x < (ssize_t) columns; x++)
+        for (x=0; x < (ssize_t) roi->width; x++)
         {
           SetPixelRed(image,ScaleShortToQuantum(*p++),q);
           SetPixelGreen(image,ScaleShortToQuantum(*p++),q);
@@ -3645,17 +3879,18 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
       }
       return;
     }
-  for (y=0; y < (ssize_t) rows; y++)
+  length=strlen(map);
+  for (y=0; y < (ssize_t) roi->height; y++)
   {
-    q=GetAuthenticPixels(image,x_offset,y_offset+y,columns,1,exception);
+    q=GetAuthenticPixels(image,roi->x,roi->y+y,roi->width,1,exception);
     if (q == (Quantum *) NULL)
       break;
-    for (x=0; x < (ssize_t) columns; x++)
+    for (x=0; x < (ssize_t) roi->width; x++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) strlen(map); i++)
+      for (i=0; i < (ssize_t) length; i++)
       {
         switch (quantum_map[i])
         {
@@ -3709,17 +3944,22 @@ static void ImportShortPixel(Image *image,const ssize_t x_offset,
   }
 }
 
-MagickExport MagickBooleanType ImportImagePixels(Image *image,
-  const ssize_t x_offset,const ssize_t y_offset,const size_t columns,
-  const size_t rows,const char *map,const StorageType type,
-  const void *pixels,ExceptionInfo *exception)
+MagickExport MagickBooleanType ImportImagePixels(Image *image,const ssize_t x,
+  const ssize_t y,const size_t width,const size_t height,const char *map,
+  const StorageType type,const void *pixels,ExceptionInfo *exception)
 {
   QuantumType
     *quantum_map;
 
+  RectangleInfo
+    roi;
+
   register ssize_t
     i;
 
+  size_t
+    length;
+
   /*
     Allocate image structure.
   */
@@ -3727,12 +3967,12 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  quantum_map=(QuantumType *) AcquireQuantumMemory(strlen(map),
-    sizeof(*quantum_map));
+  length=strlen(map);
+  quantum_map=(QuantumType *) AcquireQuantumMemory(length,sizeof(*quantum_map));
   if (quantum_map == (QuantumType *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
       image->filename);
-  for (i=0; i < (ssize_t) strlen(map); i++)
+  for (i=0; i < (ssize_t) length; i++)
   {
     switch (map[i])
     {
@@ -3740,7 +3980,7 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
       case 'A':
       {
         quantum_map[i]=AlphaQuantum;
-        image->matte=MagickTrue;
+        image->alpha_trait=BlendPixelTrait;
         break;
       }
       case 'B':
@@ -3773,6 +4013,7 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
       case 'i':
       {
         quantum_map[i]=IndexQuantum;
+        (void) SetImageColorspace(image,GRAYColorspace,exception);
         break;
       }
       case 'm':
@@ -3786,7 +4027,7 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
       case 'o':
       {
         quantum_map[i]=OpacityQuantum;
-        image->matte=MagickTrue;
+        image->alpha_trait=BlendPixelTrait;
         break;
       }
       case 'P':
@@ -3822,55 +4063,52 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
   /*
     Transfer the pixels from the pixel data to the image.
   */
+  roi.width=width;
+  roi.height=height;
+  roi.x=x;
+  roi.y=y;
   switch (type)
   {
     case CharPixel:
     {
-      ImportCharPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportCharPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case DoublePixel:
     {
-      ImportDoublePixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportDoublePixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case FloatPixel:
     {
-      ImportFloatPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportFloatPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
-    case IntegerPixel:
+    case LongPixel:
     {
-      ImportIntegerPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportLongPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
-    case LongPixel:
+    case LongLongPixel:
     {
-      ImportLongPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportLongLongPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case QuantumPixel:
     {
-      ImportQuantumPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportQuantumPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     case ShortPixel:
     {
-      ImportShortPixel(image,x_offset,y_offset,columns,rows,map,quantum_map,
-        pixels,exception);
+      ImportShortPixel(image,&roi,map,quantum_map,pixels,exception);
       break;
     }
     default:
     {
       quantum_map=(QuantumType *) RelinquishMagickMemory(quantum_map);
       (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-        "UnrecognizedPixelMap","`%s'",map);
+        "UnrecognizedStorageType","`%d'",type);
       break;
     }
   }
@@ -3900,6 +4138,101 @@ MagickExport MagickBooleanType ImportImagePixels(Image *image,
 %    o image: the image.
 %
 */
+
+static void LogPixelChannels(const Image *image)
+{
+  register ssize_t
+    i;
+
+  (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%.20g]",
+    image->filename,(double) image->number_channels);
+  for (i=0; i < (ssize_t) image->number_channels; i++)
+  {
+    char
+      traits[MaxTextExtent];
+
+    const char
+      *name;
+
+    PixelChannel
+      channel;
+
+    switch (GetPixelChannelChannel(image,i))
+    {
+      case RedPixelChannel:
+      {
+        name="red";
+        if (image->colorspace == CMYKColorspace)
+          name="cyan";
+        if (image->colorspace == GRAYColorspace)
+          name="gray";
+        break;
+      }
+      case GreenPixelChannel:
+      {
+        name="green";
+        if (image->colorspace == CMYKColorspace)
+          name="magenta";
+        break;
+      }
+      case BluePixelChannel:
+      {
+        name="blue";
+        if (image->colorspace == CMYKColorspace)
+          name="yellow";
+        break;
+      }
+      case BlackPixelChannel:
+      {
+        name="black";
+        if (image->storage_class == PseudoClass)
+          name="index";
+        break;
+      }
+      case IndexPixelChannel:
+      {
+        name="index";
+        break;
+      }
+      case AlphaPixelChannel:
+      {
+        name="alpha";
+        break;
+      }
+      case ReadMaskPixelChannel:
+      {
+        name="read-mask";
+        break;
+      }
+      case WriteMaskPixelChannel:
+      {
+        name="write-mask";
+        break;
+      }
+      case MetaPixelChannel:
+      {
+        name="meta";
+        break;
+      }
+      default:
+        name="undefined";
+    }
+    channel=GetPixelChannelChannel(image,i);
+    *traits='\0';
+    if ((GetPixelChannelTraits(image,channel) & UpdatePixelTrait) != 0)
+      (void) ConcatenateMagickString(traits,"update,",MaxTextExtent);
+    if ((GetPixelChannelTraits(image,channel) & BlendPixelTrait) != 0)
+      (void) ConcatenateMagickString(traits,"blend,",MaxTextExtent);
+    if ((GetPixelChannelTraits(image,channel) & CopyPixelTrait) != 0)
+      (void) ConcatenateMagickString(traits,"copy,",MaxTextExtent);
+    if (*traits == '\0')
+      (void) ConcatenateMagickString(traits,"undefined,",MaxTextExtent);
+    traits[strlen(traits)-1]='\0';
+    (void) LogMagickEvent(PixelEvent,GetMagickModule(),"  %.20g: %s (%s)",
+      (double) i,name,traits);
+  }
+}
+
 MagickExport void InitializePixelChannelMap(Image *image)
 {
   PixelTrait
@@ -3916,35 +4249,39 @@ MagickExport void InitializePixelChannelMap(Image *image)
   (void) ResetMagickMemory(image->channel_map,0,MaxPixelChannels*
     sizeof(*image->channel_map));
   trait=UpdatePixelTrait;
-  if (image->matte != MagickFalse)
+  if (image->alpha_trait == BlendPixelTrait)
     trait=(PixelTrait) (trait | BlendPixelTrait);
   n=0;
   if (image->colorspace == GRAYColorspace)
     {
-      SetPixelChannelMap(image,BluePixelChannel,trait,n);
-      SetPixelChannelMap(image,GreenPixelChannel,trait,n);
-      SetPixelChannelMap(image,RedPixelChannel,trait,n++);
+      SetPixelChannelAttributes(image,BluePixelChannel,trait,n);
+      SetPixelChannelAttributes(image,GreenPixelChannel,trait,n);
+      SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
     }
   else
     {
-      SetPixelChannelMap(image,RedPixelChannel,trait,n++);
-      SetPixelChannelMap(image,GreenPixelChannel,trait,n++);
-      SetPixelChannelMap(image,BluePixelChannel,trait,n++);
+      SetPixelChannelAttributes(image,RedPixelChannel,trait,n++);
+      SetPixelChannelAttributes(image,GreenPixelChannel,trait,n++);
+      SetPixelChannelAttributes(image,BluePixelChannel,trait,n++);
     }
   if (image->colorspace == CMYKColorspace)
-    SetPixelChannelMap(image,BlackPixelChannel,trait,n++);
-  if (image->matte != MagickFalse)
-    SetPixelChannelMap(image,AlphaPixelChannel,CopyPixelTrait,n++);
+    SetPixelChannelAttributes(image,BlackPixelChannel,trait,n++);
+  if (image->alpha_trait != UndefinedPixelTrait)
+    SetPixelChannelAttributes(image,AlphaPixelChannel,CopyPixelTrait,n++);
   if (image->storage_class == PseudoClass)
-    SetPixelChannelMap(image,IndexPixelChannel,CopyPixelTrait,n++);
+    SetPixelChannelAttributes(image,IndexPixelChannel,CopyPixelTrait,n++);
+  if (image->read_mask != MagickFalse)
+    SetPixelChannelAttributes(image,ReadMaskPixelChannel,CopyPixelTrait,n++);
+  if (image->write_mask != MagickFalse)
+    SetPixelChannelAttributes(image,WriteMaskPixelChannel,CopyPixelTrait,n++);
   assert((n+image->number_meta_channels) < MaxPixelChannels);
   for (i=0; i < (ssize_t) image->number_meta_channels; i++)
-    SetPixelChannelMap(image,(PixelChannel) (MetaPixelChannel+i),CopyPixelTrait,
-      n++);
+    SetPixelChannelAttributes(image,(PixelChannel) (MetaPixelChannel+i),
+      CopyPixelTrait,n++);
   image->number_channels=(size_t) n;
   if (image->debug != MagickFalse)
     LogPixelChannels(image);
-  (void) SetPixelChannelMask(image,image->channel_mask);
+  (void) SetImageChannelMask(image,image->channel_mask);
 }
 \f
 /*
@@ -3962,6 +4299,8 @@ MagickExport void InitializePixelChannelMap(Image *image)
 %  floating point coordinate and the pixels surrounding that coordinate.  No
 %  pixel area resampling, or scaling of the result is performed.
 %
+%  Interpolation is restricted to just the specified channel.
+%
 %  The format of the InterpolatePixelChannel method is:
 %
 %      MagickBooleanType InterpolatePixelChannel(const Image *image,
@@ -3987,28 +4326,51 @@ MagickExport void InitializePixelChannelMap(Image *image)
 %
 */
 
-static inline double MagickMax(const MagickRealType x,const MagickRealType y)
+static inline void CatromWeights(const double x,double (*weights)[4])
 {
-  if (x > y)
-    return(x);
-  return(y);
+  double
+    alpha,
+    beta,
+    gamma;
+
+  /*
+    Nicolas Robidoux' 10 flops (4* + 5- + 1+) refactoring of the computation
+    of the standard four 1D Catmull-Rom weights. The sampling location is
+    assumed between the second and third input pixel locations, and x is the
+    position relative to the second input pixel location. Formulas originally
+    derived for the VIPS (Virtual Image Processing System) library.
+  */
+  alpha=(double) 1.0-x;
+  beta=(double) (-0.5)*x*alpha;
+  (*weights)[0]=alpha*beta;
+  (*weights)[3]=x*beta;
+  /*
+    The following computation of the inner weights from the outer ones work
+    for all Keys cubics.
+  */
+  gamma=(*weights)[3]-(*weights)[0];
+  (*weights)[1]=alpha-(*weights)[0]+gamma;
+  (*weights)[2]=x-(*weights)[3]-gamma;
 }
 
-static inline MagickRealType CubicWeightingFunction(const MagickRealType x)
+static inline void SplineWeights(const double x,double (*weights)[4])
 {
-  MagickRealType
+  double
     alpha,
-    gamma;
+    beta;
 
-  alpha=MagickMax(x+2.0,0.0);
-  gamma=1.0*alpha*alpha*alpha;
-  alpha=MagickMax(x+1.0,0.0);
-  gamma-=4.0*alpha*alpha*alpha;
-  alpha=MagickMax(x+0.0,0.0);
-  gamma+=6.0*alpha*alpha*alpha;
-  alpha=MagickMax(x-1.0,0.0);
-  gamma-=4.0*alpha*alpha*alpha;
-  return(gamma/6.0);
+  /*
+    Nicolas Robidoux' 12 flops (6* + 5- + 1+) refactoring of the computation
+    of the standard four 1D cubic B-spline smoothing weights. The sampling
+    location is assumed between the second and third input pixel locations,
+    and x is the position relative to the second input pixel location.
+  */
+  alpha=(double) 1.0-x;
+  (*weights)[3]=(double) (1.0/6.0)*x*x*x;
+  (*weights)[0]=(double) (1.0/6.0)*alpha*alpha*alpha;
+  beta=(*weights)[3]-(*weights)[0];
+  (*weights)[1]=alpha-(*weights)[0]+beta;
+  (*weights)[2]=x-(*weights)[3]-beta;
 }
 
 static inline double MeshInterpolate(const PointInfo *delta,const double p,
@@ -4017,26 +4379,31 @@ static inline double MeshInterpolate(const PointInfo *delta,const double p,
   return(delta->x*x+delta->y*y+(1.0-delta->x-delta->y)*p);
 }
 
-static inline ssize_t NearestNeighbor(const MagickRealType x)
+/*
+static inline ssize_t NearestNeighbor(const double x)
 {
   if (x >= 0.0)
     return((ssize_t) (x+0.5));
   return((ssize_t) (x-0.5));
 }
+*/
 
 MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
   const CacheView *image_view,const PixelChannel channel,
   const PixelInterpolateMethod method,const double x,const double y,
   double *pixel,ExceptionInfo *exception)
 {
-  MagickBooleanType
-    status;
-
-  MagickRealType
+  double
     alpha[16],
     gamma,
     pixels[16];
 
+  MagickBooleanType
+    status;
+
+  PixelInterpolateMethod
+    interpolate;
+
   PixelTrait
     traits;
 
@@ -4056,64 +4423,84 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
   assert(image_view != (CacheView *) NULL);
   status=MagickTrue;
   *pixel=0.0;
-  traits=GetPixelChannelMapTraits(image,channel);
+  traits=GetPixelChannelTraits(image,channel);
   x_offset=(ssize_t) floor(x);
   y_offset=(ssize_t) floor(y);
-  switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
+  interpolate = method;
+  if ( interpolate == UndefinedInterpolatePixel )
+    interpolate = image->interpolate;
+  switch (interpolate)
   {
-    case AverageInterpolatePixel:
+    case AverageInterpolatePixel:  /* nearest 4 neighbours */
+    case Average9InterpolatePixel:  /* nearest 9 neighbours */
+    case Average16InterpolatePixel:  /* nearest 16 neighbours */
     {
-      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
-        exception);
+      ssize_t
+        count;
+
+      count=2;  /* size of the area to average - default nearest 4 */
+      if (interpolate == Average9InterpolatePixel)
+        {
+          count=3;
+          x_offset=(ssize_t) (floor(x+0.5)-1);
+          y_offset=(ssize_t) (floor(y+0.5)-1);
+        }
+      else
+        if (interpolate == Average16InterpolatePixel)
+          {
+            count=4;
+            x_offset--;
+            y_offset--;
+          }
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
+        (size_t) count,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
+      count*=count;  /* Number of pixels to average */
       if ((traits & BlendPixelTrait) == 0)
-        for (i=0; i < 16; i++)
+        for (i=0; i < (ssize_t) count; i++)
         {
           alpha[i]=1.0;
-          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+          pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
         }
       else
-        for (i=0; i < 16; i++)
+        for (i=0; i < (ssize_t) count; i++)
         {
           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
             GetPixelChannels(image));
           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
         }
-      for (i=0; i < 16; i++)
+      for (i=0; i < (ssize_t) count; i++)
       {
-        gamma=1.0/(fabs((double) alpha[i]) <= MagickEpsilon ? 1.0 : alpha[i]);
-        *pixel+=gamma*0.0625*pixels[i];
+        gamma=PerceptibleReciprocal(alpha[i])/count;
+        *pixel+=gamma*pixels[i];
       }
       break;
     }
-    case BicubicInterpolatePixel:
+    case BilinearInterpolatePixel:
+    default:
     {
-      MagickRealType
-        u[4],
-        v[4];
-
       PointInfo
-        delta;
+        delta,
+        epsilon;
 
-      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
-        exception);
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
       if ((traits & BlendPixelTrait) == 0)
-        for (i=0; i < 16; i++)
+        for (i=0; i < 4; i++)
         {
           alpha[i]=1.0;
-          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+          pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
         }
       else
-        for (i=0; i < 16; i++)
+        for (i=0; i < 4; i++)
         {
           alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
             GetPixelChannels(image));
@@ -4121,30 +4508,17 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         }
       delta.x=x-x_offset;
       delta.y=y-y_offset;
-      for (i=0; i < 4; i++)
-      {
-        u[0]=(pixels[4*i+3]-pixels[4*i+2])-(pixels[4*i+0]-pixels[4*i+1]);
-        u[1]=(pixels[4*i+0]-pixels[4*i+1])-u[0];
-        u[2]=pixels[4*i+2]-pixels[4*i+0];
-        u[3]=pixels[4*i+1];
-        v[i]=(delta.x*delta.x*delta.x*u[0])+(delta.x*delta.x*u[1])+(delta.x*
-          u[2])+u[3];
-      }
-      u[0]=(v[3]-v[2])-(v[0]-v[1]);
-      u[1]=(v[0]-v[1])-u[0];
-      u[2]=v[2]-v[0];
-      u[3]=v[1];
-      *pixel=(delta.y*delta.y*delta.y*u[0])+(delta.y*delta.y*u[1])+(delta.y*
-        u[2])+u[3];
+      epsilon.x=1.0-delta.x;
+      epsilon.y=1.0-delta.y;
+      gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
+        (epsilon.x*alpha[2]+delta.x*alpha[3])));
+      gamma=PerceptibleReciprocal(gamma);
+      *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
+        (epsilon.x*pixels[2]+delta.x*pixels[3]));
       break;
     }
-    case BilinearInterpolatePixel:
-    default:
+    case BlendInterpolatePixel:
     {
-      PointInfo
-        delta,
-        epsilon;
-
       p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
       if (p == (const Quantum *) NULL)
         {
@@ -4164,52 +4538,79 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
             GetPixelChannels(image));
           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
         }
-      delta.x=x-x_offset;
-      delta.y=y-y_offset;
-      epsilon.x=1.0-delta.x;
-      epsilon.y=1.0-delta.y;
-      gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
-        (epsilon.x*alpha[2]+delta.x*alpha[3])));
-      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
-      *pixel=gamma*(epsilon.y*(epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*
-        (epsilon.x*pixels[2]+delta.x*pixels[3]));
+      gamma=1.0;  /* number of pixels blended together (its variable) */
+      for (i=0; i <= 1L; i++) {
+        if ((y-y_offset) >= 0.75)
+          {
+            alpha[i]=alpha[i+2];  /* take right pixels */
+            pixels[i]=pixels[i+2];
+          }
+        else
+          if ((y-y_offset) > 0.25)
+            {
+              gamma=2.0;  /* blend both pixels in row */
+              alpha[i]+=alpha[i+2];  /* add up alpha weights */
+              pixels[i]+=pixels[i+2];
+            }
+      }
+      if ((x-x_offset) >= 0.75)
+        {
+          alpha[0]=alpha[1];  /* take bottom row blend */
+          pixels[0]=pixels[1];
+        }
+      else
+        if ((x-x_offset) > 0.25)
+          {
+            gamma*=2.0;  /* blend both rows */
+            alpha[0]+=alpha[1];  /* add up alpha weights */
+            pixels[0]+=pixels[1];
+          }
+      if (channel != AlphaPixelChannel)
+        gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
+      else
+        gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
+      *pixel=gamma*pixels[0];
       break;
     }
-    case FilterInterpolatePixel:
+    case CatromInterpolatePixel:
     {
-      CacheView
-        *filter_view;
-
-      Image
-        *excerpt_image,
-        *filter_image;
-
-      RectangleInfo
-        geometry;
+      double
+        cx[4],
+        cy[4];
 
-      geometry.width=4L;
-      geometry.height=4L;
-      geometry.x=x_offset-1;
-      geometry.y=y_offset-1;
-      excerpt_image=ExcerptImage(image,&geometry,exception);
-      if (excerpt_image == (Image *) NULL)
+      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
+        exception);
+      if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
-      filter_image=ResizeImage(excerpt_image,1,1,image->filter,image->blur,
-        exception);
-      excerpt_image=DestroyImage(excerpt_image);
-      if (filter_image == (Image *) NULL)
-        break;
-      filter_view=AcquireCacheView(filter_image);
-      p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
-      if (p == (const Quantum *) NULL)
-        status=MagickFalse;
+      if ((traits & BlendPixelTrait) == 0)
+        for (i=0; i < 16; i++)
+        {
+          alpha[i]=1.0;
+          pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
+        }
       else
-        *pixel=(double) GetPixelChannel(image,channel,p);
-      filter_view=DestroyCacheView(filter_view);
-      filter_image=DestroyImage(filter_image);
+        for (i=0; i < 16; i++)
+        {
+          alpha[i]=QuantumScale*GetPixelAlpha(image,p+i*
+            GetPixelChannels(image));
+          pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
+        }
+      CatromWeights((double) (x-x_offset),&cx);
+      CatromWeights((double) (y-y_offset),&cy);
+      gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
+        PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
+        alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
+        alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
+        alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
+        cx[2]*alpha[14]+cx[3]*alpha[15])));
+      *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
+        cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
+        pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
+        cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
+        pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
       break;
     }
     case IntegerInterpolatePixel:
@@ -4223,10 +4624,11 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
       *pixel=(double) GetPixelChannel(image,channel,p);
       break;
     }
-    case NearestNeighborInterpolatePixel:
+    case NearestInterpolatePixel:
     {
-      p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
-        NearestNeighbor(y),1,1,exception);
+      x_offset=(ssize_t) floor(x+0.5);
+      y_offset=(ssize_t) floor(y+0.5);
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
@@ -4251,7 +4653,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         for (i=0; i < 4; i++)
         {
           alpha[i]=1.0;
-          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+          pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
         }
       else
         for (i=0; i < 4; i++)
@@ -4262,10 +4664,10 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         }
       delta.x=x-x_offset;
       delta.y=y-y_offset;
-      luminance.x=GetPixelLuminance(image,p)-(double)
-        GetPixelLuminance(image,p+3*GetPixelChannels(image));
-      luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
-        GetPixelLuminance(image,p+2*GetPixelChannels(image));
+      luminance.x=GetPixelLuma(image,p)-(double)
+        GetPixelLuma(image,p+3*GetPixelChannels(image));
+      luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
+        GetPixelLuma(image,p+2*GetPixelChannels(image));
       if (fabs(luminance.x) < fabs(luminance.y))
         {
           /*
@@ -4278,7 +4680,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
               */
               delta.y=1.0-delta.y;
               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               *pixel=gamma*MeshInterpolate(&delta,pixels[2],pixels[3],
                 pixels[0]);
             }
@@ -4289,7 +4691,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
               */
               delta.x=1.0-delta.x;
               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               *pixel=gamma*MeshInterpolate(&delta,pixels[1],pixels[0],
                 pixels[3]);
             }
@@ -4305,7 +4707,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
                 Top-left triangle (pixel: 0, diagonal: 1-2).
               */
               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               *pixel=gamma*MeshInterpolate(&delta,pixels[0],pixels[1],
                 pixels[2]);
             }
@@ -4317,7 +4719,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
               delta.x=1.0-delta.x;
               delta.y=1.0-delta.y;
               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               *pixel=gamma*MeshInterpolate(&delta,pixels[3],pixels[2],
                 pixels[1]);
             }
@@ -4326,16 +4728,9 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
     }
     case SplineInterpolatePixel:
     {
-      MagickRealType
-        dx,
-        dy;
-
-      PointInfo
-        delta;
-
-      ssize_t
-        j,
-        n;
+      double
+        cx[4],
+        cy[4];
 
       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
         exception);
@@ -4348,7 +4743,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
         for (i=0; i < 16; i++)
         {
           alpha[i]=1.0;
-          pixels[i]=(MagickRealType) p[i*GetPixelChannels(image)+channel];
+          pixels[i]=(double) p[i*GetPixelChannels(image)+channel];
         }
       else
         for (i=0; i < 16; i++)
@@ -4357,20 +4752,19 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
             GetPixelChannels(image));
           pixels[i]=alpha[i]*p[i*GetPixelChannels(image)+channel];
         }
-      delta.x=x-x_offset;
-      delta.y=y-y_offset;
-      n=0;
-      for (i=(-1); i < 3L; i++)
-      {
-        dy=CubicWeightingFunction((MagickRealType) i-delta.y);
-        for (j=(-1); j < 3L; j++)
-        {
-          dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
-          gamma=1.0/(fabs((double) alpha[n]) <= MagickEpsilon ? 1.0 : alpha[n]);
-          *pixel+=gamma*dx*dy*pixels[n];
-          n++;
-        }
-      }
+      SplineWeights((double) (x-x_offset),&cx);
+      SplineWeights((double) (y-y_offset),&cy);
+      gamma=(channel == AlphaPixelChannel ? (double) 1.0 :
+        PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
+        alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
+        alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
+        alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
+        cx[2]*alpha[14]+cx[3]*alpha[15])));
+      *pixel=gamma*(cy[0]*(cx[0]*pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+
+        cx[3]*pixels[3])+cy[1]*(cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*
+        pixels[6]+cx[3]*pixels[7])+cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+
+        cx[2]*pixels[10]+cx[3]*pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*
+        pixels[13]+cx[2]*pixels[14]+cx[3]*pixels[15]));
       break;
     }
   }
@@ -4392,6 +4786,9 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
 %  floating point coordinate and the pixels surrounding that coordinate.  No
 %  pixel area resampling, or scaling of the result is performed.
 %
+%  Interpolation is restricted to just the current channel setting of the
+%  destination image into which the color is to be stored
+%
 %  The format of the InterpolatePixelChannels method is:
 %
 %      MagickBooleanType InterpolatePixelChannels(const Image *source,
@@ -4405,7 +4802,7 @@ MagickExport MagickBooleanType InterpolatePixelChannel(const Image *image,
 %
 %    o source_view: the source view.
 %
-%    o destination: the destination image.
+%    o destination: the destination image, for the interpolated color
 %
 %    o method: the pixel color interpolation method.
 %
@@ -4424,18 +4821,11 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
   MagickBooleanType
     status;
 
-  MagickRealType
+  double
     alpha[16],
     gamma,
     pixels[16];
 
-  PixelChannel
-    channel;
-
-  PixelTrait
-    destination_traits,
-    traits;
-
   register const Quantum
     *p;
 
@@ -4446,6 +4836,9 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
     x_offset,
     y_offset;
 
+  PixelInterpolateMethod
+    interpolate;
+
   assert(source != (Image *) NULL);
   assert(source != (Image *) NULL);
   assert(source->signature == MagickSignature);
@@ -4453,17 +4846,40 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
   status=MagickTrue;
   x_offset=(ssize_t) floor(x);
   y_offset=(ssize_t) floor(y);
-  switch (method == UndefinedInterpolatePixel ? source->interpolate : method)
+  interpolate = method;
+  if ( interpolate == UndefinedInterpolatePixel )
+    interpolate = source->interpolate;
+  switch (interpolate)
   {
-    case AverageInterpolatePixel:
+    case AverageInterpolatePixel:  /* nearest 4 neighbours */
+    case Average9InterpolatePixel:  /* nearest 9 neighbours */
+    case Average16InterpolatePixel:  /* nearest 16 neighbours */
     {
-      p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
-        exception);
+      ssize_t
+        count;
+
+      count=2;  /* size of the area to average - default nearest 4 */
+      if (interpolate == Average9InterpolatePixel)
+        {
+          count=3;
+          x_offset=(ssize_t) (floor(x+0.5)-1);
+          y_offset=(ssize_t) (floor(y+0.5)-1);
+        }
+      else
+        if (interpolate == Average16InterpolatePixel)
+          {
+            count=4;
+            x_offset--;
+            y_offset--;
+          }
+      p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,(size_t) count,
+        (size_t) count,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
+      count*=count;  /* Number of pixels to average */
       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
       {
         double
@@ -4472,94 +4888,37 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         register ssize_t
           j;
 
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
-        for (j=0; j < 16; j++)
-          pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+i];
+        for (j=0; j < (ssize_t) count; j++)
+          pixels[j]=(double) p[j*GetPixelChannels(source)+i];
         sum=0.0;
         if ((traits & BlendPixelTrait) == 0)
           {
-            for (j=0; j < 16; j++)
-              sum+=0.0625*pixels[j];
+            for (j=0; j < (ssize_t) count; j++)
+              sum+=pixels[j];
+            sum/=count;
             SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
             continue;
           }
-        for (j=0; j < 16; j++)
+        for (j=0; j < (ssize_t) count; j++)
         {
           alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
             GetPixelChannels(source));
           pixels[j]*=alpha[j];
-          gamma=1.0/(fabs((double) alpha[j]) <= MagickEpsilon ? 1.0 : alpha[j]);
-          sum+=gamma*0.0625*pixels[j];
+          gamma=PerceptibleReciprocal(alpha[j]);
+          sum+=gamma*pixels[j];
         }
+        sum/=count;
         SetPixelChannel(destination,channel,ClampToQuantum(sum),pixel);
       }
       break;
     }
-    case BicubicInterpolatePixel:
-    {
-      MagickRealType
-        u[4],
-        v[4];
-
-      PointInfo
-        delta;
-
-      p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
-        exception);
-      if (p == (const Quantum *) NULL)
-        {
-          status=MagickFalse;
-          break;
-        }
-      for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
-      {
-        register ssize_t
-          j;
-
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
-        if ((traits == UndefinedPixelTrait) ||
-            (destination_traits == UndefinedPixelTrait))
-          continue;
-        if ((traits & BlendPixelTrait) == 0)
-          for (j=0; j < 16; j++)
-          {
-            alpha[j]=1.0;
-            pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+i];
-          }
-        else
-          for (j=0; j < 16; j++)
-          {
-            alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
-              GetPixelChannels(source));
-            pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
-          }
-        delta.x=x-x_offset;
-        delta.y=y-y_offset;
-        for (j=0; j < 4; j++)
-        {
-          u[0]=(pixels[4*j+3]-pixels[4*j+2])-(pixels[4*j+0]-pixels[4*j+1]);
-          u[1]=(pixels[4*j+0]-pixels[4*j+1])-u[0];
-          u[2]=pixels[4*j+2]-pixels[4*j+0];
-          u[3]=pixels[4*j+1];
-          v[j]=(delta.x*delta.x*delta.x*u[0])+(delta.x*delta.x*u[1])+(delta.x*
-            u[2])+u[3];
-        }
-        u[0]=(v[3]-v[2])-(v[0]-v[1]);
-        u[1]=(v[0]-v[1])-u[0];
-        u[2]=v[2]-v[0];
-        u[3]=v[1];
-        SetPixelChannel(destination,channel,ClampToQuantum((delta.y*delta.y*
-          delta.y*u[0])+(delta.y*delta.y*u[1])+(delta.y*u[2])+u[3]),pixel);
-      }
-      break;
-    }
     case BilinearInterpolatePixel:
     default:
     {
@@ -4575,9 +4934,10 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
           delta,
           epsilon;
 
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
@@ -4585,14 +4945,14 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         delta.y=y-y_offset;
         epsilon.x=1.0-delta.x;
         epsilon.y=1.0-delta.y;
-        pixels[0]=(MagickRealType) p[i];
-        pixels[1]=(MagickRealType) p[GetPixelChannels(source)+i];
-        pixels[2]=(MagickRealType) p[2*GetPixelChannels(source)+i];
-        pixels[3]=(MagickRealType) p[3*GetPixelChannels(source)+i];
+        pixels[0]=(double) p[i];
+        pixels[1]=(double) p[GetPixelChannels(source)+i];
+        pixels[2]=(double) p[2*GetPixelChannels(source)+i];
+        pixels[3]=(double) p[3*GetPixelChannels(source)+i];
         if ((traits & BlendPixelTrait) == 0)
           {
             gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
-            gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+            gamma=PerceptibleReciprocal(gamma);
             SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
               (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*
               pixels[2]+delta.x*pixels[3]))),pixel);
@@ -4610,58 +4970,135 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         pixels[3]*=alpha[3];
         gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
           (epsilon.x*alpha[2]+delta.x*alpha[3])));
-        gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+        gamma=PerceptibleReciprocal(gamma);
         SetPixelChannel(destination,channel,ClampToQuantum(gamma*(epsilon.y*
           (epsilon.x*pixels[0]+delta.x*pixels[1])+delta.y*(epsilon.x*pixels[2]+
           delta.x*pixels[3]))),pixel);
       }
       break;
     }
-    case FilterInterpolatePixel:
+    case BlendInterpolatePixel:
     {
+      p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,2,2,exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
       {
-        CacheView
-          *filter_view;
+        register ssize_t
+          j;
 
-        Image
-          *excerpt_source,
-          *filter_source;
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
+        if ((traits == UndefinedPixelTrait) ||
+            (destination_traits == UndefinedPixelTrait))
+          continue;
+        if ((traits & BlendPixelTrait) == 0)
+          for (j=0; j < 4; j++)
+          {
+            alpha[j]=1.0;
+            pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+channel];
+          }
+        else
+          for (j=0; j < 4; j++)
+          {
+            alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
+              GetPixelChannels(source));
+            pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+channel];
+          }
+        gamma=1.0;  /* number of pixels blended together (its variable) */
+        for (j=0; j <= 1L; j++)
+        {
+          if ((y-y_offset) >= 0.75)
+            {
+              alpha[j]=alpha[j+2];  /* take right pixels */
+              pixels[j]=pixels[j+2];
+            }
+          else
+            if ((y-y_offset) > 0.25)
+              {
+                gamma=2.0;  /* blend both pixels in row */
+                alpha[j]+=alpha[j+2];  /* add up alpha weights */
+                pixels[j]+=pixels[j+2];
+              }
+        }
+        if ((x-x_offset) >= 0.75)
+          {
+            alpha[0]=alpha[1];  /* take bottom row blend */
+            pixels[0]=pixels[1];
+          }
+        else
+           if ((x-x_offset) > 0.25)
+             {
+               gamma*=2.0;  /* blend both rows */
+               alpha[0]+=alpha[1];  /* add up alpha weights */
+               pixels[0]+=pixels[1];
+             }
+        if ((traits & BlendPixelTrait) == 0)
+          gamma=PerceptibleReciprocal(alpha[0]);  /* (color) 1/alpha_weights */
+        else
+          gamma=PerceptibleReciprocal(gamma);  /* (alpha) 1/number_of_pixels */
+        SetPixelChannel(destination,channel,ClampToQuantum(gamma*pixels[0]),
+          pixel);
+      }
+      break;
+    }
+    case CatromInterpolatePixel:
+    {
+      double
+        cx[4],
+        cy[4];
 
-        RectangleInfo
-          geometry;
+      p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
+        exception);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
+      {
+        register ssize_t
+          j;
 
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
-        geometry.width=4L;
-        geometry.height=4L;
-        geometry.x=x_offset-1;
-        geometry.y=y_offset-1;
-        excerpt_source=ExcerptImage(source,&geometry,exception);
-        if (excerpt_source == (Image *) NULL)
+        if ((traits & BlendPixelTrait) == 0)
+          for (j=0; j < 16; j++)
           {
-            status=MagickFalse;
-            continue;
+            alpha[j]=1.0;
+            pixels[j]=(double) p[j*GetPixelChannels(source)+i];
           }
-        filter_source=ResizeImage(excerpt_source,1,1,source->filter,
-          source->blur,exception);
-        excerpt_source=DestroyImage(excerpt_source);
-        if (filter_source == (Image *) NULL)
-          continue;
-        filter_view=AcquireCacheView(filter_source);
-        p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
-        if (p == (const Quantum *) NULL)
-          status=MagickFalse;
         else
+          for (j=0; j < 16; j++)
           {
-            SetPixelChannel(destination,channel,p[i],pixel);
+            alpha[j]=QuantumScale*GetPixelAlpha(source,p+j*
+              GetPixelChannels(source));
+            pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
           }
-        filter_view=DestroyCacheView(filter_view);
-        filter_source=DestroyImage(filter_source);
+        CatromWeights((double) (x-x_offset),&cx);
+        CatromWeights((double) (y-y_offset),&cy);
+        gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
+          PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
+          alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
+          alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
+          alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
+          cx[2]*alpha[14]+cx[3]*alpha[15])));
+        SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
+          pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
+          (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
+          cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
+          pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
+          pixels[14]+cx[3]*pixels[15]))),pixel);
       }
       break;
     }
@@ -4675,9 +5112,10 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         }
       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
       {
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
@@ -4685,10 +5123,11 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
       }
       break;
     }
-    case NearestNeighborInterpolatePixel:
+    case NearestInterpolatePixel:
     {
-      p=GetCacheViewVirtualPixels(source_view,NearestNeighbor(x),
-        NearestNeighbor(y),1,1,exception);
+      x_offset=(ssize_t) floor(x+0.5);
+      y_offset=(ssize_t) floor(y+0.5);
+      p=GetCacheViewVirtualPixels(source_view,x_offset,y_offset,1,1,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
@@ -4696,9 +5135,10 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         }
       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
       {
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
@@ -4720,16 +5160,17 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
           delta,
           luminance;
 
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
-        pixels[0]=(MagickRealType) p[i];
-        pixels[1]=(MagickRealType) p[GetPixelChannels(source)+i];
-        pixels[2]=(MagickRealType) p[2*GetPixelChannels(source)+i];
-        pixels[3]=(MagickRealType) p[3*GetPixelChannels(source)+i];
+        pixels[0]=(double) p[i];
+        pixels[1]=(double) p[GetPixelChannels(source)+i];
+        pixels[2]=(double) p[2*GetPixelChannels(source)+i];
+        pixels[3]=(double) p[3*GetPixelChannels(source)+i];
         if ((traits & BlendPixelTrait) == 0)
           {
             alpha[0]=1.0;
@@ -4749,11 +5190,12 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
           }
         delta.x=x-x_offset;
         delta.y=y-y_offset;
-        luminance.x=GetPixelLuminance(source,p)-(double)
-          GetPixelLuminance(source,p+3*GetPixelChannels(source));
-        luminance.y=GetPixelLuminance(source,p+GetPixelChannels(source))-
-          (double) GetPixelLuminance(source,p+2*GetPixelChannels(source));
-        if (fabs(luminance.x) < fabs(luminance.y))
+        luminance.x=fabs((double) (GetPixelLuma(source,p)-
+          GetPixelLuma(source,p+3*GetPixelChannels(source))));
+        luminance.y=fabs((double) (GetPixelLuma(source,p+
+          GetPixelChannels(source))-GetPixelLuma(source,p+2*
+          GetPixelChannels(source))));
+        if (luminance.x < luminance.y)
           {
             /*
               Diagonal 0-3 NW-SE.
@@ -4765,7 +5207,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
                 */
                 delta.y=1.0-delta.y;
                 gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
-                gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+                gamma=PerceptibleReciprocal(gamma);
                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
                   MeshInterpolate(&delta,pixels[2],pixels[3],pixels[0])),pixel);
               }
@@ -4776,7 +5218,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
                 */
                 delta.x=1.0-delta.x;
                 gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
-                gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+                gamma=PerceptibleReciprocal(gamma);
                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
                   MeshInterpolate(&delta,pixels[1],pixels[0],pixels[3])),pixel);
               }
@@ -4792,7 +5234,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
                   Top-left triangle (pixel: 0, diagonal: 1-2).
                 */
                 gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
-                gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+                gamma=PerceptibleReciprocal(gamma);
                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
                   MeshInterpolate(&delta,pixels[0],pixels[1],pixels[2])),pixel);
               }
@@ -4804,7 +5246,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
                 delta.x=1.0-delta.x;
                 delta.y=1.0-delta.y;
                 gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
-                gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+                gamma=PerceptibleReciprocal(gamma);
                 SetPixelChannel(destination,channel,ClampToQuantum(gamma*
                   MeshInterpolate(&delta,pixels[3],pixels[2],pixels[1])),pixel);
               }
@@ -4814,6 +5256,10 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
     }
     case SplineInterpolatePixel:
     {
+      double
+        cx[4],
+        cy[4];
+
       p=GetCacheViewVirtualPixels(source_view,x_offset-1,y_offset-1,4,4,
         exception);
       if (p == (const Quantum *) NULL)
@@ -4823,26 +5269,13 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
         }
       for (i=0; i < (ssize_t) GetPixelChannels(source); i++)
       {
-        double
-          sum;
-
-        MagickRealType
-          dx,
-          dy;
-
-        PointInfo
-          delta;
-
         register ssize_t
           j;
 
-        ssize_t
-          k,
-          n;
-
-        channel=GetPixelChannelMapChannel(source,i);
-        traits=GetPixelChannelMapTraits(source,channel);
-        destination_traits=GetPixelChannelMapTraits(destination,channel);
+        PixelChannel channel=GetPixelChannelChannel(source,i);
+        PixelTrait traits=GetPixelChannelTraits(source,channel);
+        PixelTrait destination_traits=GetPixelChannelTraits(destination,
+          channel);
         if ((traits == UndefinedPixelTrait) ||
             (destination_traits == UndefinedPixelTrait))
           continue;
@@ -4850,7 +5283,7 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
           for (j=0; j < 16; j++)
           {
             alpha[j]=1.0;
-            pixels[j]=(MagickRealType) p[j*GetPixelChannels(source)+i];
+            pixels[j]=(double) p[j*GetPixelChannels(source)+i];
           }
         else
           for (j=0; j < 16; j++)
@@ -4859,23 +5292,20 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
               GetPixelChannels(source));
             pixels[j]=alpha[j]*p[j*GetPixelChannels(source)+i];
           }
-        delta.x=x-x_offset;
-        delta.y=y-y_offset;
-        sum=0.0;
-        n=0;
-        for (j=(-1); j < 3L; j++)
-        {
-          dy=CubicWeightingFunction((MagickRealType) j-delta.y);
-          for (k=(-1); k < 3L; k++)
-          {
-            dx=CubicWeightingFunction(delta.x-(MagickRealType) k);
-            gamma=1.0/(fabs((double) alpha[n]) <= MagickEpsilon ? 1.0 :
-              alpha[n]);
-            sum+=gamma*dx*dy*pixels[n];
-            n++;
-          }
-        }
-        SetPixelChannel(destination,channel,p[i],pixel);
+        SplineWeights((double) (x-x_offset),&cx);
+        SplineWeights((double) (y-y_offset),&cy);
+        gamma=((traits & BlendPixelTrait) ? (double) (1.0) :
+          PerceptibleReciprocal(cy[0]*(cx[0]*alpha[0]+cx[1]*alpha[1]+cx[2]*
+          alpha[2]+cx[3]*alpha[3])+cy[1]*(cx[0]*alpha[4]+cx[1]*alpha[5]+cx[2]*
+          alpha[6]+cx[3]*alpha[7])+cy[2]*(cx[0]*alpha[8]+cx[1]*alpha[9]+cx[2]*
+          alpha[10]+cx[3]*alpha[11])+cy[3]*(cx[0]*alpha[12]+cx[1]*alpha[13]+
+          cx[2]*alpha[14]+cx[3]*alpha[15])));
+        SetPixelChannel(destination,channel,ClampToQuantum(gamma*(cy[0]*(cx[0]*
+          pixels[0]+cx[1]*pixels[1]+cx[2]*pixels[2]+cx[3]*pixels[3])+cy[1]*
+          (cx[0]*pixels[4]+cx[1]*pixels[5]+cx[2]*pixels[6]+cx[3]*pixels[7])+
+          cy[2]*(cx[0]*pixels[8]+cx[1]*pixels[9]+cx[2]*pixels[10]+cx[3]*
+          pixels[11])+cy[3]*(cx[0]*pixels[12]+cx[1]*pixels[13]+cx[2]*
+          pixels[14]+cx[3]*pixels[15]))),pixel);
       }
       break;
     }
@@ -4898,6 +5328,8 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
 %  floating point coordinate and the pixels surrounding that coordinate.  No
 %  pixel area resampling, or scaling of the result is performed.
 %
+%  Interpolation is restricted to just RGBKA channels.
+%
 %  The format of the InterpolatePixelInfo method is:
 %
 %      MagickBooleanType InterpolatePixelInfo(const Image *image,
@@ -4922,18 +5354,18 @@ MagickExport MagickBooleanType InterpolatePixelChannels(const Image *source,
 */
 
 static inline void AlphaBlendPixelInfo(const Image *image,
-  const Quantum *pixel,PixelInfo *pixel_info,MagickRealType *alpha)
+  const Quantum *pixel,PixelInfo *pixel_info,double *alpha)
 {
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait != BlendPixelTrait)
     {
       *alpha=1.0;
-      pixel_info->red=(MagickRealType) GetPixelRed(image,pixel);
-      pixel_info->green=(MagickRealType) GetPixelGreen(image,pixel);
-      pixel_info->blue=(MagickRealType) GetPixelBlue(image,pixel);
+      pixel_info->red=(double) GetPixelRed(image,pixel);
+      pixel_info->green=(double) GetPixelGreen(image,pixel);
+      pixel_info->blue=(double) GetPixelBlue(image,pixel);
       pixel_info->black=0.0;
       if (image->colorspace == CMYKColorspace)
-        pixel_info->black=(MagickRealType) GetPixelBlack(image,pixel);
-      pixel_info->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
+        pixel_info->black=(double) GetPixelBlack(image,pixel);
+      pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
       return;
     }
   *alpha=QuantumScale*GetPixelAlpha(image,pixel);
@@ -4943,48 +5375,7 @@ static inline void AlphaBlendPixelInfo(const Image *image,
   pixel_info->black=0.0;
   if (image->colorspace == CMYKColorspace)
     pixel_info->black=(*alpha*GetPixelBlack(image,pixel));
-  pixel_info->alpha=(MagickRealType) GetPixelAlpha(image,pixel);
-}
-
-static void BicubicInterpolate(const PixelInfo *pixels,const double dx,
-  PixelInfo *pixel)
-{
-  MagickRealType
-    dx2,
-    p,
-    q,
-    r,
-    s;
-
-  dx2=dx*dx;
-  p=(pixels[3].red-pixels[2].red)-(pixels[0].red-pixels[1].red);
-  q=(pixels[0].red-pixels[1].red)-p;
-  r=pixels[2].red-pixels[0].red;
-  s=pixels[1].red;
-  pixel->red=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
-  p=(pixels[3].green-pixels[2].green)-(pixels[0].green-pixels[1].green);
-  q=(pixels[0].green-pixels[1].green)-p;
-  r=pixels[2].green-pixels[0].green;
-  s=pixels[1].green;
-  pixel->green=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
-  p=(pixels[3].blue-pixels[2].blue)-(pixels[0].blue-pixels[1].blue);
-  q=(pixels[0].blue-pixels[1].blue)-p;
-  r=pixels[2].blue-pixels[0].blue;
-  s=pixels[1].blue;
-  pixel->blue=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
-  p=(pixels[3].alpha-pixels[2].alpha)-(pixels[0].alpha-pixels[1].alpha);
-  q=(pixels[0].alpha-pixels[1].alpha)-p;
-  r=pixels[2].alpha-pixels[0].alpha;
-  s=pixels[1].alpha;
-  pixel->alpha=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
-  if (pixel->colorspace == CMYKColorspace)
-    {
-      p=(pixels[3].black-pixels[2].black)-(pixels[0].black-pixels[1].black);
-      q=(pixels[0].black-pixels[1].black)-p;
-      r=pixels[2].black-pixels[0].black;
-      s=pixels[1].black;
-      pixel->black=(dx*dx2*p)+(dx2*q)+(dx*r)+s;
-    }
+  pixel_info->alpha=(double) GetPixelAlpha(image,pixel);
 }
 
 MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
@@ -4994,7 +5385,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
   MagickBooleanType
     status;
 
-  MagickRealType
+  double
     alpha[16],
     gamma;
 
@@ -5011,104 +5402,75 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
     x_offset,
     y_offset;
 
+  PixelInterpolateMethod
+    interpolate;
+
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
   assert(image_view != (CacheView *) NULL);
   status=MagickTrue;
   x_offset=(ssize_t) floor(x);
   y_offset=(ssize_t) floor(y);
-  switch (method == UndefinedInterpolatePixel ? image->interpolate : method)
+  interpolate = method;
+  if ( interpolate == UndefinedInterpolatePixel )
+    interpolate = image->interpolate;
+  switch (interpolate)
   {
-    case AverageInterpolatePixel:
+    case AverageInterpolatePixel:  /* nearest 4 neighbours */
+    case Average9InterpolatePixel:  /* nearest 9 neighbours */
+    case Average16InterpolatePixel:  /* nearest 16 neighbours */
     {
-      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
-        exception);
+      ssize_t
+        count;
+
+      count=2;  /* size of the area to average - default nearest 4 */
+      if (interpolate == Average9InterpolatePixel)
+        {
+          count=3;
+          x_offset=(ssize_t) (floor(x+0.5)-1);
+          y_offset=(ssize_t) (floor(y+0.5)-1);
+        }
+      else if (interpolate == Average16InterpolatePixel)
+        {
+          count=4;
+          x_offset--;
+          y_offset--;
+        }
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,(size_t) count,
+        (size_t) count,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
-      AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
-      AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
-      AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
-      AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
-      AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
-      AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
-      AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
-      AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
-      AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
-      AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
-      AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
-        10);
-      AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
-        11);
-      AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
-        12);
-      AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
-        13);
-      AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
-        14);
-      AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
-        15);
       pixel->red=0.0;
       pixel->green=0.0;
       pixel->blue=0.0;
       pixel->black=0.0;
       pixel->alpha=0.0;
-      for (i=0; i < 16L; i++)
-      {
-        gamma=1.0/(fabs((double) alpha[i]) <= MagickEpsilon ? 1.0 : alpha[i]);
-        pixel->red+=gamma*0.0625*pixels[i].red;
-        pixel->green+=gamma*0.0625*pixels[i].green;
-        pixel->blue+=gamma*0.0625*pixels[i].blue;
-        if (image->colorspace == CMYKColorspace)
-          pixel->black+=gamma*0.0625*pixels[i].black;
-        pixel->alpha+=0.0625*pixels[i].alpha;
-      }
+      count*=count;  /* number of pixels - square of size */
+      for (i=0; i < (ssize_t) count; i++)
+      {
+        AlphaBlendPixelInfo(image,p,pixels,alpha);
+        gamma=PerceptibleReciprocal(alpha[0]);
+        pixel->red+=gamma*pixels[0].red;
+        pixel->green+=gamma*pixels[0].green;
+        pixel->blue+=gamma*pixels[0].blue;
+        pixel->black+=gamma*pixels[0].black;
+        pixel->alpha+=pixels[0].alpha;
+        p += GetPixelChannels(image);
+      }
+      gamma=1.0/count;   /* average weighting of each pixel in area */
+      pixel->red*=gamma;
+      pixel->green*=gamma;
+      pixel->blue*=gamma;
+      pixel->black*=gamma;
+      pixel->alpha*=gamma;
       break;
     }
-    case BicubicInterpolatePixel:
+    case BackgroundInterpolatePixel:
     {
-      PixelInfo
-        u[4];
-
-      PointInfo
-        delta;
-
-      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
-        exception);
-      if (p == (const Quantum *) NULL)
-        {
-          status=MagickFalse;
-          break;
-        }
-      AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
-      AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
-      AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
-      AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
-      AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
-      AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
-      AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
-      AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
-      AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
-      AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
-      AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
-        10);
-      AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
-        11);
-      AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
-        12);
-      AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
-        13);
-      AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
-        14);
-      AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
-        15);
-      delta.x=x-x_offset;
-      delta.y=y-y_offset;
-      for (i=0; i < 4L; i++)
-        BicubicInterpolate(pixels+4*i,delta.x,u+i);
-      BicubicInterpolate(u,delta.y,pixel);
+      *pixel=image->background_color;  /* Copy PixelInfo Structure  */
       break;
     }
     case BilinearInterpolatePixel:
@@ -5124,17 +5486,15 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
           status=MagickFalse;
           break;
         }
-      AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
-      AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
-      AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
-      AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
+      for (i=0; i < 4L; i++)
+        AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
       delta.x=x-x_offset;
       delta.y=y-y_offset;
       epsilon.x=1.0-delta.x;
       epsilon.y=1.0-delta.y;
       gamma=((epsilon.y*(epsilon.x*alpha[0]+delta.x*alpha[1])+delta.y*
         (epsilon.x*alpha[2]+delta.x*alpha[3])));
-      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+      gamma=PerceptibleReciprocal(gamma);
       pixel->red=gamma*(epsilon.y*(epsilon.x*pixels[0].red+delta.x*
         pixels[1].red)+delta.y*(epsilon.x*pixels[2].red+delta.x*pixels[3].red));
       pixel->green=gamma*(epsilon.y*(epsilon.x*pixels[0].green+delta.x*
@@ -5148,45 +5508,117 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
           pixels[1].black)+delta.y*(epsilon.x*pixels[2].black+delta.x*
           pixels[3].black));
       gamma=((epsilon.y*(epsilon.x+delta.x)+delta.y*(epsilon.x+delta.x)));
-      gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+      gamma=PerceptibleReciprocal(gamma);
       pixel->alpha=(epsilon.y*(epsilon.x*pixels[0].alpha+delta.x*
         pixels[1].alpha)+delta.y*(epsilon.x*pixels[2].alpha+delta.x*
         pixels[3].alpha));
       break;
     }
-    case FilterInterpolatePixel:
+    case BlendInterpolatePixel:
     {
-      CacheView
-        *filter_view;
-
-      Image
-        *excerpt_image,
-        *filter_image;
-
-      RectangleInfo
-        geometry;
-
-      geometry.width=4L;
-      geometry.height=4L;
-      geometry.x=x_offset-1;
-      geometry.y=y_offset-1;
-      excerpt_image=ExcerptImage(image,&geometry,exception);
-      if (excerpt_image == (Image *) NULL)
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,2,2,exception);
+      if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
           break;
         }
-      filter_image=ResizeImage(excerpt_image,1,1,image->filter,image->blur,
+      for (i=0; i < 4L; i++)
+        AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
+      gamma=1.0;  /* number of pixels blended together (its variable) */
+      for (i=0; i <= 1L; i++)
+      {
+        if ((y-y_offset) >= 0.75)
+          {
+            alpha[i]=alpha[i+2];  /* take right pixels */
+            pixels[i]=pixels[i+2];
+          }
+        else
+          if ((y-y_offset) > 0.25)
+            {
+              gamma=2.0;  /* blend both pixels in row */
+              alpha[i]+=alpha[i+2];  /* add up alpha weights */
+              pixels[i].red+=pixels[i+2].red;
+              pixels[i].green+=pixels[i+2].green;
+              pixels[i].blue+=pixels[i+2].blue;
+              pixels[i].black+=pixels[i+2].black;
+              pixels[i].alpha+=pixels[i+2].alpha;
+            }
+      }
+      if ((x-x_offset) >= 0.75)
+        {
+          alpha[0]=alpha[1];
+          pixels[0]=pixels[1];
+        }
+      else
+        if ((x-x_offset) > 0.25)
+          {
+            gamma*=2.0;  /* blend both rows */
+            alpha[0]+= alpha[1];  /* add up alpha weights */
+            pixels[0].red+=pixels[1].red;
+            pixels[0].green+=pixels[1].green;
+            pixels[0].blue+=pixels[1].blue;
+            pixels[0].black+=pixels[1].black;
+            pixels[0].alpha+=pixels[1].alpha;
+          }
+      gamma=1.0/gamma;
+      alpha[0]=PerceptibleReciprocal(alpha[0]);
+      pixel->red=alpha[0]*pixels[0].red;
+      pixel->green=alpha[0]*pixels[0].green;  /* divide by sum of alpha */
+      pixel->blue=alpha[0]*pixels[0].blue;
+      pixel->black=alpha[0]*pixels[0].black;
+      pixel->alpha=gamma*pixels[0].alpha;   /* divide by number of pixels */
+      break;
+    }
+    case CatromInterpolatePixel:
+    {
+      double
+        cx[4],
+        cy[4];
+
+      p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
         exception);
-      excerpt_image=DestroyImage(excerpt_image);
-      if (filter_image == (Image *) NULL)
-        break;
-      filter_view=AcquireCacheView(filter_image);
-      p=GetCacheViewVirtualPixels(filter_view,0,0,1,1,exception);
-      if (p != (const Quantum *) NULL)
-        GetPixelInfoPixel(image,p,pixel);
-      filter_view=DestroyCacheView(filter_view);
-      filter_image=DestroyImage(filter_image);
+      if (p == (const Quantum *) NULL)
+        {
+          status=MagickFalse;
+          break;
+        }
+      for (i=0; i < 16L; i++)
+        AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
+      CatromWeights((double) (x-x_offset),&cx);
+      CatromWeights((double) (y-y_offset),&cy);
+      pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
+        pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
+        pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
+        pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
+        pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
+        pixels[14].red+cx[3]*pixels[15].red));
+      pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
+        pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
+        cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
+        cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
+        pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*
+        pixels[12].green+cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*
+        pixels[15].green));
+      pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
+        pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
+        pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
+        pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
+        pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
+        cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
+      if (image->colorspace == CMYKColorspace)
+        pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
+          pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
+          cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
+          cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
+          pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
+          pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
+          pixels[15].black));
+      pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
+        pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
+        cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
+        cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
+        pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
+        cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
       break;
     }
     case IntegerInterpolatePixel:
@@ -5214,10 +5646,10 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         }
       delta.x=x-x_offset;
       delta.y=y-y_offset;
-      luminance.x=GetPixelLuminance(image,p)-(double)
-        GetPixelLuminance(image,p+3*GetPixelChannels(image));
-      luminance.y=GetPixelLuminance(image,p+GetPixelChannels(image))-(double)
-        GetPixelLuminance(image,p+2*GetPixelChannels(image));
+      luminance.x=GetPixelLuma(image,p)-(double)
+        GetPixelLuma(image,p+3*GetPixelChannels(image));
+      luminance.y=GetPixelLuma(image,p+GetPixelChannels(image))-(double)
+        GetPixelLuma(image,p+2*GetPixelChannels(image));
       AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
       AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
       AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
@@ -5234,7 +5666,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
               */
               delta.y=1.0-delta.y;
               gamma=MeshInterpolate(&delta,alpha[2],alpha[3],alpha[0]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               pixel->red=gamma*MeshInterpolate(&delta,pixels[2].red,
                 pixels[3].red,pixels[0].red);
               pixel->green=gamma*MeshInterpolate(&delta,pixels[2].green,
@@ -5255,7 +5687,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
               */
               delta.x=1.0-delta.x;
               gamma=MeshInterpolate(&delta,alpha[1],alpha[0],alpha[3]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               pixel->red=gamma*MeshInterpolate(&delta,pixels[1].red,
                 pixels[0].red,pixels[3].red);
               pixel->green=gamma*MeshInterpolate(&delta,pixels[1].green,
@@ -5281,7 +5713,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
                 Top-left triangle (pixel: 0, diagonal: 1-2).
               */
               gamma=MeshInterpolate(&delta,alpha[0],alpha[1],alpha[2]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               pixel->red=gamma*MeshInterpolate(&delta,pixels[0].red,
                 pixels[1].red,pixels[2].red);
               pixel->green=gamma*MeshInterpolate(&delta,pixels[0].green,
@@ -5303,7 +5735,7 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
               delta.x=1.0-delta.x;
               delta.y=1.0-delta.y;
               gamma=MeshInterpolate(&delta,alpha[3],alpha[2],alpha[1]);
-              gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+              gamma=PerceptibleReciprocal(gamma);
               pixel->red=gamma*MeshInterpolate(&delta,pixels[3].red,
                 pixels[2].red,pixels[1].red);
               pixel->green=gamma*MeshInterpolate(&delta,pixels[3].green,
@@ -5320,10 +5752,11 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
         }
       break;
     }
-    case NearestNeighborInterpolatePixel:
+    case NearestInterpolatePixel:
     {
-      p=GetCacheViewVirtualPixels(image_view,NearestNeighbor(x),
-        NearestNeighbor(y),1,1,exception);
+      x_offset=(ssize_t) floor(x+0.5);
+      y_offset=(ssize_t) floor(y+0.5);
+      p=GetCacheViewVirtualPixels(image_view,x_offset,y_offset,1,1,exception);
       if (p == (const Quantum *) NULL)
         {
           status=MagickFalse;
@@ -5334,16 +5767,9 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
     }
     case SplineInterpolatePixel:
     {
-      MagickRealType
-        dx,
-        dy;
-
-      PointInfo
-        delta;
-
-      ssize_t
-        j,
-        n;
+      double
+        cx[4],
+        cy[4];
 
       p=GetCacheViewVirtualPixels(image_view,x_offset-1,y_offset-1,4,4,
         exception);
@@ -5352,52 +5778,42 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
           status=MagickFalse;
           break;
         }
-      AlphaBlendPixelInfo(image,p,pixels+0,alpha+0);
-      AlphaBlendPixelInfo(image,p+GetPixelChannels(image),pixels+1,alpha+1);
-      AlphaBlendPixelInfo(image,p+2*GetPixelChannels(image),pixels+2,alpha+2);
-      AlphaBlendPixelInfo(image,p+3*GetPixelChannels(image),pixels+3,alpha+3);
-      AlphaBlendPixelInfo(image,p+4*GetPixelChannels(image),pixels+4,alpha+4);
-      AlphaBlendPixelInfo(image,p+5*GetPixelChannels(image),pixels+5,alpha+5);
-      AlphaBlendPixelInfo(image,p+6*GetPixelChannels(image),pixels+6,alpha+6);
-      AlphaBlendPixelInfo(image,p+7*GetPixelChannels(image),pixels+7,alpha+7);
-      AlphaBlendPixelInfo(image,p+8*GetPixelChannels(image),pixels+8,alpha+8);
-      AlphaBlendPixelInfo(image,p+9*GetPixelChannels(image),pixels+9,alpha+9);
-      AlphaBlendPixelInfo(image,p+10*GetPixelChannels(image),pixels+10,alpha+
-        10);
-      AlphaBlendPixelInfo(image,p+11*GetPixelChannels(image),pixels+11,alpha+
-        11);
-      AlphaBlendPixelInfo(image,p+12*GetPixelChannels(image),pixels+12,alpha+
-        12);
-      AlphaBlendPixelInfo(image,p+13*GetPixelChannels(image),pixels+13,alpha+
-        13);
-      AlphaBlendPixelInfo(image,p+14*GetPixelChannels(image),pixels+14,alpha+
-        14);
-      AlphaBlendPixelInfo(image,p+15*GetPixelChannels(image),pixels+15,alpha+
-        15);
-      pixel->red=0.0;
-      pixel->green=0.0;
-      pixel->blue=0.0;
-      pixel->black=0.0;
-      pixel->alpha=0.0;
-      delta.x=x-x_offset;
-      delta.y=y-y_offset;
-      n=0;
-      for (i=(-1); i < 3L; i++)
-      {
-        dy=CubicWeightingFunction((MagickRealType) i-delta.y);
-        for (j=(-1); j < 3L; j++)
-        {
-          dx=CubicWeightingFunction(delta.x-(MagickRealType) j);
-          gamma=1.0/(fabs((double) alpha[n]) <= MagickEpsilon ? 1.0 : alpha[n]);
-          pixel->red+=gamma*dx*dy*pixels[n].red;
-          pixel->green+=gamma*dx*dy*pixels[n].green;
-          pixel->blue+=gamma*dx*dy*pixels[n].blue;
-          if (image->colorspace == CMYKColorspace)
-            pixel->black+=gamma*dx*dy*pixels[n].black;
-          pixel->alpha+=dx*dy*pixels[n].alpha;
-          n++;
-        }
-      }
+      for (i=0; i < 16L; i++)
+        AlphaBlendPixelInfo(image,p+i*GetPixelChannels(image),pixels+i,alpha+i);
+      SplineWeights((double) (x-x_offset),&cx);
+      SplineWeights((double) (y-y_offset),&cy);
+      pixel->red=(cy[0]*(cx[0]*pixels[0].red+cx[1]*pixels[1].red+cx[2]*
+        pixels[2].red+cx[3]*pixels[3].red)+cy[1]*(cx[0]*pixels[4].red+cx[1]*
+        pixels[5].red+cx[2]*pixels[6].red+cx[3]*pixels[7].red)+cy[2]*(cx[0]*
+        pixels[8].red+cx[1]*pixels[9].red+cx[2]*pixels[10].red+cx[3]*
+        pixels[11].red)+cy[3]*(cx[0]*pixels[12].red+cx[1]*pixels[13].red+cx[2]*
+        pixels[14].red+cx[3]*pixels[15].red));
+      pixel->green=(cy[0]*(cx[0]*pixels[0].green+cx[1]*pixels[1].green+cx[2]*
+        pixels[2].green+cx[3]*pixels[3].green)+cy[1]*(cx[0]*pixels[4].green+
+        cx[1]*pixels[5].green+cx[2]*pixels[6].green+cx[3]*pixels[7].green)+
+        cy[2]*(cx[0]*pixels[8].green+cx[1]*pixels[9].green+cx[2]*
+        pixels[10].green+cx[3]*pixels[11].green)+cy[3]*(cx[0]*pixels[12].green+
+        cx[1]*pixels[13].green+cx[2]*pixels[14].green+cx[3]*pixels[15].green));
+      pixel->blue=(cy[0]*(cx[0]*pixels[0].blue+cx[1]*pixels[1].blue+cx[2]*
+        pixels[2].blue+cx[3]*pixels[3].blue)+cy[1]*(cx[0]*pixels[4].blue+cx[1]*
+        pixels[5].blue+cx[2]*pixels[6].blue+cx[3]*pixels[7].blue)+cy[2]*(cx[0]*
+        pixels[8].blue+cx[1]*pixels[9].blue+cx[2]*pixels[10].blue+cx[3]*
+        pixels[11].blue)+cy[3]*(cx[0]*pixels[12].blue+cx[1]*pixels[13].blue+
+        cx[2]*pixels[14].blue+cx[3]*pixels[15].blue));
+      if (image->colorspace == CMYKColorspace)
+        pixel->black=(cy[0]*(cx[0]*pixels[0].black+cx[1]*pixels[1].black+cx[2]*
+          pixels[2].black+cx[3]*pixels[3].black)+cy[1]*(cx[0]*pixels[4].black+
+          cx[1]*pixels[5].black+cx[2]*pixels[6].black+cx[3]*pixels[7].black)+
+          cy[2]*(cx[0]*pixels[8].black+cx[1]*pixels[9].black+cx[2]*
+          pixels[10].black+cx[3]*pixels[11].black)+cy[3]*(cx[0]*
+          pixels[12].black+cx[1]*pixels[13].black+cx[2]*pixels[14].black+cx[3]*
+          pixels[15].black));
+      pixel->alpha=(cy[0]*(cx[0]*pixels[0].alpha+cx[1]*pixels[1].alpha+cx[2]*
+        pixels[2].alpha+cx[3]*pixels[3].alpha)+cy[1]*(cx[0]*pixels[4].alpha+
+        cx[1]*pixels[5].alpha+cx[2]*pixels[6].alpha+cx[3]*pixels[7].alpha)+
+        cy[2]*(cx[0]*pixels[8].alpha+cx[1]*pixels[9].alpha+cx[2]*
+        pixels[10].alpha+cx[3]*pixels[11].alpha)+cy[3]*(cx[0]*pixels[12].alpha+
+        cx[1]*pixels[13].alpha+cx[2]*pixels[14].alpha+cx[3]*pixels[15].alpha));
       break;
     }
   }
@@ -5438,25 +5854,24 @@ MagickExport MagickBooleanType InterpolatePixelInfo(const Image *image,
 MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
   const Quantum *p,const Image *destination,const Quantum *q)
 {
-  MagickRealType
+  double
     fuzz,
     pixel;
 
-  register MagickRealType
+  register double
     distance,
     scale;
 
-  fuzz=MagickMax(source->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(
+  fuzz=(double) MagickMax(source->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(
     destination->fuzz,(MagickRealType) MagickSQ1_2);
   scale=1.0;
   distance=0.0;
-  if (source->matte != MagickFalse)
+  if (source->alpha_trait == BlendPixelTrait)
     {
       /*
         Transparencies are involved - set alpha distance
       */
-      pixel=GetPixelAlpha(source,p)-(MagickRealType)
-        GetPixelAlpha(destination,q);
+      pixel=GetPixelAlpha(source,p)-(double) GetPixelAlpha(destination,q);
       distance=pixel*pixel;
       if (distance > fuzz)
         return(MagickFalse);
@@ -5474,7 +5889,7 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
   */
   distance*=3.0;  /* rescale appropriately */
   fuzz*=3.0;
-  pixel=GetPixelRed(source,p)-(MagickRealType) GetPixelRed(destination,q);
+  pixel=GetPixelRed(source,p)-(double) GetPixelRed(destination,q);
   if ((source->colorspace == HSLColorspace) ||
       (source->colorspace == HSBColorspace) ||
       (source->colorspace == HWBColorspace))
@@ -5490,11 +5905,11 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
   distance+=scale*pixel*pixel;
   if (distance > fuzz)
     return(MagickFalse);
-  pixel=GetPixelGreen(source,p)-(MagickRealType) GetPixelGreen(destination,q);
+  pixel=GetPixelGreen(source,p)-(double) GetPixelGreen(destination,q);
   distance+=scale*pixel*pixel;
   if (distance > fuzz)
     return(MagickFalse);
-  pixel=GetPixelBlue(source,p)-(MagickRealType) GetPixelBlue(destination,q);
+  pixel=GetPixelBlue(source,p)-(double) GetPixelBlue(destination,q);
   distance+=scale*pixel*pixel;
   if (distance > fuzz)
     return(MagickFalse);
@@ -5548,34 +5963,35 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixel(const Image *source,
 MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
   const PixelInfo *q)
 {
-  MagickRealType
+  double
     fuzz,
     pixel;
 
-  register MagickRealType
+  register double
     scale,
     distance;
 
   if ((p->fuzz == 0.0) && (q->fuzz == 0.0))
     return(IsPixelInfoEquivalent(p,q));
   if (p->fuzz == 0.0)
-    fuzz=MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(q->fuzz,
-      (MagickRealType) MagickSQ1_2);
+    fuzz=MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2)*
+      MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
   else if (q->fuzz == 0.0)
-    fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(p->fuzz,
-      (MagickRealType) MagickSQ1_2);
+    fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
+      MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2);
   else
-    fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*MagickMax(q->fuzz,
-      (MagickRealType) MagickSQ1_2);
+    fuzz=MagickMax(p->fuzz,(MagickRealType) MagickSQ1_2)*
+      MagickMax(q->fuzz,(MagickRealType) MagickSQ1_2);
   scale=1.0;
   distance=0.0;
-  if ((p->matte != MagickFalse) || (q->matte != MagickFalse))
+  if ((p->alpha_trait == BlendPixelTrait) ||
+      (q->alpha_trait == BlendPixelTrait))
     {
       /*
         Transparencies are involved - set alpha distance.
       */
-      pixel=(p->matte != MagickFalse ? p->alpha : OpaqueAlpha)-
-        (q->matte != MagickFalse ? q->alpha : OpaqueAlpha);
+      pixel=(p->alpha_trait == BlendPixelTrait ? p->alpha : OpaqueAlpha)-
+        (q->alpha_trait == BlendPixelTrait ? q->alpha : OpaqueAlpha);
       distance=pixel*pixel;
       if (distance > fuzz)
         return(MagickFalse);
@@ -5583,9 +5999,9 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
         Generate a alpha scaling factor to generate a 4D cone on colorspace.
         If one color is transparent, distance has no color component.
       */
-      if (p->matte != MagickFalse)
+      if (p->alpha_trait == BlendPixelTrait)
         scale=(QuantumScale*p->alpha);
-      if (q->matte != MagickFalse)
+      if (q->alpha_trait == BlendPixelTrait)
         scale*=(QuantumScale*q->alpha);
       if (scale <= MagickEpsilon )
         return(MagickTrue);
@@ -5599,8 +6015,8 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
       distance+=pixel*pixel*scale;
       if (distance > fuzz)
         return(MagickFalse);
-      scale*=(MagickRealType) (QuantumScale*(QuantumRange-p->black));
-      scale*=(MagickRealType) (QuantumScale*(QuantumRange-q->black));
+      scale*=(double) (QuantumScale*(QuantumRange-p->black));
+      scale*=(double) (QuantumScale*(QuantumRange-q->black));
     }
   /*
     RGB or CMY color cube.
@@ -5612,9 +6028,9 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
       (p->colorspace == HWBColorspace))
     {
       /*
-        This calculates a arc distance for hue-- it should be a vector angle
-        of 'S'/'W' length with 'L'/'B' forming appropriate cones.  In other
-        words this is a hack - Anthony.
+        This calculates a arc distance for hue-- it should be a vector
+        angle of 'S'/'W' length with 'L'/'B' forming appropriate cones.
+        In other words this is a hack - Anthony.
       */
       if (fabs((double) pixel) > (QuantumRange/2))
         pixel-=QuantumRange;
@@ -5639,27 +6055,27 @@ MagickExport MagickBooleanType IsFuzzyEquivalencePixelInfo(const PixelInfo *p,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   S e t P i x e l C h a n n e l M a p M a s k                               %
+%   S e t P i x e l C h a n n e l M a s k                                     %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  SetPixelChannelMapMask() sets the pixel channel map from the specified
-%  channel mask.
+%  SetPixelChannelMask() sets the pixel channel map from the specified channel
+%  mask.
 %
-%  The format of the SetPixelChannelMapMask method is:
+%  The format of the SetPixelChannelMask method is:
 %
-%      void SetPixelChannelMapMask(Image *image,const ChannelType channel_mask)
+%      void SetPixelChannelMask(Image *image,const ChannelType channel_mask)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o mask: the channel mask.
+%    o channel_mask: the channel mask.
 %
 */
-MagickExport void SetPixelChannelMapMask(Image *image,
+MagickExport void SetPixelChannelMask(Image *image,
   const ChannelType channel_mask)
 {
 #define GetChannelBit(mask,bit)  (((size_t) (mask) >> (size_t) (bit)) & 0x01)
@@ -5667,20 +6083,24 @@ MagickExport void SetPixelChannelMapMask(Image *image,
   register ssize_t
     i;
 
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(PixelEvent,GetMagickModule(),"%s[%08x]", \
+      image->filename,channel_mask); \
   image->channel_mask=channel_mask;
   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
   {
-    PixelChannel
-      channel;
-
-    channel=GetPixelChannelMapChannel(image,i);
-    SetPixelChannelMapTraits(image,channel,
+    PixelChannel channel=GetPixelChannelChannel(image,i);
+    SetPixelChannelTraits(image,channel,
       GetChannelBit(channel_mask,channel) == 0 ? CopyPixelTrait :
-      image->matte == MagickFalse || (channel == AlphaPixelChannel) ?
-      UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | BlendPixelTrait));
+      image->alpha_trait != BlendPixelTrait || (channel == AlphaPixelChannel) ?
+      UpdatePixelTrait : (PixelTrait) (UpdatePixelTrait | image->alpha_trait));
   }
   if (image->storage_class == PseudoClass)
-    SetPixelChannelMapTraits(image,IndexPixelChannel,CopyPixelTrait);
+    SetPixelChannelTraits(image,IndexPixelChannel,CopyPixelTrait);
+  if (image->read_mask != MagickFalse)
+    SetPixelChannelTraits(image,ReadMaskPixelChannel,CopyPixelTrait);
+  if (image->write_mask != MagickFalse)
+    SetPixelChannelTraits(image,WriteMaskPixelChannel,CopyPixelTrait);
   if (image->debug != MagickFalse)
     LogPixelChannels(image);
 }
@@ -5690,35 +6110,31 @@ MagickExport void SetPixelChannelMapMask(Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   S e t P i x e l C h a n n e l M a s k                                     %
+%   S e t P i x e l M e t a C h a n n e l s                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  SetPixelChannelMask() sets the pixel channel mask from the specified channel
-%  mask.
+%  SetPixelMetaChannels() sets the image meta channels.
 %
-%  The format of the SetPixelChannelMask method is:
+%  The format of the SetPixelMetaChannels method is:
 %
-%      ChannelType SetPixelChannelMask(Image *image,
-%        const ChannelType channel_mask)
+%      MagickBooleanType SetPixelMetaChannels(Image *image,
+%        const size_t number_meta_channels,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o channel_mask: the channel mask.
+%    o number_meta_channels:  the number of meta channels.
+%
+%    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport ChannelType SetPixelChannelMask(Image *image,
-  const ChannelType channel_mask)
+MagickExport MagickBooleanType SetPixelMetaChannels(Image *image,
+  const size_t number_meta_channels,ExceptionInfo *exception)
 {
-  ChannelType
-    mask;
-
-  mask=image->channel_mask;
-  image->channel_mask=channel_mask;
-  SetPixelChannelMapMask(image,channel_mask);
-  return(mask);
+  image->number_meta_channels=number_meta_channels;
+  return(SyncImagePixelCache(image,exception));
 }