]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/effect.c
Add RobidouxSharp filter depreciate Bessel Filter and Static Gravity
[imagemagick] / MagickCore / effect.c
index 7394e75dbb9581437006c5693077f55154cb9709..1b677690723358a2b07b0d7b835442269337594e 100644 (file)
@@ -17,7 +17,7 @@
 %                                 October 1996                                %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the License.  You may  %
@@ -82,6 +82,7 @@
 #include "MagickCore/segment.h"
 #include "MagickCore/shear.h"
 #include "MagickCore/signature-private.h"
+#include "MagickCore/statistic.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/transform.h"
 %  The format of the AdaptiveBlurImage method is:
 %
 %      Image *AdaptiveBlurImage(const Image *image,const double radius,
-%        const double sigma,const double bias,ExceptionInfo *exception)
+%        const double sigma,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %
 %    o sigma: the standard deviation of the Laplacian, in pixels.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
@@ -169,7 +168,7 @@ MagickExport MagickBooleanType AdaptiveLevelImage(Image *image,
 }
 
 MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
-  const double sigma,const double bias,ExceptionInfo *exception)
+  const double sigma,ExceptionInfo *exception)
 {
 #define AdaptiveBlurImageTag  "Convolve/Image"
 #define MagickSigma  (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
@@ -233,7 +232,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
       return((Image *) NULL);
     }
   (void) AdaptiveLevelImage(edge_image,"20%,95%",exception);
-  gaussian_image=GaussianBlurImage(edge_image,radius,sigma,bias,exception);
+  gaussian_image=GaussianBlurImage(edge_image,radius,sigma,exception);
   if (gaussian_image != (Image *) NULL)
     {
       edge_image=DestroyImage(edge_image);
@@ -244,7 +243,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
     Create a set of kernels from maximum (radius,sigma) to minimum.
   */
   width=GetOptimalKernelWidth2D(radius,sigma);
-  kernel=(double **) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
+  kernel=(double **) AcquireAlignedMemory((size_t) width,sizeof(*kernel));
   if (kernel == (double **) NULL)
     {
       edge_image=DestroyImage(edge_image);
@@ -254,7 +253,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
   (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
   for (i=0; i < (ssize_t) width; i+=2)
   {
-    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
+    kernel[i]=(double *) AcquireAlignedMemory((size_t) (width-i),(width-i)*
       sizeof(**kernel));
     if (kernel[i] == (double *) NULL)
       break;
@@ -280,8 +279,8 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
   if (i < (ssize_t) width)
     {
       for (i-=2; i >= 0; i-=2)
-        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
-      kernel=(double **) RelinquishMagickMemory(kernel);
+        kernel[i]=(double *) RelinquishAlignedMemory(kernel[i]);
+      kernel=(double **) RelinquishAlignedMemory(kernel);
       edge_image=DestroyImage(edge_image);
       blur_image=DestroyImage(blur_image);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -291,11 +290,11 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  edge_view=AcquireCacheView(edge_image);
-  blur_view=AcquireCacheView(blur_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  edge_view=AcquireVirtualCacheView(edge_image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_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)
 #endif
   for (y=0; y < (ssize_t) blur_image->rows; y++)
   {
@@ -343,8 +342,14 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
         (ssize_t) ((width-j)/2L),width-j,width-j,exception);
       if (p == (const Quantum *) NULL)
         break;
-      center=(ssize_t) GetPixelChannels(image)*(width-j)*
-        ((width-j)/2L)+GetPixelChannels(image)*((width-j)/2L);
+      center=(ssize_t) GetPixelChannels(image)*(width-j)*((width-j)/2L)+
+        GetPixelChannels(image)*((width-j)/2L);
+      if (GetPixelMask(image,p) != 0)
+        {
+          q+=GetPixelChannels(blur_image);
+          r+=GetPixelChannels(edge_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -371,8 +376,8 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
         ssize_t
           v;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -384,7 +389,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
           }
         k=kernel[j];
         pixels=p;
-        pixel=bias;
+        pixel=0.0;
         gamma=0.0;
         if ((blur_traits & BlendPixelTrait) == 0)
           {
@@ -433,7 +438,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_AdaptiveBlurImage)
+        #pragma omp critical (MagickCore_AdaptiveBlurImage)
 #endif
         proceed=SetImageProgress(image,AdaptiveBlurImageTag,progress++,
           image->rows);
@@ -447,8 +452,8 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
   image_view=DestroyCacheView(image_view);
   edge_image=DestroyImage(edge_image);
   for (i=0; i < (ssize_t) width;  i+=2)
-    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
-  kernel=(double **) RelinquishMagickMemory(kernel);
+    kernel[i]=(double *) RelinquishAlignedMemory(kernel[i]);
+  kernel=(double **) RelinquishAlignedMemory(kernel);
   if (status == MagickFalse)
     blur_image=DestroyImage(blur_image);
   return(blur_image);
@@ -474,7 +479,7 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
 %  The format of the AdaptiveSharpenImage method is:
 %
 %      Image *AdaptiveSharpenImage(const Image *image,const double radius,
-%        const double sigma,const double bias,ExceptionInfo *exception)
+%        const double sigma,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -485,13 +490,11 @@ MagickExport Image *AdaptiveBlurImage(const Image *image,const double radius,
 %
 %    o sigma: the standard deviation of the Laplacian, in pixels.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
 MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
-  const double sigma,const double bias,ExceptionInfo *exception)
+  const double sigma,ExceptionInfo *exception)
 {
 #define AdaptiveSharpenImageTag  "Convolve/Image"
 #define MagickSigma  (fabs(sigma) <= MagickEpsilon ? 1.0 : sigma)
@@ -555,7 +558,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
       return((Image *) NULL);
     }
   (void) AdaptiveLevelImage(edge_image,"20%,95%",exception);
-  gaussian_image=GaussianBlurImage(edge_image,radius,sigma,bias,exception);
+  gaussian_image=GaussianBlurImage(edge_image,radius,sigma,exception);
   if (gaussian_image != (Image *) NULL)
     {
       edge_image=DestroyImage(edge_image);
@@ -566,7 +569,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
     Create a set of kernels from maximum (radius,sigma) to minimum.
   */
   width=GetOptimalKernelWidth2D(radius,sigma);
-  kernel=(double **) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
+  kernel=(double **) AcquireAlignedMemory((size_t) width,sizeof(*kernel));
   if (kernel == (double **) NULL)
     {
       edge_image=DestroyImage(edge_image);
@@ -576,7 +579,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
   (void) ResetMagickMemory(kernel,0,(size_t) width*sizeof(*kernel));
   for (i=0; i < (ssize_t) width; i+=2)
   {
-    kernel[i]=(double *) AcquireQuantumMemory((size_t) (width-i),(width-i)*
+    kernel[i]=(double *) AcquireAlignedMemory((size_t) (width-i),(width-i)*
       sizeof(**kernel));
     if (kernel[i] == (double *) NULL)
       break;
@@ -602,8 +605,8 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
   if (i < (ssize_t) width)
     {
       for (i-=2; i >= 0; i-=2)
-        kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
-      kernel=(double **) RelinquishMagickMemory(kernel);
+        kernel[i]=(double *) RelinquishAlignedMemory(kernel[i]);
+      kernel=(double **) RelinquishAlignedMemory(kernel);
       edge_image=DestroyImage(edge_image);
       sharp_image=DestroyImage(sharp_image);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -613,11 +616,11 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  edge_view=AcquireCacheView(edge_image);
-  sharp_view=AcquireCacheView(sharp_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  edge_view=AcquireVirtualCacheView(edge_image,exception);
+  sharp_view=AcquireAuthenticCacheView(sharp_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)
 #endif
   for (y=0; y < (ssize_t) sharp_image->rows; y++)
   {
@@ -665,9 +668,15 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
         (ssize_t) ((width-j)/2L),width-j,width-j,exception);
       if (p == (const Quantum *) NULL)
         break;
-      center=(ssize_t) GetPixelChannels(image)*(width-j)*
-        ((width-j)/2L)+GetPixelChannels(image)*((width-j)/2);
-      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      center=(ssize_t) GetPixelChannels(image)*(width-j)*((width-j)/2L)+
+        GetPixelChannels(image)*((width-j)/2);
+      if (GetPixelMask(image,p) != 0)
+        {
+          q+=GetPixelChannels(sharp_image);
+          r+=GetPixelChannels(edge_image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(sharp_image); i++)
       {
         MagickRealType
           alpha,
@@ -693,8 +702,8 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
         ssize_t
           v;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         sharp_traits=GetPixelChannelMapTraits(sharp_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (sharp_traits == UndefinedPixelTrait))
@@ -706,7 +715,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
           }
         k=kernel[j];
         pixels=p;
-        pixel=bias;
+        pixel=0.0;
         gamma=0.0;
         if ((sharp_traits & BlendPixelTrait) == 0)
           {
@@ -755,7 +764,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_AdaptiveSharpenImage)
+        #pragma omp critical (MagickCore_AdaptiveSharpenImage)
 #endif
         proceed=SetImageProgress(image,AdaptiveSharpenImageTag,progress++,
           image->rows);
@@ -769,8 +778,8 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
   image_view=DestroyCacheView(image_view);
   edge_image=DestroyImage(edge_image);
   for (i=0; i < (ssize_t) width;  i+=2)
-    kernel[i]=(double *) RelinquishMagickMemory(kernel[i]);
-  kernel=(double **) RelinquishMagickMemory(kernel);
+    kernel[i]=(double *) RelinquishAlignedMemory(kernel[i]);
+  kernel=(double **) RelinquishAlignedMemory(kernel);
   if (status == MagickFalse)
     sharp_image=DestroyImage(sharp_image);
   return(sharp_image);
@@ -799,7 +808,7 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
 %  The format of the BlurImage method is:
 %
 %      Image *BlurImage(const Image *image,const double radius,
-%        const double sigma,const double bias,ExceptionInfo *exception)
+%        const double sigma,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -810,8 +819,6 @@ MagickExport Image *AdaptiveSharpenImage(const Image *image,const double radius,
 %
 %    o sigma: the standard deviation of the Gaussian, in pixels.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
@@ -833,7 +840,7 @@ static double *GetBlurKernel(const size_t width,const double sigma)
     Generate a 1-D convolution kernel.
   */
   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
-  kernel=(double *) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
+  kernel=(double *) AcquireAlignedMemory((size_t) width,sizeof(*kernel));
   if (kernel == (double *) NULL)
     return(0);
   normalize=0.0;
@@ -852,7 +859,7 @@ static double *GetBlurKernel(const size_t width,const double sigma)
 }
 
 MagickExport Image *BlurImage(const Image *image,const double radius,
-  const double sigma,const double bias,ExceptionInfo *exception)
+  const double sigma,ExceptionInfo *exception)
 {
 #define BlurImageTag  "Blur/Image"
 
@@ -919,7 +926,7 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
         *k;
 
       (void) LogMagickEvent(TransformEvent,GetMagickModule(),
-        "  BlurImage with %.20g kernel:",(double) width);
+        "  blur image with kernel width %.20g:",(double) width);
       message=AcquireString("");
       k=kernel;
       for (i=0; i < (ssize_t) width; i++)
@@ -939,10 +946,10 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
   status=MagickTrue;
   progress=0;
   center=(ssize_t) GetPixelChannels(image)*(width/2L);
-  image_view=AcquireCacheView(image);
-  blur_view=AcquireCacheView(blur_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_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)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -959,7 +966,7 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
       continue;
     p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y,
       image->columns+width,1,exception);
-    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
+    q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
@@ -971,6 +978,12 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
       register ssize_t
         i;
 
+      if (GetPixelMask(image,p) != 0)
+        {
+          p+=GetPixelChannels(image);
+          q+=GetPixelChannels(blur_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -994,8 +1007,8 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
         register ssize_t
           u;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -1048,7 +1061,7 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_BlurImage)
+        #pragma omp critical (MagickCore_BlurImage)
 #endif
         proceed=SetImageProgress(image,BlurImageTag,progress++,blur_image->rows+
           blur_image->columns);
@@ -1061,12 +1074,13 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
   /*
     Blur columns.
   */
-  image_view=AcquireCacheView(blur_image);
-  blur_view=AcquireCacheView(blur_image);
+  center=(ssize_t) GetPixelChannels(blur_image)*(width/2L);
+  image_view=AcquireVirtualCacheView(blur_image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_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)
 #endif
-  for (x=0; x < (ssize_t) image->columns; x++)
+  for (x=0; x < (ssize_t) blur_image->columns; x++)
   {
     register const Quantum
       *restrict p;
@@ -1080,19 +1094,25 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
     if (status == MagickFalse)
       continue;
     p=GetCacheViewVirtualPixels(image_view,x,-((ssize_t) width/2L),1,
-      image->rows+width,exception);
+      blur_image->rows+width,exception);
     q=GetCacheViewAuthenticPixels(blur_view,x,0,1,blur_image->rows,exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
         status=MagickFalse;
         continue;
       }
-    for (y=0; y < (ssize_t) image->rows; y++)
+    for (y=0; y < (ssize_t) blur_image->rows; y++)
     {
       register ssize_t
         i;
 
-      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      if (GetPixelMask(image,p) != 0)
+        {
+           p+=GetPixelChannels(blur_image);
+           q+=GetPixelChannels(blur_image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(blur_image); i++)
       {
         MagickRealType
           alpha,
@@ -1115,8 +1135,8 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
         register ssize_t
           u;
 
-        traits=GetPixelChannelMapTraits(blur_image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(blur_image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(blur_image,i);
+        traits=GetPixelChannelMapTraits(blur_image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -1149,8 +1169,8 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
         gamma=0.0;
         for (u=0; u < (ssize_t) width; u++)
         {
-          alpha=(MagickRealType) (QuantumScale*
-            GetPixelAlpha(blur_image,pixels));
+          alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(blur_image,
+            pixels));
           pixel+=(*k)*alpha*pixels[i];
           gamma+=(*k)*alpha;
           k++;
@@ -1170,7 +1190,7 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_BlurImage)
+        #pragma omp critical (MagickCore_BlurImage)
 #endif
         proceed=SetImageProgress(blur_image,BlurImageTag,progress++,
           blur_image->rows+blur_image->columns);
@@ -1180,10 +1200,10 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
   }
   blur_view=DestroyCacheView(blur_view);
   image_view=DestroyCacheView(image_view);
-  kernel=(double *) RelinquishMagickMemory(kernel);
+  kernel=(double *) RelinquishAlignedMemory(kernel);
+  blur_image->type=image->type;
   if (status == MagickFalse)
     blur_image=DestroyImage(blur_image);
-  blur_image->type=image->type;
   return(blur_image);
 }
 \f
@@ -1217,223 +1237,7 @@ MagickExport Image *BlurImage(const Image *image,const double radius,
 MagickExport Image *ConvolveImage(const Image *image,
   const KernelInfo *kernel_info,ExceptionInfo *exception)
 {
-#define ConvolveImageTag  "Convolve/Image"
-
-  CacheView
-    *convolve_view,
-    *image_view;
-
-  Image
-    *convolve_image;
-
-  MagickBooleanType
-    status;
-
-  MagickOffsetType
-    progress;
-
-  ssize_t
-    center,
-    y;
-
-  /*
-    Initialize convolve image attributes.
-  */
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  if ((kernel_info->width % 2) == 0)
-    ThrowImageException(OptionError,"KernelWidthMustBeAnOddNumber");
-  convolve_image=CloneImage(image,image->columns,image->rows,MagickTrue,
-    exception);
-  if (convolve_image == (Image *) NULL)
-    return((Image *) NULL);
-  if (SetImageStorageClass(convolve_image,DirectClass,exception) == MagickFalse)
-    {
-      convolve_image=DestroyImage(convolve_image);
-      return((Image *) NULL);
-    }
-  if (image->debug != MagickFalse)
-    {
-      char
-        format[MaxTextExtent],
-        *message;
-
-      register const double
-        *k;
-
-      register ssize_t
-        u;
-
-      ssize_t
-        v;
-
-      (void) LogMagickEvent(TransformEvent,GetMagickModule(),
-        "  ConvolveImage with %.20gx%.20g kernel:",(double) kernel_info->width,
-        (double) kernel_info->height);
-      message=AcquireString("");
-      k=kernel_info->values;
-      for (v=0; v < (ssize_t) kernel_info->width; v++)
-      {
-        *message='\0';
-        (void) FormatLocaleString(format,MaxTextExtent,"%.20g: ",(double) v);
-        (void) ConcatenateString(&message,format);
-        for (u=0; u < (ssize_t) kernel_info->height; u++)
-        {
-          (void) FormatLocaleString(format,MaxTextExtent,"%g ",*k++);
-          (void) ConcatenateString(&message,format);
-        }
-        (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
-      }
-      message=DestroyString(message);
-    }
-  status=AccelerateConvolveImage(image,kernel_info,convolve_image,exception);
-  if (status == MagickTrue)
-    return(convolve_image);
-  /*
-    Convolve image.
-  */
-  center=(ssize_t) GetPixelChannels(image)*(image->columns+kernel_info->width)*
-    (kernel_info->height/2L)+GetPixelChannels(image)*(kernel_info->width/2L);
-  status=MagickTrue;
-  progress=0;
-  image_view=AcquireCacheView(image);
-  convolve_view=AcquireCacheView(convolve_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
-  for (y=0; y < (ssize_t) image->rows; y++)
-  {
-    register const Quantum
-      *restrict p;
-
-    register Quantum
-      *restrict q;
-
-    register ssize_t
-      x;
-
-    if (status == MagickFalse)
-      continue;
-    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) kernel_info->width/2L),y-
-      (ssize_t) (kernel_info->height/2L),image->columns+kernel_info->width,
-      kernel_info->height,exception);
-    q=QueueCacheViewAuthenticPixels(convolve_view,0,y,convolve_image->columns,1,
-      exception);
-    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
-      {
-        status=MagickFalse;
-        continue;
-      }
-    for (x=0; x < (ssize_t) image->columns; x++)
-    {
-      register ssize_t
-        i;
-
-      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-      {
-        MagickRealType
-          alpha,
-          gamma,
-          pixel;
-
-        PixelChannel
-          channel;
-
-        PixelTrait
-          convolve_traits,
-          traits;
-
-        register const double
-          *restrict k;
-
-        register const Quantum
-          *restrict pixels;
-
-        register ssize_t
-          u;
-
-        ssize_t
-          v;
-
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
-        convolve_traits=GetPixelChannelMapTraits(convolve_image,channel);
-        if ((traits == UndefinedPixelTrait) ||
-            (convolve_traits == UndefinedPixelTrait))
-          continue;
-        if ((convolve_traits & CopyPixelTrait) != 0)
-          {
-            SetPixelChannel(convolve_image,channel,p[center+i],q);
-            continue;
-          }
-        k=kernel_info->values;
-        pixels=p;
-        pixel=kernel_info->bias;
-        if ((convolve_traits & BlendPixelTrait) == 0)
-          {
-            /*
-              No alpha blending.
-            */
-            for (v=0; v < (ssize_t) kernel_info->height; v++)
-            {
-              for (u=0; u < (ssize_t) kernel_info->width; u++)
-              {
-                pixel+=(*k)*pixels[i];
-                k++;
-                pixels+=GetPixelChannels(image);
-              }
-              pixels+=image->columns*GetPixelChannels(image);
-            }
-            SetPixelChannel(convolve_image,channel,ClampToQuantum(pixel),q);
-            continue;
-          }
-        /*
-          Alpha blending.
-        */
-        gamma=0.0;
-        for (v=0; v < (ssize_t) kernel_info->height; v++)
-        {
-          for (u=0; u < (ssize_t) kernel_info->width; u++)
-          {
-            alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(image,pixels));
-            pixel+=(*k)*alpha*pixels[i];
-            gamma+=(*k)*alpha;
-            k++;
-            pixels+=GetPixelChannels(image);
-          }
-          pixels+=image->columns*GetPixelChannels(image);
-        }
-        gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
-        SetPixelChannel(convolve_image,channel,ClampToQuantum(gamma*pixel),q);
-      }
-      p+=GetPixelChannels(image);
-      q+=GetPixelChannels(convolve_image);
-    }
-    if (SyncCacheViewAuthenticPixels(convolve_view,exception) == MagickFalse)
-      status=MagickFalse;
-    if (image->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_ConvolveImage)
-#endif
-        proceed=SetImageProgress(image,ConvolveImageTag,progress++,image->rows);
-        if (proceed == MagickFalse)
-          status=MagickFalse;
-      }
-  }
-  convolve_image->type=image->type;
-  convolve_view=DestroyCacheView(convolve_view);
-  image_view=DestroyCacheView(image_view);
-  if (status == MagickFalse)
-    convolve_image=DestroyImage(convolve_image);
-  return(convolve_image);
+  return(MorphologyImage(image,ConvolveMorphology,1,kernel_info,exception));
 }
 \f
 /*
@@ -1448,7 +1252,10 @@ MagickExport Image *ConvolveImage(const Image *image,
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  DespeckleImage() reduces the speckle noise in an image while perserving the
-%  edges of the original image.
+%  edges of the original image.  A speckle removing filter uses a complementary %  hulling technique (raising pixels that are darker than their surrounding
+%  neighbors, then complementarily lowering pixels that are brighter than their
+%  surrounding neighbors) to reduce the speckle index of that image (reference
+%  Crimmins speckle removal).
 %
 %  The format of the DespeckleImage method is:
 %
@@ -1463,21 +1270,15 @@ MagickExport Image *ConvolveImage(const Image *image,
 */
 
 static void Hull(const ssize_t x_offset,const ssize_t y_offset,
-  const size_t columns,const size_t rows,Quantum *f,Quantum *g,
-  const int polarity)
+  const size_t columns,const size_t rows,const int polarity,Quantum *restrict f,
+  Quantum *restrict g)
 {
-  MagickRealType
-    v;
-
   register Quantum
     *p,
     *q,
     *r,
     *s;
 
-  register ssize_t
-    x;
-
   ssize_t
     y;
 
@@ -1485,80 +1286,76 @@ static void Hull(const ssize_t x_offset,const ssize_t y_offset,
   assert(g != (Quantum *) NULL);
   p=f+(columns+2);
   q=g+(columns+2);
-  r=p+(y_offset*((ssize_t) columns+2)+x_offset);
+  r=p+(y_offset*(columns+2)+x_offset);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(static)
+#endif
   for (y=0; y < (ssize_t) rows; y++)
   {
-    p++;
-    q++;
-    r++;
+    register ssize_t
+      i,
+      x;
+
+    SignedQuantum
+      v;
+
+    i=(2*y+1)+y*columns;
     if (polarity > 0)
-      for (x=(ssize_t) columns; x != 0; x--)
+      for (x=0; x < (ssize_t) columns; x++)
       {
-        v=(MagickRealType) (*p);
-        if ((MagickRealType) *r >= (v+(MagickRealType) ScaleCharToQuantum(2)))
+        v=(SignedQuantum) p[i];
+        if ((SignedQuantum) r[i] >= (v+ScaleCharToQuantum(2)))
           v+=ScaleCharToQuantum(1);
-        *q=(Quantum) v;
-        p++;
-        q++;
-        r++;
+        q[i]=(Quantum) v;
+        i++;
       }
     else
-      for (x=(ssize_t) columns; x != 0; x--)
+      for (x=0; x < (ssize_t) columns; x++)
       {
-        v=(MagickRealType) (*p);
-        if ((MagickRealType) *r <= (v-(MagickRealType) ScaleCharToQuantum(2)))
-          v-=(ssize_t) ScaleCharToQuantum(1);
-        *q=(Quantum) v;
-        p++;
-        q++;
-        r++;
+        v=(SignedQuantum) p[i];
+        if ((SignedQuantum) r[i] <= (v-ScaleCharToQuantum(2)))
+          v-=ScaleCharToQuantum(1);
+        q[i]=(Quantum) v;
+        i++;
       }
-    p++;
-    q++;
-    r++;
   }
   p=f+(columns+2);
   q=g+(columns+2);
-  r=q+(y_offset*((ssize_t) columns+2)+x_offset);
-  s=q-(y_offset*((ssize_t) columns+2)+x_offset);
+  r=q+(y_offset*(columns+2)+x_offset);
+  s=q-(y_offset*(columns+2)+x_offset);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(static)
+#endif
   for (y=0; y < (ssize_t) rows; y++)
   {
-    p++;
-    q++;
-    r++;
-    s++;
+    register ssize_t
+      i,
+      x;
+
+    SignedQuantum
+      v;
+
+    i=(2*y+1)+y*columns;
     if (polarity > 0)
-      for (x=(ssize_t) columns; x != 0; x--)
+      for (x=0; x < (ssize_t) columns; x++)
       {
-        v=(MagickRealType) (*q);
-        if (((MagickRealType) *s >=
-             (v+(MagickRealType) ScaleCharToQuantum(2))) &&
-            ((MagickRealType) *r > v))
+        v=(SignedQuantum) q[i];
+        if (((SignedQuantum) s[i] >= (v+ScaleCharToQuantum(2))) &&
+            ((SignedQuantum) r[i] > v))
           v+=ScaleCharToQuantum(1);
-        *p=(Quantum) v;
-        p++;
-        q++;
-        r++;
-        s++;
+        p[i]=(Quantum) v;
+        i++;
       }
     else
-      for (x=(ssize_t) columns; x != 0; x--)
+      for (x=0; x < (ssize_t) columns; x++)
       {
-        v=(MagickRealType) (*q);
-        if (((MagickRealType) *s <=
-             (v-(MagickRealType) ScaleCharToQuantum(2))) &&
-            ((MagickRealType) *r < v))
-          v-=(MagickRealType) ScaleCharToQuantum(1);
-        *p=(Quantum) v;
-        p++;
-        q++;
-        r++;
-        s++;
+        v=(SignedQuantum) q[i];
+        if (((SignedQuantum) s[i] <= (v-ScaleCharToQuantum(2))) &&
+            ((SignedQuantum) r[i] < v))
+          v-=ScaleCharToQuantum(1);
+        p[i]=(Quantum) v;
+        i++;
       }
-    p++;
-    q++;
-    r++;
-    s++;
   }
 }
 
@@ -1577,7 +1374,7 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
     status;
 
   Quantum
-    *restrict buffers,
+    *restrict buffer,
     *restrict pixels;
 
   register ssize_t
@@ -1609,15 +1406,15 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
       return((Image *) NULL);
     }
   /*
-    Allocate image buffers.
+    Allocate image buffer.
   */
   length=(size_t) ((image->columns+2)*(image->rows+2));
-  pixels=(Quantum *) AcquireQuantumMemory(length,2*sizeof(*pixels));
-  buffers=(Quantum *) AcquireQuantumMemory(length,2*sizeof(*pixels));
-  if ((pixels == (Quantum *) NULL) || (buffers == (Quantum *) NULL))
+  pixels=(Quantum *) AcquireQuantumMemory(length,sizeof(*pixels));
+  buffer=(Quantum *) AcquireQuantumMemory(length,sizeof(*buffer));
+  if ((pixels == (Quantum *) NULL) || (buffer == (Quantum *) NULL))
     {
-      if (buffers != (Quantum *) NULL)
-        buffers=(Quantum *) RelinquishMagickMemory(buffers);
+      if (buffer != (Quantum *) NULL)
+        buffer=(Quantum *) RelinquishMagickMemory(buffer);
       if (pixels != (Quantum *) NULL)
         pixels=(Quantum *) RelinquishMagickMemory(pixels);
       despeckle_image=DestroyImage(despeckle_image);
@@ -1627,8 +1424,8 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
     Reduce speckle in the image.
   */
   status=MagickTrue;
-  image_view=AcquireCacheView(image);
-  despeckle_view=AcquireCacheView(despeckle_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  despeckle_view=AcquireAuthenticCacheView(despeckle_image,exception);
   for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
   {
     PixelChannel
@@ -1638,10 +1435,6 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
       despeckle_traits,
       traits;
 
-    register Quantum
-      *buffer,
-      *pixel;
-
     register ssize_t
       k,
       x;
@@ -1652,17 +1445,15 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
 
     if (status == MagickFalse)
       continue;
-    traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-    channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+    channel=GetPixelChannelMapChannel(image,i);
+    traits=GetPixelChannelMapTraits(image,channel);
     despeckle_traits=GetPixelChannelMapTraits(despeckle_image,channel);
     if ((traits == UndefinedPixelTrait) ||
         (despeckle_traits == UndefinedPixelTrait))
       continue;
     if ((despeckle_traits & CopyPixelTrait) != 0)
       continue;
-    pixel=pixels;
-    (void) ResetMagickMemory(pixel,0,length*sizeof(*pixel));
-    buffer=buffers;
+    (void) ResetMagickMemory(pixels,0,length*sizeof(*pixels));
     j=(ssize_t) image->columns+2;
     for (y=0; y < (ssize_t) image->rows; y++)
     {
@@ -1678,7 +1469,7 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
       j++;
       for (x=0; x < (ssize_t) image->columns; x++)
       {
-        pixel[j++]=p[i];
+        pixels[j++]=p[i];
         p+=GetPixelChannels(image);
       }
       j++;
@@ -1686,10 +1477,10 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
     (void) ResetMagickMemory(buffer,0,length*sizeof(*buffer));
     for (k=0; k < 4; k++)
     {
-      Hull(X[k],Y[k],image->columns,image->rows,pixel,buffer,1);
-      Hull(-X[k],-Y[k],image->columns,image->rows,pixel,buffer,1);
-      Hull(-X[k],-Y[k],image->columns,image->rows,pixel,buffer,-1);
-      Hull(X[k],Y[k],image->columns,image->rows,pixel,buffer,-1);
+      Hull(X[k],Y[k],image->columns,image->rows,1,pixels,buffer);
+      Hull(-X[k],-Y[k],image->columns,image->rows,1,pixels,buffer);
+      Hull(-X[k],-Y[k],image->columns,image->rows,-1,pixels,buffer);
+      Hull(X[k],Y[k],image->columns,image->rows,-1,pixels,buffer);
     }
     j=(ssize_t) image->columns+2;
     for (y=0; y < (ssize_t) image->rows; y++)
@@ -1700,8 +1491,8 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
       register Quantum
         *restrict q;
 
-      q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
-        1,exception);
+      q=QueueCacheViewAuthenticPixels(despeckle_view,0,y,
+        despeckle_image->columns,1,exception);
       if (q == (Quantum *) NULL)
         {
           status=MagickFalse;
@@ -1710,7 +1501,7 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
       j++;
       for (x=0; x < (ssize_t) image->columns; x++)
       {
-        SetPixelChannel(despeckle_image,channel,pixel[j++],q);
+        SetPixelChannel(despeckle_image,channel,pixels[j++],q);
         q+=GetPixelChannels(despeckle_image);
       }
       sync=SyncCacheViewAuthenticPixels(despeckle_view,exception);
@@ -1731,7 +1522,7 @@ MagickExport Image *DespeckleImage(const Image *image,ExceptionInfo *exception)
   }
   despeckle_view=DestroyCacheView(despeckle_view);
   image_view=DestroyCacheView(image_view);
-  buffers=(Quantum *) RelinquishMagickMemory(buffers);
+  buffer=(Quantum *) RelinquishMagickMemory(buffer);
   pixels=(Quantum *) RelinquishMagickMemory(pixels);
   despeckle_image->type=image->type;
   if (status == MagickFalse)
@@ -1796,15 +1587,15 @@ MagickExport Image *EdgeImage(const Image *image,const double radius,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  width=GetOptimalKernelWidth2D(radius,sigma);
+  width=GetOptimalKernelWidth1D(radius,sigma);
   kernel_info=AcquireKernelInfo((const char *) NULL);
   if (kernel_info == (KernelInfo *) NULL)
     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
   kernel_info->width=width;
   kernel_info->height=width;
-  kernel_info->values=(double *) AcquireAlignedMemory(kernel_info->width,
-    kernel_info->width*sizeof(*kernel_info->values));
-  if (kernel_info->values == (double *) NULL)
+  kernel_info->values=(MagickRealType *) AcquireAlignedMemory(
+    kernel_info->width,kernel_info->width*sizeof(*kernel_info->values));
+  if (kernel_info->values == (MagickRealType *) NULL)
     {
       kernel_info=DestroyKernelInfo(kernel_info);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -1820,7 +1611,6 @@ MagickExport Image *EdgeImage(const Image *image,const double radius,
     }
   }
   kernel_info->values[i/2]=(double) (width*width-1.0);
-  kernel_info->bias=image->bias;   /* FUTURE: User bias on a edge image? */
   edge_image=ConvolveImage(image,kernel_info,exception);
   kernel_info=DestroyKernelInfo(kernel_info);
   return(edge_image);
@@ -1886,15 +1676,15 @@ MagickExport Image *EmbossImage(const Image *image,const double radius,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
-  width=GetOptimalKernelWidth2D(radius,sigma);
+  width=GetOptimalKernelWidth1D(radius,sigma);
   kernel_info=AcquireKernelInfo((const char *) NULL);
   if (kernel_info == (KernelInfo *) NULL)
     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
   kernel_info->width=width;
   kernel_info->height=width;
-  kernel_info->values=(double *) AcquireAlignedMemory(kernel_info->width,
-    kernel_info->width*sizeof(*kernel_info->values));
-  if (kernel_info->values == (double *) NULL)
+  kernel_info->values=(MagickRealType *) AcquireAlignedMemory(
+    kernel_info->width,kernel_info->width*sizeof(*kernel_info->values));
+  if (kernel_info->values == (MagickRealType *) NULL)
     {
       kernel_info=DestroyKernelInfo(kernel_info);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -1915,7 +1705,6 @@ MagickExport Image *EmbossImage(const Image *image,const double radius,
     }
     k--;
   }
-  kernel_info->bias=image->bias;  /* FUTURE: user bias on an edge image */
   emboss_image=ConvolveImage(image,kernel_info,exception);
   kernel_info=DestroyKernelInfo(kernel_info);
   if (emboss_image != (Image *) NULL)
@@ -1942,7 +1731,7 @@ MagickExport Image *EmbossImage(const Image *image,const double radius,
 %  The format of the GaussianBlurImage method is:
 %
 %      Image *GaussianBlurImage(const Image *image,onst double radius,
-%        const double sigma,const double bias,ExceptionInfo *exception)
+%        const double sigma,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -1953,13 +1742,11 @@ MagickExport Image *EmbossImage(const Image *image,const double radius,
 %
 %    o sigma: the standard deviation of the Gaussian, in pixels.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
 MagickExport Image *GaussianBlurImage(const Image *image,const double radius,
-  const double sigma,const double bias,ExceptionInfo *exception)
+  const double sigma,ExceptionInfo *exception)
 {
   Image
     *blur_image;
@@ -1991,11 +1778,10 @@ MagickExport Image *GaussianBlurImage(const Image *image,const double radius,
   (void) ResetMagickMemory(kernel_info,0,sizeof(*kernel_info));
   kernel_info->width=width;
   kernel_info->height=width;
-  kernel_info->bias=bias;  /* FUTURE: user bias on Gaussian Blur! non-sense */
   kernel_info->signature=MagickSignature;
-  kernel_info->values=(double *) AcquireAlignedMemory(kernel_info->width,
-    kernel_info->width*sizeof(*kernel_info->values));
-  if (kernel_info->values == (double *) NULL)
+  kernel_info->values=(MagickRealType *) AcquireAlignedMemory(
+    kernel_info->width,kernel_info->width*sizeof(*kernel_info->values));
+  if (kernel_info->values == (MagickRealType *) NULL)
     {
       kernel_info=DestroyKernelInfo(kernel_info);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -2038,8 +1824,7 @@ MagickExport Image *GaussianBlurImage(const Image *image,const double radius,
 %  The format of the MotionBlurImage method is:
 %
 %    Image *MotionBlurImage(const Image *image,const double radius,
-%      const double sigma,const double angle,const double bias,
-%      ExceptionInfo *exception)
+%      const double sigma,const double angle,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -2052,8 +1837,6 @@ MagickExport Image *GaussianBlurImage(const Image *image,const double radius,
 %
 %    o angle: Apply the effect along this angle.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
@@ -2071,7 +1854,7 @@ static double *GetMotionBlurKernel(const size_t width,const double sigma)
    Generate a 1-D convolution kernel.
   */
   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
-  kernel=(double *) AcquireQuantumMemory((size_t) width,sizeof(*kernel));
+  kernel=(double *) AcquireAlignedMemory((size_t) width,sizeof(*kernel));
   if (kernel == (double *) NULL)
     return(kernel);
   normalize=0.0;
@@ -2087,12 +1870,12 @@ static double *GetMotionBlurKernel(const size_t width,const double sigma)
 }
 
 MagickExport Image *MotionBlurImage(const Image *image,const double radius,
-  const double sigma,const double angle,const double bias,
-  ExceptionInfo *exception)
+  const double sigma,const double angle,ExceptionInfo *exception)
 {
   CacheView
     *blur_view,
-    *image_view;
+    *image_view,
+    *motion_view;
 
   double
     *kernel;
@@ -2133,19 +1916,19 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
   offset=(OffsetInfo *) AcquireQuantumMemory(width,sizeof(*offset));
   if (offset == (OffsetInfo *) NULL)
     {
-      kernel=(double *) RelinquishMagickMemory(kernel);
+      kernel=(double *) RelinquishAlignedMemory(kernel);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
     }
   blur_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
   if (blur_image == (Image *) NULL)
     {
-      kernel=(double *) RelinquishMagickMemory(kernel);
+      kernel=(double *) RelinquishAlignedMemory(kernel);
       offset=(OffsetInfo *) RelinquishMagickMemory(offset);
       return((Image *) NULL);
     }
   if (SetImageStorageClass(blur_image,DirectClass,exception) == MagickFalse)
     {
-      kernel=(double *) RelinquishMagickMemory(kernel);
+      kernel=(double *) RelinquishAlignedMemory(kernel);
       offset=(OffsetInfo *) RelinquishMagickMemory(offset);
       blur_image=DestroyImage(blur_image);
       return((Image *) NULL);
@@ -2162,10 +1945,11 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  blur_view=AcquireCacheView(blur_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  motion_view=AcquireVirtualCacheView(image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1)
+  #pragma omp parallel for schedule(static,4) shared(progress,status)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2180,8 +1964,8 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
 
     if (status == MagickFalse)
       continue;
-    p=GetCacheViewVirtualPixels(blur_view,0,y,image->columns,1,exception);
-    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
@@ -2193,6 +1977,12 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
       register ssize_t
         i;
 
+      if (GetPixelMask(image,p) != 0)
+        {
+          p+=GetPixelChannels(image);
+          q+=GetPixelChannels(blur_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -2216,8 +2006,8 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
         register ssize_t
           j;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -2228,12 +2018,12 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
             continue;
           }
         k=kernel;
-        pixel=bias;
+        pixel=0.0;
         if ((blur_traits & BlendPixelTrait) == 0)
           {
             for (j=0; j < (ssize_t) width; j++)
             {
-              r=GetCacheViewVirtualPixels(image_view,x+offset[j].x,y+
+              r=GetCacheViewVirtualPixels(motion_view,x+offset[j].x,y+
                 offset[j].y,1,1,exception);
               if (r == (const Quantum *) NULL)
                 {
@@ -2250,7 +2040,7 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
         gamma=0.0;
         for (j=0; j < (ssize_t) width; j++)
         {
-          r=GetCacheViewVirtualPixels(image_view,x+offset[j].x,y+offset[j].y,1,
+          r=GetCacheViewVirtualPixels(motion_view,x+offset[j].x,y+offset[j].y,1,
             1,exception);
           if (r == (const Quantum *) NULL)
             {
@@ -2276,7 +2066,7 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_MotionBlurImage)
+        #pragma omp critical (MagickCore_MotionBlurImage)
 #endif
         proceed=SetImageProgress(image,BlurImageTag,progress++,image->rows);
         if (proceed == MagickFalse)
@@ -2284,8 +2074,9 @@ MagickExport Image *MotionBlurImage(const Image *image,const double radius,
       }
   }
   blur_view=DestroyCacheView(blur_view);
+  motion_view=DestroyCacheView(motion_view);
   image_view=DestroyCacheView(image_view);
-  kernel=(double *) RelinquishMagickMemory(kernel);
+  kernel=(double *) RelinquishAlignedMemory(kernel);
   offset=(OffsetInfo *) RelinquishMagickMemory(offset);
   if (status == MagickFalse)
     blur_image=DestroyImage(blur_image);
@@ -2595,17 +2386,14 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview,
       }
       case SharpenPreview:
       {
-        /* FUTURE: user bias on sharpen! This is non-sensical! */
-        preview_image=SharpenImage(thumbnail,radius,sigma,image->bias,
-          exception);
+        preview_image=SharpenImage(thumbnail,radius,sigma,exception);
         (void) FormatLocaleString(label,MaxTextExtent,"sharpen %gx%g",
           radius,sigma);
         break;
       }
       case BlurPreview:
       {
-        /* FUTURE: user bias on blur! This is non-sensical! */
-        preview_image=BlurImage(thumbnail,radius,sigma,image->bias,exception);
+        preview_image=BlurImage(thumbnail,radius,sigma,exception);
         (void) FormatLocaleString(label,MaxTextExtent,"blur %gx%g",radius,
           sigma);
         break;
@@ -2676,7 +2464,7 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview,
         if (preview_image == (Image *) NULL)
           break;
         threshold+=0.4f;
-        (void) SegmentImage(preview_image,RGBColorspace,MagickFalse,threshold,
+        (void) SegmentImage(preview_image,sRGBColorspace,MagickFalse,threshold,
           threshold,exception);
         (void) FormatLocaleString(label,MaxTextExtent,"segment %gx%g",
           threshold,threshold);
@@ -2717,9 +2505,8 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview,
       }
       case CharcoalDrawingPreview:
       {
-        /* FUTURE: user bias on charcoal! This is non-sensical! */
         preview_image=CharcoalImage(thumbnail,(double) radius,(double) sigma,
-          image->bias,exception);
+          exception);
         (void) FormatLocaleString(label,MaxTextExtent,"charcoal %gx%g",
           radius,sigma);
         break;
@@ -2843,7 +2630,7 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview,
 %  The format of the RadialBlurImage method is:
 %
 %    Image *RadialBlurImage(const Image *image,const double angle,
-%      const double blur,ExceptionInfo *exception)
+%      ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -2857,11 +2644,12 @@ MagickExport Image *PreviewImage(const Image *image,const PreviewType preview,
 %
 */
 MagickExport Image *RadialBlurImage(const Image *image,const double angle,
-  const double bias,ExceptionInfo *exception)
+  ExceptionInfo *exception)
 {
   CacheView
     *blur_view,
-    *image_view;
+    *image_view,
+    *radial_view;
 
   Image
     *blur_image;
@@ -2934,10 +2722,11 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  blur_view=AcquireCacheView(blur_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  radial_view=AcquireVirtualCacheView(image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_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)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2952,8 +2741,8 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
 
     if (status == MagickFalse)
       continue;
-    p=GetCacheViewVirtualPixels(blur_view,0,y,image->columns,1,exception);
-    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
@@ -2988,6 +2777,12 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
             if (step >= n)
               step=n-1;
         }
+      if (GetPixelMask(image,p) != 0)
+        {
+          p+=GetPixelChannels(image);
+          q+=GetPixelChannels(blur_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -3007,8 +2802,8 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
         register ssize_t
           j;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -3019,12 +2814,12 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
             continue;
           }
         gamma=0.0;
-        pixel=bias;
+        pixel=0.0;
         if ((blur_traits & BlendPixelTrait) == 0)
           {
             for (j=0; j < (ssize_t) n; j+=(ssize_t) step)
             {
-              r=GetCacheViewVirtualPixels(image_view, (ssize_t) (blur_center.x+
+              r=GetCacheViewVirtualPixels(radial_view, (ssize_t) (blur_center.x+
                 center.x*cos_theta[j]-center.y*sin_theta[j]+0.5),(ssize_t)
                 (blur_center.y+center.x*sin_theta[j]+center.y*cos_theta[j]+0.5),
                 1,1,exception);
@@ -3042,7 +2837,7 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
           }
         for (j=0; j < (ssize_t) n; j+=(ssize_t) step)
         {
-          r=GetCacheViewVirtualPixels(image_view, (ssize_t) (blur_center.x+
+          r=GetCacheViewVirtualPixels(radial_view, (ssize_t) (blur_center.x+
             center.x*cos_theta[j]-center.y*sin_theta[j]+0.5),(ssize_t)
             (blur_center.y+center.x*sin_theta[j]+center.y*cos_theta[j]+0.5),
             1,1,exception);
@@ -3068,7 +2863,7 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_RadialBlurImage)
+        #pragma omp critical (MagickCore_RadialBlurImage)
 #endif
         proceed=SetImageProgress(image,BlurImageTag,progress++,image->rows);
         if (proceed == MagickFalse)
@@ -3076,6 +2871,7 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
       }
   }
   blur_view=DestroyCacheView(blur_view);
+  radial_view=DestroyCacheView(radial_view);
   image_view=DestroyCacheView(image_view);
   cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
   sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
@@ -3102,8 +2898,7 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
 %  The format of the SelectiveBlurImage method is:
 %
 %      Image *SelectiveBlurImage(const Image *image,const double radius,
-%        const double sigma,const double threshold,const double bias,
-%        ExceptionInfo *exception)
+%        const double sigma,const double threshold,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -3117,14 +2912,11 @@ MagickExport Image *RadialBlurImage(const Image *image,const double angle,
 %    o threshold: only pixels within this contrast threshold are included
 %      in the blur operation.
 %
-%    o bias: the bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
 MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
-  const double sigma,const double threshold,const double bias,
-  ExceptionInfo *exception)
+  const double sigma,const double threshold,ExceptionInfo *exception)
 {
 #define SelectiveBlurImageTag  "SelectiveBlur/Image"
 
@@ -3167,7 +2959,7 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
   assert(exception != (ExceptionInfo *) NULL);
   assert(exception->signature == MagickSignature);
   width=GetOptimalKernelWidth1D(radius,sigma);
-  kernel=(double *) AcquireQuantumMemory((size_t) width,width*sizeof(*kernel));
+  kernel=(double *) AcquireAlignedMemory((size_t) width,width*sizeof(*kernel));
   if (kernel == (double *) NULL)
     ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
   j=(ssize_t) width/2;
@@ -3225,10 +3017,10 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
   progress=0;
   center=(ssize_t) (GetPixelChannels(image)*(image->columns+width)*(width/2L)+
     GetPixelChannels(image)*(width/2L));
-  image_view=AcquireCacheView(image);
-  blur_view=AcquireCacheView(blur_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  blur_view=AcquireAuthenticCacheView(blur_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)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3251,7 +3043,7 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
       continue;
     p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t)
       (width/2L),image->columns+width,width,exception);
-    q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
+    q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
@@ -3263,6 +3055,12 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
       register ssize_t
         i;
 
+      if (GetPixelMask(image,p) != 0)
+        {
+          p+=GetPixelChannels(image);
+          q+=GetPixelChannels(blur_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -3290,8 +3088,8 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
         ssize_t
           v;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         blur_traits=GetPixelChannelMapTraits(blur_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (blur_traits == UndefinedPixelTrait))
@@ -3302,7 +3100,7 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
             continue;
           }
         k=kernel;
-        pixel=bias;
+        pixel=0.0;
         pixels=p;
         intensity=(MagickRealType) GetPixelIntensity(image,p+center);
         gamma=0.0;
@@ -3369,7 +3167,7 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_SelectiveBlurImage)
+        #pragma omp critical (MagickCore_SelectiveBlurImage)
 #endif
         proceed=SetImageProgress(image,SelectiveBlurImageTag,progress++,
           image->rows);
@@ -3380,7 +3178,7 @@ MagickExport Image *SelectiveBlurImage(const Image *image,const double radius,
   blur_image->type=image->type;
   blur_view=DestroyCacheView(blur_view);
   image_view=DestroyCacheView(image_view);
-  kernel=(double *) RelinquishMagickMemory(kernel);
+  kernel=(double *) RelinquishAlignedMemory(kernel);
   if (status == MagickFalse)
     blur_image=DestroyImage(blur_image);
   return(blur_image);
@@ -3472,10 +3270,10 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  shade_view=AcquireCacheView(shade_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  shade_view=AcquireAuthenticCacheView(shade_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)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3549,6 +3347,14 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
                 shade=distance/sqrt((double) normal_distance);
             }
         }
+      if (GetPixelMask(image,p) != 0)
+        {
+          pre+=GetPixelChannels(image);
+          center+=GetPixelChannels(image);
+          post+=GetPixelChannels(image);
+          q+=GetPixelChannels(shade_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         PixelChannel
@@ -3558,8 +3364,8 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
           shade_traits,
           traits;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         shade_traits=GetPixelChannelMapTraits(shade_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (shade_traits == UndefinedPixelTrait))
@@ -3590,7 +3396,7 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_ShadeImage)
+        #pragma omp critical (MagickCore_ShadeImage)
 #endif
         proceed=SetImageProgress(image,ShadeImageTag,progress++,image->rows);
         if (proceed == MagickFalse)
@@ -3628,7 +3434,7 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
 %  The format of the SharpenImage method is:
 %
 %    Image *SharpenImage(const Image *image,const double radius,
-%      const double sigma,const double bias,ExceptionInfo *exception)
+%      const double sigma,ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
@@ -3639,13 +3445,11 @@ MagickExport Image *ShadeImage(const Image *image,const MagickBooleanType gray,
 %
 %    o sigma: the standard deviation of the Laplacian, in pixels.
 %
-%    o bias: bias.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
 MagickExport Image *SharpenImage(const Image *image,const double radius,
-  const double sigma,const double bias,ExceptionInfo *exception)
+  const double sigma,ExceptionInfo *exception)
 {
   double
     normalize;
@@ -3680,11 +3484,10 @@ MagickExport Image *SharpenImage(const Image *image,const double radius,
   (void) ResetMagickMemory(kernel_info,0,sizeof(*kernel_info));
   kernel_info->width=width;
   kernel_info->height=width;
-  kernel_info->bias=bias;   /* FUTURE: user bias - non-sensical! */
   kernel_info->signature=MagickSignature;
-  kernel_info->values=(double *) AcquireAlignedMemory(kernel_info->width,
-    kernel_info->width*sizeof(*kernel_info->values));
-  if (kernel_info->values == (double *) NULL)
+  kernel_info->values=(MagickRealType *) AcquireAlignedMemory(
+    kernel_info->width,kernel_info->width*sizeof(*kernel_info->values));
+  if (kernel_info->values == (MagickRealType *) NULL)
     {
       kernel_info=DestroyKernelInfo(kernel_info);
       ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
@@ -3751,6 +3554,7 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
     *spread_image;
 
   MagickBooleanType
+    concurrent,
     status;
 
   MagickOffsetType
@@ -3790,10 +3594,12 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
   progress=0;
   width=GetOptimalKernelWidth1D(radius,0.5);
   random_info=AcquireRandomInfoThreadSet();
-  image_view=AcquireCacheView(image);
-  spread_view=AcquireCacheView(spread_image);
+  concurrent=GetRandomSecretKey(random_info[0]) == ~0UL ? MagickTrue :
+    MagickFalse;
+  image_view=AcquireVirtualCacheView(image,exception);
+  spread_view=AcquireAuthenticCacheView(spread_image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status) omp_throttle(1)
+  #pragma omp parallel for schedule(static,8) shared(progress,status) omp_concurrent(concurrent)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -3838,7 +3644,7 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_SpreadImage)
+        #pragma omp critical (MagickCore_SpreadImage)
 #endif
         proceed=SetImageProgress(image,SpreadImageTag,progress++,image->rows);
         if (proceed == MagickFalse)
@@ -3856,692 +3662,7 @@ MagickExport Image *SpreadImage(const Image *image,const double radius,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%     S t a t i s t i c I m a g e                                             %
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-%  StatisticImage() makes each pixel the min / max / median / mode / etc. of
-%  the neighborhood of the specified width and height.
-%
-%  The format of the StatisticImage method is:
-%
-%      Image *StatisticImage(const Image *image,const StatisticType type,
-%        const size_t width,const size_t height,ExceptionInfo *exception)
-%
-%  A description of each parameter follows:
-%
-%    o image: the image.
-%
-%    o type: the statistic type (median, mode, etc.).
-%
-%    o width: the width of the pixel neighborhood.
-%
-%    o height: the height of the pixel neighborhood.
-%
-%    o exception: return any errors or warnings in this structure.
-%
-*/
-
-typedef struct _SkipNode
-{
-  size_t
-    next[9],
-    count,
-    signature;
-} SkipNode;
-
-typedef struct _SkipList
-{
-  ssize_t
-    level;
-
-  SkipNode
-    *nodes;
-} SkipList;
-
-typedef struct _PixelList
-{
-  size_t
-    length,
-    seed;
-
-  SkipList
-    skip_list;
-
-  size_t
-    signature;
-} PixelList;
-
-static PixelList *DestroyPixelList(PixelList *pixel_list)
-{
-  if (pixel_list == (PixelList *) NULL)
-    return((PixelList *) NULL);
-  if (pixel_list->skip_list.nodes != (SkipNode *) NULL)
-    pixel_list->skip_list.nodes=(SkipNode *) RelinquishMagickMemory(
-      pixel_list->skip_list.nodes);
-  pixel_list=(PixelList *) RelinquishMagickMemory(pixel_list);
-  return(pixel_list);
-}
-
-static PixelList **DestroyPixelListThreadSet(PixelList **pixel_list)
-{
-  register ssize_t
-    i;
-
-  assert(pixel_list != (PixelList **) NULL);
-  for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
-    if (pixel_list[i] != (PixelList *) NULL)
-      pixel_list[i]=DestroyPixelList(pixel_list[i]);
-  pixel_list=(PixelList **) RelinquishMagickMemory(pixel_list);
-  return(pixel_list);
-}
-
-static PixelList *AcquirePixelList(const size_t width,const size_t height)
-{
-  PixelList
-    *pixel_list;
-
-  pixel_list=(PixelList *) AcquireMagickMemory(sizeof(*pixel_list));
-  if (pixel_list == (PixelList *) NULL)
-    return(pixel_list);
-  (void) ResetMagickMemory((void *) pixel_list,0,sizeof(*pixel_list));
-  pixel_list->length=width*height;
-  pixel_list->skip_list.nodes=(SkipNode *) AcquireQuantumMemory(65537UL,
-    sizeof(*pixel_list->skip_list.nodes));
-  if (pixel_list->skip_list.nodes == (SkipNode *) NULL)
-    return(DestroyPixelList(pixel_list));
-  (void) ResetMagickMemory(pixel_list->skip_list.nodes,0,65537UL*
-    sizeof(*pixel_list->skip_list.nodes));
-  pixel_list->signature=MagickSignature;
-  return(pixel_list);
-}
-
-static PixelList **AcquirePixelListThreadSet(const size_t width,
-  const size_t height)
-{
-  PixelList
-    **pixel_list;
-
-  register ssize_t
-    i;
-
-  size_t
-    number_threads;
-
-  number_threads=GetOpenMPMaximumThreads();
-  pixel_list=(PixelList **) AcquireQuantumMemory(number_threads,
-    sizeof(*pixel_list));
-  if (pixel_list == (PixelList **) NULL)
-    return((PixelList **) NULL);
-  (void) ResetMagickMemory(pixel_list,0,number_threads*sizeof(*pixel_list));
-  for (i=0; i < (ssize_t) number_threads; i++)
-  {
-    pixel_list[i]=AcquirePixelList(width,height);
-    if (pixel_list[i] == (PixelList *) NULL)
-      return(DestroyPixelListThreadSet(pixel_list));
-  }
-  return(pixel_list);
-}
-
-static void AddNodePixelList(PixelList *pixel_list,const size_t color)
-{
-  register SkipList
-    *p;
-
-  register ssize_t
-    level;
-
-  size_t
-    search,
-    update[9];
-
-  /*
-    Initialize the node.
-  */
-  p=(&pixel_list->skip_list);
-  p->nodes[color].signature=pixel_list->signature;
-  p->nodes[color].count=1;
-  /*
-    Determine where it belongs in the list.
-  */
-  search=65536UL;
-  for (level=p->level; level >= 0; level--)
-  {
-    while (p->nodes[search].next[level] < color)
-      search=p->nodes[search].next[level];
-    update[level]=search;
-  }
-  /*
-    Generate a pseudo-random level for this node.
-  */
-  for (level=0; ; level++)
-  {
-    pixel_list->seed=(pixel_list->seed*42893621L)+1L;
-    if ((pixel_list->seed & 0x300) != 0x300)
-      break;
-  }
-  if (level > 8)
-    level=8;
-  if (level > (p->level+2))
-    level=p->level+2;
-  /*
-    If we're raising the list's level, link back to the root node.
-  */
-  while (level > p->level)
-  {
-    p->level++;
-    update[p->level]=65536UL;
-  }
-  /*
-    Link the node into the skip-list.
-  */
-  do
-  {
-    p->nodes[color].next[level]=p->nodes[update[level]].next[level];
-    p->nodes[update[level]].next[level]=color;
-  } while (level-- > 0);
-}
-
-static inline void GetMaximumPixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  register SkipList
-    *p;
-
-  size_t
-    color,
-    maximum;
-
-  ssize_t
-    count;
-
-  /*
-    Find the maximum value for each of the color.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  count=0;
-  maximum=p->nodes[color].next[0];
-  do
-  {
-    color=p->nodes[color].next[0];
-    if (color > maximum)
-      maximum=color;
-    count+=p->nodes[color].count;
-  } while (count < (ssize_t) pixel_list->length);
-  *pixel=ScaleShortToQuantum((unsigned short) maximum);
-}
-
-static inline void GetMeanPixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  MagickRealType
-    sum;
-
-  register SkipList
-    *p;
-
-  size_t
-    color;
-
-  ssize_t
-    count;
-
-  /*
-    Find the mean value for each of the color.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  count=0;
-  sum=0.0;
-  do
-  {
-    color=p->nodes[color].next[0];
-    sum+=(MagickRealType) p->nodes[color].count*color;
-    count+=p->nodes[color].count;
-  } while (count < (ssize_t) pixel_list->length);
-  sum/=pixel_list->length;
-  *pixel=ScaleShortToQuantum((unsigned short) sum);
-}
-
-static inline void GetMedianPixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  register SkipList
-    *p;
-
-  size_t
-    color;
-
-  ssize_t
-    count;
-
-  /*
-    Find the median value for each of the color.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  count=0;
-  do
-  {
-    color=p->nodes[color].next[0];
-    count+=p->nodes[color].count;
-  } while (count <= (ssize_t) (pixel_list->length >> 1));
-  *pixel=ScaleShortToQuantum((unsigned short) color);
-}
-
-static inline void GetMinimumPixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  register SkipList
-    *p;
-
-  size_t
-    color,
-    minimum;
-
-  ssize_t
-    count;
-
-  /*
-    Find the minimum value for each of the color.
-  */
-  p=(&pixel_list->skip_list);
-  count=0;
-  color=65536UL;
-  minimum=p->nodes[color].next[0];
-  do
-  {
-    color=p->nodes[color].next[0];
-    if (color < minimum)
-      minimum=color;
-    count+=p->nodes[color].count;
-  } while (count < (ssize_t) pixel_list->length);
-  *pixel=ScaleShortToQuantum((unsigned short) minimum);
-}
-
-static inline void GetModePixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  register SkipList
-    *p;
-
-  size_t
-    color,
-    max_count,
-    mode;
-
-  ssize_t
-    count;
-
-  /*
-    Make each pixel the 'predominant color' of the specified neighborhood.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  mode=color;
-  max_count=p->nodes[mode].count;
-  count=0;
-  do
-  {
-    color=p->nodes[color].next[0];
-    if (p->nodes[color].count > max_count)
-      {
-        mode=color;
-        max_count=p->nodes[mode].count;
-      }
-    count+=p->nodes[color].count;
-  } while (count < (ssize_t) pixel_list->length);
-  *pixel=ScaleShortToQuantum((unsigned short) mode);
-}
-
-static inline void GetNonpeakPixelList(PixelList *pixel_list,Quantum *pixel)
-{
-  register SkipList
-    *p;
-
-  size_t
-    color,
-    next,
-    previous;
-
-  ssize_t
-    count;
-
-  /*
-    Finds the non peak value for each of the colors.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  next=p->nodes[color].next[0];
-  count=0;
-  do
-  {
-    previous=color;
-    color=next;
-    next=p->nodes[color].next[0];
-    count+=p->nodes[color].count;
-  } while (count <= (ssize_t) (pixel_list->length >> 1));
-  if ((previous == 65536UL) && (next != 65536UL))
-    color=next;
-  else
-    if ((previous != 65536UL) && (next == 65536UL))
-      color=previous;
-  *pixel=ScaleShortToQuantum((unsigned short) color);
-}
-
-static inline void GetStandardDeviationPixelList(PixelList *pixel_list,
-  Quantum *pixel)
-{
-  MagickRealType
-    sum,
-    sum_squared;
-
-  register SkipList
-    *p;
-
-  size_t
-    color;
-
-  ssize_t
-    count;
-
-  /*
-    Find the standard-deviation value for each of the color.
-  */
-  p=(&pixel_list->skip_list);
-  color=65536L;
-  count=0;
-  sum=0.0;
-  sum_squared=0.0;
-  do
-  {
-    register ssize_t
-      i;
-
-    color=p->nodes[color].next[0];
-    sum+=(MagickRealType) p->nodes[color].count*color;
-    for (i=0; i < (ssize_t) p->nodes[color].count; i++)
-      sum_squared+=((MagickRealType) color)*((MagickRealType) color);
-    count+=p->nodes[color].count;
-  } while (count < (ssize_t) pixel_list->length);
-  sum/=pixel_list->length;
-  sum_squared/=pixel_list->length;
-  *pixel=ScaleShortToQuantum((unsigned short) sqrt(sum_squared-(sum*sum)));
-}
-
-static inline void InsertPixelList(const Image *image,const Quantum pixel,
-  PixelList *pixel_list)
-{
-  size_t
-    signature;
-
-  unsigned short
-    index;
-
-  index=ScaleQuantumToShort(pixel);
-  signature=pixel_list->skip_list.nodes[index].signature;
-  if (signature == pixel_list->signature)
-    {
-      pixel_list->skip_list.nodes[index].count++;
-      return;
-    }
-  AddNodePixelList(pixel_list,index);
-}
-
-static inline MagickRealType MagickAbsoluteValue(const MagickRealType x)
-{
-  if (x < 0)
-    return(-x);
-  return(x);
-}
-
-static inline size_t MagickMax(const size_t x,const size_t y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static void ResetPixelList(PixelList *pixel_list)
-{
-  int
-    level;
-
-  register SkipNode
-    *root;
-
-  register SkipList
-    *p;
-
-  /*
-    Reset the skip-list.
-  */
-  p=(&pixel_list->skip_list);
-  root=p->nodes+65536UL;
-  p->level=0;
-  for (level=0; level < 9; level++)
-    root->next[level]=65536UL;
-  pixel_list->seed=pixel_list->signature++;
-}
-
-MagickExport Image *StatisticImage(const Image *image,const StatisticType type,
-  const size_t width,const size_t height,ExceptionInfo *exception)
-{
-#define StatisticImageTag  "Statistic/Image"
-
-  CacheView
-    *image_view,
-    *statistic_view;
-
-  Image
-    *statistic_image;
-
-  MagickBooleanType
-    status;
-
-  MagickOffsetType
-    progress;
-
-  PixelList
-    **restrict pixel_list;
-
-  ssize_t
-    center,
-    y;
-
-  /*
-    Initialize statistics image attributes.
-  */
-  assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
-  if (image->debug != MagickFalse)
-    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
-  statistic_image=CloneImage(image,image->columns,image->rows,MagickTrue,
-    exception);
-  if (statistic_image == (Image *) NULL)
-    return((Image *) NULL);
-  status=SetImageStorageClass(statistic_image,DirectClass,exception);
-  if (status == MagickFalse)
-    {
-      statistic_image=DestroyImage(statistic_image);
-      return((Image *) NULL);
-    }
-  pixel_list=AcquirePixelListThreadSet(MagickMax(width,1),MagickMax(height,1));
-  if (pixel_list == (PixelList **) NULL)
-    {
-      statistic_image=DestroyImage(statistic_image);
-      ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
-    }
-  /*
-    Make each pixel the min / max / median / mode / etc. of the neighborhood.
-  */
-  center=(ssize_t) GetPixelChannels(image)*(image->columns+MagickMax(width,1))*
-    (MagickMax(height,1)/2L)+GetPixelChannels(image)*(MagickMax(width,1)/2L);
-  status=MagickTrue;
-  progress=0;
-  image_view=AcquireCacheView(image);
-  statistic_view=AcquireCacheView(statistic_image);
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
-#endif
-  for (y=0; y < (ssize_t) statistic_image->rows; y++)
-  {
-    const int
-      id = GetOpenMPThreadId();
-
-    register const Quantum
-      *restrict p;
-
-    register Quantum
-      *restrict q;
-
-    register ssize_t
-      x;
-
-    if (status == MagickFalse)
-      continue;
-    p=GetCacheViewVirtualPixels(image_view,-((ssize_t) MagickMax(width,1)/2L),y-
-      (ssize_t) (MagickMax(height,1)/2L),image->columns+MagickMax(width,1),
-      MagickMax(height,1),exception);
-    q=QueueCacheViewAuthenticPixels(statistic_view,0,y,statistic_image->columns,      1,exception);
-    if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
-      {
-        status=MagickFalse;
-        continue;
-      }
-    for (x=0; x < (ssize_t) statistic_image->columns; x++)
-    {
-      register ssize_t
-        i;
-
-      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-      {
-        PixelChannel
-          channel;
-
-        PixelTrait
-          statistic_traits,
-          traits;
-
-        Quantum
-          pixel;
-
-        register const Quantum
-          *restrict pixels;
-
-        register ssize_t
-          u;
-
-        ssize_t
-          v;
-
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
-        statistic_traits=GetPixelChannelMapTraits(statistic_image,channel);
-        if ((traits == UndefinedPixelTrait) ||
-            (statistic_traits == UndefinedPixelTrait))
-          continue;
-        if ((statistic_traits & CopyPixelTrait) != 0)
-          {
-            SetPixelChannel(statistic_image,channel,p[center+i],q);
-            continue;
-          }
-        pixels=p;
-        ResetPixelList(pixel_list[id]);
-        for (v=0; v < (ssize_t) MagickMax(height,1); v++)
-        {
-          for (u=0; u < (ssize_t) MagickMax(width,1); u++)
-          {
-            InsertPixelList(image,pixels[i],pixel_list[id]);
-            pixels+=GetPixelChannels(image);
-          }
-          pixels+=image->columns*GetPixelChannels(image);
-        }
-        switch (type)
-        {
-          case GradientStatistic:
-          {
-            MagickRealType
-              maximum,
-              minimum;
-
-            GetMinimumPixelList(pixel_list[id],&pixel);
-            minimum=(MagickRealType) pixel;
-            GetMaximumPixelList(pixel_list[id],&pixel);
-            maximum=(MagickRealType) pixel;
-            pixel=ClampToQuantum(MagickAbsoluteValue(maximum-minimum));
-            break;
-          }
-          case MaximumStatistic:
-          {
-            GetMaximumPixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case MeanStatistic:
-          {
-            GetMeanPixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case MedianStatistic:
-          default:
-          {
-            GetMedianPixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case MinimumStatistic:
-          {
-            GetMinimumPixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case ModeStatistic:
-          {
-            GetModePixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case NonpeakStatistic:
-          {
-            GetNonpeakPixelList(pixel_list[id],&pixel);
-            break;
-          }
-          case StandardDeviationStatistic:
-          {
-            GetStandardDeviationPixelList(pixel_list[id],&pixel);
-            break;
-          }
-        }
-        SetPixelChannel(statistic_image,channel,pixel,q);
-      }
-      p+=GetPixelChannels(image);
-      q+=GetPixelChannels(statistic_image);
-    }
-    if (SyncCacheViewAuthenticPixels(statistic_view,exception) == MagickFalse)
-      status=MagickFalse;
-    if (image->progress_monitor != (MagickProgressMonitor) NULL)
-      {
-        MagickBooleanType
-          proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_StatisticImage)
-#endif
-        proceed=SetImageProgress(image,StatisticImageTag,progress++,
-          image->rows);
-        if (proceed == MagickFalse)
-          status=MagickFalse;
-      }
-  }
-  statistic_view=DestroyCacheView(statistic_view);
-  image_view=DestroyCacheView(image_view);
-  pixel_list=DestroyPixelListThreadSet(pixel_list);
-  return(statistic_image);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%                                                                             %
-%                                                                             %
-%                                                                             %
-%     U n s h a r p M a s k I m a g e                                         %
+%     U n s h a r p M a s k I m a g e                                         %
 %                                                                             %
 %                                                                             %
 %                                                                             %
@@ -4605,11 +3726,7 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(exception != (ExceptionInfo *) NULL);
-
-
-  /* FUTURE:  use of bias on sharpen is non-sensical */
-  unsharp_image=BlurImage(image,radius,sigma,image->bias,exception);
-
+  unsharp_image=BlurImage(image,radius,sigma,exception);
   if (unsharp_image == (Image *) NULL)
     return((Image *) NULL);
   quantum_threshold=(MagickRealType) QuantumRange*threshold;
@@ -4618,10 +3735,10 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
   */
   status=MagickTrue;
   progress=0;
-  image_view=AcquireCacheView(image);
-  unsharp_view=AcquireCacheView(unsharp_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  unsharp_view=AcquireAuthenticCacheView(unsharp_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)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -4637,7 +3754,7 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
     if (status == MagickFalse)
       continue;
     p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
-    q=GetCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
+    q=QueueCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
       exception);
     if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
       {
@@ -4649,6 +3766,12 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
       register ssize_t
         i;
 
+      if (GetPixelMask(image,p) != 0)
+        {
+          p+=GetPixelChannels(image);
+          q+=GetPixelChannels(unsharp_image);
+          continue;
+        }
       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
       {
         MagickRealType
@@ -4661,8 +3784,8 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
           traits,
           unsharp_traits;
 
-        traits=GetPixelChannelMapTraits(image,(PixelChannel) i);
-        channel=GetPixelChannelMapChannel(image,(PixelChannel) i);
+        channel=GetPixelChannelMapChannel(image,i);
+        traits=GetPixelChannelMapTraits(image,channel);
         unsharp_traits=GetPixelChannelMapTraits(unsharp_image,channel);
         if ((traits == UndefinedPixelTrait) ||
             (unsharp_traits == UndefinedPixelTrait))
@@ -4690,7 +3813,7 @@ MagickExport Image *UnsharpMaskImage(const Image *image,const double radius,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_UnsharpMaskImage)
+        #pragma omp critical (MagickCore_UnsharpMaskImage)
 #endif
         proceed=SetImageProgress(image,SharpenImageTag,progress++,image->rows);
         if (proceed == MagickFalse)