]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/morphology.c
(no commit message)
[imagemagick] / MagickCore / morphology.c
index 462b1f335194a638e8d0088df68df4a8225b62b3..7fa89f0e8af9be4b1d28e5f2558e730510725e72 100644 (file)
@@ -17,7 +17,7 @@
 %                               January 2010                                  %
 %                                                                             %
 %                                                                             %
-%  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  %
@@ -64,6 +64,7 @@
 #include "MagickCore/list.h"
 #include "MagickCore/magick.h"
 #include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/morphology.h"
 #include "MagickCore/morphology-private.h"
 #include "MagickCore/pixel-accessor.h"
 #include "MagickCore/prepress.h"
 #include "MagickCore/quantize.h"
+#include "MagickCore/resource_.h"
 #include "MagickCore/registry.h"
 #include "MagickCore/semaphore.h"
 #include "MagickCore/splay-tree.h"
 #include "MagickCore/statistic.h"
 #include "MagickCore/string_.h"
 #include "MagickCore/string-private.h"
+#include "MagickCore/thread-private.h"
 #include "MagickCore/token.h"
 #include "MagickCore/utility.h"
 #include "MagickCore/utility-private.h"
@@ -91,7 +94,7 @@
 ** part of the kernel neighbourhood for convolution or morphology processing,
 ** and thus should be ignored.  This allows the use of 'shaped' kernels.
 **
-** The special properity that two NaN's are never equal, even if they are from
+** The special property that two NaN's are never equal, even if they are from
 ** the same variable allow you to test if a value is special NaN value.
 **
 ** This macro  IsNaN() is thus is only true if the value given is NaN.
@@ -112,6 +115,21 @@ static inline double MagickMax(const double x,const double y)
 #define Minimize(assign,value) assign=MagickMin(assign,value)
 #define Maximize(assign,value) assign=MagickMax(assign,value)
 
+/* Integer Factorial Function - for a Binomial kernel */
+#if 1
+static inline size_t fact(size_t n)
+{
+  size_t f,l;
+  for(f=1, l=2; l <= n; f=f*l, l++);
+  return(f);
+}
+#elif 1 /* glibc floating point alternatives */
+#define fact(n) ((size_t)tgamma((double)n+1))
+#else
+#define fact(n) ((size_t)lgamma((double)n+1))
+#endif
+
+
 /* Currently these are only internal to this module */
 static void
   CalcKernelMetaData(KernelInfo *),
@@ -260,7 +278,9 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
   /* clear flags - for Expanding kernel lists thorugh rotations */
    flags = NoValue;
 
-  /* Has a ':' in argument - New user kernel specification */
+  /* Has a ':' in argument - New user kernel specification
+     FUTURE: this split on ':' could be done by StringToken()
+   */
   p = strchr(kernel_string, ':');
   if ( p != (char *) NULL && p < end)
     {
@@ -284,9 +304,9 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
       if ( args.xi  < 0.0 || args.psi < 0.0 )
         return(DestroyKernelInfo(kernel));
       kernel->x = ((flags & XValue)!=0) ? (ssize_t)args.xi
-                                               : (ssize_t) (kernel->width-1)/2;
+                                        : (ssize_t) (kernel->width-1)/2;
       kernel->y = ((flags & YValue)!=0) ? (ssize_t)args.psi
-                                               : (ssize_t) (kernel->height-1)/2;
+                                        : (ssize_t) (kernel->height-1)/2;
       if ( kernel->x >= (ssize_t) kernel->width ||
            kernel->y >= (ssize_t) kernel->height )
         return(DestroyKernelInfo(kernel));
@@ -314,9 +334,9 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
     }
 
   /* Read in the kernel values from rest of input string argument */
-  kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-    kernel->height*sizeof(*kernel->values));
-  if (kernel->values == (double *) NULL)
+  kernel->values=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
+    kernel->width,kernel->height*sizeof(*kernel->values)));
+  if (kernel->values == (MagickRealType *) NULL)
     return(DestroyKernelInfo(kernel));
   kernel->minimum = +MagickHuge;
   kernel->maximum = -MagickHuge;
@@ -328,10 +348,10 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
       GetMagickToken(p,&p,token);
     if (    LocaleCompare("nan",token) == 0
         || LocaleCompare("-",token) == 0 ) {
-      kernel->values[i] = nan; /* do not include this value in kernel */
+      kernel->values[i] = nan; /* this value is not part of neighbourhood */
     }
     else {
-      kernel->values[i]=StringToDouble(token,(char **) NULL);
+      kernel->values[i] = StringToDouble(token,(char **) NULL);
       ( kernel->values[i] < 0)
           ?  ( kernel->negative_range += kernel->values[i] )
           :  ( kernel->positive_range += kernel->values[i] );
@@ -629,6 +649,10 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
 %       Note that the first argument is the width of the kernel and not the
 %       radius of the kernel.
 %
+%    Binomial:[{radius}]
+%       Generate a discrete kernel using a 2 dimentional Pascel's Triangle
+%       of values. Used for special forma of image filters.
+%
 %    # Still to be implemented...
 %    #
 %    # Filter2D
@@ -991,6 +1015,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
     case LoGKernel:
     case BlurKernel:
     case CometKernel:
+    case BinomialKernel:
     case DiamondKernel:
     case SquareKernel:
     case RectangleKernel:
@@ -1028,9 +1053,9 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
       {
         kernel->height = kernel->width = (size_t) 1;
         kernel->x = kernel->y = (ssize_t) 0;
-        kernel->values=(double *) AcquireAlignedMemory(1,
-          sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(1,sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
         kernel->maximum = kernel->values[0] = args->rho;
         break;
@@ -1052,9 +1077,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
           kernel->width = GetOptimalKernelWidth2D(args->rho,sigma2);
         kernel->height = kernel->width;
         kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         /* WARNING: The following generates a 'sampled gaussian' kernel.
@@ -1143,9 +1169,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         kernel->x = (ssize_t) (kernel->width-1)/2;
         kernel->y = 0;
         kernel->negative_range = kernel->positive_range = 0.0;
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
 #if 1
@@ -1180,7 +1207,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         else /* special case - generate a unity kernel */
           kernel->values[kernel->x+kernel->y*kernel->width] = 1.0;
 #else
-        /* Direct calculation without curve averaging */
+        /* Direct calculation without curve averaging
+           This is equivelent to a KernelRank of 1 */
 
         /* Calculate a Positive Gaussian */
         if ( sigma > MagickEpsilon )
@@ -1197,10 +1225,11 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
 #endif
         /* Note the above kernel may have been 'clipped' by a user defined
         ** radius, producing a smaller (darker) kernel.  Also for very small
-        ** sigma's (> 0.1) the central value becomes larger than one, and thus
-        ** producing a very bright kernel.
+        ** sigma's (> 0.1) the central value becomes larger than one, as a
+        ** result of not generating a actual 'discrete' kernel, and thus
+        ** producing a very bright 'impulse'.
         **
-        ** Normalization will still be needed.
+        ** Becuase of these two factors Normalization is required!
         */
 
         /* Normalize the 1D Gaussian Kernel
@@ -1227,9 +1256,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         kernel->x = kernel->y = 0;
         kernel->height = 1;
         kernel->negative_range = kernel->positive_range = 0.0;
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         /* A comet blur is half a 1D gaussian curve, so that the object is
@@ -1264,8 +1294,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             /* B = 1.0/(MagickSQ2PI*sigma); */
             for ( i=0; i < (ssize_t) kernel->width; i++)
               kernel->positive_range +=
-                kernel->values[i] =
-                  exp(-((double)(i*i))*A);
+                kernel->values[i] = exp(-((double)(i*i))*A);
                 /* exp(-((double)(i*i))/2.0*sigma*sigma)/(MagickSQ2PI*sigma); */
 #endif
           }
@@ -1284,6 +1313,38 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         RotateKernelInfo(kernel, args->xi); /* Rotate by angle */
         break;
       }
+    case BinomialKernel:
+      {
+        size_t
+          order_f;
+
+        if (args->rho < 1.0)
+          kernel->width = kernel->height = 3;  /* default radius = 1 */
+        else
+          kernel->width = kernel->height = ((size_t)args->rho)*2+1;
+        kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
+
+        order_f = fact(kernel->width-1);
+
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
+          return(DestroyKernelInfo(kernel));
+
+        /* set all kernel values within diamond area to scale given */
+        for ( i=0, v=0; v < (ssize_t)kernel->height; v++)
+          { size_t
+              alpha = order_f / ( fact((size_t) v) * fact(kernel->height-v-1) );
+            for ( u=0; u < (ssize_t)kernel->width; u++, i++)
+              kernel->positive_range += kernel->values[i] = (double)
+                (alpha * order_f / ( fact((size_t) u) * fact(kernel->height-u-1) ));
+          }
+        kernel->minimum = 1.0;
+        kernel->maximum = kernel->values[kernel->x+kernel->y*kernel->width];
+        kernel->negative_range = 0.0;
+        break;
+      }
 
     /*
       Convolution Kernels - Well Known Named Constant Kernels
@@ -1382,8 +1443,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[3] = +MagickSQ2;
-            kernel->values[5] = -MagickSQ2;
+            kernel->values[3] = +(MagickRealType) MagickSQ2;
+            kernel->values[5] = -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);     /* recalculate meta-data */
             break;
           case 2:
@@ -1391,8 +1452,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[1] = kernel->values[3] = +MagickSQ2;
-            kernel->values[5] = kernel->values[7] = -MagickSQ2;
+            kernel->values[1] = kernel->values[3]= +(MagickRealType) MagickSQ2;
+            kernel->values[5] = kernel->values[7]= -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);     /* recalculate meta-data */
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1407,8 +1468,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[3] = +MagickSQ2;
-            kernel->values[5] = -MagickSQ2;
+            kernel->values[3] = +(MagickRealType) MagickSQ2;
+            kernel->values[5] = -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);     /* recalculate meta-data */
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1417,8 +1478,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[1] = +MagickSQ2;
-            kernel->values[7] = +MagickSQ2;
+            kernel->values[1] = +(double) MagickSQ2;
+            kernel->values[7] = +(double) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1427,8 +1488,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[0] = +MagickSQ2;
-            kernel->values[8] = -MagickSQ2;
+            kernel->values[0] = +(MagickRealType) MagickSQ2;
+            kernel->values[8] = -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1437,8 +1498,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[2] = -MagickSQ2;
-            kernel->values[6] = +MagickSQ2;
+            kernel->values[2] = -(MagickRealType) MagickSQ2;
+            kernel->values[6] = +(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1478,7 +1539,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             ScaleKernelInfo(kernel, 1.0/3.0, NoValue);
             break;
         }
-        if ( fabs(args->sigma) > MagickEpsilon )
+        if ( fabs(args->sigma) >= MagickEpsilon )
           /* Rotate by correctly supplied 'angle' */
           RotateKernelInfo(kernel, args->sigma);
         else if ( args->rho > 30.0 || args->rho < -30.0 )
@@ -1498,9 +1559,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
           kernel->width = kernel->height = ((size_t)args->rho)*2+1;
         kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         /* set all kernel values within diamond area to scale given */
@@ -1539,9 +1601,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->y = (ssize_t) args->psi;
             scale = 1.0;
           }
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         /* set all kernel values to scale given */
@@ -1560,9 +1623,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = ((size_t)args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
@@ -1586,9 +1650,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = (size_t)fabs(args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
@@ -1608,9 +1673,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = ((size_t)args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           /* set all kernel values along axises to given scale */
@@ -1629,9 +1695,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = ((size_t)args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           /* set all kernel values along axises to given scale */
@@ -1670,9 +1737,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
 
           kernel->height = kernel->width;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           /* set a ring of points of 'scale' ( 0.0 for PeaksKernel ) */
@@ -2040,9 +2108,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = ((size_t)args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
@@ -2060,9 +2129,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->width = kernel->height = ((size_t)args->rho)*2+1;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-          kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
-          if (kernel->values == (double *) NULL)
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
+          if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
           for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
@@ -2080,9 +2150,10 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
           kernel->width = kernel->height = ((size_t)args->rho)*2+1;
         kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
@@ -2105,15 +2176,16 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
           kernel->width = kernel->height = ((size_t)args->rho)*2+1;
         kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
 
-        kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
-        if (kernel->values == (double *) NULL)
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
+        if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
         for ( i=0, v=-kernel->y; v <= (ssize_t)kernel->y; v++)
           for ( u=-kernel->x; u <= (ssize_t)kernel->x; u++, i++)
             kernel->positive_range += ( kernel->values[i] =
-                 args->sigma*sqrt((double)(u*u+v*v)) );
+              args->sigma*sqrt((double)(u*u+v*v)) );
         kernel->maximum = kernel->values[0];
         break;
       }
@@ -2144,7 +2216,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
 %
 %  CloneKernelInfo() creates a new clone of the given Kernel List so that its
 %  can be modified without effecting the original.  The cloned kernel should
-%  be destroyed using DestroyKernelInfo() when no longer needed.
+%  be destroyed using DestoryKernelInfo() when no longer needed.
 %
 %  The format of the CloneKernelInfo method is:
 %
@@ -2170,9 +2242,9 @@ MagickExport KernelInfo *CloneKernelInfo(const KernelInfo *kernel)
   *new_kernel=(*kernel); /* copy values in structure */
 
   /* replace the values with a copy of the values */
-  new_kernel->values=(double *) AcquireAlignedMemory(kernel->width,
-    kernel->height*sizeof(*kernel->values));
-  if (new_kernel->values == (double *) NULL)
+  new_kernel->values=(MagickRealType *) MagickAssumeAligned(
+    AcquireAlignedMemory(kernel->width,kernel->height*sizeof(*kernel->values)));
+  if (new_kernel->values == (MagickRealType *) NULL)
     return(DestroyKernelInfo(new_kernel));
   for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
     new_kernel->values[i]=kernel->values[i];
@@ -2215,7 +2287,7 @@ MagickExport KernelInfo *DestroyKernelInfo(KernelInfo *kernel)
   assert(kernel != (KernelInfo *) NULL);
   if ( kernel->next != (KernelInfo *) NULL )
     kernel->next=DestroyKernelInfo(kernel->next);
-  kernel->values=(double *) RelinquishAlignedMemory(kernel->values);
+  kernel->values=(MagickRealType *) RelinquishAlignedMemory(kernel->values);
   kernel=(KernelInfo *) RelinquishMagickMemory(kernel);
   return(kernel);
 }
@@ -2349,7 +2421,7 @@ static MagickBooleanType SameKernelInfo(const KernelInfo *kernel1,
     if ( IsNan(kernel2->values[i]) && !IsNan(kernel1->values[i]) )
       return MagickFalse;
     /* Test actual values are equivalent */
-    if ( fabs(kernel1->values[i] - kernel2->values[i]) > MagickEpsilon )
+    if ( fabs(kernel1->values[i] - kernel2->values[i]) >= MagickEpsilon )
       return MagickFalse;
   }
 
@@ -2444,7 +2516,9 @@ static void CalcKernelMetaData(KernelInfo *kernel)
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  MorphologyApply() applies a morphological method, multiple times using
-%  a list of multiple kernels.
+%  a list of multiple kernels.  This is the method that should be called by
+%  other 'operators' that internally use morphology operations as part of
+%  their processing.
 %
 %  It is basically equivalent to as MorphologyImage() (see below) but
 %  without any user controls.  This allows internel programs to use this
@@ -2454,10 +2528,9 @@ static void CalcKernelMetaData(KernelInfo *kernel)
 %  It is MorphologyImage() task to extract any such user controls, and
 %  pass them to this function for processing.
 %
-%  More specifically kernels are not normalized/scaled/blended by the
-%  'convolve:scale' Image Artifact (setting), nor is the convolve bias
-%  (-bias setting or image->bias) loooked at, but must be supplied from the
-%  function arguments.
+%  More specifically all given kernels should already be scaled, normalised,
+%  and blended appropriatally before being parred to this routine. The
+%  appropriate bias, and compose (typically 'UndefinedComposeOp') given.
 %
 %  The format of the MorphologyApply method is:
 %
@@ -2533,8 +2606,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
   changed=0;
   progress=0;
 
-  image_view=AcquireCacheView(image);
-  morphology_view=AcquireCacheView(morphology_image);
+  image_view=AcquireVirtualCacheView(image,exception);
+  morphology_view=AcquireAuthenticCacheView(morphology_image,exception);
   virt_width=image->columns+kernel->width-1;
 
   /* Some methods (including convolve) needs use a reflected kernel.
@@ -2546,7 +2619,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     case ConvolveMorphology:
     case DilateMorphology:
     case DilateIntensityMorphology:
-    /*case DistanceMorphology:*/
+    case IterativeDistanceMorphology:
       /* kernel needs to used with reflection about origin */
       offx = (ssize_t) kernel->width-offx-1;
       offy = (ssize_t) kernel->height-offy-1;
@@ -2583,7 +2656,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
       x;
 
 #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) \
+      dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
     for (x=0; x < (ssize_t) image->columns; x++)
     {
@@ -2618,15 +2692,15 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         PixelInfo
           result;
 
-        register ssize_t
-          v;
-
-        register const double
+        register const MagickRealType
           *restrict k;
 
         register const Quantum
           *restrict k_pixels;
 
+        register ssize_t
+          v;
+
         /* Copy input image to the output image for unused channels
         * This removes need for 'cloning' a new image every iteration
         */
@@ -2641,11 +2715,11 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             GetPixelChannels(image)),q);
 
         /* Set the bias of the weighted average output */
-        result.red     =
-        result.green   =
-        result.blue    =
+        result.red   =
+        result.green =
+        result.blue  =
         result.alpha =
-        result.black   = bias;
+        result.black = bias;
 
 
         /* Weighted Average of pixels using reflected kernel
@@ -2656,9 +2730,10 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         */
         k = &kernel->values[ kernel->height-1 ];
         k_pixels = p;
-        if ( (image->channel_mask != DefaultChannels) || (image->matte == MagickFalse) )
+        if ( (image->channel_mask != DefaultChannels) ||
+             (image->alpha_trait != BlendPixelTrait) )
           { /* No 'Sync' involved.
-            ** Convolution is simple greyscale channel operation
+            ** Convolution is just a simple greyscale channel operation
             */
             for (v=0; v < (ssize_t) kernel->height; v++) {
               if ( IsNan(*k) ) continue;
@@ -2681,7 +2756,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 (image->colorspace == CMYKColorspace))
               SetPixelBlack(morphology_image,ClampToQuantum(result.black),q);
             if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                (image->matte == MagickTrue))
+                (image->alpha_trait == BlendPixelTrait))
               SetPixelAlpha(morphology_image,ClampToQuantum(result.alpha),q);
           }
         else
@@ -2689,37 +2764,37 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             ** Weight the color channels with Alpha Channel so that
             ** transparent pixels are not part of the results.
             */
-            MagickRealType
-              alpha,  /* alpha weighting of colors : kernel*alpha  */
-              gamma;  /* divisor, sum of color weighting values */
+            double
+              alpha,  /* alpha weighting for colors : alpha  */
+              gamma;  /* divisor, sum of color alpha weighting */
+            size_t
+              count;  /* alpha valus collected, number kernel values */
 
+            count=0;
             gamma=0.0;
             for (v=0; v < (ssize_t) kernel->height; v++) {
               if ( IsNan(*k) ) continue;
-              alpha=(*k)*(QuantumScale*GetPixelAlpha(image,k_pixels));
-              gamma += alpha;
+              alpha=QuantumScale*GetPixelAlpha(image,k_pixels);
+              gamma += alpha; /* normalize alpha weights only */
+              count++;        /* number of alpha values collected */
+              alpha*=(*k);    /* include kernel weighting now */
               result.red     += alpha*GetPixelRed(image,k_pixels);
               result.green   += alpha*GetPixelGreen(image,k_pixels);
               result.blue    += alpha*GetPixelBlue(image,k_pixels);
               if (image->colorspace == CMYKColorspace)
                 result.black += alpha*GetPixelBlack(image,k_pixels);
-              result.alpha += (*k)*GetPixelAlpha(image,k_pixels);
+              result.alpha   += (*k)*GetPixelAlpha(image,k_pixels);
               k--;
               k_pixels+=GetPixelChannels(image);
             }
             /* Sync'ed channels, all channels are modified */
-            gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
-            SetPixelRed(morphology_image,
-              ClampToQuantum(gamma*result.red),q);
-            SetPixelGreen(morphology_image,
-              ClampToQuantum(gamma*result.green),q);
-            SetPixelBlue(morphology_image,
-              ClampToQuantum(gamma*result.blue),q);
+            gamma=(double)count/(fabs((double) gamma) < MagickEpsilon ? MagickEpsilon : gamma);
+            SetPixelRed(morphology_image,ClampToQuantum(gamma*result.red),q);
+            SetPixelGreen(morphology_image,ClampToQuantum(gamma*result.green),q);
+            SetPixelBlue(morphology_image,ClampToQuantum(gamma*result.blue),q);
             if (image->colorspace == CMYKColorspace)
-              SetPixelBlack(morphology_image,
-                ClampToQuantum(gamma*result.black),q);
-            SetPixelAlpha(morphology_image,
-              ClampToQuantum(result.alpha),q);
+              SetPixelBlack(morphology_image,ClampToQuantum(gamma*result.black),q);
+            SetPixelAlpha(morphology_image,ClampToQuantum(result.alpha),q);
           }
 
         /* Count up changed pixels */
@@ -2741,7 +2816,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_MorphologyImage)
+          #pragma omp critical (MagickCore_MorphologyImage)
 #endif
           proceed=SetImageProgress(image,MorphologyTag,progress++,image->rows);
           if (proceed == MagickFalse)
@@ -2758,7 +2833,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
   ** Normal handling of horizontal or rectangular kernels (row by row)
   */
 #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) \
+    dynamic_number_threads(image,image->columns,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -2790,22 +2866,22 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
 
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-       ssize_t
-        v;
-
-      register ssize_t
-        u;
+      PixelInfo
+        result,
+        min,
+        max;
 
-      register const double
+      register const MagickRealType
         *restrict k;
 
       register const Quantum
         *restrict k_pixels;
 
-      PixelInfo
-        result,
-        min,
-        max;
+      register ssize_t
+        u;
+
+      ssize_t
+        v;
 
       /* Copy input image to the output image for unused channels
        * This removes need for 'cloning' a new image every iteration
@@ -2825,20 +2901,20 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
       min.green   =
       min.blue    =
       min.alpha =
-      min.black   = (MagickRealType) QuantumRange;
+      min.black   = (double) QuantumRange;
       max.red     =
       max.green   =
       max.blue    =
       max.alpha =
-      max.black   = (MagickRealType) 0;
+      max.black   = (double) 0;
       /* default result is the original pixel value */
-      result.red     = (MagickRealType) GetPixelRed(image,p+r*GetPixelChannels(image));
-      result.green   = (MagickRealType) GetPixelGreen(image,p+r*GetPixelChannels(image));
-      result.blue    = (MagickRealType) GetPixelBlue(image,p+r*GetPixelChannels(image));
+      result.red     = (double) GetPixelRed(image,p+r*GetPixelChannels(image));
+      result.green   = (double) GetPixelGreen(image,p+r*GetPixelChannels(image));
+      result.blue    = (double) GetPixelBlue(image,p+r*GetPixelChannels(image));
       result.black   = 0.0;
       if (image->colorspace == CMYKColorspace)
-        result.black = (MagickRealType) GetPixelBlack(image,p+r*GetPixelChannels(image));
-      result.alpha=(MagickRealType) GetPixelAlpha(image,p+r*GetPixelChannels(image));
+        result.black = (double) GetPixelBlack(image,p+r*GetPixelChannels(image));
+      result.alpha=(double) GetPixelAlpha(image,p+r*GetPixelChannels(image));
 
       switch (method) {
         case ConvolveMorphology:
@@ -2881,7 +2957,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             k = &kernel->values[ kernel->width*kernel->height-1 ];
             k_pixels = p;
             if ( (image->channel_mask != DefaultChannels) ||
-                 (image->matte == MagickFalse) )
+                 (image->alpha_trait != BlendPixelTrait) )
               { /* No 'Sync' involved.
                 ** Convolution is simple greyscale channel operation
                 */
@@ -2916,7 +2992,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   SetPixelBlack(morphology_image,ClampToQuantum(result.black),
                     q);
                 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-                    (image->matte == MagickTrue))
+                    (image->alpha_trait == BlendPixelTrait))
                   SetPixelAlpha(morphology_image,ClampToQuantum(result.alpha),
                     q);
               }
@@ -2925,17 +3001,22 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 ** Weight the color channels with Alpha Channel so that
                 ** transparent pixels are not part of the results.
                 */
-                MagickRealType
-                  alpha,  /* alpha weighting of colors : kernel*alpha  */
-                  gamma;  /* divisor, sum of color weighting values */
+                double
+                  alpha,  /* alpha weighting for colors : alpha  */
+                  gamma;  /* divisor, sum of color alpha weighting */
+                size_t
+                  count;  /* alpha valus collected, number kernel values */
 
+                count=0;
                 gamma=0.0;
                 for (v=0; v < (ssize_t) kernel->height; v++) {
                   for (u=0; u < (ssize_t) kernel->width; u++, k--) {
                     if ( IsNan(*k) ) continue;
-                    alpha=(*k)*(QuantumScale*GetPixelAlpha(image,k_pixels+u*
-                      GetPixelChannels(image)));
-                    gamma += alpha;
+                    alpha=QuantumScale*GetPixelAlpha(image,
+                                k_pixels+u*GetPixelChannels(image));
+                    gamma += alpha;    /* normalize alpha weights only */
+                    count++;           /* number of alpha values collected */
+                    alpha=alpha*(*k);  /* include kernel weighting now */
                     result.red     += alpha*
                       GetPixelRed(image,k_pixels+u*GetPixelChannels(image));
                     result.green   += alpha*
@@ -2943,15 +3024,15 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                     result.blue    += alpha*
                       GetPixelBlue(image,k_pixels+u*GetPixelChannels(image));
                     if (image->colorspace == CMYKColorspace)
-                      result.black+=alpha*
+                      result.black += alpha*
                         GetPixelBlack(image,k_pixels+u*GetPixelChannels(image));
-                    result.alpha += (*k)*
+                    result.alpha   += (*k)*
                       GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image));
                   }
                   k_pixels += virt_width*GetPixelChannels(image);
                 }
                 /* Sync'ed channels, all channels are modified */
-                gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
+                gamma=(double)count/(fabs((double) gamma) < MagickEpsilon ? MagickEpsilon : gamma);
                 SetPixelRed(morphology_image,
                   ClampToQuantum(gamma*result.red),q);
                 SetPixelGreen(morphology_image,
@@ -2981,15 +3062,15 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 if ( IsNan(*k) || (*k) < 0.5 ) continue;
                 Minimize(min.red,     (double)
                   GetPixelRed(image,k_pixels+u*GetPixelChannels(image)));
-                Minimize(min.green,   (double) 
+                Minimize(min.green,   (double)
                   GetPixelGreen(image,k_pixels+u*GetPixelChannels(image)));
                 Minimize(min.blue,    (double)
                   GetPixelBlue(image,k_pixels+u*GetPixelChannels(image)));
+                Minimize(min.alpha,   (double)
+                  GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                 if (image->colorspace == CMYKColorspace)
-                  Minimize(min.black,(double)
+                  Minimize(min.black,  (double)
                     GetPixelBlack(image,k_pixels+u*GetPixelChannels(image)));
-                Minimize(min.alpha,(double)
-                  GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
               }
               k_pixels += virt_width*GetPixelChannels(image);
             }
@@ -3014,15 +3095,15 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 if ( IsNan(*k) || (*k) < 0.5 ) continue;
                 Maximize(max.red,     (double)
                   GetPixelRed(image,k_pixels+u*GetPixelChannels(image)));
-                Maximize(max.green,   (double) 
+                Maximize(max.green,   (double)
                   GetPixelGreen(image,k_pixels+u*GetPixelChannels(image)));
-                Maximize(max.blue,    (double) 
+                Maximize(max.blue,    (double)
                   GetPixelBlue(image,k_pixels+u*GetPixelChannels(image)));
+                Maximize(max.alpha,   (double)
+                  GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                 if (image->colorspace == CMYKColorspace)
                   Maximize(max.black,   (double)
                     GetPixelBlack(image,k_pixels+u*GetPixelChannels(image)));
-                Maximize(max.alpha,(double) 
-                  GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
               }
               k_pixels += virt_width*GetPixelChannels(image);
             }
@@ -3055,11 +3136,11 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                     GetPixelGreen(image,k_pixels+u*GetPixelChannels(image)));
                   Minimize(min.blue,    (double)
                     GetPixelBlue(image,k_pixels+u*GetPixelChannels(image)));
+                  Minimize(min.alpha,(double)
+                    GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                   if ( image->colorspace == CMYKColorspace)
                     Minimize(min.black,(double)
                       GetPixelBlack(image,k_pixels+u*GetPixelChannels(image)));
-                  Minimize(min.alpha,(double)
-                    GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                 }
                 else if ( (*k) < 0.3 )
                 { /* maximum of background pixels */
@@ -3069,11 +3150,11 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                     GetPixelGreen(image,k_pixels+u*GetPixelChannels(image)));
                   Maximize(max.blue,    (double)
                     GetPixelBlue(image,k_pixels+u*GetPixelChannels(image)));
+                  Maximize(max.alpha,(double)
+                    GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                   if (image->colorspace == CMYKColorspace)
                     Maximize(max.black,   (double)
                       GetPixelBlack(image,k_pixels+u*GetPixelChannels(image)));
-                  Maximize(max.alpha,(double)
-                    GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                 }
               }
               k_pixels += virt_width*GetPixelChannels(image);
@@ -3153,43 +3234,52 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
               k_pixels += virt_width*GetPixelChannels(image);
             }
             break;
-#if 0
-  This code has been obsoleted by the MorphologyPrimitiveDirect() function.
-  However it is still (almost) correct coding for Grayscale Morphology.
-  That is...
-
-  GrayErode    is equivalent but with kernel values subtracted from pixels
-               without the kernel rotation
-  GreyDilate   is equivalent but using Maximum() instead of Minimum()
-               using kernel rotation
 
-  It has thus been preserved for future implementation of those methods.
-
-        case DistanceMorphology:
-            /* Add kernel Value and select the minimum value found.
-            ** The result is a iterative distance from edge of image shape.
+        case IterativeDistanceMorphology:
+            /* Work out an iterative distance from black edge of a white image
+            ** shape.  Essentually white values are decreased to the smallest
+            ** 'distance from edge' it can find.
+            **
+            ** It works by adding kernel values to the neighbourhood, and and
+            ** select the minimum value found. The kernel is rotated before
+            ** use, so kernel distances match resulting distances, when a user
+            ** provided asymmetric kernel is applied.
+            **
+            **
+            ** This code is almost identical to True GrayScale Morphology But
+            ** not quite.
             **
-            ** All Distance Kernels are symetrical, but that may not always
-            ** be the case. For example how about a distance from left edges?
-            ** To work correctly with asymetrical kernels the reflected kernel
-            ** needs to be applied.
+            ** GreyDilate  Kernel values added, maximum value found Kernel is
+            ** rotated before use.
+            **
+            ** GrayErode:  Kernel values subtracted and minimum value found No
+            ** kernel rotation used.
+            **
+            ** Note the the Iterative Distance method is essentially a
+            ** GrayErode, but with negative kernel values, and kernel
+            ** rotation applied.
             */
             k = &kernel->values[ kernel->width*kernel->height-1 ];
             k_pixels = p;
             for (v=0; v < (ssize_t) kernel->height; v++) {
               for (u=0; u < (ssize_t) kernel->width; u++, k--) {
                 if ( IsNan(*k) ) continue;
-                Minimize(result.red,     (*k)+k_pixels[u].red);
-                Minimize(result.green,   (*k)+k_pixels[u].green);
-                Minimize(result.blue,    (*k)+k_pixels[u].blue);
-                Minimize(result.alpha, (*k)+k_pixels[u].alpha);
+                Minimize(result.red,     (*k)+(double)
+                     GetPixelRed(image,k_pixels+u*GetPixelChannels(image)));
+                Minimize(result.green,   (*k)+(double)
+                     GetPixelGreen(image,k_pixels+u*GetPixelChannels(image)));
+                Minimize(result.blue,    (*k)+(double)
+                     GetPixelBlue(image,k_pixels+u*GetPixelChannels(image)));
+                Minimize(result.alpha,   (*k)+(double)
+                     GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)));
                 if ( image->colorspace == CMYKColorspace)
-                  Minimize(result.black,(*k)+GetPixelBlack(p_image,k_indexes+u));
+                  Maximize(result.black, (*k)+(double)
+                      GetPixelBlack(image,k_pixels+u*GetPixelChannels(image)));
               }
               k_pixels += virt_width*GetPixelChannels(image);
             }
             break;
-#endif
+
         case UndefinedMorphology:
         default:
             break; /* Do nothing */
@@ -3215,7 +3305,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
           result.green   -= min.green;
           result.blue    -= min.blue;
           result.black   -= min.black;
-          result.alpha -= min.alpha;
+          result.alpha   -= min.alpha;
           break;
         case ThickenMorphology:
           /* Add the pattern matchs to the original */
@@ -3223,7 +3313,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
           result.green   += min.green;
           result.blue    += min.blue;
           result.black   += min.black;
-          result.alpha += min.alpha;
+          result.alpha   += min.alpha;
           break;
         default:
           /* result directly calculated or assigned */
@@ -3247,7 +3337,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
               (image->colorspace == CMYKColorspace))
             SetPixelBlack(morphology_image,ClampToQuantum(result.black),q);
           if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
-              (image->matte == MagickTrue))
+              (image->alpha_trait == BlendPixelTrait))
             SetPixelAlpha(morphology_image,ClampToQuantum(result.alpha),q);
           break;
       }
@@ -3270,7 +3360,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
           proceed;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp critical (MagickCore_MorphologyImage)
+        #pragma omp critical (MagickCore_MorphologyImage)
 #endif
         proceed=SetImageProgress(image,MorphologyTag,progress++,image->rows);
         if (proceed == MagickFalse)
@@ -3283,13 +3373,15 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
 }
 
 /* This is almost identical to the MorphologyPrimative() function above,
-** but will apply the primitive directly to the image in two passes.
+** but will apply the primitive directly to the actual image using two
+** passes, once in each direction, with the results of the previous (and
+** current) row being re-used.
 **
 ** That is after each row is 'Sync'ed' into the image, the next row will
 ** make use of those values as part of the calculation of the next row.
 ** It then repeats, but going in the oppisite (bottom-up) direction.
 **
-** Because of this 'iterative' handling this function can not make use
+** Because of this 're-use of results' this function can not make use
 ** of multi-threaded, parellel processing.
 */
 static ssize_t MorphologyPrimitiveDirect(Image *image,
@@ -3348,8 +3440,8 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
 
   /* DO NOT THREAD THIS CODE! */
   /* two views into same image (virtual, and actual) */
-  virt_view=AcquireCacheView(image);
-  auth_view=AcquireCacheView(image);
+  virt_view=AcquireVirtualCacheView(image,exception);
+  auth_view=AcquireAuthenticCacheView(image,exception);
   virt_width=image->columns+kernel->width-1;
 
   for (y=0; y < (ssize_t) image->rows; y++)
@@ -3389,24 +3481,24 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
 
     for (x=0; x < (ssize_t) image->columns; x++)
     {
-      ssize_t
-        v;
-
-      register ssize_t
-        u;
+      PixelInfo
+        result;
 
-      register const double
+      register const MagickRealType
         *restrict k;
 
       register const Quantum
         *restrict k_pixels;
 
-      PixelInfo
-        result;
+      register ssize_t
+        u;
+
+      ssize_t
+        v;
 
       /* Starting Defaults */
       GetPixelInfo(image,&result);
-      SetPixelInfo(image,q,&result);
+      GetPixelInfoPixel(image,q,&result);
       if ( method != VoronoiMorphology )
         result.alpha = QuantumRange - result.alpha;
 
@@ -3452,10 +3544,12 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
               }
             break;
         case VoronoiMorphology:
-            /* Apply Distance to 'Matte' channel, coping the closest color.
+            /* Apply Distance to 'Matte' channel, while coping the color
+            ** values of the closest pixel.
             **
             ** This is experimental, and realy the 'alpha' component should
-            ** be completely separate 'masking' channel.
+            ** be completely separate 'masking' channel so that alpha can
+            ** also be used as part of the results.
             */
             k = &kernel->values[ kernel->width*kernel->height-1 ];
             k_pixels = p;
@@ -3464,7 +3558,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
                 if ( IsNan(*k) ) continue;
                 if( result.alpha > (*k)+GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)) )
                   {
-                    SetPixelInfo(image,k_pixels+u*GetPixelChannels(image),
+                    GetPixelInfoPixel(image,k_pixels+u*GetPixelChannels(image),
                       &result);
                     result.alpha += *k;
                   }
@@ -3479,7 +3573,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
                 if ( IsNan(*k) ) continue;
                 if( result.alpha > (*k)+GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)) )
                   {
-                    SetPixelInfo(image,k_pixels+u*GetPixelChannels(image),
+                    GetPixelInfoPixel(image,k_pixels+u*GetPixelChannels(image),
                       &result);
                     result.alpha += *k;
                   }
@@ -3492,7 +3586,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
       /* Assign the resulting pixel values - Clamping Result */
       switch ( method ) {
         case VoronoiMorphology:
-          SetPixelPixelInfo(image,&result,q);
+          SetPixelInfoPixel(image,&result,q);
           break;
         default:
           if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
@@ -3505,7 +3599,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
               (image->colorspace == CMYKColorspace))
             SetPixelBlack(image,ClampToQuantum(result.black),q);
           if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0 &&
-              (image->matte == MagickTrue))
+              (image->alpha_trait == BlendPixelTrait))
             SetPixelAlpha(image,ClampToQuantum(result.alpha),q);
           break;
       }
@@ -3573,24 +3667,24 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
 
     for (x=(ssize_t)image->columns-1; x >= 0; x--)
     {
-      ssize_t
-        v;
-
-      register ssize_t
-        u;
+      PixelInfo
+        result;
 
-      register const double
+      register const MagickRealType
         *restrict k;
 
       register const Quantum
         *restrict k_pixels;
 
-      PixelInfo
-        result;
+      register ssize_t
+        u;
+
+      ssize_t
+        v;
 
       /* Default - previously modified pixel */
       GetPixelInfo(image,&result);
-      SetPixelInfo(image,q,&result);
+      GetPixelInfoPixel(image,q,&result);
       if ( method != VoronoiMorphology )
         result.alpha = QuantumRange - result.alpha;
 
@@ -3648,7 +3742,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
                 if ( IsNan(*k) ) continue;
                 if( result.alpha > (*k)+GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)) )
                   {
-                    SetPixelInfo(image,k_pixels+u*GetPixelChannels(image),
+                    GetPixelInfoPixel(image,k_pixels+u*GetPixelChannels(image),
                       &result);
                     result.alpha += *k;
                   }
@@ -3663,7 +3757,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
                 if ( IsNan(*k) ) continue;
                 if( result.alpha > (*k)+GetPixelAlpha(image,k_pixels+u*GetPixelChannels(image)) )
                   {
-                    SetPixelInfo(image,k_pixels+u*GetPixelChannels(image),
+                    GetPixelInfoPixel(image,k_pixels+u*GetPixelChannels(image),
                       &result);
                     result.alpha += *k;
                   }
@@ -3676,7 +3770,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
       /* Assign the resulting pixel values - Clamping Result */
       switch ( method ) {
         case VoronoiMorphology:
-          SetPixelPixelInfo(image,&result,q);
+          SetPixelInfoPixel(image,&result,q);
           break;
         default:
           if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
@@ -3689,7 +3783,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
               (image->colorspace == CMYKColorspace))
             SetPixelBlack(image,ClampToQuantum(result.black),q);
           if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0 &&
-              (image->matte == MagickTrue))
+              (image->alpha_trait == BlendPixelTrait))
             SetPixelAlpha(image,ClampToQuantum(result.alpha),q);
           break;
       }
@@ -3719,12 +3813,12 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
   return(status ? (ssize_t) changed : -1);
 }
 
-/* Apply a Morphology by calling theabove low level primitive application
-** functions.  This function handles any iteration loops, composition or
-** re-iteration of results, and compound morphology methods that is based
-** on multiple low-level (staged) morphology methods.
+/* Apply a Morphology by calling one of the above low level primitive
+** application functions.  This function handles any iteration loops,
+** composition or re-iteration of results, and compound morphology methods
+** that is based on multiple low-level (staged) morphology methods.
 **
-** Basically this provides the complex grue between the requested morphology
+** Basically this provides the complex glue between the requested morphology
 ** method and raw low-level implementation (above).
 */
 MagickPrivate Image *MorphologyApply(const Image *image,
@@ -3790,7 +3884,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
   if ( iterations < 0 )  /* negative interations = infinite (well alomst) */
      kernel_limit = image->columns>image->rows ? image->columns : image->rows;
 
-  verbose = IsMagickTrue(GetImageArtifact(image,"verbose"));
+  verbose = IsStringTrue(GetImageArtifact(image,"verbose"));
 
   /* initialise for cleanup */
   curr_image = (Image *) image;
@@ -3831,7 +3925,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
       break;
     case DistanceMorphology:
     case VoronoiMorphology:
-      special = MagickTrue;
+      special = MagickTrue;         /* use special direct primative */
       break;
     default:
       break;
@@ -3851,7 +3945,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
       changed = MorphologyPrimitiveDirect(rslt_image, method,
          kernel, exception);
 
-      if ( verbose == MagickTrue )
+      if ( IfMagickTrue(verbose) )
         (void) (void) FormatLocaleFile(stderr,
           "%s:%.20g.%.20g #%.20g => Changed %.20g\n",
           CommandOptionToMnemonic(MagickMorphologyOptions, method),
@@ -3864,8 +3958,8 @@ MagickPrivate Image *MorphologyApply(const Image *image,
         /* Preserve the alpha channel of input image - but turned off */
         (void) SetImageAlphaChannel(rslt_image, DeactivateAlphaChannel,
           exception);
-        (void) CompositeImage(rslt_image, CopyOpacityCompositeOp, image, 0, 0,
-          exception);
+        (void) CompositeImage(rslt_image,image,CopyAlphaCompositeOp,
+          MagickTrue,0,0,exception);
         (void) SetImageAlphaChannel(rslt_image, DeactivateAlphaChannel,
           exception);
       }
@@ -3999,7 +4093,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
         assert( this_kernel != (KernelInfo *) NULL );
 
         /* Extra information for debugging compound operations */
-        if ( verbose == MagickTrue ) {
+        if ( IfMagickTrue(verbose) ) {
           if ( stage_limit > 1 )
             (void) FormatLocaleString(v_info,MaxTextExtent,"%s:%.20g.%.20g -> ",
              CommandOptionToMnemonic(MagickMorphologyOptions,method),(double)
@@ -4035,7 +4129,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
           changed = MorphologyPrimitive(curr_image, work_image, primitive,
                        this_kernel, bias, exception);
 
-          if ( verbose == MagickTrue ) {
+          if ( IfMagickTrue(verbose) ) {
             if ( kernel_loop > 1 )
               (void) FormatLocaleFile(stderr, "\n"); /* add end-of-line from previous */
             (void) (void) FormatLocaleFile(stderr,
@@ -4060,9 +4154,9 @@ MagickPrivate Image *MorphologyApply(const Image *image,
 
         } /* End Loop 4: Iterate the kernel with primitive */
 
-        if ( verbose == MagickTrue && kernel_changed != (size_t)changed )
+        if ( IfMagickTrue(verbose) && kernel_changed != (size_t)changed )
           (void) FormatLocaleFile(stderr, "   Total %.20g",(double) kernel_changed);
-        if ( verbose == MagickTrue && stage_loop < stage_limit )
+        if ( IfMagickTrue(verbose) && stage_loop < stage_limit )
           (void) FormatLocaleFile(stderr, "\n"); /* add end-of-line before looping */
 
 #if 0
@@ -4087,20 +4181,20 @@ MagickPrivate Image *MorphologyApply(const Image *image,
         case EdgeInMorphology:
         case TopHatMorphology:
         case BottomHatMorphology:
-          if ( verbose == MagickTrue )
+          if ( IfMagickTrue(verbose) )
             (void) FormatLocaleFile(stderr,
               "\n%s: Difference with original image",CommandOptionToMnemonic(
               MagickMorphologyOptions, method) );
-          (void) CompositeImage(curr_image,DifferenceCompositeOp,image,0,0,
-            exception);
+          (void) CompositeImage(curr_image,image,DifferenceCompositeOp,
+            MagickTrue,0,0,exception);
           break;
         case EdgeMorphology:
-          if ( verbose == MagickTrue )
+          if ( IfMagickTrue(verbose) )
             (void) FormatLocaleFile(stderr,
               "\n%s: Difference of Dilate and Erode",CommandOptionToMnemonic(
               MagickMorphologyOptions, method) );
-          (void) CompositeImage(curr_image,DifferenceCompositeOp,save_image,0,
-            0,exception);
+          (void) CompositeImage(curr_image,save_image,DifferenceCompositeOp,
+            MagickTrue,0,0,exception);
           save_image = DestroyImage(save_image); /* finished with save image */
           break;
         default:
@@ -4111,7 +4205,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
       if ( kernel->next == (KernelInfo *) NULL )
         rslt_image = curr_image;   /* just return the resulting image */
       else if ( rslt_compose == NoCompositeOp )
-        { if ( verbose == MagickTrue ) {
+        { if ( IfMagickTrue(verbose) ) {
             if ( this_kernel->next != (KernelInfo *) NULL )
               (void) FormatLocaleFile(stderr, " (re-iterate)");
             else
@@ -4120,7 +4214,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
           rslt_image = curr_image; /* return result, and re-iterate */
         }
       else if ( rslt_image == (Image *) NULL)
-        { if ( verbose == MagickTrue )
+        { if ( IfMagickTrue(verbose) )
             (void) FormatLocaleFile(stderr, " (save for compose)");
           rslt_image = curr_image;
           curr_image = (Image *) image;  /* continue with original image */
@@ -4133,15 +4227,15 @@ MagickPrivate Image *MorphologyApply(const Image *image,
           ** purely mathematical way, and only to the selected channels.
           ** IE: Turn off SVG composition 'alpha blending'.
           */
-          if ( verbose == MagickTrue )
+          if ( IfMagickTrue(verbose) )
             (void) FormatLocaleFile(stderr, " (compose \"%s\")",
-                 CommandOptionToMnemonic(MagickComposeOptions, rslt_compose) );
-          (void) CompositeImage(rslt_image, rslt_compose, curr_image, 0, 0,
-            exception);
+              CommandOptionToMnemonic(MagickComposeOptions, rslt_compose) );
+          (void) CompositeImage(rslt_image,curr_image,rslt_compose,MagickTrue,
+            0,0,exception);
           curr_image = DestroyImage(curr_image);
           curr_image = (Image *) image;  /* continue with original image */
         }
-      if ( verbose == MagickTrue )
+      if ( IfMagickTrue(verbose) )
         (void) FormatLocaleFile(stderr, "\n");
 
       /* loop to the next kernel in a multi-kernel list */
@@ -4194,20 +4288,20 @@ exit_cleanup:
 %  the above internal function MorphologyApply().
 %
 %  User defined settings include...
-%    * Output Bias for Convolution and correlation   ("-bias")
-%    * Kernel Scale/normalize settings     ("-set 'option:convolve:scale'")
+%    * Output Bias for Convolution and correlation ("-define convolve:bias=??")
+%    * Kernel Scale/normalize settings             ("-define convolve:scale=??")
 %      This can also includes the addition of a scaled unity kernel.
-%    * Show Kernel being applied           ("-set option:showkernel 1")
+%    * Show Kernel being applied                   ("-define showkernel=1")
+%
+%  Other operators that do not want user supplied options interfering,
+%  especially "convolve:bias" and "showkernel" should use MorphologyApply()
+%  directly.
 %
 %  The format of the MorphologyImage method is:
 %
 %      Image *MorphologyImage(const Image *image,MorphologyMethod method,
 %        const ssize_t iterations,KernelInfo *kernel,ExceptionInfo *exception)
 %
-%      Image *MorphologyImage(const Image *image, const ChannelType
-%        channel,MorphologyMethod method,const ssize_t iterations,
-%        KernelInfo *kernel,ExceptionInfo *exception)
-%
 %  A description of each parameter follows:
 %
 %    o image: the image.
@@ -4238,32 +4332,53 @@ MagickExport Image *MorphologyImage(const Image *image,
   Image
     *morphology_image;
 
+  double
+    bias;
+
+  curr_kernel = (KernelInfo *) kernel;
+  bias=0.0;
+  compose = UndefinedCompositeOp;  /* use default for method */
 
   /* Apply Convolve/Correlate Normalization and Scaling Factors.
    * This is done BEFORE the ShowKernelInfo() function is called so that
    * users can see the results of the 'option:convolve:scale' option.
    */
-  curr_kernel = (KernelInfo *) kernel;
-  if ( method == ConvolveMorphology ||  method == CorrelateMorphology )
-    {
+  if ( method == ConvolveMorphology || method == CorrelateMorphology ) {
       const char
         *artifact;
+
+      /* Get the bias value as it will be needed */
+      artifact = GetImageArtifact(image,"convolve:bias");
+      if ( artifact != (const char *) NULL) {
+        if (IfMagickFalse(IsGeometry(artifact)))
+          (void) ThrowMagickException(exception,GetMagickModule(),
+               OptionWarning,"InvalidSetting","'%s' '%s'",
+               "convolve:bias",artifact);
+        else
+          bias=StringToDoubleInterval(artifact,(double) QuantumRange+1.0);
+      }
+
+      /* Scale kernel according to user wishes */
       artifact = GetImageArtifact(image,"convolve:scale");
       if ( artifact != (const char *)NULL ) {
-        if ( curr_kernel == kernel )
-          curr_kernel = CloneKernelInfo(kernel);
-        if (curr_kernel == (KernelInfo *) NULL) {
-          curr_kernel=DestroyKernelInfo(curr_kernel);
-          return((Image *) NULL);
+        if (IfMagickFalse(IsGeometry(artifact)))
+          (void) ThrowMagickException(exception,GetMagickModule(),
+               OptionWarning,"InvalidSetting","'%s' '%s'",
+               "convolve:scale",artifact);
+        else {
+          if ( curr_kernel == kernel )
+            curr_kernel = CloneKernelInfo(kernel);
+          if (curr_kernel == (KernelInfo *) NULL)
+            return((Image *) NULL);
+          ScaleGeometryKernelInfo(curr_kernel, artifact);
         }
-        ScaleGeometryKernelInfo(curr_kernel, artifact);
       }
     }
 
   /* display the (normalized) kernel via stderr */
-  if ( IsMagickTrue(GetImageArtifact(image,"showkernel"))
-    || IsMagickTrue(GetImageArtifact(image,"convolve:showkernel"))
-    || IsMagickTrue(GetImageArtifact(image,"morphology:showkernel")) )
+  if ( IfStringTrue(GetImageArtifact(image,"showkernel"))
+    || IfStringTrue(GetImageArtifact(image,"convolve:showkernel"))
+    || IfStringTrue(GetImageArtifact(image,"morphology:showkernel")) )
     ShowKernelInfo(curr_kernel);
 
   /* Override the default handling of multi-kernel morphology results
@@ -4274,15 +4389,24 @@ MagickExport Image *MorphologyImage(const Image *image,
    */
   { const char
       *artifact;
+    ssize_t
+      parse;
+
     artifact = GetImageArtifact(image,"morphology:compose");
-    compose = UndefinedCompositeOp;  /* use default for method */
-    if ( artifact != (const char *) NULL)
-      compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
+    if ( artifact != (const char *) NULL) {
+      parse=ParseCommandOption(MagickComposeOptions,
         MagickFalse,artifact);
+      if ( parse < 0 )
+        (void) ThrowMagickException(exception,GetMagickModule(),
+             OptionWarning,"UnrecognizedComposeOperator","'%s' '%s'",
+             "morphology:compose",artifact);
+      else
+        compose=(CompositeOperator)parse;
+    }
   }
   /* Apply the Morphology */
-  morphology_image = MorphologyApply(image, method, iterations,
-    curr_kernel, compose, image->bias, exception);
+  morphology_image = MorphologyApply(image,method,iterations,
+    curr_kernel,compose,bias,exception);
 
   /* Cleanup and Exit */
   if ( curr_kernel != kernel )
@@ -4378,7 +4502,7 @@ static void RotateKernelInfo(KernelInfo *kernel, double angle)
     {
       if ( kernel->width == 3 && kernel->height == 3 )
         { /* Rotate a 3x3 square by 45 degree angle */
-          MagickRealType t  = kernel->values[0];
+          double t  = kernel->values[0];
           kernel->values[0] = kernel->values[3];
           kernel->values[3] = kernel->values[6];
           kernel->values[6] = kernel->values[7];
@@ -4429,13 +4553,15 @@ static void RotateKernelInfo(KernelInfo *kernel, double angle)
         }
       else if ( kernel->width == kernel->height )
         { /* Rotate a square array of values by 90 degrees */
-          { register size_t
+          { register ssize_t
               i,j,x,y;
+
             register MagickRealType
               *k,t;
+
             k=kernel->values;
-            for( i=0, x=kernel->width-1;  i<=x;   i++, x--)
-              for( j=0, y=kernel->height-1;  j<y;   j++, y--)
+            for( i=0, x=(ssize_t) kernel->width-1;  i<=x;   i++, x--)
+              for( j=0, y=(ssize_t) kernel->height-1;  j<y;   j++, y--)
                 { t                    = k[i+j*kernel->width];
                   k[i+j*kernel->width] = k[j+x*kernel->width];
                   k[j+x*kernel->width] = k[x+y*kernel->width];
@@ -4463,13 +4589,19 @@ static void RotateKernelInfo(KernelInfo *kernel, double angle)
        * Basically all that is needed is a reversal of the kernel data!
        * And a reflection of the origon
        */
-      size_t
-        i,j;
-      register double
-        *k,t;
+      double
+        t;
+
+      register MagickRealType
+        *k;
+
+      ssize_t
+        i,
+        j;
 
       k=kernel->values;
-      for ( i=0, j=kernel->width*kernel->height-1;  i<j;  i++, j--)
+      j=(ssize_t) (kernel->width*kernel->height-1);
+      for (i=0;  i < j;  i++, j--)
         t=k[i],  k[i]=k[j],  k[j]=t;
 
       kernel->x = (ssize_t) kernel->width  - kernel->x - 1;
@@ -4522,13 +4654,15 @@ static void RotateKernelInfo(KernelInfo *kernel, double angle)
 MagickExport void ScaleGeometryKernelInfo (KernelInfo *kernel,
      const char *geometry)
 {
-  GeometryFlags
+  //GeometryFlags
+  MagickStatusType
     flags;
+
   GeometryInfo
     args;
 
   SetGeometryInfo(&args);
-  flags = (GeometryFlags) ParseGeometry(geometry, &args);
+  flags = ParseGeometry(geometry, &args);
 
 #if 0
   /* For Debugging Geometry Input */
@@ -4545,7 +4679,7 @@ MagickExport void ScaleGeometryKernelInfo (KernelInfo *kernel,
     args.sigma = 0.0;
 
   /* Scale/Normalize the input kernel */
-  ScaleKernelInfo(kernel, args.rho, flags);
+  ScaleKernelInfo(kernel, args.rho, (GeometryFlags) flags);
 
   /* Add Unity Kernel, for blending with original */
   if ( (flags & SigmaValue) != 0 )
@@ -4641,7 +4775,7 @@ MagickExport void ScaleKernelInfo(KernelInfo *kernel,
   /* Normalization of Kernel */
   pos_scale = 1.0;
   if ( (normalize_flags&NormalizeValue) != 0 ) {
-    if ( fabs(kernel->positive_range + kernel->negative_range) > MagickEpsilon )
+    if ( fabs(kernel->positive_range + kernel->negative_range) >= MagickEpsilon )
       /* non-zero-summing kernel (generally positive) */
       pos_scale = fabs(kernel->positive_range + kernel->negative_range);
     else
@@ -4650,9 +4784,9 @@ MagickExport void ScaleKernelInfo(KernelInfo *kernel,
   }
   /* Force kernel into a normalized zero-summing kernel */
   if ( (normalize_flags&CorrelateNormalizeValue) != 0 ) {
-    pos_scale = ( fabs(kernel->positive_range) > MagickEpsilon )
+    pos_scale = ( fabs(kernel->positive_range) >= MagickEpsilon )
                  ? kernel->positive_range : 1.0;
-    neg_scale = ( fabs(kernel->negative_range) > MagickEpsilon )
+    neg_scale = ( fabs(kernel->negative_range) >= MagickEpsilon )
                  ? -kernel->negative_range : 1.0;
   }
   else
@@ -4725,7 +4859,7 @@ MagickPrivate void ShowKernelInfo(const KernelInfo *kernel)
       (void) FormatLocaleFile(stderr, " #%lu", (unsigned long) c );
     (void) FormatLocaleFile(stderr, " \"%s",
           CommandOptionToMnemonic(MagickKernelOptions, k->type) );
-    if ( fabs(k->angle) > MagickEpsilon )
+    if ( fabs(k->angle) >= MagickEpsilon )
       (void) FormatLocaleFile(stderr, "@%lg", k->angle);
     (void) FormatLocaleFile(stderr, "\" of size %lux%lu%+ld%+ld",(unsigned long)
       k->width,(unsigned long) k->height,(long) k->x,(long) k->y);
@@ -4750,7 +4884,7 @@ MagickPrivate void ShowKernelInfo(const KernelInfo *kernel)
           (void) FormatLocaleFile(stderr," %*s", GetMagickPrecision()+3, "nan");
         else
           (void) FormatLocaleFile(stderr," %*.*lg", GetMagickPrecision()+3,
-              GetMagickPrecision(), k->values[i]);
+              GetMagickPrecision(), (double) k->values[i]);
       (void) FormatLocaleFile(stderr,"\n");
     }
   }