]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/morphology.c
(no commit message)
[imagemagick] / MagickCore / morphology.c
index c08c136eae38bd49d492f01df7f992fbeeba8a6b..7fa89f0e8af9be4b1d28e5f2558e730510725e72 100644 (file)
@@ -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 *),
@@ -316,8 +334,8 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
     }
 
   /* Read in the kernel values from rest of input string argument */
-  kernel->values=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-    kernel->height*sizeof(*kernel->values));
+  kernel->values=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
+    kernel->width,kernel->height*sizeof(*kernel->values)));
   if (kernel->values == (MagickRealType *) NULL)
     return(DestroyKernelInfo(kernel));
   kernel->minimum = +MagickHuge;
@@ -631,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
@@ -993,6 +1015,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
     case LoGKernel:
     case BlurKernel:
     case CometKernel:
+    case BinomialKernel:
     case DiamondKernel:
     case SquareKernel:
     case RectangleKernel:
@@ -1030,8 +1053,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
       {
         kernel->height = kernel->width = (size_t) 1;
         kernel->x = kernel->y = (ssize_t) 0;
-        kernel->values=(MagickRealType *) AcquireAlignedMemory(1,
-          sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(1,sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
         kernel->maximum = kernel->values[0] = args->rho;
@@ -1054,8 +1077,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -1145,8 +1169,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -1182,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 )
@@ -1199,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
@@ -1229,8 +1256,9 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         kernel->x = kernel->y = 0;
         kernel->height = 1;
         kernel->negative_range = kernel->positive_range = 0.0;
-        kernel->values=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -1266,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
           }
@@ -1286,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
@@ -1384,8 +1443,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[3]+=(MagickRealType) MagickSQ2;
-            kernel->values[5]-=(MagickRealType) MagickSQ2;
+            kernel->values[3] = +(MagickRealType) MagickSQ2;
+            kernel->values[5] = -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);     /* recalculate meta-data */
             break;
           case 2:
@@ -1393,8 +1452,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[1] = kernel->values[3]+=(MagickRealType) MagickSQ2;
-            kernel->values[5] = kernel->values[7]-=(MagickRealType) 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;
@@ -1409,8 +1468,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[3]+=(MagickRealType) MagickSQ2;
-            kernel->values[5]-=(MagickRealType) 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;
@@ -1419,8 +1478,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[1]+=(MagickRealType) MagickSQ2;
-            kernel->values[7]+=(MagickRealType) MagickSQ2;
+            kernel->values[1] = +(double) MagickSQ2;
+            kernel->values[7] = +(double) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1429,8 +1488,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[0]+=(MagickRealType) MagickSQ2;
-            kernel->values[8]-=(MagickRealType) MagickSQ2;
+            kernel->values[0] = +(MagickRealType) MagickSQ2;
+            kernel->values[8] = -(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1439,8 +1498,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             kernel->type = type;
-            kernel->values[2]-=(MagickRealType) MagickSQ2;
-            kernel->values[6]+=(MagickRealType) MagickSQ2;
+            kernel->values[2] = -(MagickRealType) MagickSQ2;
+            kernel->values[6] = +(MagickRealType) MagickSQ2;
             CalcKernelMetaData(kernel);
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
@@ -1480,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 )
@@ -1500,8 +1559,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -1541,8 +1601,9 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             kernel->y = (ssize_t) args->psi;
             scale = 1.0;
           }
-        kernel->values=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -1562,8 +1623,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -1588,8 +1650,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -1610,8 +1673,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -1631,8 +1695,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -1672,8 +1737,9 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
 
           kernel->height = kernel->width;
           kernel->x = kernel->y = (ssize_t) (kernel->width-1)/2;
-          kernel->values=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -2042,8 +2108,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -2062,8 +2129,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-            kernel->height*sizeof(*kernel->values));
+          kernel->values=(MagickRealType *) MagickAssumeAligned(
+            AcquireAlignedMemory(kernel->width,kernel->height*
+            sizeof(*kernel->values)));
           if (kernel->values == (MagickRealType *) NULL)
             return(DestroyKernelInfo(kernel));
 
@@ -2082,8 +2150,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -2107,8 +2176,9 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-          kernel->height*sizeof(*kernel->values));
+        kernel->values=(MagickRealType *) MagickAssumeAligned(
+          AcquireAlignedMemory(kernel->width,kernel->height*
+          sizeof(*kernel->values)));
         if (kernel->values == (MagickRealType *) NULL)
           return(DestroyKernelInfo(kernel));
 
@@ -2172,8 +2242,8 @@ 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=(MagickRealType *) AcquireAlignedMemory(kernel->width,
-    kernel->height*sizeof(*kernel->values));
+  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++)
@@ -2351,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;
   }
 
@@ -2586,7 +2656,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
       x;
 
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-#pragma omp parallel for schedule(static,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++)
     {
@@ -2621,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
         */
@@ -2644,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
@@ -2660,7 +2731,7 @@ 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) )
+             (image->alpha_trait != BlendPixelTrait) )
           { /* No 'Sync' involved.
             ** Convolution is just a simple greyscale channel operation
             */
@@ -2685,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
@@ -2693,7 +2764,7 @@ 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
+            double
               alpha,  /* alpha weighting for colors : alpha  */
               gamma;  /* divisor, sum of color alpha weighting */
             size_t
@@ -2717,7 +2788,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
               k_pixels+=GetPixelChannels(image);
             }
             /* Sync'ed channels, all channels are modified */
-            gamma=(double)count/(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,ClampToQuantum(gamma*result.green),q);
             SetPixelBlue(morphology_image,ClampToQuantum(gamma*result.blue),q);
@@ -2745,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)
@@ -2762,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(static,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++)
   {
@@ -2794,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
@@ -2829,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:
@@ -2885,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
                 */
@@ -2920,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);
               }
@@ -2929,7 +3001,7 @@ 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
+                double
                   alpha,  /* alpha weighting for colors : alpha  */
                   gamma;  /* divisor, sum of color alpha weighting */
                 size_t
@@ -2960,7 +3032,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   k_pixels += virt_width*GetPixelChannels(image);
                 }
                 /* Sync'ed channels, all channels are modified */
-                gamma=(double)count/(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,
@@ -3265,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;
       }
@@ -3288,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)
@@ -3409,20 +3481,20 @@ 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);
@@ -3527,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;
       }
@@ -3595,20 +3667,20 @@ 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);
@@ -3711,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;
       }
@@ -4265,7 +4337,7 @@ MagickExport Image *MorphologyImage(const Image *image,
 
   curr_kernel = (KernelInfo *) kernel;
   bias=0.0;
-  compose = (ssize_t)UndefinedCompositeOp;  /* use default for method */
+  compose = UndefinedCompositeOp;  /* use default for method */
 
   /* Apply Convolve/Correlate Normalization and Scaling Factors.
    * This is done BEFORE the ShowKernelInfo() function is called so that
@@ -4430,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];
@@ -4481,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 double
+
+            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];
@@ -4518,7 +4592,7 @@ static void RotateKernelInfo(KernelInfo *kernel, double angle)
       double
         t;
 
-      register double
+      register MagickRealType
         *k;
 
       ssize_t
@@ -4581,8 +4655,9 @@ MagickExport void ScaleGeometryKernelInfo (KernelInfo *kernel,
      const char *geometry)
 {
   //GeometryFlags
-  int
+  MagickStatusType
     flags;
+
   GeometryInfo
     args;
 
@@ -4604,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 )
@@ -4700,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
@@ -4709,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
@@ -4784,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);
@@ -4809,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");
     }
   }