]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/morphology.c
Update web pages
[imagemagick] / MagickCore / morphology.c
index 1174a00fdbf41bfd2938f7d1ab223a3763d0922a..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)
 
@@ -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);
 
@@ -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,14 +483,16 @@ 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;
@@ -505,8 +500,15 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
   if (kernel_string == (const char *) NULL)
     return(ParseKernelArray(kernel_string));
   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 */
@@ -514,7 +516,7 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
       {
         /* tokens starting with alpha is a Named kernel */
         if (isalpha((int) ((unsigned char) *token)) != 0)
-          new_kernel=ParseKernelName(p);
+          new_kernel=ParseKernelName(p,exception);
         else /* otherwise a user defined kernel array */
           new_kernel=ParseKernelArray(p);
 
@@ -539,9 +541,10 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
       break;
     p++;
   }
+  if (kernel_cache != (char *) NULL)
+    kernel_cache=DestroyString(kernel_cache);
   return(kernel);
 }
-
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -946,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;
@@ -966,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 */
@@ -1019,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;
   }
 
@@ -1436,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");
@@ -1742,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;
@@ -1751,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;
@@ -1796,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,-");
@@ -1826,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,-");
@@ -1948,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;
@@ -1959,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)
@@ -1974,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;
@@ -2394,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 )
@@ -2554,43 +2559,39 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     *image_view,
     *morphology_view;
 
-  MagickBooleanType
-    status;
-
-  MagickOffsetType
-    progress;
-
   OffsetInfo
     offset;
 
-  PixelChannel
-    channel[MaxPixelChannels];
-
-  PixelTrait
-    morphology_traits[MaxPixelChannels],
-    traits[MaxPixelChannels];
-
   register ssize_t
     i;
 
+  ssize_t
+    y;
+
   size_t
     *changes,
     changed,
     width;
 
-  ssize_t
-    y;
+  MagickBooleanType
+    status;
+
+  MagickOffsetType
+    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;
   offset.y=0;
   switch (method)
@@ -2619,7 +2620,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     }
     default:
     {
-      assert("not a primitive morphology method" != (char *) NULL);
+      assert("Not a Primitive Morphology Method" != (char *) NULL);
       break;
     }
   }
@@ -2630,31 +2631,26 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   for (i=0; i < (ssize_t) GetOpenMPMaximumThreads(); i++)
     changes[i]=0;
-  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-  {
-    channel[i]=GetPixelChannelChannel(image,i);
-    traits[i]=GetPixelChannelTraits(image,channel[i]);
-    morphology_traits[i]=GetPixelChannelTraits(morphology_image,channel[i]);
-  }
-  image_view=AcquireVirtualCacheView(image,exception);
-  morphology_view=AcquireAuthenticCacheView(morphology_image,exception);
   if ((method == ConvolveMorphology) && (kernel->width == 1))
     {
-      const int
-        id = GetOpenMPThreadId();
-
-      ssize_t
+      register ssize_t
         x;
 
       /*
-        Optimized 1-D vertical (column-based) convolution kernel.
-      */
+        Special handling (for speed) of vertical (blur) kernels.  This performs
+        its handling in columns rather than in rows.  This is only done
+        for convolve as it is the only method that generates very large 1-D
+        vertical kernels (such as a 'BlurKernel')
+     */
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-      #pragma omp parallel for schedule(static,4) shared(progress,status) \
-        magick_threads(image,morphology_image,image->columns,1)
+     #pragma omp parallel for schedule(static,4) shared(progress,status) \
+       magick_threads(image,morphology_image,image->columns,1)
 #endif
       for (x=0; x < (ssize_t) image->columns; x++)
       {
+        const int
+          id = GetOpenMPThreadId();
+
         register const Quantum
           *restrict p;
 
@@ -2681,74 +2677,93 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         center=(ssize_t) GetPixelChannels(image)*offset.y;
         for (y=0; y < (ssize_t) image->rows; y++)
         {
-          double
-            gamma[MaxPixelChannels],
-            pixel[MaxPixelChannels];
+          register ssize_t
+            i;
 
-          register const MagickRealType
-            *restrict k;
+          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+          {
+            double
+              alpha,
+              gamma,
+              pixel;
 
-          register const Quantum
-            *restrict pixels;
+            PixelChannel
+              channel;
 
-          register ssize_t
-            i;
+            PixelTrait
+              morphology_traits,
+              traits;
 
-          size_t
-            count[MaxPixelChannels];
+            register const MagickRealType
+              *restrict k;
 
-          ssize_t
-            v;
+            register const Quantum
+              *restrict pixels;
 
-          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-          {
-            pixel[i]=bias;
-            gamma[i]=0.0;
-            count[i]=0;
-          }
-          pixels=p;
-          k=(&kernel->values[kernel->width*kernel->height-1]);
-          for (v=0; v < (ssize_t) kernel->height; v++)
-          {
             register ssize_t
               u;
 
-            for (u=0; u < (ssize_t) kernel->width; u++)
-            {
-              if (IfNaN(*k) == MagickFalse)
-                for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-                {
-                  double
-                    alpha;
-
-                  alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
-                  if ((traits[i] & BlendPixelTrait) == 0)
-                    alpha=1.0;
-                  pixel[i]+=alpha*(*k)*pixels[i];
-                  gamma[i]+=alpha*(*k);
-                  count[i]++;
-                }
-              k--;
-              pixels+=GetPixelChannels(image);
-            }
-          }
-          for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
-          {
-            if ((traits[i] == UndefinedPixelTrait) ||
-                (morphology_traits[i] == UndefinedPixelTrait))
+            size_t
+              count;
+
+            ssize_t
+              v;
+
+            channel=GetPixelChannelChannel(image,i);
+            traits=GetPixelChannelTraits(image,channel);
+            morphology_traits=GetPixelChannelTraits(morphology_image,channel);
+            if ((traits == UndefinedPixelTrait) ||
+                (morphology_traits == UndefinedPixelTrait))
               continue;
-            if (GetPixelReadMask(image,p+center) == 0)
+            if (((traits & CopyPixelTrait) != 0) ||
+                (GetPixelReadMask(image,p+center) == 0))
               {
-                SetPixelChannel(morphology_image,channel[i],p[center+i],q);
+                SetPixelChannel(morphology_image,channel,p[center+i],q);
                 continue;
               }
-            if (fabs(pixel[i]-p[center+i]) > MagickEpsilon)
+            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++)
+              {
+                for (u=0; u < (ssize_t) kernel->width; u++)
+                {
+                  if (!IsNaN(*k))
+                    {
+                      pixel+=(*k)*pixels[i];
+                      gamma+=(*k);
+                      count++;
+                    }
+                  k--;
+                  pixels+=GetPixelChannels(image);
+                }
+              }
+            else
+              for (v=0; v < (ssize_t) kernel->height; v++)
+              {
+                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[i]=PerceptibleReciprocal(gamma[i]);
-            if (count[i] != 0)
-              gamma[i]*=(double) kernel->height*kernel->width/count[i];
-            SetPixelChannel(morphology_image,channel[i],ClampToQuantum(gamma[i]*
-              pixel[i]),q);
+            gamma=PerceptibleReciprocal(gamma);
+            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);
@@ -2780,7 +2795,6 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
   /*
     Normal handling of horizontal or rectangular kernels (row by row).
   */
-  width=image->columns+kernel->width-1;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
     magick_threads(image,morphology_image,image->rows,1)
@@ -2825,6 +2839,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         double
           alpha,
           gamma,
+          intensity,
           maximum,
           minimum,
           pixel;
@@ -2857,7 +2872,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         if ((traits == UndefinedPixelTrait) ||
             (morphology_traits == UndefinedPixelTrait))
           continue;
-        if (GetPixelReadMask(image,p+center) == 0)
+        if (((traits & CopyPixelTrait) != 0) ||
+            (GetPixelReadMask(image,p+center) == 0))
           {
             SetPixelChannel(morphology_image,channel,p[center+i],q);
             continue;
@@ -2891,23 +2907,24 @@ 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
             */
             k=(&kernel->values[kernel->width*kernel->height-1]);
+            count=0;
             if ((morphology_traits & BlendPixelTrait) == 0)
               {
                 /*
@@ -2917,8 +2934,11 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                 {
                   for (u=0; u < (ssize_t) kernel->width; u++)
                   {
-                    if (IfNaN(*k) == MagickFalse)
-                      pixel+=(*k)*pixels[i];
+                    if (!IsNaN(*k))
+                      {
+                        pixel+=(*k)*pixels[i];
+                        count++;
+                      }
                     k--;
                     pixels+=GetPixelChannels(image);
                   }
@@ -2929,13 +2949,12 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             /*
               Alpha blending.
             */
-            count=0;
             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+=alpha*(*k)*pixels[i];
@@ -2964,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];
@@ -2995,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);
@@ -3030,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)
                       {
@@ -3073,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++;
                   }
@@ -3102,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++;
                   }
@@ -3149,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);
@@ -3237,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;
@@ -3347,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);
@@ -3361,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);
@@ -3378,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);
@@ -3392,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);
@@ -3508,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);
@@ -3519,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;
           }
@@ -3540,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);
@@ -3551,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;
           }
@@ -3647,18 +3665,18 @@ MagickPrivate Image *MorphologyApply(const Image *image,
     changed;        /* number pixels changed by last primitive operation */
 
   char
-    v_info[MaxTextExtent];
+    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) */
@@ -3874,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
@@ -4066,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:
 %
@@ -4100,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;
@@ -4120,7 +4141,7 @@ MagickExport Image *MorphologyImage(const Image *image,
    * This is done BEFORE the ShowKernelInfo() function is called so that
    * users can see the results of the 'option:convolve:scale' option.
    */
-  if ((method == ConvolveMorphology) || (method == CorrelateMorphology)) {
+  if ( method == ConvolveMorphology || method == CorrelateMorphology ) {
       const char
         *artifact;
 
@@ -4137,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'",
@@ -4153,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
@@ -4164,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;
 
@@ -4573,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 */
@@ -4609,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:
 %
@@ -4656,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,
@@ -4744,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;
 }