]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Sat, 22 Feb 2014 21:44:38 +0000 (21:44 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Sat, 22 Feb 2014 21:44:38 +0000 (21:44 +0000)
MagickCore/compare.c
MagickCore/statistic.c
MagickCore/statistic.h
MagickCore/version.h

index 7322ad1b4bcdc3ffdfcb02f3044cbfdb28a11dc3..7e3b60971459e763e98e5a6091ed905d0079d51f 100644 (file)
@@ -1112,71 +1112,28 @@ static MagickBooleanType GetPeakSignalToNoiseRatio(const Image *image,
   return(status);
 }
 
-static Image *PerceptualImageHash(const Image *image,
-  const ColorspaceType colorspace,ExceptionInfo *exception)
-{
-  Image
-    *phash_image;
-
-  MagickBooleanType
-    status;
-
-  /*
-    Transform colorspace then blur perceptual hash image.
-  */
-  phash_image=BlurImage(image,0.0,1.0,exception);
-  if (phash_image == (Image *) NULL)
-    return((Image *) NULL);
-  phash_image->depth=8;
-  status=TransformImageColorspace(phash_image,colorspace,exception);
-  if (status == MagickFalse)
-    phash_image=DestroyImage(phash_image);
-  return(phash_image);
-}
-
 static MagickBooleanType GetPerceptualHashDistortion(const Image *image,
   const Image *reconstruct_image,double *distortion,ExceptionInfo *exception)
 {
-  ChannelMoments
-    *image_moments,
-    *reconstruct_moments;
-
-  Image
-    *phash_image;
-
-  MagickBooleanType
-    grayscale;
+  ChannelPerceptualHash
+    *image_phash,
+    *reconstruct_phash;
 
   ssize_t
     channel;
 
   /*
-    Compute perceptual hash in the native image colorspace.
+    Compute perceptual hash in the sRGB colorspace.
   */
-  phash_image=PerceptualImageHash(image,image->colorspace,exception);
-  if (phash_image == (Image *) NULL)
+  image_phash=GetImageChannelPerceptualHash(image,exception);
+  if (image_phash == (ChannelPerceptualHash *) NULL)
     return(MagickFalse);
-  image_moments=GetImageMoments(phash_image,exception);
-  phash_image=DestroyImage(phash_image);
-  if (image_moments == (ChannelMoments *) NULL)
-    return(MagickFalse);
-  phash_image=PerceptualImageHash(reconstruct_image,
-    reconstruct_image->colorspace,exception);
-  if (phash_image == (Image *) NULL)
-    {
-      image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
-      return(MagickFalse);
-    }
-  reconstruct_moments=GetImageMoments(phash_image,exception);
-  phash_image=DestroyImage(phash_image);
-  if (reconstruct_moments == (ChannelMoments *) NULL)
+  reconstruct_phash=GetImageChannelPerceptualHash(reconstruct_image,exception);
+  if (image_phash == (ChannelPerceptualHash *) NULL)
     {
-      image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
+      image_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(image_phash);
       return(MagickFalse);
     }
-  /*
-    Compute sum of moment differences squared.
-  */
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4)
 #endif
@@ -1195,8 +1152,8 @@ static MagickBooleanType GetPerceptualHashDistortion(const Image *image,
         alpha,
         beta;
 
-      alpha=MagickLog10(image_moments[channel].I[i]);
-      beta=MagickLog10(reconstruct_moments[channel].I[i]);
+      alpha=image_phash[channel].P[i];
+      beta=reconstruct_phash[channel].P[i];
       difference+=(beta-alpha)*(beta-alpha);
     }
     distortion[channel]+=difference;
@@ -1205,40 +1162,9 @@ static MagickBooleanType GetPerceptualHashDistortion(const Image *image,
 #endif
     distortion[CompositePixelChannel]+=difference;
   }
-  image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
-  reconstruct_moments=(ChannelMoments *) RelinquishMagickMemory(
-    reconstruct_moments);
-  grayscale=(IsImageGray(image,exception) != MagickFalse) &&
-    (IsImageGray(reconstruct_image,exception) != MagickFalse) ? MagickTrue :
-    MagickFalse;
-  if (grayscale != MagickFalse)
-    return(MagickTrue);
   /*
     Compute perceptual hash in the HCLP colorspace.
   */
-  phash_image=PerceptualImageHash(image,HCLpColorspace,exception);
-  if (phash_image == (Image *) NULL)
-    return(MagickFalse);
-  image_moments=GetImageMoments(phash_image,exception);
-  phash_image=DestroyImage(phash_image);
-  if (image_moments == (ChannelMoments *) NULL)
-    return(MagickFalse);
-  phash_image=PerceptualImageHash(reconstruct_image,HCLpColorspace,exception);
-  if (phash_image == (Image *) NULL)
-    {
-      image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
-      return(MagickFalse);
-    }
-  reconstruct_moments=GetImageMoments(phash_image,exception);
-  phash_image=DestroyImage(phash_image);
-  if (reconstruct_moments == (ChannelMoments *) NULL)
-    {
-      image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
-      return(MagickFalse);
-    }
-  /*
-    Compute sum of moment differences squared.
-  */
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4)
 #endif
@@ -1257,8 +1183,8 @@ static MagickBooleanType GetPerceptualHashDistortion(const Image *image,
         alpha,
         beta;
 
-      alpha=MagickLog10(image_moments[channel].I[i]);
-      beta=MagickLog10(reconstruct_moments[channel].I[i]);
+      alpha=image_phash[channel].Q[i];
+      beta=reconstruct_phash[channel].Q[i];
       difference+=(beta-alpha)*(beta-alpha);
     }
     distortion[channel]+=difference;
@@ -1267,13 +1193,17 @@ static MagickBooleanType GetPerceptualHashDistortion(const Image *image,
 #endif
     distortion[CompositePixelChannel]+=difference;
   }
-  image_moments=(ChannelMoments *) RelinquishMagickMemory(image_moments);
-  reconstruct_moments=(ChannelMoments *) RelinquishMagickMemory(
-    reconstruct_moments);
+  /*
+    Free resources.
+  */
+  reconstruct_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(
+    reconstruct_phash);
+  image_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(image_phash);
   return(MagickTrue);
 }
 
 
+
 static MagickBooleanType GetRootMeanSquaredDistortion(const Image *image,
   const Image *reconstruct_image,double *distortion,ExceptionInfo *exception)
 {
index 31b56caf065fd1a85b355be49e861ca492edcd37..84183350481a258d11f3bf456133388ba433bd32 100644 (file)
@@ -1640,6 +1640,118 @@ MagickExport ChannelMoments *GetImageMoments(const Image *image,
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   G e t I m a g e C h a n n e l P e r c e p t u a l H a s h                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  GetImageChannelPerceptualHash() returns the perceptual hash of one or more
+%  image channels.
+%
+%  The format of the GetImageChannelPerceptualHash method is:
+%
+%      ChannelPerceptualHash *GetImageChannelPerceptualHash(const Image *image,
+%        ExceptionInfo *exception)
+%
+%  A description of each parameter follows:
+%
+%    o image: the image.
+%
+%    o exception: return any errors or warnings in this structure.
+%
+*/
+
+static inline double MagickLog10(const double x)
+{
+#define Log10Epsilon  (1.0e-11)
+
+ if (fabs(x) < Log10Epsilon)
+   return(log10(Log10Epsilon));
+ return(log10(fabs(x)));
+}
+
+MagickExport ChannelPerceptualHash *GetImageChannelPerceptualHash(
+  const Image *image,ExceptionInfo *exception)
+{
+  ChannelMoments
+    *moments;
+
+  ChannelPerceptualHash
+    *perceptual_hash;
+
+  Image
+    *hash_image;
+
+  MagickBooleanType
+    status;
+
+  register ssize_t
+    i;
+
+  ssize_t
+    channel;
+
+  /*
+    Blur then transform to sRGB colorspace.
+  */
+  hash_image=BlurImage(image,0.0,1.0,exception);
+  if (hash_image == (Image *) NULL)
+    return((ChannelPerceptualHash *) NULL);
+  hash_image->depth=8;
+  status=TransformImageColorspace(hash_image,sRGBColorspace,exception);
+  if (status == MagickFalse)
+    return((ChannelPerceptualHash *) NULL);
+  moments=GetImageMoments(hash_image,exception);
+  hash_image=DestroyImage(hash_image);
+  if (moments == (ChannelMoments *) NULL)
+    return((ChannelPerceptualHash *) NULL);
+  perceptual_hash=(ChannelPerceptualHash *) AcquireQuantumMemory(
+    CompositeChannels+1UL,sizeof(*perceptual_hash));
+  if (perceptual_hash == (ChannelPerceptualHash *) NULL)
+    return((ChannelPerceptualHash *) NULL);
+  for (channel=0; channel <= MaxPixelChannels; channel++)
+    for (i=0; i < 7; i++)
+      perceptual_hash[channel].P[i]=MagickLog10(moments[channel].I[i]);
+  moments=(ChannelMoments *) RelinquishMagickMemory(moments);
+  /*
+    Blur then transform to HCLp colorspace.
+  */
+  hash_image=BlurImage(image,0.0,1.0,exception);
+  if (hash_image == (Image *) NULL)
+    {
+      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
+        perceptual_hash);
+      return((ChannelPerceptualHash *) NULL);
+    }
+  hash_image->depth=8;
+  status=TransformImageColorspace(hash_image,HCLpColorspace,exception);
+  if (status == MagickFalse)
+    {
+      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
+        perceptual_hash);
+      return((ChannelPerceptualHash *) NULL);
+    }
+  moments=GetImageMoments(hash_image,exception);
+  hash_image=DestroyImage(hash_image);
+  if (moments == (ChannelMoments *) NULL)
+    {
+      perceptual_hash=(ChannelPerceptualHash *) RelinquishMagickMemory(
+        perceptual_hash);
+      return((ChannelPerceptualHash *) NULL);
+    }
+  for (channel=0; channel <= MaxPixelChannels; channel++)
+    for (i=0; i < 7; i++)
+      perceptual_hash[channel].Q[i]=MagickLog10(moments[channel].I[i]);
+  moments=(ChannelMoments *) RelinquishMagickMemory(moments);
+  return(perceptual_hash);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   G e t I m a g e R a n g e                                                 %
 %                                                                             %
 %                                                                             %
index b3dc676d9dd93449dd646c8f9419a58d9b59eb24..b6bc8056159c173c08c202e818ea5b5c1a5760b3 100644 (file)
@@ -57,6 +57,13 @@ typedef struct _ChannelMoments
     ellipse_intensity;
 } ChannelMoments;
 
+typedef struct _ChannelPerceptualHash
+{
+  double
+    P[32],
+    Q[32];
+} ChannelPerceptualHash;
+
 typedef enum
 {
   UndefinedEvaluateOperator,
@@ -121,6 +128,9 @@ extern MagickExport ChannelStatistics
 extern MagickExport ChannelMoments
   *GetImageMoments(const Image *,ExceptionInfo *);
 
+extern MagickExport ChannelPerceptualHash
+  *GetImageChannelPerceptualHash(const Image *,ExceptionInfo *);
+
 extern MagickExport Image
   *EvaluateImages(const Image *,const MagickEvaluateOperator,ExceptionInfo *),
   *PolynomialImage(const Image *,const size_t,const double *,ExceptionInfo *),
index c55cba3a339108c89855cb6f0ca25c101b122f63..42773b9a1f06b37a2eb01baa313c7abcbd285a84 100644 (file)
@@ -48,7 +48,7 @@ extern "C" {
 #define MagickppLibAddendum  "-0"
 #define MagickppLibInterface  1
 #define MagickppLibMinInterface  1
-#define MagickReleaseDate  "2014-02-08"
+#define MagickReleaseDate  "2014-02-22"
 #define MagickChangeDate   "20120427"
 #define MagickAuthoritativeURL  "http://www.imagemagick.org"
 #define MagickFeatures "DPC HDRI OpenMP"