]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/identify.c
(no commit message)
[imagemagick] / MagickCore / identify.c
index 8d57509abf650c0c68935441d376097b67ea2470..0c9c0095df3150aaa562f9f4da81b4bc090f88f5 100644 (file)
@@ -349,8 +349,11 @@ static ssize_t PrintChannelLocations(FILE *file,const Image *image,
 }
 
 static ssize_t PrintChannelMoments(FILE *file,const PixelChannel channel,
-  const char *name,const ChannelMoments *channel_moments)
+  const char *name,const double scale,const ChannelMoments *channel_moments)
 {
+  double
+    powers[8] = { 1.0, 2.0, 3.0, 3.0, 6.0, 4.0, 6.0, 4.0 };
+
   register ssize_t
     i;
 
@@ -368,11 +371,31 @@ static ssize_t PrintChannelMoments(FILE *file,const PixelChannel channel,
     GetMagickPrecision(),channel_moments[channel].ellipse_angle);
   n+=FormatLocaleFile(file,"      Ellipse eccentricity: %.*g\n",
     GetMagickPrecision(),channel_moments[channel].ellipse_eccentricity);
-  n+=FormatLocaleFile(file,"      Ellipse intensity: %.*g\n",
-    GetMagickPrecision(),channel_moments[channel].ellipse_intensity);
+  n+=FormatLocaleFile(file,"      Ellipse intensity: %.*g (%.*g)\n",
+    GetMagickPrecision(),pow(scale,powers[0])*
+    channel_moments[channel].ellipse_intensity,GetMagickPrecision(),
+    channel_moments[channel].ellipse_intensity);
   for (i=0; i < 8; i++)
-    n+=FormatLocaleFile(file,"      I%.20g: %.*g\n",i+1.0,GetMagickPrecision(),
-      channel_moments[channel].I[i]);
+    n+=FormatLocaleFile(file,"      I%.20g: %.*g (%.*g)\n",i+1.0,
+      GetMagickPrecision(),channel_moments[channel].I[i]/pow(scale,powers[i]),
+      GetMagickPrecision(),channel_moments[channel].I[i]);
+  return(n);
+}
+
+static ssize_t PrintChannelPerceptualHash(FILE *file,const ChannelType channel,
+  const char *name,const ChannelPerceptualHash *channel_phash)
+{
+  register ssize_t
+    i;
+
+  ssize_t
+    n;
+
+  n=FormatLocaleFile(file,"    %s:\n",name);
+  for (i=0; i < 7; i++)
+    n+=FormatLocaleFile(file,"      PH%.20g: %.*g, %.*g\n",i+1.0,
+      GetMagickPrecision(),channel_phash[channel].P[i],
+      GetMagickPrecision(),channel_phash[channel].Q[i]);
   return(n);
 }
 
@@ -414,6 +437,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   ChannelMoments
     *channel_moments;
 
+  ChannelPerceptualHash
+    *channel_phash;
+
   ChannelStatistics
     *channel_statistics;
 
@@ -433,6 +459,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
 
   double
     elapsed_time,
+    scale,
     user_time;
 
   ImageType
@@ -449,8 +476,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
     x;
 
   size_t
-    distance,
-    scale;
+    distance;
 
   ssize_t
     y;
@@ -461,6 +487,73 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   if (file == (FILE *) NULL)
     file=stdout;
+  locate=GetImageArtifact(image,"identify:locate");
+  if (locate != (const char *) NULL)
+    {
+      const char
+        *limit;
+
+      size_t
+        max_locations;
+
+      StatisticType
+        type;
+
+      /*
+        Display minimum, maximum, or mean pixel locations.
+      */
+      type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
+        MagickFalse,locate);
+      limit=GetImageArtifact(image,"identify:limit");
+      max_locations=0;
+      if (limit != (const char *) NULL)
+        max_locations=StringToUnsignedLong(limit);
+      channel_statistics=GetLocationStatistics(image,type,exception);
+      if (channel_statistics == (ChannelStatistics *) NULL)
+        return(MagickFalse);
+      colorspace=image->colorspace;
+      if (IsImageGray(image,exception) != MagickFalse)
+        colorspace=GRAYColorspace;
+      (void) FormatLocaleFile(file,"Channel %s locations:\n",locate);
+      switch (colorspace)
+      {
+        case RGBColorspace:
+        default:
+        {
+          (void) PrintChannelLocations(file,image,RedPixelChannel,"Red",
+            type,max_locations,channel_statistics);
+          (void) PrintChannelLocations(file,image,GreenPixelChannel,"Green",
+            type,max_locations,channel_statistics);
+          (void) PrintChannelLocations(file,image,BluePixelChannel,"Blue",
+            type,max_locations,channel_statistics);
+          break;
+        }
+        case CMYKColorspace:
+        {
+          (void) PrintChannelLocations(file,image,CyanPixelChannel,"Cyan",
+            type,max_locations,channel_statistics);
+          (void) PrintChannelLocations(file,image,MagentaPixelChannel,"Magenta",
+            type,max_locations,channel_statistics);
+          (void) PrintChannelLocations(file,image,YellowPixelChannel,"Yellow",
+            type,max_locations,channel_statistics);
+          (void) PrintChannelLocations(file,image,BlackPixelChannel,"Black",
+            type,max_locations,channel_statistics);
+          break;
+        }
+        case GRAYColorspace:
+        {
+          (void) PrintChannelLocations(file,image,GrayPixelChannel,"Gray",
+            type,max_locations,channel_statistics);
+          break;
+        }
+      }
+      if (image->alpha_trait == BlendPixelTrait)
+        (void) PrintChannelLocations(file,image,AlphaPixelChannel,"Alpha",
+          type,max_locations,channel_statistics);
+      channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
+        channel_statistics);
+      return(ferror(file) != 0 ? MagickFalse : MagickTrue);
+    }
   *format='\0';
   elapsed_time=GetElapsedTime(&image->timer);
   user_time=GetUserTime(&image->timer);
@@ -588,72 +681,6 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
       MagickTypeOptions,(ssize_t) image->type));
   (void) FormatLocaleFile(file,"  Endianess: %s\n",CommandOptionToMnemonic(
     MagickEndianOptions,(ssize_t) image->endian));
-  locate=GetImageArtifact(image,"identify:locate");
-  if (locate != (const char *) NULL)
-    {
-      const char
-        *limit;
-
-      size_t
-        max_locations;
-
-      StatisticType
-        type;
-
-      /*
-        Display minimum, maximum, or mean pixel locations.
-      */
-      type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
-        MagickFalse,locate);
-      limit=GetImageArtifact(image,"identify:limit");
-      max_locations=0;
-      if (limit != (const char *) NULL)
-        max_locations=StringToUnsignedLong(limit);
-      channel_statistics=GetLocationStatistics(image,type,exception);
-      if (channel_statistics == (ChannelStatistics *) NULL)
-        return(MagickFalse);
-      colorspace=image->colorspace;
-      if (IsImageGray(image,exception) != MagickFalse)
-        colorspace=GRAYColorspace;
-      (void) FormatLocaleFile(file,"Channel %s locations:\n",locate);
-      switch (colorspace)
-      {
-        case RGBColorspace:
-        default:
-        {
-          (void) PrintChannelLocations(file,image,RedPixelChannel,"Red",
-            type,max_locations,channel_statistics);
-          (void) PrintChannelLocations(file,image,GreenPixelChannel,"Green",
-            type,max_locations,channel_statistics);
-          (void) PrintChannelLocations(file,image,BluePixelChannel,"Blue",
-            type,max_locations,channel_statistics);
-          break;
-        }
-        case CMYKColorspace:
-        {
-          (void) PrintChannelLocations(file,image,CyanPixelChannel,"Cyan",
-            type,max_locations,channel_statistics);
-          (void) PrintChannelLocations(file,image,MagentaPixelChannel,"Magenta",
-            type,max_locations,channel_statistics);
-          (void) PrintChannelLocations(file,image,YellowPixelChannel,"Yellow",
-            type,max_locations,channel_statistics);
-          (void) PrintChannelLocations(file,image,BlackPixelChannel,"Black",
-            type,max_locations,channel_statistics);
-          break;
-        }
-        case GRAYColorspace:
-        {
-          (void) PrintChannelLocations(file,image,GrayPixelChannel,"Gray",
-            type,max_locations,channel_statistics);
-          break;
-        }
-      }
-      if (image->alpha_trait == BlendPixelTrait)
-        (void) PrintChannelLocations(file,image,AlphaPixelChannel,"Alpha",
-          type,max_locations,channel_statistics);
-      channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
-        channel_statistics);
-    }
   /*
     Detail channel depth and extrema.
   */
@@ -661,9 +688,10 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
     MagickColorspaceOptions,(ssize_t) image->colorspace));
   channel_statistics=(ChannelStatistics *) NULL;
   channel_moments=(ChannelMoments *) NULL;
+  channel_phash=(ChannelPerceptualHash *) NULL;
   channel_features=(ChannelFeatures *) NULL;
   colorspace=image->colorspace;
-  scale=1;
+  scale=1.0;
   if (ping == MagickFalse)
     {
       size_t
@@ -674,7 +702,10 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
         return(MagickFalse);
       artifact=GetImageArtifact(image,"identify:moments");
       if (artifact != (const char *) NULL)
-         channel_moments=GetImageMoments(image,exception);
+        {
+          channel_moments=GetImageMoments(image,exception);
+          channel_phash=GetImagePerceptualHash(image,exception);
+        }
       artifact=GetImageArtifact(image,"identify:features");
       if (artifact != (const char *) NULL)
         {
@@ -726,9 +757,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
       if (image->alpha_trait == BlendPixelTrait)
         (void) FormatLocaleFile(file,"    alpha: %.20g-bit\n",(double)
           channel_statistics[AlphaPixelChannel].depth);
-      scale=1;
+      scale=1.0;
       if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
-        scale=QuantumRange/((size_t) QuantumRange >> ((size_t)
+        scale=(double) QuantumRange/((size_t) QuantumRange >> ((size_t)
           MAGICKCORE_QUANTUM_DEPTH-image->depth));
     }
   if (channel_statistics != (ChannelStatistics *) NULL)
@@ -782,51 +813,67 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
     }
   if (channel_moments != (ChannelMoments *) NULL)
     {
+      scale=(double) ((1UL << image->depth)-1);
       (void) FormatLocaleFile(file,"  Channel moments:\n");
       switch (colorspace)
       {
         case RGBColorspace:
         default:
         {
-          (void) PrintChannelMoments(file,RedPixelChannel,"Red",
+          (void) PrintChannelMoments(file,RedPixelChannel,"Red",scale,
             channel_moments);
-          (void) PrintChannelMoments(file,GreenPixelChannel,"Green",
+          (void) PrintChannelMoments(file,GreenPixelChannel,"Green",scale,
             channel_moments);
-          (void) PrintChannelMoments(file,BluePixelChannel,"Blue",
+          (void) PrintChannelMoments(file,BluePixelChannel,"Blue",scale,
             channel_moments);
           break;
         }
         case CMYKColorspace:
         {
-          (void) PrintChannelMoments(file,CyanPixelChannel,"Cyan",
+          (void) PrintChannelMoments(file,CyanPixelChannel,"Cyan",scale,
             channel_moments);
-          (void) PrintChannelMoments(file,MagentaPixelChannel,"Magenta",
+          (void) PrintChannelMoments(file,MagentaPixelChannel,"Magenta",scale,
             channel_moments);
-          (void) PrintChannelMoments(file,YellowPixelChannel,"Yellow",
+          (void) PrintChannelMoments(file,YellowPixelChannel,"Yellow",scale,
             channel_moments);
-          (void) PrintChannelMoments(file,BlackPixelChannel,"Black",
+          (void) PrintChannelMoments(file,BlackPixelChannel,"Black",scale,
             channel_moments);
           break;
         }
         case GRAYColorspace:
         {
-          (void) PrintChannelMoments(file,GrayPixelChannel,"Gray",
+          (void) PrintChannelMoments(file,GrayPixelChannel,"Gray",scale,
             channel_moments);
           break;
         }
       }
       if (image->alpha_trait == BlendPixelTrait)
-        (void) PrintChannelMoments(file,AlphaPixelChannel,"Alpha",
+        (void) PrintChannelMoments(file,AlphaPixelChannel,"Alpha",scale,
           channel_moments);
       if (colorspace != GRAYColorspace)
         {
           (void) FormatLocaleFile(file,"  Image moments:\n");
           (void) PrintChannelMoments(file,(PixelChannel) MaxPixelChannels,
-            "Overall",channel_moments);
+            "Overall",scale,channel_moments);
         }
       channel_moments=(ChannelMoments *) RelinquishMagickMemory(
         channel_moments);
     }
+  if (channel_phash != (ChannelPerceptualHash *) NULL)
+    {
+      (void) FormatLocaleFile(file,"  Channel perceptual hash:\n");
+      (void) PrintChannelPerceptualHash(file,RedChannel,"Red, Hue",
+        channel_phash);
+      (void) PrintChannelPerceptualHash(file,GreenChannel,"Green, Chroma",
+        channel_phash);
+      (void) PrintChannelPerceptualHash(file,BlueChannel,"Blue, Luma",
+        channel_phash);
+      if (image->alpha_trait == BlendPixelTrait)
+        (void) PrintChannelPerceptualHash(file,AlphaChannel,"Alpha, Alpha",
+          channel_phash);
+      channel_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(
+        channel_phash);
+    }
   if (channel_features != (ChannelFeatures *) NULL)
     {
       (void) FormatLocaleFile(file,"  Channel features (horizontal, vertical, "