]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/morphology.c
(no commit message)
[imagemagick] / MagickCore / morphology.c
index 359413f06d1d57a2ecd5a494f47101e3f86956ba..927a7222528d6b5969b0d44b9ee988f81cd40b30 100644 (file)
@@ -17,7 +17,7 @@
 %                               January 2010                                  %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 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  %
@@ -127,7 +127,7 @@ static void
 static inline KernelInfo *LastKernelInfo(KernelInfo *kernel)
 {
   while (kernel->next != (KernelInfo *) NULL)
-    kernel = kernel->next;
+    kernel=kernel->next;
   return(kernel);
 }
 
@@ -323,8 +323,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 +365,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 */
@@ -492,7 +492,6 @@ static KernelInfo *ParseKernelName(const char *kernel_string)
 
 MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
 {
-
   KernelInfo
     *kernel,
     *new_kernel;
@@ -503,48 +502,42 @@ MagickExport KernelInfo *AcquireKernelInfo(const char *kernel_string)
   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' ) {
+  p=kernel_string;
+  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) *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);
-        return((KernelInfo *) NULL);
-      }
+    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)
+          {
+            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++;
-
   }
   return(kernel);
 }
@@ -2270,7 +2263,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);
@@ -2420,10 +2413,12 @@ static void ExpandRotateKernelInfo(KernelInfo *kernel, const double angle)
     *last;
 
   last = kernel;
+DisableMSCWarning(4127)
   while(1) {
+RestoreMSCWarning
     clone = CloneKernelInfo(last);
     RotateKernelInfo(clone, angle);
-    if ( SameKernelInfo(kernel, clone) == MagickTrue )
+    if ( SameKernelInfo(kernel, clone) != MagickFalse )
       break;
     LastKernelInfo(last)->next = clone;
     last = clone;
@@ -2592,6 +2587,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
   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;
   switch (method)
   {
     case ConvolveMorphology:
@@ -2682,6 +2679,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
           {
             double
               alpha,
+              gamma,
               pixel;
 
             PixelChannel
@@ -2700,6 +2698,9 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             register ssize_t
               u;
 
+            size_t
+              count;
+
             ssize_t
               v;
 
@@ -2718,6 +2719,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             k=(&kernel->values[kernel->width*kernel->height-1]);
             pixels=p;
             pixel=bias;
+            count=0;
             if ((morphology_traits & BlendPixelTrait) == 0)
               {
                 /*
@@ -2728,20 +2730,25 @@ 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];
+                      {
+                        pixel+=(*k)*pixels[i];
+                        count++;
+                      }
                     k--;
                     pixels+=GetPixelChannels(image);
                   }
                 }
                 if (fabs(pixel-p[center+i]) > MagickEpsilon)
                   changes[id]++;
-                SetPixelChannel(morphology_image,channel,ClampToQuantum(pixel),
-                  q);
+                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++)
@@ -2750,6 +2757,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   {
                     alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
                     pixel+=(*k)*alpha*pixels[i];
+                    gamma+=(*k)*alpha;
+                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -2757,7 +2766,10 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
             }
             if (fabs(pixel-p[center+i]) > MagickEpsilon)
               changes[id]++;
-            SetPixelChannel(morphology_image,channel,ClampToQuantum(pixel),q);
+            gamma=PerceptibleReciprocal(gamma);
+            gamma*=(double) kernel->height*kernel->width/count;
+            SetPixelChannel(morphology_image,channel,ClampToQuantum(gamma*
+              pixel),q);
           }
           p+=GetPixelChannels(image);
           q+=GetPixelChannels(morphology_image);
@@ -2832,6 +2844,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
       {
         double
           alpha,
+          gamma,
           maximum,
           minimum,
           pixel;
@@ -2852,6 +2865,9 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         register ssize_t
           u;
 
+        size_t
+          count;
+
         ssize_t
           v;
 
@@ -2870,6 +2886,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         pixels=p;
         maximum=0.0;
         minimum=(double) QuantumRange;
+        count=kernel->width*kernel->height;
         switch (method)
         {
           case ConvolveMorphology: pixel=bias; break;
@@ -2887,6 +2904,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
           }
           default: pixel=0; break;
         }
+        gamma=1.0;
         switch (method)
         {
           case ConvolveMorphology:
@@ -2911,6 +2929,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                  http://www.cs.umd.edu/~djacobs/CMSC426/Convolution.pdf
             */
             k=(&kernel->values[kernel->width*kernel->height-1]);
+            count=0;
             if ((morphology_traits & BlendPixelTrait) == 0)
               {
                 /*
@@ -2921,7 +2940,10 @@ 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];
+                      {
+                        pixel+=(*k)*pixels[i];
+                        count++;
+                      }
                     k--;
                     pixels+=GetPixelChannels(image);
                   }
@@ -2940,6 +2962,8 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   {
                     alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
                     pixel+=(*k)*alpha*pixels[i];
+                    gamma+=(*k)*alpha;
+                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -2988,6 +3012,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                added to the real value, this is currently not done, due to the
                nature of the boolean kernels being used.
             */
+            count=0;
             k=(&kernel->values[kernel->width*kernel->height-1]);
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
@@ -2997,6 +3022,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   {
                     if ((double) pixels[i] > pixel)
                       pixel=(double) pixels[i];
+                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -3021,6 +3047,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                cause Thinning/Thicken to not work correctly when used against a
                greyscale image.
             */
+            count=0;
             k=kernel->values;
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
@@ -3039,6 +3066,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                           if ((double) pixels[i] > maximum)
                             maximum=(double) pixels[i];
                         }
+                    count++;
                   }
                 k++;
                 pixels+=GetPixelChannels(image);
@@ -3062,6 +3090,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
 
               The kernel is not reflected for this operation.
             */
+            count=0;
             k=kernel->values;
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
@@ -3074,6 +3103,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                         pixel=(double) pixels[i];
                         minimum=GetPixelIntensity(image,pixels);
                       }
+                    count++;
                   }
                 k++;
                 pixels+=GetPixelChannels(image);
@@ -3089,6 +3119,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
 
               The kernel is not reflected for this operation.
             */
+            count=0;
             k=(&kernel->values[kernel->width*kernel->height-1]);
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
@@ -3101,6 +3132,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                         pixel=(double) pixels[i];
                         maximum=GetPixelIntensity(image,pixels);
                       }
+                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -3134,6 +3166,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                GrayErode, but with negative kernel values, and kernel rotation
                applied.
             */
+            count=0;
             k=(&kernel->values[kernel->width*kernel->height-1]);
             for (v=0; v < (ssize_t) kernel->height; v++)
             {
@@ -3143,6 +3176,7 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
                   {
                     if ((pixels[i]+(*k)) < pixel)
                       pixel=(double) pixels[i]+(*k);
+                    count++;
                   }
                 k--;
                 pixels+=GetPixelChannels(image);
@@ -3157,7 +3191,9 @@ static ssize_t MorphologyPrimitive(const Image *image,Image *morphology_image,
         }
         if (fabs(pixel-p[center+i]) > MagickEpsilon)
           changes[id]++;
-        SetPixelChannel(morphology_image,channel,ClampToQuantum(pixel),q);
+        gamma=PerceptibleReciprocal(gamma);
+        gamma*=(double) kernel->height*kernel->width/count;
+        SetPixelChannel(morphology_image,channel,ClampToQuantum(gamma*pixel),q);
       }
       p+=GetPixelChannels(image);
       q+=GetPixelChannels(morphology_image);
@@ -3633,7 +3669,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
     changed;        /* number pixels changed by last primitive operation */
 
   char
-    v_info[80];
+    v_info[MaxTextExtent];
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -3650,7 +3686,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
   if ( iterations < 0 )  /* negative interations = infinite (well alomst) */
      kernel_limit = image->columns>image->rows ? image->columns : image->rows;
 
-  verbose = IsStringTrue(GetImageArtifact(image,"verbose"));
+  verbose = IsStringTrue(GetImageArtifact(image,"debug"));
 
   /* initialise for cleanup */
   curr_image = (Image *) image;
@@ -3700,7 +3736,7 @@ MagickPrivate Image *MorphologyApply(const Image *image,
   /* Apply special methods with special requirments
   ** For example, single run only, or post-processing requirements
   */
-  if ( special == MagickTrue )
+  if ( special != MagickFalse )
     {
       rslt_image=CloneImage(image,0,0,MagickTrue,exception);
       if (rslt_image == (Image *) NULL)