]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/distort.c
...
[imagemagick] / MagickCore / distort.c
index 3817cfb6cd59baf28a7e53bc292f0b37efa7e174..5685cbfd442db7e58e0ba59056e402bf6d1694f9 100644 (file)
 %                     MagickCore Image Distortion Methods                     %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                              Anthony Thyssen                                %
 %                                 June 2007                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
 #include "MagickCore/artifact.h"
 #include "MagickCore/cache.h"
 #include "MagickCore/cache-view.h"
+#include "MagickCore/channel.h"
 #include "MagickCore/colorspace-private.h"
 #include "MagickCore/composite-private.h"
 #include "MagickCore/distort.h"
 #include "MagickCore/exception.h"
 #include "MagickCore/exception-private.h"
 #include "MagickCore/gem.h"
-#include "MagickCore/hashmap.h"
 #include "MagickCore/image.h"
+#include "MagickCore/linked-list.h"
 #include "MagickCore/list.h"
 #include "MagickCore/matrix.h"
 #include "MagickCore/matrix-private.h"
 #include "MagickCore/option.h"
 #include "MagickCore/pixel.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
 #include "MagickCore/resample.h"
 #include "MagickCore/resample-private.h"
 #include "MagickCore/registry.h"
+#include "MagickCore/resource_.h"
 #include "MagickCore/semaphore.h"
 #include "MagickCore/shear.h"
 #include "MagickCore/string_.h"
 /*
   Numerous internal routines for image distortions.
 */
-static inline double MagickMin(const double x,const double y)
-{
-  return( x < y ? x : y);
-}
-static inline double MagickMax(const double x,const double y)
-{
-  return( x > y ? x : y);
-}
-
 static inline void AffineArgsToCoefficients(double *affine)
 {
   /* map  external sx,ry,rx,sy,tx,ty  to  internal c0,c2,c4,c1,c3,c5 */
@@ -103,7 +97,7 @@ static void InvertAffineCoefficients(const double *coeff,double *inverse)
   /* From "Digital Image Warping" by George Wolberg, page 50 */
   double determinant;
 
-  determinant=1.0/(coeff[0]*coeff[4]-coeff[1]*coeff[3]);
+  determinant=PerceptibleReciprocal(coeff[0]*coeff[4]-coeff[1]*coeff[3]);
   inverse[0]=determinant*coeff[4];
   inverse[1]=determinant*(-coeff[1]);
   inverse[2]=determinant*(coeff[1]*coeff[5]-coeff[2]*coeff[4]);
@@ -118,7 +112,7 @@ static void InvertPerspectiveCoefficients(const double *coeff,
   /* From "Digital Image Warping" by George Wolberg, page 53 */
   double determinant;
 
-  determinant=1.0/(coeff[0]*coeff[4]-coeff[3]*coeff[1]);
+  determinant=PerceptibleReciprocal(coeff[0]*coeff[4]-coeff[3]*coeff[1]);
   inverse[0]=determinant*(coeff[4]-coeff[7]*coeff[5]);
   inverse[1]=determinant*(coeff[7]*coeff[2]-coeff[1]);
   inverse[2]=determinant*(coeff[1]*coeff[5]-coeff[4]*coeff[2]);
@@ -129,16 +123,6 @@ static void InvertPerspectiveCoefficients(const double *coeff,
   inverse[7]=determinant*(coeff[6]*coeff[1]-coeff[0]*coeff[7]);
 }
 
-static inline double MagickRound(double x)
-{
-  /*
-    Round the fraction to nearest integer.
-  */
-  if (x >= 0.0)
-    return((double) ((ssize_t) (x+0.5)));
-  return((double) ((ssize_t) (x-0.5)));
-}
-
 /*
  * Polynomial Term Defining Functions
  *
@@ -309,12 +293,12 @@ MagickExport Image *AffineTransformImage(const Image *image,
   /*
     Affine transform image.
   */
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(affine_matrix != (AffineMatrix *) NULL);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   distort[0]=affine_matrix->sx;
   distort[1]=affine_matrix->rx;
   distort[2]=affine_matrix->ry;
@@ -344,7 +328,7 @@ MagickExport Image *AffineTransformImage(const Image *image,
 %
 %  The format of the GenerateCoefficients() method is:
 %
-%    Image *GenerateCoefficients(const Image *image,DistortImageMethod method,
+%    Image *GenerateCoefficients(const Image *image,DistortMethod method,
 %        const size_t number_arguments,const double *arguments,
 %        size_t number_values, ExceptionInfo *exception)
 %
@@ -376,9 +360,19 @@ MagickExport Image *AffineTransformImage(const Image *image,
 %  outside other MagickCore library methods.
 */
 
+static inline double MagickRound(double x)
+{
+  /*
+    Round the fraction to nearest integer.
+  */
+  if ((x-floor(x)) < (ceil(x)-x))
+    return(floor(x));
+  return(ceil(x));
+}
+
 static double *GenerateCoefficients(const Image *image,
-  DistortImageMethod *method,const size_t number_arguments,
-  const double *arguments,size_t number_values,ExceptionInfo *exception)
+  DistortMethod *method,const size_t number_arguments,const double *arguments,
+  size_t number_values,ExceptionInfo *exception)
 {
   double
     *coeff;
@@ -429,13 +423,6 @@ static double *GenerateCoefficients(const Image *image,
       break;
     case PolynomialDistortion:
       /* number of coefficents depend on the given polynomal 'order' */
-      if ( number_arguments <= 1 && (number_arguments-1)%cp_size != 0)
-      {
-        (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-                   "InvalidArgument","%s : '%s'","Polynomial",
-                   "Invalid number of args: order [CPs]...");
-        return((double *) NULL);
-      }
       i = poly_number_terms(arguments[0]);
       number_coeff = 2 + i*number_values;
       if ( i == 0 ) {
@@ -469,7 +456,7 @@ static double *GenerateCoefficients(const Image *image,
 #endif
       break;
     case ShepardsDistortion:
-      number_coeff=1;  /* not used, but provide some type of return */
+      number_coeff=1;  /* The power factor to use */
       break;
     case ArcDistortion:
       number_coeff=5;
@@ -493,7 +480,7 @@ static double *GenerateCoefficients(const Image *image,
       number_coeff=10;
       break;
     default:
-      assert(! "Unknown Method Given"); /* just fail assertion */
+      perror("unknown method given"); /* just fail assertion */
   }
 
   /* allocate the array of coefficients needed */
@@ -1406,18 +1393,32 @@ static double *GenerateCoefficients(const Image *image,
       if ( number_arguments%cp_size != 0 ||
            number_arguments < cp_size ) {
         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
-              "InvalidArgument", "%s : 'require at least %.20g CPs'",
-              CommandOptionToMnemonic(MagickDistortOptions, *method), 1.0);
+              "InvalidArgument", "%s : 'requires CP's (4 numbers each)'",
+              CommandOptionToMnemonic(MagickDistortOptions, *method));
         coeff=(double *) RelinquishMagickMemory(coeff);
         return((double *) NULL);
       }
+      /* User defined weighting power for Shepard's Method */
+      { const char *artifact=GetImageArtifact(image,"shepards:power");
+        if ( artifact != (const char *) NULL ) {
+          coeff[0]=StringToDouble(artifact,(char **) NULL) / 2.0;
+          if ( coeff[0] < MagickEpsilon ) {
+            (void) ThrowMagickException(exception,GetMagickModule(),
+                OptionError,"InvalidArgument","%s", "-define shepards:power" );
+            coeff=(double *) RelinquishMagickMemory(coeff);
+            return((double *) NULL);
+          }
+        }
+        else
+          coeff[0]=1.0;  /* Default power of 2 (Inverse Squared) */
+      }
       return(coeff);
     }
     default:
       break;
   }
   /* you should never reach this point */
-  assert(! "No Method Handler"); /* just fail assertion */
+  perror("no method handler"); /* just fail assertion */
   return((double *) NULL);
 }
 \f
@@ -1442,7 +1443,7 @@ static double *GenerateCoefficients(const Image *image,
 %
 %  The format of the DistortResizeImage method is:
 %
-%      Image *AdaptiveResizeImage(const Image *image,const size_t columns,
+%      Image *DistortResizeImage(const Image *image,const size_t columns,
 %        const size_t rows,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
@@ -1478,17 +1479,15 @@ MagickExport Image *DistortResizeImage(const Image *image,
     Distort resize image.
   */
   assert(image != (const Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   if ((columns == 0) || (rows == 0))
     return((Image *) NULL);
   /* Do not short-circuit this resize if final image size is unchanged */
 
-  (void) SetImageVirtualPixelMethod(image,TransparentVirtualPixelMethod);
-
   (void) ResetMagickMemory(distort_args,0,12*sizeof(double));
   distort_args[4]=(double) image->columns;
   distort_args[6]=(double) columns;
@@ -1500,9 +1499,10 @@ MagickExport Image *DistortResizeImage(const Image *image,
   tmp_image=CloneImage(image,0,0,MagickTrue,exception);
   if ( tmp_image == (Image *) NULL )
     return((Image *) NULL);
-  (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod);
+  (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod,
+    exception);
 
-  if (image->matte == MagickFalse)
+  if (image->alpha_trait == UndefinedPixelTrait)
     {
       /*
         Image has not transparency channel, so we free to use it
@@ -1515,16 +1515,11 @@ MagickExport Image *DistortResizeImage(const Image *image,
       if ( resize_image == (Image *) NULL )
         return((Image *) NULL);
 
-      (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel,exception);
+      (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel,
+        exception);
     }
   else
     {
-      ChannelType
-        channel_mask;
-
-      Image
-        *resize_alpha;
-
       /*
         Image has transparency so handle colors and alpha separatly.
         Basically we need to separate Virtual-Pixel alpha in the resized
@@ -1532,9 +1527,10 @@ MagickExport Image *DistortResizeImage(const Image *image,
 
         distort alpha channel separately
       */
-      channel_mask=SetPixelChannelMask(tmp_image,AlphaChannel);
-      (void) SeparateImage(tmp_image,exception);
-      SetPixelChannelMap(tmp_image,channel_mask);
+      Image
+        *resize_alpha;
+
+      (void) SetImageAlphaChannel(tmp_image,ExtractAlphaChannel,exception);
       (void) SetImageAlphaChannel(tmp_image,OpaqueAlphaChannel,exception);
       resize_alpha=DistortImage(tmp_image,AffineDistortion,12,distort_args,
         MagickTrue,exception),
@@ -1546,8 +1542,7 @@ MagickExport Image *DistortResizeImage(const Image *image,
       tmp_image=CloneImage(image,0,0,MagickTrue,exception);
       if ( tmp_image == (Image *) NULL )
         return((Image *) NULL);
-      (void) SetImageVirtualPixelMethod(tmp_image,
-        TransparentVirtualPixelMethod);
+      (void) SetImageVirtualPixelMethod(tmp_image,TransparentVirtualPixelMethod,        exception);
       resize_image=DistortImage(tmp_image,AffineDistortion,12,distort_args,
         MagickTrue,exception),
       tmp_image=DestroyImage(tmp_image);
@@ -1557,15 +1552,13 @@ MagickExport Image *DistortResizeImage(const Image *image,
           return((Image *) NULL);
         }
       /* replace resize images alpha with the separally distorted alpha */
-      (void) SetImageAlphaChannel(resize_image,DeactivateAlphaChannel,
-        exception);
-      (void) SetImageAlphaChannel(resize_alpha,DeactivateAlphaChannel,
-        exception);
-      (void) CompositeImage(resize_image,CopyOpacityCompositeOp,resize_alpha,
-        0,0,exception);
+      (void) SetImageAlphaChannel(resize_image,OffAlphaChannel,exception);
+      (void) SetImageAlphaChannel(resize_alpha,OffAlphaChannel,exception);
+      (void) CompositeImage(resize_image,resize_alpha,CopyAlphaCompositeOp,
+        MagickTrue,0,0,exception);
       resize_alpha=DestroyImage(resize_alpha);
     }
-  (void) SetImageVirtualPixelMethod(resize_image,vp_save);
+  (void) SetImageVirtualPixelMethod(resize_image,vp_save,exception);
 
   /*
     Clean up the results of the Distortion
@@ -1578,10 +1571,13 @@ MagickExport Image *DistortResizeImage(const Image *image,
   tmp_image=resize_image;
   resize_image=CropImage(tmp_image,&crop_area,exception);
   tmp_image=DestroyImage(tmp_image);
-
-  if ( resize_image == (Image *) NULL )
-    return((Image *) NULL);
-
+  if (resize_image != (Image *) NULL)
+    {
+      resize_image->alpha_trait=image->alpha_trait;
+      resize_image->compose=image->compose;
+      resize_image->page.width=0;
+      resize_image->page.height=0;
+    }
   return(resize_image);
 }
 \f
@@ -1612,7 +1608,7 @@ MagickExport Image *DistortResizeImage(const Image *image,
 %
 %  The format of the DistortImage() method is:
 %
-%      Image *DistortImage(const Image *image,const DistortImageMethod method,
+%      Image *DistortImage(const Image *image,const DistortMethod method,
 %        const size_t number_arguments,const double *arguments,
 %        MagickBooleanType bestfit, ExceptionInfo *exception)
 %
@@ -1673,7 +1669,7 @@ MagickExport Image *DistortResizeImage(const Image *image,
 %                    instead
 %
 */
-MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
+MagickExport Image *DistortImage(const Image *image, DistortMethod method,
   const size_t number_arguments,const double *arguments,
   MagickBooleanType bestfit,ExceptionInfo *exception)
 {
@@ -1693,12 +1689,11 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
     viewport_given;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-
+  assert(exception->signature == MagickCoreSignature);
 
   /*
     Handle Special Compound Distortions
@@ -1803,28 +1798,28 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
         s.x = (double) image->page.x;
         s.y = (double) image->page.y;
         scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
-        scale=1.0/(  (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+        scale=PerceptibleReciprocal(scale);
         d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
         d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
         InitalBounds(d);
         s.x = (double) image->page.x+image->columns;
         s.y = (double) image->page.y;
         scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
-        scale=1.0/(  (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+        scale=PerceptibleReciprocal(scale);
         d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
         d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
         ExpandBounds(d);
         s.x = (double) image->page.x;
         s.y = (double) image->page.y+image->rows;
         scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
-        scale=1.0/(  (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+        scale=PerceptibleReciprocal(scale);
         d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
         d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
         ExpandBounds(d);
         s.x = (double) image->page.x+image->columns;
         s.y = (double) image->page.y+image->rows;
         scale=inverse[6]*s.x+inverse[7]*s.y+1.0;
-        scale=1.0/(  (fabs(scale) <= MagickEpsilon) ? 1.0 : scale );
+        scale=PerceptibleReciprocal(scale);
         d.x = scale*(inverse[0]*s.x+inverse[1]*s.y+inverse[2]);
         d.y = scale*(inverse[3]*s.x+inverse[4]*s.y+inverse[5]);
         ExpandBounds(d);
@@ -1953,21 +1948,26 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
   { const char *artifact=GetImageArtifact(image,"distort:viewport");
     viewport_given = MagickFalse;
     if ( artifact != (const char *) NULL ) {
-      (void) ParseAbsoluteGeometry(artifact,&geometry);
-      viewport_given = MagickTrue;
+      MagickStatusType flags=ParseAbsoluteGeometry(artifact,&geometry);
+      if (flags==NoValue)
+        (void) ThrowMagickException(exception,GetMagickModule(),
+             OptionWarning,"InvalidSetting","'%s' '%s'",
+             "distort:viewport",artifact);
+      else
+        viewport_given = MagickTrue;
     }
   }
 
   /* Verbose output */
-  if ( GetImageArtifact(image,"verbose") != (const char *) NULL ) {
+  if (IsStringTrue(GetImageArtifact(image,"verbose")) != MagickFalse) {
     register ssize_t
        i;
-    char image_gen[MaxTextExtent];
+    char image_gen[MagickPathExtent];
     const char *lookup;
 
     /* Set destination image size and virtual offset */
     if ( bestfit || viewport_given ) {
-      (void) FormatLocaleString(image_gen, MaxTextExtent,"  -size %.20gx%.20g "
+      (void) FormatLocaleString(image_gen, MagickPathExtent,"  -size %.20gx%.20g "
         "-page %+.20g%+.20g xc: +insert \\\n",(double) geometry.width,
         (double) geometry.height,(double) geometry.x,(double) geometry.y);
       lookup="v.p{ xx-v.page.x-.5, yy-v.page.y-.5 }";
@@ -2168,7 +2168,7 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
           (void) FormatLocaleFile(stderr, "  c%.20g = %+lf\n", (double) i, coeff[i]);
         (void) FormatLocaleFile(stderr, "DePolar Distort, FX Equivelent:\n");
         (void) FormatLocaleFile(stderr, "%s", image_gen);
-        (void) FormatLocaleFile(stderr, "  -fx 'aa=(i+.5)*%lf %+lf;\n", coeff[6], -coeff[4] );
+        (void) FormatLocaleFile(stderr, "  -fx 'aa=(i+.5)*%lf %+lf;\n", coeff[6], +coeff[4] );
         (void) FormatLocaleFile(stderr, "       rr=(j+.5)*%lf %+lf;\n", coeff[7], +coeff[1] );
         (void) FormatLocaleFile(stderr, "       xx=rr*sin(aa) %+lf;\n", coeff[2] );
         (void) FormatLocaleFile(stderr, "       yy=rr*cos(aa) %+lf;\n", coeff[3] );
@@ -2248,10 +2248,10 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
     output_scaling = 1.0;
     if (artifact != (const char *) NULL) {
       output_scaling = fabs(StringToDouble(artifact,(char **) NULL));
-      geometry.width  *= (size_t) output_scaling;
-      geometry.height *= (size_t) output_scaling;
-      geometry.x      *= (ssize_t) output_scaling;
-      geometry.y      *= (ssize_t) output_scaling;
+      geometry.width=(size_t) (output_scaling*geometry.width+0.5);
+      geometry.height=(size_t) (output_scaling*geometry.height+0.5);
+      geometry.x=(ssize_t) (output_scaling*geometry.x+0.5);
+      geometry.y=(ssize_t) (output_scaling*geometry.y+0.5);
       if ( output_scaling < 0.1 ) {
         coeff = (double *) RelinquishMagickMemory(coeff);
         (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
@@ -2279,10 +2279,13 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
       distort_image=DestroyImage(distort_image);
       return((Image *) NULL);
     }
+  if ((IsPixelInfoGray(&distort_image->background_color) == MagickFalse) &&
+      (IsGrayColorspace(distort_image->colorspace) != MagickFalse))
+    (void) SetImageColorspace(distort_image,sRGBColorspace,exception);
+  if (distort_image->background_color.alpha_trait != UndefinedPixelTrait)
+    distort_image->alpha_trait=BlendPixelTrait;
   distort_image->page.x=geometry.x;
   distort_image->page.y=geometry.y;
-  if (distort_image->background_color.alpha != OpaqueAlpha)
-    distort_image->matte=MagickTrue;
 
   { /* ----- MAIN CODE -----
        Sample the source image to each pixel in the distort image.
@@ -2300,7 +2303,7 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
       zero;
 
     ResampleFilter
-      **restrict resample_filter;
+      **magick_restrict resample_filter;
 
     ssize_t
       j;
@@ -2310,9 +2313,10 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
     GetPixelInfo(distort_image,&zero);
     resample_filter=AcquireResampleFilterThreadSet(image,
       UndefinedVirtualPixelMethod,MagickFalse,exception);
-    distort_view=AcquireCacheView(distort_image);
+    distort_view=AcquireAuthenticCacheView(distort_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+    #pragma omp parallel for schedule(static,4) shared(progress,status) \
+      magick_threads(image,distort_image,distort_image->rows,1)
 #endif
     for (j=0; j < (ssize_t) distort_image->rows; j++)
     {
@@ -2337,7 +2341,7 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
         i;
 
       register Quantum
-        *restrict q;
+        *magick_restrict q;
 
       q=QueueCacheViewAuthenticPixels(distort_view,0,j,distort_image->columns,1,
         exception);
@@ -2369,9 +2373,8 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
       */
       validity = 1.0;
 
-      invalid=distort_image->matte_color;
-      if (distort_image->colorspace == CMYKColorspace)
-        ConvertRGBToCMYK(&invalid);   /* what about other color spaces? */
+      ConformPixelInfo(distort_image,&distort_image->matte_color,&invalid,
+        exception);
       for (i=0; i < (ssize_t) distort_image->columns; i++)
       {
         /* map pixel coordinate to distortion space coordinate */
@@ -2550,7 +2553,7 @@ MagickExport Image *DistortImage(const Image *image,DistortImageMethod method,
           case DePolarDistortion:
           { /* @D Polar to Carteasain  */
             /* ignore all destination virtual offsets */
-            d.x = ((double)i+0.5)*output_scaling*coeff[6]-coeff[4];
+            d.x = ((double)i+0.5)*output_scaling*coeff[6]+coeff[4];
             d.y = ((double)j+0.5)*output_scaling*coeff[7]+coeff[1];
             s.x = d.y*sin(d.x) + coeff[2];
             s.y = d.y*cos(d.x) + coeff[3];
@@ -2601,7 +2604,7 @@ if ( i == 0 && j == 0 ) {
               /* derivatives...  (see Anthony Thyssen's personal notes) */
               ScaleFilter( resample_filter[id],
                     cx*cx, 0.0, s.y*cx/coeff[1], cx );
-#if 1
+#if 0
 /*if ( i == 0 && j == 0 )*/
 if ( d.x == 0.5 && d.y == 0.5 ) {
   fprintf(stderr, "x=%lf  y=%lf  u=%lf  v=%lf\n", d.x*coeff[1], d.y, s.x, s.y);
@@ -2660,10 +2663,13 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
           }
           case ShepardsDistortion:
           { /* Shepards Method, or Inverse Weighted Distance for
-              displacement around the destination image control points
-              The input arguments are the coefficents to the function.
-              This is more of a 'displacement' function rather than an
-              absolute distortion function.
+               displacement around the destination image control points
+               The input arguments are the coefficents to the function.
+               This is more of a 'displacement' function rather than an
+               absolute distortion function.
+
+               Note: We can not determine derivatives using shepards method
+               so only a point sample interpolatation can be used.
             */
             size_t
               i;
@@ -2675,10 +2681,8 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
               double weight =
                   ((double)d.x-arguments[i+2])*((double)d.x-arguments[i+2])
                 + ((double)d.y-arguments[i+3])*((double)d.y-arguments[i+3]);
-              if ( weight != 0 )
-                weight = 1/weight;
-              else
-                weight = 1;
+              weight = pow(weight,coeff[0]); /* shepards power factor */
+              weight = ( weight < 1.0 ) ? 1.0 : 1.0/weight;
 
               s.x += (arguments[ i ]-arguments[i+2])*weight;
               s.y += (arguments[i+1]-arguments[i+3])*weight;
@@ -2686,11 +2690,8 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
             }
             s.x /= denominator;
             s.y /= denominator;
-            s.x += d.x;
+            s.x += d.x;   /* make it as relative displacement */
             s.y += d.y;
-
-            /* We can not determine derivatives using shepards method
-               only color interpolatation, not area-resampling */
             break;
           }
           default:
@@ -2706,11 +2707,12 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
 
         if ( validity <= 0.0 ) {
           /* result of distortion is an invalid pixel - don't resample */
-          SetPixelInfoPixel(distort_image,&invalid,q);
+          SetPixelViaPixelInfo(distort_image,&invalid,q);
         }
         else {
           /* resample the source image to find its correct color */
-          (void) ResamplePixelColor(resample_filter[id],s.x,s.y,&pixel);
+          (void) ResamplePixelColor(resample_filter[id],s.x,s.y,&pixel,
+            exception);
           /* if validity between 0.0 and 1.0 mix result with invalid pixel */
           if ( validity < 1.0 ) {
             /* Do a blend of sample color and invalid pixel */
@@ -2718,7 +2720,7 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
             CompositePixelInfoBlend(&pixel,validity,&invalid,(1.0-validity),
               &pixel);
           }
-          SetPixelInfoPixel(distort_image,&pixel,q);
+          SetPixelViaPixelInfo(distort_image,&pixel,q);
         }
         q+=GetPixelChannels(distort_image);
       }
@@ -2731,7 +2733,7 @@ if ( d.x == 0.5 && d.y == 0.5 ) {
             proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_DistortImage)
+          #pragma omp critical (MagickCore_DistortImage)
 #endif
           proceed=SetImageProgress(image,DistortImageTag,progress++,
             image->rows);
@@ -2795,9 +2797,10 @@ MagickExport Image *RotateImage(const Image *image,const double degrees,
   ExceptionInfo *exception)
 {
   Image
+    *distort_image,
     *rotate_image;
 
-  MagickRealType
+  double
     angle;
 
   PointInfo
@@ -2806,18 +2809,15 @@ MagickExport Image *RotateImage(const Image *image,const double degrees,
   size_t
     rotations;
 
-  VirtualPixelMethod
-    method;
-
   /*
     Adjust rotation angle.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   angle=degrees;
   while (angle < -45.0)
     angle+=360.0;
@@ -2828,10 +2828,14 @@ MagickExport Image *RotateImage(const Image *image,const double degrees,
   shear.y=sin((double) DegreesToRadians(angle));
   if ((fabs(shear.x) < MagickEpsilon) && (fabs(shear.y) < MagickEpsilon))
     return(IntegralRotateImage(image,rotations,exception));
-  method=SetImageVirtualPixelMethod(image,BackgroundVirtualPixelMethod);
-  rotate_image=DistortImage(image,ScaleRotateTranslateDistortion,1,&degrees,
-    MagickTrue,exception);
-  method=SetImageVirtualPixelMethod(image,method);
+  distort_image=CloneImage(image,0,0,MagickTrue,exception);
+  if (distort_image == (Image *) NULL)
+    return((Image *) NULL);
+  (void) SetImageVirtualPixelMethod(distort_image,BackgroundVirtualPixelMethod,
+    exception);
+  rotate_image=DistortImage(distort_image,ScaleRotateTranslateDistortion,1,
+    &degrees,MagickTrue,exception);
+  distort_image=DestroyImage(distort_image);
   return(rotate_image);
 }
 \f
@@ -2893,11 +2897,11 @@ MagickExport Image *SparseColorImage(const Image *image,
     number_colors;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
 
   /* Determine number of color values needed per control point */
   number_colors=0;
@@ -2911,17 +2915,17 @@ MagickExport Image *SparseColorImage(const Image *image,
       (image->colorspace == CMYKColorspace))
     number_colors++;
   if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-      (image->matte != MagickFalse))
+      (image->alpha_trait != UndefinedPixelTrait))
     number_colors++;
 
   /*
     Convert input arguments into mapping coefficients, this this case
     we are mapping (distorting) colors, rather than coordinates.
   */
-  { DistortImageMethod
+  { DistortMethod
       distort_method;
 
-    distort_method=(DistortImageMethod) method;
+    distort_method=(DistortMethod) method;
     if ( distort_method >= SentinelDistortion )
       distort_method = ShepardsDistortion; /* Pretend to be Shepards */
     coeff = GenerateCoefficients(image, &distort_method, number_arguments,
@@ -2936,11 +2940,13 @@ MagickExport Image *SparseColorImage(const Image *image,
     */
     sparse_method = (SparseColorMethod) distort_method;
     if ( distort_method == ShepardsDistortion )
-      sparse_method = method;   /* return non-distiort methods to normal */
+      sparse_method = method;   /* return non-distort methods to normal */
+    if ( sparse_method == InverseColorInterpolate )
+      coeff[0]=0.5;            /* sqrt() the squared distance for inverse */
   }
 
   /* Verbose output */
-  if ( GetImageArtifact(image,"verbose") != (const char *) NULL ) {
+  if (IsStringTrue(GetImageArtifact(image,"verbose")) != MagickFalse) {
 
     switch (sparse_method) {
       case BarycentricColorInterpolate:
@@ -2961,7 +2967,7 @@ MagickExport Image *SparseColorImage(const Image *image,
           (void) FormatLocaleFile(stderr, "  -channel K -fx '%+lf*i %+lf*j %+lf' \\\n",
               coeff[x], coeff[x+1], coeff[x+2]),x+=3;
         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-            (image->matte != MagickFalse))
+            (image->alpha_trait != UndefinedPixelTrait))
           (void) FormatLocaleFile(stderr, "  -channel A -fx '%+lf*i %+lf*j %+lf' \\\n",
               coeff[x], coeff[x+1], coeff[x+2]),x+=3;
         break;
@@ -2988,7 +2994,7 @@ MagickExport Image *SparseColorImage(const Image *image,
               coeff[ x ], coeff[x+1],
               coeff[x+2], coeff[x+3]),x+=4;
         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-            (image->matte != MagickFalse))
+            (image->alpha_trait != UndefinedPixelTrait))
           (void) FormatLocaleFile(stderr, "   -channel A -fx '%+lf*i %+lf*j %+lf*i*j %+lf;\n",
               coeff[ x ], coeff[x+1],
               coeff[x+2], coeff[x+3]),x+=4;
@@ -3029,9 +3035,10 @@ MagickExport Image *SparseColorImage(const Image *image,
 
     status=MagickTrue;
     progress=0;
-    sparse_view=AcquireCacheView(sparse_image);
+    sparse_view=AcquireAuthenticCacheView(sparse_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
+    #pragma omp parallel for schedule(static,4) shared(progress,status) \
+      magick_threads(image,sparse_image,sparse_image->rows,1)
 #endif
     for (j=0; j < (ssize_t) sparse_image->rows; j++)
     {
@@ -3045,7 +3052,7 @@ MagickExport Image *SparseColorImage(const Image *image,
         i;
 
       register Quantum
-        *restrict q;
+        *magick_restrict q;
 
       q=GetCacheViewAuthenticPixels(sparse_view,0,j,sparse_image->columns,
         1,exception);
@@ -3077,7 +3084,7 @@ MagickExport Image *SparseColorImage(const Image *image,
               pixel.black   = coeff[x]*i +coeff[x+1]*j
                               +coeff[x+2], x+=3;
             if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                (image->matte != MagickFalse))
+                (image->alpha_trait != UndefinedPixelTrait))
               pixel.alpha = coeff[x]*i +coeff[x+1]*j
                               +coeff[x+2], x+=3;
             break;
@@ -3099,7 +3106,7 @@ MagickExport Image *SparseColorImage(const Image *image,
               pixel.black   = coeff[x]*i     + coeff[x+1]*j +
                               coeff[x+2]*i*j + coeff[x+3], x+=4;
             if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                (image->matte != MagickFalse))
+                (image->alpha_trait != UndefinedPixelTrait))
               pixel.alpha = coeff[x]*i     + coeff[x+1]*j +
                               coeff[x+2]*i*j + coeff[x+3], x+=4;
             break;
@@ -3122,7 +3129,7 @@ MagickExport Image *SparseColorImage(const Image *image,
                 (image->colorspace == CMYKColorspace))
               pixel.black=0.0;
             if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                (image->matte != MagickFalse))
+                (image->alpha_trait != UndefinedPixelTrait))
               pixel.alpha=0.0;
             denominator = 0.0;
             for(k=0; k<number_arguments; k+=2+number_colors) {
@@ -3130,8 +3137,7 @@ MagickExport Image *SparseColorImage(const Image *image,
               double weight =
                   ((double)i-arguments[ k ])*((double)i-arguments[ k ])
                 + ((double)j-arguments[k+1])*((double)j-arguments[k+1]);
-              if ( method == InverseColorInterpolate )
-                weight = sqrt(weight);  /* inverse, not inverse squared */
+              weight = pow(weight,coeff[0]); /* inverse of power factor */
               weight = ( weight < 1.0 ) ? 1.0 : 1.0/weight;
               if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
                 pixel.red     += arguments[x++]*weight;
@@ -3143,7 +3149,7 @@ MagickExport Image *SparseColorImage(const Image *image,
                   (image->colorspace == CMYKColorspace))
                 pixel.black   += arguments[x++]*weight;
               if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                  (image->matte != MagickFalse))
+                  (image->alpha_trait != UndefinedPixelTrait))
                 pixel.alpha += arguments[x++]*weight;
               denominator += weight;
             }
@@ -3157,19 +3163,57 @@ MagickExport Image *SparseColorImage(const Image *image,
                 (image->colorspace == CMYKColorspace))
               pixel.black/=denominator;
             if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                (image->matte != MagickFalse))
+                (image->alpha_trait != UndefinedPixelTrait))
               pixel.alpha/=denominator;
             break;
           }
+          case ManhattanColorInterpolate:
+          {
+            size_t
+              k;
+
+            double
+              minimum = MagickMaximumValue;
+
+            /*
+              Just use the closest control point you can find!
+            */
+            for(k=0; k<number_arguments; k+=2+number_colors) {
+              double distance =
+                  fabs((double)i-arguments[ k ])
+                + fabs((double)j-arguments[k+1]);
+              if ( distance < minimum ) {
+                register ssize_t x=(ssize_t) k+2;
+                if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
+                  pixel.red=arguments[x++];
+                if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
+                  pixel.green=arguments[x++];
+                if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
+                  pixel.blue=arguments[x++];
+                if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
+                    (image->colorspace == CMYKColorspace))
+                  pixel.black=arguments[x++];
+                if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
+                    (image->alpha_trait != UndefinedPixelTrait))
+                  pixel.alpha=arguments[x++];
+                minimum = distance;
+              }
+            }
+            break;
+          }
           case VoronoiColorInterpolate:
           default:
-          { /* Just use the closest control point you can find! */
+          {
             size_t
               k;
+
             double
-              minimum = MagickHuge;
+              minimum = MagickMaximumValue;
 
-            for(k=0; k<number_arguments; k+=2+number_colors) {
+            /*
+              Just use the closest control point you can find!
+            */
+            for (k=0; k<number_arguments; k+=2+number_colors) {
               double distance =
                   ((double)i-arguments[ k ])*((double)i-arguments[ k ])
                 + ((double)j-arguments[k+1])*((double)j-arguments[k+1]);
@@ -3185,7 +3229,7 @@ MagickExport Image *SparseColorImage(const Image *image,
                     (image->colorspace == CMYKColorspace))
                   pixel.black=arguments[x++];
                 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                    (image->matte != MagickFalse))
+                    (image->alpha_trait != UndefinedPixelTrait))
                   pixel.alpha=arguments[x++];
                 minimum = distance;
               }
@@ -3195,18 +3239,18 @@ MagickExport Image *SparseColorImage(const Image *image,
         }
         /* set the color directly back into the source image */
         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
-          pixel.red*=QuantumRange;
+          pixel.red=ClampPixel(QuantumRange*pixel.red);
         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
-          pixel.green*=QuantumRange;
+          pixel.green=ClampPixel(QuantumRange*pixel.green);
         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
-          pixel.blue*=QuantumRange;
+          pixel.blue=ClampPixel(QuantumRange*pixel.blue);
         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
             (image->colorspace == CMYKColorspace))
-          pixel.black*=QuantumRange;
+          pixel.black=ClampPixel(QuantumRange*pixel.black);
         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-            (image->matte != MagickFalse))
-          pixel.alpha*=QuantumRange;
-        SetPixelInfoPixel(sparse_image,&pixel,q);
+            (image->alpha_trait != UndefinedPixelTrait))
+          pixel.alpha=ClampPixel(QuantumRange*pixel.alpha);
+        SetPixelViaPixelInfo(sparse_image,&pixel,q);
         q+=GetPixelChannels(sparse_image);
       }
       sync=SyncCacheViewAuthenticPixels(sparse_view,exception);
@@ -3218,7 +3262,7 @@ MagickExport Image *SparseColorImage(const Image *image,
             proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_SparseColorImage)
+          #pragma omp critical (MagickCore_SparseColorImage)
 #endif
           proceed=SetImageProgress(image,SparseColorTag,progress++,image->rows);
           if (proceed == MagickFalse)