]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/segment.c
The 8bim profile will be updated when the iptc profile is changed.
[imagemagick] / MagickCore / segment.c
index 9314e7a51cb360a054058b32bfe190e04943e670..771eb113261f851f50292b006ea17f2d0e68d37d 100644 (file)
 %    MagickCore Methods to Segment an Image with Thresholding Fuzzy c-Means   %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                April 1993                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2012 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  %
@@ -96,6 +96,7 @@
 #include "MagickCore/monitor.h"
 #include "MagickCore/monitor-private.h"
 #include "MagickCore/pixel-accessor.h"
+#include "MagickCore/pixel-private.h"
 #include "MagickCore/quantize.h"
 #include "MagickCore/quantum.h"
 #include "MagickCore/quantum-private.h"
 */
 typedef struct _ExtentPacket
 {
-  MagickRealType
+  double
     center;
 
   ssize_t
@@ -149,14 +150,14 @@ typedef struct _Cluster
 
 typedef struct _IntervalTree
 {
-  MagickRealType
+  double
     tau;
 
   ssize_t
     left,
     right;
 
-  MagickRealType
+  double
     mean_stability,
     stability;
 
@@ -167,7 +168,7 @@ typedef struct _IntervalTree
 
 typedef struct _ZeroCrossing
 {
-  MagickRealType
+  double
     tau,
     histogram[256];
 
@@ -188,7 +189,7 @@ static const int
 /*
   Method prototypes.
 */
-static MagickRealType
+static double
   OptimalTau(const ssize_t *,const double,const double,const double,
     const double,short *);
 
@@ -197,8 +198,8 @@ static ssize_t
 
 static void
   InitializeHistogram(const Image *,ssize_t **,ExceptionInfo *),
-  ScaleSpace(const ssize_t *,const MagickRealType,MagickRealType *),
-  ZeroCrossHistogram(MagickRealType *,const MagickRealType,short *);
+  ScaleSpace(const ssize_t *,const double,double *),
+  ZeroCrossHistogram(double *,const double,short *);
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -218,8 +219,8 @@ static void
 %  The format of the Classify method is:
 %
 %      MagickBooleanType Classify(Image *image,short **extrema,
-%        const MagickRealType cluster_threshold,
-%        const MagickRealType weighting_exponent,
+%        const double cluster_threshold,
+%        const double weighting_exponent,
 %        const MagickBooleanType verbose,ExceptionInfo *exception)
 %
 %  A description of each parameter follows.
@@ -230,7 +231,7 @@ static void
 %      represent the peaks and valleys of the histogram for each color
 %      component.
 %
-%    o cluster_threshold:  This MagickRealType represents the minimum number of
+%    o cluster_threshold:  This double represents the minimum number of
 %      pixels contained in a hexahedra before it can be considered valid
 %      (expressed as a percentage).
 %
@@ -243,8 +244,8 @@ static void
 %
 */
 static MagickBooleanType Classify(Image *image,short **extrema,
-  const MagickRealType cluster_threshold,
-  const MagickRealType weighting_exponent,const MagickBooleanType verbose,
+  const double cluster_threshold,
+  const double weighting_exponent,const MagickBooleanType verbose,
   ExceptionInfo *exception)
 {
 #define SegmentImageTag  "Segment/Image"
@@ -266,7 +267,7 @@ static MagickBooleanType Classify(Image *image,short **extrema,
   MagickOffsetType
     progress;
 
-  MagickRealType
+  double
     *free_squares;
 
   MagickStatusType
@@ -275,7 +276,7 @@ static MagickBooleanType Classify(Image *image,short **extrema,
   register ssize_t
     i;
 
-  register MagickRealType
+  register double
     *squares;
 
   size_t
@@ -386,11 +387,11 @@ static MagickBooleanType Classify(Image *image,short **extrema,
               Count this pixel.
             */
             count++;
-            cluster->red.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->red.center+=(double) ScaleQuantumToChar(
               GetPixelRed(image,p));
-            cluster->green.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->green.center+=(double) ScaleQuantumToChar(
               GetPixelGreen(image,p));
-            cluster->blue.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->blue.center+=(double) ScaleQuantumToChar(
               GetPixelBlue(image,p));
             cluster->count++;
             break;
@@ -503,13 +504,13 @@ static MagickBooleanType Classify(Image *image,short **extrema,
   /*
     Speed up distance calculations.
   */
-  squares=(MagickRealType *) AcquireQuantumMemory(513UL,sizeof(*squares));
-  if (squares == (MagickRealType *) NULL)
+  squares=(double *) AcquireQuantumMemory(513UL,sizeof(*squares));
+  if (squares == (double *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
       image->filename);
   squares+=255;
   for (i=(-255); i <= 255; i++)
-    squares[i]=(MagickRealType) i*(MagickRealType) i;
+    squares[i]=(double) i*(double) i;
   /*
     Allocate image colormap.
   */
@@ -533,7 +534,7 @@ static MagickBooleanType Classify(Image *image,short **extrema,
   image_view=AcquireAuthenticCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(progress,status) \
-    IsConcurrentDos(image->columns,image->rows,64)
+    magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
   {
@@ -584,7 +585,7 @@ static MagickBooleanType Classify(Image *image,short **extrema,
       }
       if (cluster == (Cluster *) NULL)
         {
-          MagickRealType
+          double
             distance_squared,
             local_minima,
             numerator,
@@ -664,7 +665,7 @@ static MagickBooleanType Classify(Image *image,short **extrema,
   }
   squares-=255;
   free_squares=squares;
-  free_squares=(MagickRealType *) RelinquishMagickMemory(free_squares);
+  free_squares=(double *) RelinquishMagickMemory(free_squares);
   return(MagickTrue);
 }
 \f
@@ -877,21 +878,21 @@ static ssize_t DefineRegion(const short *extrema,ExtentPacket *extents)
 %
 %  The format of the DerivativeHistogram method is:
 %
-%      DerivativeHistogram(const MagickRealType *histogram,
-%        MagickRealType *derivative)
+%      DerivativeHistogram(const double *histogram,
+%        double *derivative)
 %
 %  A description of each parameter follows.
 %
-%    o histogram: Specifies an array of MagickRealTypes representing the number
+%    o histogram: Specifies an array of doubles representing the number
 %      of pixels for each intensity of a particular color component.
 %
-%    o derivative: This array of MagickRealTypes is initialized by
+%    o derivative: This array of doubles is initialized by
 %      DerivativeHistogram to the derivative of the histogram using central
 %      differencing.
 %
 */
-static void DerivativeHistogram(const MagickRealType *histogram,
-  MagickRealType *derivative)
+static void DerivativeHistogram(const double *histogram,
+  double *derivative)
 {
   register ssize_t
     i,
@@ -934,7 +935,7 @@ static void DerivativeHistogram(const MagickRealType *histogram,
 %
 %    o image: the image.
 %
-%    o cluster_threshold:  This MagickRealType represents the minimum number of
+%    o cluster_threshold:  This double represents the minimum number of
 %      pixels contained in a hexahedra before it can be considered valid
 %      (expressed as a percentage).
 %
@@ -967,7 +968,7 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
   MagickBooleanType
     proceed;
 
-  MagickRealType
+  double
     threshold;
 
   register const Quantum
@@ -1005,7 +1006,7 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
           histogram[i]=(ssize_t *) RelinquishMagickMemory(histogram[i]);
         }
         (void) ThrowMagickException(exception,GetMagickModule(),
-          ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
+          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
         return(MagickFalse);
       }
   }
@@ -1052,7 +1053,7 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
         if (cluster == (Cluster *) NULL)
           {
             (void) ThrowMagickException(exception,GetMagickModule(),
-              ResourceLimitError,"MemoryAllocationFailed","'%s'",
+              ResourceLimitError,"MemoryAllocationFailed","`%s'",
               image->filename);
             return(MagickFalse);
           }
@@ -1076,7 +1077,7 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
       if (cluster == (Cluster *) NULL)
         {
           (void) ThrowMagickException(exception,GetMagickModule(),
-            ResourceLimitError,"MemoryAllocationFailed","'%s'",image->filename);
+            ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
           return(MagickFalse);
         }
       /*
@@ -1118,11 +1119,11 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
               Count this pixel.
             */
             count++;
-            cluster->red.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->red.center+=(double) ScaleQuantumToChar(
               GetPixelRed(image,p));
-            cluster->green.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->green.center+=(double) ScaleQuantumToChar(
               GetPixelGreen(image,p));
-            cluster->blue.center+=(MagickRealType) ScaleQuantumToChar(
+            cluster->blue.center+=(double) ScaleQuantumToChar(
               GetPixelBlue(image,p));
             cluster->count++;
             break;
@@ -1185,15 +1186,18 @@ MagickExport MagickBooleanType GetImageDynamicThreshold(const Image *image,
         cluster=cluster->next;
       }
     }
-  threshold=(background->red.center+object->red.center)/2.0;
-  pixel->red=(MagickRealType) ScaleCharToQuantum((unsigned char)
-    (threshold+0.5));
-  threshold=(background->green.center+object->green.center)/2.0;
-  pixel->green=(MagickRealType) ScaleCharToQuantum((unsigned char)
-    (threshold+0.5));
-  threshold=(background->blue.center+object->blue.center)/2.0;
-  pixel->blue=(MagickRealType) ScaleCharToQuantum((unsigned char)
-    (threshold+0.5));
+  if (background != (Cluster *) NULL)
+    {
+      threshold=(background->red.center+object->red.center)/2.0;
+      pixel->red=(double) ScaleCharToQuantum((unsigned char)
+        (threshold+0.5));
+      threshold=(background->green.center+object->green.center)/2.0;
+      pixel->green=(double) ScaleCharToQuantum((unsigned char)
+        (threshold+0.5));
+      threshold=(background->blue.center+object->blue.center)/2.0;
+      pixel->blue=(double) ScaleCharToQuantum((unsigned char)
+        (threshold+0.5));
+    }
   /*
     Relinquish resources.
   */
@@ -1326,7 +1330,7 @@ static void MeanStability(IntervalTree *node)
       register ssize_t
         count;
 
-      register MagickRealType
+      register double
         sum;
 
       sum=0.0;
@@ -1336,7 +1340,7 @@ static void MeanStability(IntervalTree *node)
         sum+=child->stability;
         count++;
       }
-      node->mean_stability=sum/(MagickRealType) count;
+      node->mean_stability=sum/(double) count;
     }
   MeanStability(node->sibling);
   MeanStability(node->child);
@@ -1464,7 +1468,7 @@ static IntervalTree *InitializeIntervalTree(const ZeroCrossing *zero_crossing,
 %
 %  The format of the OptimalTau method is:
 %
-%    MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
+%    double OptimalTau(const ssize_t *histogram,const double max_tau,
 %      const double min_tau,const double delta_tau,
 %      const double smooth_threshold,short *extrema)
 %
@@ -1505,7 +1509,7 @@ static void FreeNodes(IntervalTree *node)
   node=(IntervalTree *) RelinquishMagickMemory(node);
 }
 
-static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
+static double OptimalTau(const ssize_t *histogram,const double max_tau,
   const double min_tau,const double delta_tau,const double smooth_threshold,
   short *extrema)
 {
@@ -1517,7 +1521,7 @@ static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
   MagickBooleanType
     peak;
 
-  MagickRealType
+  double
     average_tau,
     *derivative,
     *second_derivative,
@@ -1561,11 +1565,11 @@ static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
   /*
     Initialize zero crossing list.
   */
-  derivative=(MagickRealType *) AcquireQuantumMemory(256,sizeof(*derivative));
-  second_derivative=(MagickRealType *) AcquireQuantumMemory(256,
+  derivative=(double *) AcquireQuantumMemory(256,sizeof(*derivative));
+  second_derivative=(double *) AcquireQuantumMemory(256,
     sizeof(*second_derivative));
-  if ((derivative == (MagickRealType *) NULL) ||
-      (second_derivative == (MagickRealType *) NULL))
+  if ((derivative == (double *) NULL) ||
+      (second_derivative == (double *) NULL))
     ThrowFatalException(ResourceLimitFatalError,
       "UnableToAllocateDerivatives");
   i=0;
@@ -1584,14 +1588,14 @@ static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
   */
   zero_crossing[i].tau=0.0;
   for (j=0; j <= 255; j++)
-    zero_crossing[i].histogram[j]=(MagickRealType) histogram[j];
+    zero_crossing[i].histogram[j]=(double) histogram[j];
   DerivativeHistogram(zero_crossing[i].histogram,derivative);
   DerivativeHistogram(derivative,second_derivative);
   ZeroCrossHistogram(second_derivative,smooth_threshold,
     zero_crossing[i].crossings);
   number_crossings=(size_t) i;
-  derivative=(MagickRealType *) RelinquishMagickMemory(derivative);
-  second_derivative=(MagickRealType *)
+  derivative=(double *) RelinquishMagickMemory(derivative);
+  second_derivative=(double *)
     RelinquishMagickMemory(second_derivative);
   /*
     Ensure the scale-space fingerprints form lines in scale-space, not loops.
@@ -1678,7 +1682,7 @@ static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
   average_tau=0.0;
   for (i=0; i < number_nodes; i++)
     average_tau+=list[i]->tau;
-  average_tau/=(MagickRealType) number_nodes;
+  average_tau/=(double) number_nodes;
   /*
     Relinquish resources.
   */
@@ -1703,20 +1707,20 @@ static MagickRealType OptimalTau(const ssize_t *histogram,const double max_tau,
 %
 %  The format of the ScaleSpace method is:
 %
-%      ScaleSpace(const ssize_t *histogram,const MagickRealType tau,
-%        MagickRealType *scale_histogram)
+%      ScaleSpace(const ssize_t *histogram,const double tau,
+%        double *scale_histogram)
 %
 %  A description of each parameter follows.
 %
-%    o histogram: Specifies an array of MagickRealTypes representing the number
+%    o histogram: Specifies an array of doubles representing the number
 %      of pixels for each intensity of a particular color component.
 %
 */
 
-static void ScaleSpace(const ssize_t *histogram,const MagickRealType tau,
-  MagickRealType *scale_histogram)
+static void ScaleSpace(const ssize_t *histogram,const double tau,
+  double *scale_histogram)
 {
-  MagickRealType
+  double
     alpha,
     beta,
     *gamma,
@@ -1726,12 +1730,12 @@ static void ScaleSpace(const ssize_t *histogram,const MagickRealType tau,
     u,
     x;
 
-  gamma=(MagickRealType *) AcquireQuantumMemory(256,sizeof(*gamma));
-  if (gamma == (MagickRealType *) NULL)
+  gamma=(double *) AcquireQuantumMemory(256,sizeof(*gamma));
+  if (gamma == (double *) NULL)
     ThrowFatalException(ResourceLimitFatalError,
       "UnableToAllocateGammaMap");
-  alpha=1.0/(tau*sqrt(2.0*MagickPI));
-  beta=(-1.0/(2.0*tau*tau));
+  alpha=PerceptibleReciprocal(tau*sqrt(2.0*MagickPI));
+  beta=(-1.0*PerceptibleReciprocal(2.0*tau*tau));
   for (x=0; x <= 255; x++)
     gamma[x]=0.0;
   for (x=0; x <= 255; x++)
@@ -1744,10 +1748,10 @@ static void ScaleSpace(const ssize_t *histogram,const MagickRealType tau,
   {
     sum=0.0;
     for (u=0; u <= 255; u++)
-      sum+=(MagickRealType) histogram[u]*gamma[MagickAbsoluteValue(x-u)];
+      sum+=(double) histogram[u]*gamma[MagickAbsoluteValue(x-u)];
     scale_histogram[x]=alpha*sum;
   }
-  gamma=(MagickRealType *) RelinquishMagickMemory(gamma);
+  gamma=(double *) RelinquishMagickMemory(gamma);
 }
 \f
 /*
@@ -1797,6 +1801,9 @@ MagickExport MagickBooleanType SegmentImage(Image *image,
   const double cluster_threshold,const double smooth_threshold,
   ExceptionInfo *exception)
 {
+  ColorspaceType
+    previous_colorspace;
+
   MagickBooleanType
     status;
 
@@ -1831,11 +1838,11 @@ MagickExport MagickBooleanType SegmentImage(Image *image,
           image->filename)
       }
   }
-  if (IssRGBColorspace(colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,colorspace,exception);
   /*
     Initialize histogram.
   */
+  previous_colorspace=image->colorspace;
+  (void) TransformImageColorspace(image,colorspace,exception);
   InitializeHistogram(image,histogram,exception);
   (void) OptimalTau(histogram[Red],Tau,0.2,DeltaTau,
     smooth_threshold == 0.0 ? 1.0 : smooth_threshold,extrema[Red]);
@@ -1848,8 +1855,7 @@ MagickExport MagickBooleanType SegmentImage(Image *image,
   */
   status=Classify(image,extrema,cluster_threshold,WeightingExponent,verbose,
     exception);
-  if (IssRGBColorspace(colorspace) == MagickFalse)
-    (void) TransformImageColorspace(image,colorspace,exception);
+  (void) TransformImageColorspace(image,previous_colorspace,exception);
   /*
     Relinquish resources.
   */
@@ -1878,12 +1884,12 @@ MagickExport MagickBooleanType SegmentImage(Image *image,
 %
 %  The format of the ZeroCrossHistogram method is:
 %
-%      ZeroCrossHistogram(MagickRealType *second_derivative,
-%        const MagickRealType smooth_threshold,short *crossings)
+%      ZeroCrossHistogram(double *second_derivative,
+%        const double smooth_threshold,short *crossings)
 %
 %  A description of each parameter follows.
 %
-%    o second_derivative: Specifies an array of MagickRealTypes representing the
+%    o second_derivative: Specifies an array of doubles representing the
 %      second derivative of the histogram of a particular color component.
 %
 %    o crossings:  This array of integers is initialized with
@@ -1891,8 +1897,8 @@ MagickExport MagickBooleanType SegmentImage(Image *image,
 %      of a particular color component.
 %
 */
-static void ZeroCrossHistogram(MagickRealType *second_derivative,
-  const MagickRealType smooth_threshold,short *crossings)
+static void ZeroCrossHistogram(double *second_derivative,
+  const double smooth_threshold,short *crossings)
 {
   register ssize_t
     i;