]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Tue, 7 Jan 2014 15:09:37 +0000 (15:09 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Tue, 7 Jan 2014 15:09:37 +0000 (15:09 +0000)
MagickCore/identify.c
MagickCore/option.c
MagickCore/statistic.c
MagickCore/statistic.h
MagickWand/identify.c
MagickWand/mogrify.c
MagickWand/operation.c
utilities/identify.1.in

index 3e9f9f11d36a58071f932b9d485fab35b044acdb..9b834b4245f1325bc9ba38877290d71fc98bc87c 100644 (file)
@@ -368,6 +368,32 @@ static ssize_t PrintChannelLocations(FILE *file,const Image *image,
   return(n);
 }
 
+static ssize_t PrintChannelMoments(FILE *file,const PixelChannel channel,
+  const char *name,const ChannelMoments *channel_moments)
+{
+  ssize_t
+    n;
+
+  n=FormatLocaleFile(file,"%s:\n",name);
+  n+=FormatLocaleFile(file,"      i1: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I1);
+  n+=FormatLocaleFile(file,"      i2: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I2);
+  n+=FormatLocaleFile(file,"      i3: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I3);
+  n+=FormatLocaleFile(file,"      i4: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I4);
+  n+=FormatLocaleFile(file,"      i5: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I5);
+  n+=FormatLocaleFile(file,"      i6: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I6);
+  n+=FormatLocaleFile(file,"      i7: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I7);
+  n+=FormatLocaleFile(file,"      i8: %.*g",GetMagickPrecision(),
+    channel_moments[channel].I8);
+  return(n);
+}
+
 static ssize_t PrintChannelStatistics(FILE *file,const PixelChannel channel,
   const char *name,const double scale,
   const ChannelStatistics *channel_statistics)
@@ -403,6 +429,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   ChannelFeatures
     *channel_features;
 
+  ChannelMoments
+    *channel_moments;
+
   ChannelStatistics
     *channel_statistics;
 
@@ -650,6 +679,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   (void) FormatLocaleFile(file,"  Colorspace: %s\n",CommandOptionToMnemonic(
     MagickColorspaceOptions,(ssize_t) image->colorspace));
   channel_statistics=(ChannelStatistics *) NULL;
+  channel_moments=(ChannelMoments *) NULL;
   channel_features=(ChannelFeatures *) NULL;
   colorspace=image->colorspace;
   scale=1;
@@ -661,6 +691,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
       channel_statistics=GetImageStatistics(image,exception);
       if (channel_statistics == (ChannelStatistics *) NULL)
         return(MagickFalse);
+      artifact=GetImageArtifact(image,"identify:moments");
+      if (artifact != (const char *) NULL)
+         channel_moments=GetImageMoments(image,exception);
       artifact=GetImageArtifact(image,"identify:features");
       if (artifact != (const char *) NULL)
         {
@@ -766,6 +799,47 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
       channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
         channel_statistics);
     }
+  if (channel_moments != (ChannelMoments *) NULL)
+    {
+      (void) FormatLocaleFile(file,"  Channel moments\n");
+      switch (colorspace)
+      {
+        case RGBColorspace:
+        default:
+        {
+          (void) PrintChannelMoments(file,RedPixelChannel,"Red",
+            channel_moments);
+          (void) PrintChannelMoments(file,GreenPixelChannel,"Green",
+            channel_moments);
+          (void) PrintChannelMoments(file,BluePixelChannel,"Blue",
+            channel_moments);
+          break;
+        }
+        case CMYKColorspace:
+        {
+          (void) PrintChannelMoments(file,CyanPixelChannel,"Cyan",
+            channel_moments);
+          (void) PrintChannelMoments(file,MagentaPixelChannel,"Magenta",
+            channel_moments);
+          (void) PrintChannelMoments(file,YellowPixelChannel,"Yellow",
+            channel_moments);
+          (void) PrintChannelMoments(file,BlackPixelChannel,"Black",
+            channel_moments);
+          break;
+        }
+        case GRAYColorspace:
+        {
+          (void) PrintChannelMoments(file,GrayPixelChannel,"Gray",
+            channel_moments);
+          break;
+        }
+      }
+      if (image->alpha_trait == BlendPixelTrait)
+        (void) PrintChannelMoments(file,AlphaPixelChannel,"Alpha",
+          channel_moments);
+      channel_moments=(ChannelMoments *) RelinquishMagickMemory(
+        channel_moments);
+    }
   if (channel_features != (ChannelFeatures *) NULL)
     {
       (void) FormatLocaleFile(file,"  Channel features (horizontal, vertical, "
index a6de8a8afb9b94282a5d87962a7e864fd714895a..94915a331ec040a624ca3d14da89162244ff83a0 100644 (file)
@@ -509,6 +509,8 @@ static const OptionInfo
     { "-metric", 1L, ListOperatorFlag | FireOptionFlag, MagickFalse },
     { "+minimum", 0L, DeprecateOptionFlag | FireOptionFlag, MagickTrue },
     { "-minimum", 0L, DeprecateOptionFlag | FireOptionFlag, MagickTrue },
+    { "+moments", 0L, SimpleOperatorFlag | FireOptionFlag, MagickFalse },
+    { "-moments", 0L, SimpleOperatorFlag | FireOptionFlag, MagickFalse },
     { "+mode", 1L, NonMagickOptionFlag, MagickFalse },
     { "-mode", 1L, ReplacedOptionFlag | SimpleOperatorFlag, MagickTrue },
     { "+modulate", 1L, DeprecateOptionFlag, MagickTrue },
index 5099b03b1531f22c0539404c3ccbb893214216cc..017b4f6317e183a54319249dc425f41e2317cc64 100644 (file)
@@ -1127,6 +1127,144 @@ MagickExport MagickBooleanType GetImageExtrema(const Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   G e t I m a g e K u r t o s i s                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetImageKurtosis() returns the kurtosis and skewness of one or more image
+%  channels.
+%
+%  The format of the GetImageKurtosis method is:
+%
+%      MagickBooleanType GetImageKurtosis(const Image *image,double *kurtosis,
+%        double *skewness,ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o kurtosis: the kurtosis of the channel.
+%
+%    o skewness: the skewness of the channel.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport MagickBooleanType GetImageKurtosis(const Image *image,
+  double *kurtosis,double *skewness,ExceptionInfo *exception)
+{
+  CacheView
+    *image_view;
+
+  double
+    area,
+    mean,
+    standard_deviation,
+    sum_squares,
+    sum_cubes,
+    sum_fourth_power;
+
+  MagickBooleanType
+    status;
+
+  ssize_t
+    y;
+
+  assert(image != (Image *) NULL);
+  assert(image->signature == MagickSignature);
+  if (image->debug != MagickFalse)
+    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  status=MagickTrue;
+  *kurtosis=0.0;
+  *skewness=0.0;
+  area=0.0;
+  mean=0.0;
+  standard_deviation=0.0;
+  sum_squares=0.0;
+  sum_cubes=0.0;
+  sum_fourth_power=0.0;
+  image_view=AcquireVirtualCacheView(image,exception);
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+  #pragma omp parallel for schedule(static,4) shared(status) \
+    magick_threads(image,image,image->rows,1)
+#endif
+  for (y=0; y < (ssize_t) image->rows; y++)
+  {
+    register const Quantum
+      *restrict p;
+
+    register ssize_t
+      x;
+
+    if (status == MagickFalse)
+      continue;
+    p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
+    if (p == (const Quantum *) NULL)
+      {
+        status=MagickFalse;
+        continue;
+      }
+    for (x=0; x < (ssize_t) image->columns; x++)
+    {
+      register ssize_t
+        i;
+
+      if (GetPixelReadMask(image,p) == 0)
+        {
+          p+=GetPixelChannels(image);
+          continue;
+        }
+      for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
+      {
+        PixelChannel channel=GetPixelChannelChannel(image,i);
+        PixelTrait traits=GetPixelChannelTraits(image,channel);
+        if (traits == UndefinedPixelTrait)
+          continue;
+        if ((traits & UpdatePixelTrait) == 0)
+          continue;
+#if defined(MAGICKCORE_OPENMP_SUPPORT)
+        #pragma omp critical (MagickCore_GetImageKurtosis)
+#endif
+        {
+          mean+=p[i];
+          sum_squares+=(double) p[i]*p[i];
+          sum_cubes+=(double) p[i]*p[i]*p[i];
+          sum_fourth_power+=(double) p[i]*p[i]*p[i]*p[i];
+          area++;
+        }
+      }
+      p+=GetPixelChannels(image);
+    }
+  }
+  image_view=DestroyCacheView(image_view);
+  if (area != 0.0)
+    {
+      mean/=area;
+      sum_squares/=area;
+      sum_cubes/=area;
+      sum_fourth_power/=area;
+    }
+  standard_deviation=sqrt(sum_squares-(mean*mean));
+  if (standard_deviation != 0.0)
+    {
+      *kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares-
+        3.0*mean*mean*mean*mean;
+      *kurtosis/=standard_deviation*standard_deviation*standard_deviation*
+        standard_deviation;
+      *kurtosis-=3.0;
+      *skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean;
+      *skewness/=standard_deviation*standard_deviation*standard_deviation;
+    }
+  return(status);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   G e t I m a g e M e a n                                                   %
 %                                                                             %
 %                                                                             %
@@ -1204,48 +1342,44 @@ MagickExport MagickBooleanType GetImageMean(const Image *image,double *mean,
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   G e t I m a g e K u r t o s i s                                           %
+%   G e t I m a g e M o m e n t s                                             %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  GetImageKurtosis() returns the kurtosis and skewness of one or more image
-%  channels.
+%  GetImageMoments() returns the moments of one or more image channels.
 %
-%  The format of the GetImageKurtosis method is:
+%  The format of the GetImageMoments method is:
 %
-%      MagickBooleanType GetImageKurtosis(const Image *image,double *kurtosis,
-%        double *skewness,ExceptionInfo *exception)
+%      ChannelMoments *GetImageMoments(const Image *image,
+%        ExceptionInfo *exception)
 %
 %  A description of each parameter follows:
 %
 %    o image: the image.
 %
-%    o kurtosis: the kurtosis of the channel.
-%
-%    o skewness: the skewness of the channel.
-%
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport MagickBooleanType GetImageKurtosis(const Image *image,
-  double *kurtosis,double *skewness,ExceptionInfo *exception)
+MagickExport ChannelMoments *GetImageMoments(const Image *image,
+  ExceptionInfo *exception)
 {
+#define MaxNumberImageMoments  8
+
   CacheView
     *image_view;
 
-  double
-    area,
-    mean,
-    standard_deviation,
-    sum_squares,
-    sum_cubes,
-    sum_fourth_power;
+  ChannelMoments
+    *channel_moments;
 
   MagickBooleanType
+    initialize,
     status;
 
+  register ssize_t
+    i;
+
   ssize_t
     y;
 
@@ -1253,18 +1387,27 @@ MagickExport MagickBooleanType GetImageKurtosis(const Image *image,
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+  channel_moments=(ChannelMoments *) AcquireQuantumMemory(MaxPixelChannels+1,
+    sizeof(*channel_moments));
+  if (channel_moments == (ChannelMoments *) NULL)
+    return(channel_moments);
+  (void) ResetMagickMemory(channel_moments,0,length*sizeof(*channel_moments));
+  for (i=0; i <= (ssize_t) MaxPixelChannels; i++)
+  {
+    channel_moments[i].I1=0.0;
+    channel_moments[i].I2=0.0;
+    channel_moments[i].I3=0.0;
+    channel_moments[i].I4=0.0;
+    channel_moments[i].I5=0.0;
+    channel_moments[i].I6=0.0;
+    channel_moments[i].I7=0.0;
+    channel_moments[i].I8=0.0;
+  }
   status=MagickTrue;
-  *kurtosis=0.0;
-  *skewness=0.0;
-  area=0.0;
-  mean=0.0;
-  standard_deviation=0.0;
-  sum_squares=0.0;
-  sum_cubes=0.0;
-  sum_fourth_power=0.0;
+  initialize=MagickTrue;
   image_view=AcquireVirtualCacheView(image,exception);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-  #pragma omp parallel for schedule(static,4) shared(status) \
+  #pragma omp parallel for schedule(static,4) shared(status,initialize) \
     magick_threads(image,image,image->rows,1)
 #endif
   for (y=0; y < (ssize_t) image->rows; y++)
@@ -1302,39 +1445,25 @@ MagickExport MagickBooleanType GetImageKurtosis(const Image *image,
         if ((traits & UpdatePixelTrait) == 0)
           continue;
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
-        #pragma omp critical (MagickCore_GetImageKurtosis)
+        #pragma omp critical (MagickCore_GetImageMoments)
 #endif
         {
-          mean+=p[i];
-          sum_squares+=(double) p[i]*p[i];
-          sum_cubes+=(double) p[i]*p[i]*p[i];
-          sum_fourth_power+=(double) p[i]*p[i]*p[i]*p[i];
-          area++;
+          if (initialize != MagickFalse)
+            {
+              initialize=MagickFalse;
+            }
+          else
+            {
+           }
         }
       }
       p+=GetPixelChannels(image);
     }
   }
   image_view=DestroyCacheView(image_view);
-  if (area != 0.0)
-    {
-      mean/=area;
-      sum_squares/=area;
-      sum_cubes/=area;
-      sum_fourth_power/=area;
-    }
-  standard_deviation=sqrt(sum_squares-(mean*mean));
-  if (standard_deviation != 0.0)
-    {
-      *kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares-
-        3.0*mean*mean*mean*mean;
-      *kurtosis/=standard_deviation*standard_deviation*standard_deviation*
-        standard_deviation;
-      *kurtosis-=3.0;
-      *skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean;
-      *skewness/=standard_deviation*standard_deviation*standard_deviation;
-    }
-  return(status);
+  if (status == MagickFalse)
+    channel_moments=(ChannelMoments *) RelinquishMagickMemory(channel_moments);
+  return(channel_moments);
 }
 \f
 /*
index 6df0cbdb46470192df4a62ff5ca7d5e14874dc99..ab06b366c7dc2c07c493ae82e0cda032473ab528 100644 (file)
@@ -42,6 +42,19 @@ typedef struct _ChannelStatistics
     skewness;
 } ChannelStatistics;
 
+typedef struct _ChannelMoments
+{
+  double
+    I1,
+    I2,
+    I3,
+    I4,
+    I5,
+    I6,
+    I7,
+    I8;
+} ChannelMoments;
+
 typedef enum
 {
   UndefinedEvaluateOperator,
@@ -103,6 +116,9 @@ typedef enum
 extern MagickExport ChannelStatistics
   *GetImageStatistics(const Image *,ExceptionInfo *);
 
+extern MagickExport ChannelMoments
+  *GetImageMoments(const Image *,ExceptionInfo *);
+
 extern MagickExport Image
   *EvaluateImages(const Image *,const MagickEvaluateOperator,ExceptionInfo *),
   *PolynomialImage(const Image *,const size_t,const double *,ExceptionInfo *),
index 29797ddd59bc545712c69e97803ebb9fe2fb2f86..1d53822a39b21c1b446f548462e37916ce5ae2d8 100644 (file)
@@ -139,6 +139,7 @@ static MagickBooleanType IdentifyUsage(void)
       "-limit type value    pixel cache resource limit",
       "-mask filename       associate a mask with the image",
       "-matte               store matte channel if the image has one",
+      "-moments             report image moments",
       "-monitor             monitor progress",
       "-ping                efficiently determine image attributes",
       "-precision value     maximum number of significant digits to print",
index 7f984f8aa1f487af40cabfa48256659d0e3101ac..0824eb0fa16281fb4e2fd804118035787b9e162d 100644 (file)
@@ -2091,6 +2091,16 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc,
             (void) ModulateImage(*image,argv[i+1],exception);
             break;
           }
+        if (LocaleCompare("moments",option+1) == 0)
+          {
+            if (*option == '+')
+              {
+                (void) DeleteImageArtifact(*image,"identify:moments");
+                break;
+              }
+            (void) SetImageArtifact(*image,"identify:moments",argv[i+1]);
+            break;
+          }
         if (LocaleCompare("monitor",option+1) == 0)
           {
             if (*option == '+')
index 2037de6315e8f878e02a104193875cd8e6250100..90518de655a3d0bce80b2eb1a00beef89a9ef208 100644 (file)
@@ -1112,6 +1112,14 @@ WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand,
           (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
           break;
         }
+      if (LocaleCompare("moments",option+1) == 0)
+        {
+          (void) SetImageOption(_image_info,"identify:moments",
+            ArgBooleanString);
+          if (IfSetOption)
+            (void) SetImageArtifact(_image,"verbose","true");
+          break;
+        }
       if (LocaleCompare("monitor",option+1) == 0)
         {
           (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
index 2f531fbf2c8542886b4730d5314123237c139cd5..6aba2ef6723fb0dce43a16fdd51f733045d51951 100644 (file)
@@ -38,6 +38,7 @@ Image Settings:
                        Resource, or Type
   \-mask filename       associate a mask with the image
   \-matte               store matte channel if the image has one
+  \-moments             report image moments
   \-monitor             monitor progress
   \-ping                efficiently determine image attributes
   \-precision value     maximum number of significant digits to print