]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/morphology.c
Update web pages
[imagemagick] / MagickCore / morphology.c
index 0039409bb4d1c25b8ff5f36ead2de7b50615f6a1..26ea08e94326a7b485993b952fbbe821dcedf6d2 100644 (file)
@@ -17,7 +17,7 @@
 %                               January 2010                                  %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2015 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  %
@@ -33,8 +33,8 @@
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-% Morpology is the the application of various kernels, of any size and even
-% shape, to a image in various ways (typically binary, but not always).
+% Morphology is the application of various kernels, of any size or shape, to an
+% image in various ways (typically binary, but not always).
 %
 % Convolution (weighted sum or average) is just one specific type of
 % morphology. Just one that is very common for image bluring and sharpening
 /*
   Other global definitions used by module.
 */
-static inline double MagickMin(const double x,const double y)
-{
-  return( x < y ? x : y);
-}
-static inline double MagickMax(const double x,const double y)
-{
-  return( x > y ? x : y);
-}
 #define Minimize(assign,value) assign=MagickMin(assign,value)
 #define Maximize(assign,value) assign=MagickMax(assign,value)
 
@@ -127,7 +119,7 @@ static void
 static inline KernelInfo *LastKernelInfo(KernelInfo *kernel)
 {
   while (kernel->next != (KernelInfo *) NULL)
-    kernel = kernel->next;
+    kernel=kernel->next;
   return(kernel);
 }
 
@@ -225,7 +217,7 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
     *kernel;
 
   char
-    token[MaxTextExtent];
+    token[MagickPathExtent];
 
   const char
     *p,
@@ -244,14 +236,14 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
     args;
 
   kernel=(KernelInfo *) AcquireQuantumMemory(1,sizeof(*kernel));
-  if (kernel == (KernelInfo *)NULL)
+  if (kernel == (KernelInfo *) NULL)
     return(kernel);
   (void) ResetMagickMemory(kernel,0,sizeof(*kernel));
   kernel->minimum = kernel->maximum = kernel->angle = 0.0;
   kernel->negative_range = kernel->positive_range = 0.0;
   kernel->type = UserDefinedKernel;
   kernel->next = (KernelInfo *) NULL;
-  kernel->signature = MagickSignature;
+  kernel->signature=MagickCoreSignature;
   if (kernel_string == (const char *) NULL)
     return(kernel);
 
@@ -323,8 +315,8 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
     kernel->width,kernel->height*sizeof(*kernel->values)));
   if (kernel->values == (MagickRealType *) NULL)
     return(DestroyKernelInfo(kernel));
-  kernel->minimum = +MagickHuge;
-  kernel->maximum = -MagickHuge;
+  kernel->minimum=MagickMaximumValue;
+  kernel->maximum=(-MagickMaximumValue);
   kernel->negative_range = kernel->positive_range = 0.0;
   for (i=0; (i < (ssize_t) (kernel->width*kernel->height)) && (p < end); i++)
   {
@@ -365,7 +357,7 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
 #endif
 
   /* check that we recieved at least one real (non-nan) value! */
-  if ( kernel->minimum == MagickHuge )
+  if (kernel->minimum == MagickMaximumValue)
     return(DestroyKernelInfo(kernel));
 
   if ( (flags & AreaValue) != 0 )         /* '@' symbol in kernel size */
@@ -378,10 +370,11 @@ static KernelInfo *ParseKernelArray(const char *kernel_string)
   return(kernel);
 }
 
-static KernelInfo *ParseKernelName(const char *kernel_string)
+static KernelInfo *ParseKernelName(const char *kernel_string,
+  ExceptionInfo *exception)
 {
   char
-    token[MaxTextExtent];
+    token[MagickPathExtent];
 
   const char
     *p,
@@ -403,7 +396,7 @@ static KernelInfo *ParseKernelName(const char *kernel_string)
   GetMagickToken(kernel_string,&p,token);
   type=ParseCommandOption(MagickKernelOptions,MagickFalse,token);
   if ( type < 0 || type == UserDefinedKernel )
-    return((KernelInfo *)NULL);  /* not a valid named kernel */
+    return((KernelInfo *) NULL);  /* not a valid named kernel */
 
   while (((isspace((int) ((unsigned char) *p)) != 0) ||
           (*p == ',') || (*p == ':' )) && (*p != '\0') && (*p != ';'))
@@ -473,7 +466,7 @@ static KernelInfo *ParseKernelName(const char *kernel_string)
       break;
   }
 
-  kernel = AcquireKernelBuiltIn((KernelInfoType)type, &args);
+  kernel = AcquireKernelBuiltIn((KernelInfoType)type, &args, exception);
   if ( kernel == (KernelInfo *) NULL )
     return(kernel);
 
@@ -490,65 +483,68 @@ static KernelInfo *ParseKernelName(const char *kernel_string)
   return(kernel);
 }
 
-MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
+MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string,
+  ExceptionInfo *exception)
 {
-
   KernelInfo
     *kernel,
     *new_kernel;
 
   char
-    token[MaxTextExtent];
+    *kernel_cache,
+    token[MagickPathExtent];
 
   const char
     *p;
 
-  size_t
-    kernel_number;
-
   if (kernel_string == (const char *) NULL)
     return(ParseKernelArray(kernel_string));
-  p = kernel_string;
-  kernel = NULL;
-  kernel_number = 0;
-
-  while ( GetMagickToken(p,NULL,token),  *token != '\0' ) {
-
-    /* ignore extra or multiple ';' kernel separators */
-    if ( *token != ';' ) {
-
-      /* tokens starting with alpha is a Named kernel */
-      if (isalpha((int) ((unsigned char) *token)) != 0)
-        new_kernel = ParseKernelName(p);
-      else /* otherwise a user defined kernel array */
-        new_kernel = ParseKernelArray(p);
-
-      /* Error handling -- this is not proper error handling! */
-      if ( new_kernel == (KernelInfo *) NULL ) {
-        (void) FormatLocaleFile(stderr,"Failed to parse kernel number #%.20g\n",
-          (double) kernel_number);
-        if ( kernel != (KernelInfo *) NULL )
-          kernel=DestroyKernelInfo(kernel);
+  p=kernel_string;
+  kernel_cache=(char *) NULL;
+  if (*kernel_string == '@')
+    {
+      kernel_cache=FileToString(kernel_string+1,~0UL,exception);
+      if (kernel_cache == (char *) NULL)
         return((KernelInfo *) NULL);
-      }
+      p=(const char *) kernel_cache;
+    }    
+  kernel=NULL;
+  while (GetMagickToken(p,NULL,token), *token != '\0')
+  {
+    /* ignore extra or multiple ';' kernel separators */
+    if (*token != ';')
+      {
+        /* tokens starting with alpha is a Named kernel */
+        if (isalpha((int) ((unsigned char) *token)) != 0)
+          new_kernel=ParseKernelName(p,exception);
+        else /* otherwise a user defined kernel array */
+          new_kernel=ParseKernelArray(p);
+
+        /* Error handling -- this is not proper error handling! */
+        if (new_kernel == (KernelInfo *) NULL)
+          {
+            if (kernel != (KernelInfo *) NULL)
+              kernel=DestroyKernelInfo(kernel);
+            return((KernelInfo *) NULL);
+          }
 
-      /* initialise or append the kernel list */
-      if ( kernel == (KernelInfo *) NULL )
-        kernel = new_kernel;
-      else
-        LastKernelInfo(kernel)->next = new_kernel;
-    }
+        /* initialise or append the kernel list */
+        if (kernel == (KernelInfo *) NULL)
+          kernel=new_kernel;
+        else
+          LastKernelInfo(kernel)->next=new_kernel;
+      }
 
     /* look for the next kernel in list */
-    p = strchr(p, ';');
-    if ( p == (char *) NULL )
+    p=strchr(p,';');
+    if (p == (char *) NULL)
       break;
     p++;
-
   }
+  if (kernel_cache != (char *) NULL)
+    kernel_cache=DestroyString(kernel_cache);
   return(kernel);
 }
-
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -953,7 +949,7 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
 */
 
 MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
-   const GeometryInfo *args)
+  const GeometryInfo *args,ExceptionInfo *exception)
 {
   KernelInfo
     *kernel;
@@ -973,7 +969,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
   switch(type) {
     case UndefinedKernel:    /* These should not call this function */
     case UserDefinedKernel:
-      assert("Should not call this function" != (char *)NULL);
+      assert("Should not call this function" != (char *) NULL);
       break;
     case LaplacianKernel:   /* Named Descrete Convolution Kernels */
     case SobelKernel:       /* these are defined using other kernels */
@@ -1026,7 +1022,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
       kernel->negative_range = kernel->positive_range = 0.0;
       kernel->type = type;
       kernel->next = (KernelInfo *) NULL;
-      kernel->signature = MagickSignature;
+      kernel->signature=MagickCoreSignature;
       break;
   }
 
@@ -1443,10 +1439,12 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             ScaleKernelInfo(kernel, (double) (1.0/2.0*MagickSQ2), NoValue);
             break;
           case 10:
-            kernel=AcquireKernelInfo("FreiChen:11;FreiChen:12;FreiChen:13;FreiChen:14;FreiChen:15;FreiChen:16;FreiChen:17;FreiChen:18;FreiChen:19");
+          {
+            kernel=AcquireKernelInfo("FreiChen:11;FreiChen:12;FreiChen:13;FreiChen:14;FreiChen:15;FreiChen:16;FreiChen:17;FreiChen:18;FreiChen:19",exception);
             if (kernel == (KernelInfo *) NULL)
               return(kernel);
             break;
+          }
           case 1:
           case 11:
             kernel=ParseKernelArray("3: 1,0,-1  2,0,-2  1,0,-1");
@@ -1749,7 +1747,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         }
       case EdgesKernel:
         {
-          kernel=AcquireKernelInfo("ThinSE:482");
+          kernel=AcquireKernelInfo("ThinSE:482",exception);
           if (kernel == (KernelInfo *) NULL)
             return(kernel);
           kernel->type = type;
@@ -1758,7 +1756,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
         }
       case CornersKernel:
         {
-          kernel=AcquireKernelInfo("ThinSE:87");
+          kernel=AcquireKernelInfo("ThinSE:87",exception);
           if (kernel == (KernelInfo *) NULL)
             return(kernel);
           kernel->type = type;
@@ -1803,7 +1801,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             case 0:
             default:
               /* set of kernels to find all end of lines */
-              return(AcquireKernelInfo("LineEnds:1>;LineEnds:2>"));
+              return(AcquireKernelInfo("LineEnds:1>;LineEnds:2>",exception));
             case 1:
               /* kernel for 4-connected line ends - no rotation */
               kernel=ParseKernelArray("3: 0,0,-  0,1,1  0,0,-");
@@ -1833,7 +1831,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
             case 0:
             default:
               /* set of kernels to find all line junctions */
-              return(AcquireKernelInfo("LineJunctions:1@;LineJunctions:2>"));
+              return(AcquireKernelInfo("LineJunctions:1@;LineJunctions:2>",exception));
             case 1:
               /* Y Junction */
               kernel=ParseKernelArray("3: 1,-,1  -,1,-  -,1,-");
@@ -1955,7 +1953,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
               /* Traditional Skeleton...
               ** A cyclically rotated single kernel
               */
-              kernel=AcquireKernelInfo("ThinSE:482");
+              kernel=AcquireKernelInfo("ThinSE:482",exception);
               if (kernel == (KernelInfo *) NULL)
                 return(kernel);
               kernel->type = type;
@@ -1966,7 +1964,7 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
               ** Corners of the traditional method made more forgiving,
               ** but the retain the same cyclic order.
               */
-              kernel=AcquireKernelInfo("ThinSE:482; ThinSE:87x90;");
+              kernel=AcquireKernelInfo("ThinSE:482; ThinSE:87x90;",exception);
               if (kernel == (KernelInfo *) NULL)
                 return(kernel);
               if (kernel->next == (KernelInfo *) NULL)
@@ -1981,8 +1979,8 @@ MagickExport KernelInfo *AcquireKernelBuiltIn(const KernelInfoType type,
               ** by Dan S. Bloomberg, available on Leptonica, Selected Papers,
               **   http://www.leptonica.com/papers/conn.pdf
               */
-              kernel=AcquireKernelInfo(
-                            "ThinSE:41; ThinSE:42; ThinSE:43");
+              kernel=AcquireKernelInfo("ThinSE:41; ThinSE:42; ThinSE:43",
+                exception);
               if (kernel == (KernelInfo *) NULL)
                 return(kernel);
               kernel->type = type;
@@ -2270,7 +2268,7 @@ MagickExport KernelInfo *CloneKernelInfo(const KernelInfo *kernel)
 MagickExport KernelInfo *DestroyKernelInfo(KernelInfo *kernel)
 {
   assert(kernel != (KernelInfo *) NULL);
-  if ( kernel->next != (KernelInfo *) NULL )
+  if (kernel->next != (KernelInfo *) NULL)
     kernel->next=DestroyKernelInfo(kernel->next);
   kernel->values=(MagickRealType *) RelinquishAlignedMemory(kernel->values);
   kernel=(KernelInfo *) RelinquishMagickMemory(kernel);
@@ -2401,9 +2399,9 @@ static MagickBooleanType SameKernelInfo(const KernelInfo *kernel1,
   /* check actual kernel values */
   for (i=0; i < (kernel1->width*kernel1->height); i++) {
     /* Test for Nan equivalence */
-    if ( IfNaN(kernel1->values[i]) && !IfNaN(kernel2->values[i]) )
+    if ( IsNaN(kernel1->values[i]) && !IsNaN(kernel2->values[i]) )
       return MagickFalse;
-    if ( IfNaN(kernel2->values[i]) && !IfNaN(kernel1->values[i]) )
+    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 )
@@ -2582,20 +2580,20 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     progress;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(morphology_image != (Image *) NULL);
-  assert(morphology_image->signature == MagickSignature);
+  assert(morphology_image->signature == MagickCoreSignature);
   assert(kernel != (KernelInfo *) NULL);
-  assert(kernel->signature == MagickSignature);
+  assert(kernel->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   status=MagickTrue;
   progress=0;
   image_view=AcquireVirtualCacheView(image,exception);
   morphology_view=AcquireAuthenticCacheView(morphology_image,exception);
   width=image->columns+kernel->width-1;
-  offset.x=0.0;
-  offset.y=0.0;
+  offset.x=0;
+  offset.y=0;
   switch (method)
   {
     case ConvolveMorphology:
@@ -2635,9 +2633,6 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     changes[i]=0;
   if ((method == ConvolveMorphology) && (kernel->width == 1))
     {
-      const int
-        id = GetOpenMPThreadId();
-
       register ssize_t
         x;
 
@@ -2653,6 +2648,9 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
 #endif
       for (x=0; x < (ssize_t) image->columns; x++)
       {
+        const int
+          id = GetOpenMPThreadId();
+
         register const Quantum
           *restrict p;
 
@@ -2717,7 +2715,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             if ((traits == UndefinedPixelTrait) ||
                 (morphology_traits == UndefinedPixelTrait))
               continue;
-            if (((morphology_traits & CopyPixelTrait) != 0) ||
+            if (((traits & CopyPixelTrait) != 0) ||
                 (GetPixelReadMask(image,p+center) == 0))
               {
                 SetPixelChannel(morphology_image,channel,p[center+i],q);
@@ -2726,55 +2724,44 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             k=(&kernel->values[kernel->width*kernel->height-1]);
             pixels=p;
             pixel=bias;
+            gamma=0.0;
             count=0;
             if ((morphology_traits & BlendPixelTrait) == 0)
+              for (v=0; v < (ssize_t) kernel->height; v++)
               {
-                /*
-                  No alpha blending.
-                */
-                for (v=0; v < (ssize_t) kernel->height; v++)
+                for (u=0; u < (ssize_t) kernel->width; u++)
                 {
-                  for (u=0; u < (ssize_t) kernel->width; u++)
-                  {
-                    if (IfNaN(*k) == MagickFalse)
-                      {
-                        pixel+=(*k)*pixels[i];
-                        count++;
-                      }
-                    k--;
-                    pixels+=GetPixelChannels(image);
-                  }
+                  if (!IsNaN(*k))
+                    {
+                      pixel+=(*k)*pixels[i];
+                      gamma+=(*k);
+                      count++;
+                    }
+                  k--;
+                  pixels+=GetPixelChannels(image);
                 }
-                if (fabs(pixel-p[center+i]) > MagickEpsilon)
-                  changes[id]++;
-                gamma=(double) kernel->height*kernel->width/count;
-                SetPixelChannel(morphology_image,channel,ClampToQuantum(gamma*
-                  pixel),q);
-                continue;
               }
-            /*
-              Alpha blending.
-            */
-            gamma=0.0;
-            for (v=0; v < (ssize_t) kernel->height; v++)
-            {
-              for (u=0; u < (ssize_t) kernel->width; u++)
+            else
+              for (v=0; v < (ssize_t) kernel->height; v++)
               {
-                if (IfNaN(*k) == MagickFalse)
-                  {
-                    alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
-                    pixel+=(*k)*alpha*pixels[i];
-                    gamma+=(*k)*alpha;
-                    count++;
-                  }
-                k--;
-                pixels+=GetPixelChannels(image);
+                for (u=0; u < (ssize_t) kernel->width; u++)
+                {
+                  if (!IsNaN(*k))
+                    {
+                      alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
+                      pixel+=alpha*(*k)*pixels[i];
+                      gamma+=alpha*(*k);
+                      count++;
+                    }
+                  k--;
+                  pixels+=GetPixelChannels(image);
+                }
               }
-            }
             if (fabs(pixel-p[center+i]) > MagickEpsilon)
               changes[id]++;
             gamma=PerceptibleReciprocal(gamma);
-            gamma*=(double) kernel->height*kernel->width/count;
+            if (count != 0)
+              gamma*=(double) kernel->height*kernel->width/count;
             SetPixelChannel(morphology_image,channel,ClampToQuantum(gamma*
               pixel),q);
           }
@@ -2852,6 +2839,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         double
           alpha,
           gamma,
+          intensity,
           maximum,
           minimum,
           pixel;
@@ -2884,7 +2872,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         if ((traits == UndefinedPixelTrait) ||
             (morphology_traits == UndefinedPixelTrait))
           continue;
-        if (((morphology_traits & CopyPixelTrait) != 0) ||
+        if (((traits & CopyPixelTrait) != 0) ||
             (GetPixelReadMask(image,p+center) == 0))
           {
             SetPixelChannel(morphology_image,channel,p[center+i],q);
@@ -2919,18 +2907,18 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             /*
                Weighted Average of pixels using reflected kernel
 
-               For correct working of this operation for asymetrical
-               kernels, the kernel needs to be applied in its reflected form.
-               That is its values needs to be reversed.
+               For correct working of this operation for asymetrical kernels,
+               the kernel needs to be applied in its reflected form.  That is
+               its values needs to be reversed.
 
                Correlation is actually the same as this but without reflecting
-               the kernel, and thus 'lower-level' that Convolution.  However
-               as Convolution is the more common method used, and it does not
+               the kernel, and thus 'lower-level' that Convolution.  However as
+               Convolution is the more common method used, and it does not
                really cost us much in terms of processing to use a reflected
                kernel, so it is Convolution that is implemented.
 
-               Correlation will have its kernel reflected before calling
-               this function to do a Convolve.
+               Correlation will have its kernel reflected before calling this
+               function to do a Convolve.
 
                For more details of Correlation vs Convolution see
                  http://www.cs.umd.edu/~djacobs/CMSC426/Convolution.pdf
@@ -2946,7 +2934,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 {
                   for (u=0; u < (ssize_t) kernel->width; u++)
                   {
-                    if (IfNaN(*k) == MagickFalse)
+                    if (!IsNaN(*k))
                       {
                         pixel+=(*k)*pixels[i];
                         count++;
@@ -2961,15 +2949,16 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             /*
               Alpha blending.
             */
+            gamma=0.0;
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
-                    pixel+=(*k)*alpha*pixels[i];
-                    gamma+=(*k)*alpha;
+                    pixel+=alpha*(*k)*pixels[i];
+                    gamma+=alpha*(*k);
                     count++;
                   }
                 k--;
@@ -2994,7 +2983,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if ((IfNaN(*k) == MagickFalse) && (*k >= 0.5))
+                if (!IsNaN(*k) && (*k >= 0.5))
                   {
                     if ((double) pixels[i] < pixel)
                       pixel=(double) pixels[i];
@@ -3025,11 +3014,10 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if ((IfNaN(*k) == MagickFalse) && (*k > 0.5))
+                if (!IsNaN(*k) && (*k > 0.5))
                   {
                     if ((double) pixels[i] > pixel)
                       pixel=(double) pixels[i];
-                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -3060,7 +3048,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if (*k > 0.7)
                       {
@@ -3103,12 +3091,13 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if ((IfNaN(*k) == MagickFalse) && (*k >= 0.5))
+                if (!IsNaN(*k) && (*k >= 0.5))
                   {
-                    if (GetPixelIntensity(image,pixels) < minimum)
+                    intensity=(double) GetPixelIntensity(image,pixels);
+                    if (intensity < minimum)
                       {
                         pixel=(double) pixels[i];
-                        minimum=GetPixelIntensity(image,pixels);
+                        minimum=intensity;
                       }
                     count++;
                   }
@@ -3132,12 +3121,13 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if ((IfNaN(*k) == MagickFalse) && (*k >= 0.5))
+                if (!IsNaN(*k) && (*k >= 0.5))
                   {
-                    if (GetPixelIntensity(image,pixels) > maximum)
+                    intensity=(double) GetPixelIntensity(image,pixels);
+                    if (intensity > maximum)
                       {
                         pixel=(double) pixels[i];
-                        maximum=GetPixelIntensity(image,pixels);
+                        maximum=intensity;
                       }
                     count++;
                   }
@@ -3179,7 +3169,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
@@ -3199,13 +3189,14 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         if (fabs(pixel-p[center+i]) > MagickEpsilon)
           changes[id]++;
         gamma=PerceptibleReciprocal(gamma);
-        gamma*=(double) kernel->height*kernel->width/count;
+        if (count != 0)
+          gamma*=(double) kernel->height*kernel->width/count;
         SetPixelChannel(morphology_image,channel,ClampToQuantum(gamma*pixel),q);
       }
       p+=GetPixelChannels(image);
       q+=GetPixelChannels(morphology_image);
     }
-    if ( SyncCacheViewAuthenticPixels(morphology_view,exception) == MagickFalse)
+    if (SyncCacheViewAuthenticPixels(morphology_view,exception) == MagickFalse)
       status=MagickFalse;
     if (image->progress_monitor != (MagickProgressMonitor) NULL)
       {
@@ -3266,11 +3257,11 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
     y;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(kernel != (KernelInfo *) NULL);
-  assert(kernel->signature == MagickSignature);
+  assert(kernel->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
   status=MagickTrue;
   changed=0;
   progress=0;
@@ -3376,7 +3367,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
@@ -3390,7 +3381,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             pixels=q-offset.x*GetPixelChannels(image);
             for (u=0; u < offset.x; u++)
             {
-              if ((IfNaN(*k) == MagickFalse) && ((x+u-offset.x) >= 0))
+              if (!IsNaN(*k) && ((x+u-offset.x) >= 0))
                 {
                   if ((pixels[i]+(*k)) < pixel)
                     pixel=(double) pixels[i]+(*k);
@@ -3407,7 +3398,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
@@ -3421,7 +3412,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             pixels=q-offset.x*GetPixelChannels(image);
             for (u=0; u < offset.x; u++)
             {
-              if ((IfNaN(*k) == MagickFalse) && ((x+u-offset.x) >= 0))
+              if (!IsNaN(*k) && ((x+u-offset.x) >= 0))
                 {
                   if ((pixels[i]+(*k)) < pixel)
                     pixel=(double) pixels[i]+(*k);
@@ -3537,7 +3528,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
@@ -3548,17 +3539,16 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
               pixels+=(image->columns-1)*GetPixelChannels(image);
             }
             k=(&kernel->values[kernel->width*kernel->y+kernel->x-1]);
-            pixels=q-offset.x*GetPixelChannels(image);
+            pixels=q;
             for (u=offset.x+1; u < (ssize_t) kernel->width; u++)
             {
-              if ((IfNaN(*k) == MagickFalse) &&
-                  ((x+u-offset.x) < (ssize_t) image->columns))
+              pixels+=GetPixelChannels(image);
+              if (!IsNaN(*k) && ((x+u-offset.x) < (ssize_t) image->columns))
                 {
                   if ((pixels[i]+(*k)) < pixel)
                     pixel=(double) pixels[i]+(*k);
                 }
               k--;
-              pixels+=GetPixelChannels(image);
             }
             break;
           }
@@ -3569,7 +3559,7 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
             {
               for (u=0; u < (ssize_t) kernel->width; u++)
               {
-                if (IfNaN(*k) == MagickFalse)
+                if (!IsNaN(*k))
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
@@ -3580,17 +3570,16 @@ static ssize_t MorphologyPrimitiveDirect(Image *image,
               pixels+=(image->columns-1)*GetPixelChannels(image);
             }
             k=(&kernel->values[kernel->width*(kernel->y+1)-1]);
-            pixels=q-offset.x*GetPixelChannels(image);
+            pixels=q;
             for (u=offset.x+1; u < (ssize_t) kernel->width; u++)
             {
-              if ((IfNaN(*k) == MagickFalse) &&
-                  ((x+u-offset.x) < (ssize_t) image->columns))
+              pixels+=GetPixelChannels(image);
+              if (!IsNaN(*k) && ((x+u-offset.x) < (ssize_t) image->columns))
                 {
                   if ((pixels[i]+(*k)) < pixel)
                     pixel=(double) pixels[i]+(*k);
                 }
               k--;
-              pixels+=GetPixelChannels(image);
             }
             break;
           }
@@ -3676,18 +3665,18 @@ MagickPrivate Image *MorphologyApply(const Image *image,
     changed;        /* number pixels changed by last primitive operation */
 
   char
-    v_info[80];
+    v_info[MagickPathExtent];
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   assert(kernel != (KernelInfo *) NULL);
-  assert(kernel->signature == MagickSignature);
+  assert(kernel->signature == MagickCoreSignature);
   assert(exception != (ExceptionInfo *) NULL);
-  assert(exception->signature == MagickSignature);
+  assert(exception->signature == MagickCoreSignature);
 
   count = 0;      /* number of low-level morphology primitives performed */
   if ( iterations == 0 )
-    return((Image *)NULL);   /* null operation - nothing to do! */
+    return((Image *) NULL);   /* null operation - nothing to do! */
 
   kernel_limit = (size_t) iterations;
   if ( iterations < 0 )  /* negative interations = infinite (well alomst) */
@@ -3903,11 +3892,11 @@ MagickPrivate Image *MorphologyApply(const Image *image,
         /* Extra information for debugging compound operations */
         if ( IfMagickTrue(verbose) ) {
           if ( stage_limit > 1 )
-            (void) FormatLocaleString(v_info,MaxTextExtent,"%s:%.20g.%.20g -> ",
+            (void) FormatLocaleString(v_info,MagickPathExtent,"%s:%.20g.%.20g -> ",
              CommandOptionToMnemonic(MagickMorphologyOptions,method),(double)
              method_loop,(double) stage_loop);
           else if ( primitive != method )
-            (void) FormatLocaleString(v_info, MaxTextExtent, "%s:%.20g -> ",
+            (void) FormatLocaleString(v_info, MagickPathExtent, "%s:%.20g -> ",
               CommandOptionToMnemonic(MagickMorphologyOptions, method),(double)
               method_loop);
           else
@@ -3935,7 +3924,6 @@ MagickPrivate Image *MorphologyApply(const Image *image,
           count++;
           changed = MorphologyPrimitive(curr_image, work_image, primitive,
                        this_kernel, bias, exception);
-
           if ( IfMagickTrue(verbose) ) {
             if ( kernel_loop > 1 )
               (void) FormatLocaleFile(stderr, "\n"); /* add end-of-line from previous */
@@ -4096,13 +4084,13 @@ exit_cleanup:
 %
 %  User defined settings include...
 %    * Output Bias for Convolution and correlation ("-define convolve:bias=??")
-%    * Kernel Scale/normalize settings             ("-define convolve:scale=??")
+%    * Kernel Scale/normalize settings            ("-define convolve:scale=??")
 %      This can also includes the addition of a scaled unity kernel.
-%    * Show Kernel being applied                   ("-define showkernel=1")
+%    * Show Kernel being applied            ("-define morphology:showkernel=1")
 %
 %  Other operators that do not want user supplied options interfering,
-%  especially "convolve:bias" and "showkernel" should use MorphologyApply()
-%  directly.
+%  especially "convolve:bias" and "morphology:showkernel" should use
+%  MorphologyApply() directly.
 %
 %  The format of the MorphologyImage method is:
 %
@@ -4130,17 +4118,20 @@ MagickExport Image *MorphologyImage(const Image *image,
   const MorphologyMethod method,const ssize_t iterations,
   const KernelInfo *kernel,ExceptionInfo *exception)
 {
-  KernelInfo
-    *curr_kernel;
+  const char
+    *artifact;
 
   CompositeOperator
     compose;
 
+  double
+    bias;
+
   Image
     *morphology_image;
 
-  double
-    bias;
+  KernelInfo
+    *curr_kernel;
 
   curr_kernel = (KernelInfo *) kernel;
   bias=0.0;
@@ -4167,7 +4158,7 @@ MagickExport Image *MorphologyImage(const Image *image,
 
       /* Scale kernel according to user wishes */
       artifact = GetImageArtifact(image,"convolve:scale");
-      if ( artifact != (const char *)NULL ) {
+      if ( artifact != (const char *) NULL ) {
         if (IfMagickFalse(IsGeometry(artifact)))
           (void) ThrowMagickException(exception,GetMagickModule(),
                OptionWarning,"InvalidSetting","'%s' '%s'",
@@ -4183,9 +4174,8 @@ MagickExport Image *MorphologyImage(const Image *image,
     }
 
   /* display the (normalized) kernel via stderr */
-  if ( IfStringTrue(GetImageArtifact(image,"showkernel"))
-    || IfStringTrue(GetImageArtifact(image,"convolve:showkernel"))
-    || IfStringTrue(GetImageArtifact(image,"morphology:showkernel")) )
+  artifact=GetImageArtifact(image,"morphology:showkernel");
+  if (IsStringTrue(artifact) != MagickFalse)
     ShowKernelInfo(curr_kernel);
 
   /* Override the default handling of multi-kernel morphology results
@@ -4194,8 +4184,7 @@ MagickExport Image *MorphologyImage(const Image *image,
    * Otherwise merge resulting images using compose method given.
    * Default for 'HitAndMiss' is 'Lighten'.
    */
-  { const char
-      *artifact;
+  {
     ssize_t
       parse;
 
@@ -4603,7 +4592,7 @@ MagickExport void ScaleKernelInfo(KernelInfo *kernel,
   neg_scale = scaling_factor/neg_scale;
 
   for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
-    if ( ! IfNaN(kernel->values[i]) )
+    if (!IsNaN(kernel->values[i]))
       kernel->values[i] *= (kernel->values[i] >= 0) ? pos_scale : neg_scale;
 
   /* convolution output range */
@@ -4639,7 +4628,8 @@ MagickExport void ScaleKernelInfo(KernelInfo *kernel,
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  ShowKernelInfo() outputs the details of the given kernel defination to
-%  standard error, generally due to a users 'showkernel' option request.
+%  standard error, generally due to a users 'morphology:showkernel' option
+%  request.
 %
 %  The format of the ShowKernel method is:
 %
@@ -4686,7 +4676,7 @@ MagickPrivate void ShowKernelInfo(const KernelInfo *kernel)
     for (i=v=0; v < k->height; v++) {
       (void) FormatLocaleFile(stderr, "%2lu:", (unsigned long) v );
       for (u=0; u < k->width; u++, i++)
-        if ( IfNaN(k->values[i]) )
+        if (IsNaN(k->values[i]))
           (void) FormatLocaleFile(stderr," %*s", GetMagickPrecision()+3, "nan");
         else
           (void) FormatLocaleFile(stderr," %*.*lg", GetMagickPrecision()+3,
@@ -4774,12 +4764,12 @@ MagickPrivate void ZeroKernelNans(KernelInfo *kernel)
     i;
 
   /* do the other kernels in a multi-kernel list first */
-  if ( kernel->next != (KernelInfo *) NULL)
+  if (kernel->next != (KernelInfo *) NULL)
     ZeroKernelNans(kernel->next);
 
   for (i=0; i < (kernel->width*kernel->height); i++)
-    if ( IfNaN(kernel->values[i]) )
-      kernel->values[i] = 0.0;
+    if (IsNaN(kernel->values[i]))
+      kernel->values[i]=0.0;
 
   return;
 }