]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/identify.c
(no commit message)
[imagemagick] / MagickCore / identify.c
index 53d2f7b155e67210b7b5aca0a8705a856afd04bd..0c9c0095df3150aaa562f9f4da81b4bc090f88f5 100644 (file)
 #include "MagickCore/utility.h"
 #include "MagickCore/utility-private.h"
 #include "MagickCore/version.h"
-#if defined(MAGICKCORE_LCMS_DELEGATE)
-#if defined(MAGICKCORE_HAVE_LCMS_LCMS2_H)
-#include <lcms/lcms2.h>
-#elif defined(MAGICKCORE_HAVE_LCMS2_H)
-#include "lcms2.h"
-#elif defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
-#include <lcms/lcms.h>
-#else
-#include "lcms.h"
-#endif
-#endif
-\f
-/*
-  Define declarations.
-*/
-#if defined(MAGICKCORE_LCMS_DELEGATE)
-#if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
-#define cmsUInt32Number  DWORD
-#endif
-#endif
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -177,12 +157,12 @@ static ChannelStatistics *GetLocationStatistics(const Image *image,
       case MaximumStatistic:
       default:
       {
-        channel_statistics[i].maxima=(-MagickHuge);
+        channel_statistics[i].maxima=(-MagickMaximumValue);
         break;
       }
       case MinimumStatistic:
       {
-        channel_statistics[i].minima=MagickHuge;
+        channel_statistics[i].minima=MagickMaximumValue;
         break;
       }
     }
@@ -369,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;
 
@@ -388,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);
 }
 
@@ -434,6 +437,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   ChannelMoments
     *channel_moments;
 
+  ChannelPerceptualHash
+    *channel_phash;
+
   ChannelStatistics
     *channel_statistics;
 
@@ -453,6 +459,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
 
   double
     elapsed_time,
+    scale,
     user_time;
 
   ImageType
@@ -469,8 +476,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
     x;
 
   size_t
-    distance,
-    scale;
+    distance;
 
   ssize_t
     y;
@@ -682,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
@@ -695,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)
         {
@@ -747,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)
@@ -803,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, "
@@ -893,8 +919,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   if (ping == MagickFalse)
     {
       if (image->colorspace == CMYKColorspace)
-        (void) FormatLocaleFile(file,"  Total ink density: %.20g%%\n",100.0*
-          GetImageTotalInkDensity(image,exception)/(double) QuantumRange);
+        (void) FormatLocaleFile(file,"  Total ink density: %*g%%\n",
+          GetMagickPrecision(),100.0*GetImageTotalInkDensity(image,exception)/
+          (double) QuantumRange);
       x=0;
       if (image->alpha_trait == BlendPixelTrait)
         {
@@ -1073,6 +1100,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
   if (image->iterations != 1)
     (void) FormatLocaleFile(file,"  Iterations: %.20g\n",(double)
       image->iterations);
+  if (image->duration != 0)
+    (void) FormatLocaleFile(file,"  Duration: %.20g\n",(double)
+      image->duration);
   if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
     (void) FormatLocaleFile(file,"  Scene: %.20g of %.20g\n",(double)
       image->scene,(double) GetImageListLength(image));
@@ -1142,6 +1172,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
       image_info=DestroyImageInfo(image_info);
     }
   (void) GetImageProperty(image,"exif:*",exception);
+  (void) GetImageProperty(image,"icc:*",exception);
+  (void) GetImageProperty(image,"iptc:*",exception);
+  (void) GetImageProperty(image,"xmp:*",exception);
   ResetImagePropertyIterator(image);
   property=GetNextImageProperty(image);
   if (property != (const char *) NULL)
@@ -1189,45 +1222,6 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
           continue;
         (void) FormatLocaleFile(file,"    Profile-%s: %.20g bytes\n",name,
           (double) GetStringInfoLength(profile));
-#if defined(MAGICKCORE_LCMS_DELEGATE)
-        if ((LocaleCompare(name,"icc") == 0) ||
-            (LocaleCompare(name,"icm") == 0))
-          {
-            cmsHPROFILE
-              icc_profile;
-
-            icc_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
-              (cmsUInt32Number) GetStringInfoLength(profile));
-            if (icc_profile != (cmsHPROFILE *) NULL)
-              {
-#if defined(LCMS_VERSION) && (LCMS_VERSION < 2000)
-                const char
-                  *name;
-
-                name=cmsTakeProductName(icc_profile);
-                if (name != (const char *) NULL)
-                  (void) FormatLocaleFile(file,"      %s\n",name);
-#else
-                char
-                  info[MaxTextExtent];
-
-                (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoDescription,
-                  "en","US",info,MaxTextExtent);
-                (void) FormatLocaleFile(file,"      Description: %s\n",info);
-                (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoManufacturer,
-                  "en","US",info,MaxTextExtent);
-                (void) FormatLocaleFile(file,"      Manufacturer: %s\n",info);
-                (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoModel,"en",
-                  "US",info,MaxTextExtent);
-                (void) FormatLocaleFile(file,"      Model: %s\n",info);
-                (void) cmsGetProfileInfoASCII(icc_profile,cmsInfoCopyright,
-                  "en","US",info,MaxTextExtent);
-                (void) FormatLocaleFile(file,"      Copyright: %s\n",info);
-#endif
-                (void) cmsCloseProfile(icc_profile);
-              }
-          }
-#endif
         if (LocaleCompare(name,"iptc") == 0)
           {
             char