From: cristy Date: Sat, 22 Feb 2014 21:44:38 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 7.0.1-0~2654 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f8f39d49973e8d7305a84f53f5ad2f569d7cb020;p=imagemagick --- diff --git a/MagickCore/compare.c b/MagickCore/compare.c index 7322ad1b4..7e3b60971 100644 --- a/MagickCore/compare.c +++ b/MagickCore/compare.c @@ -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) { diff --git a/MagickCore/statistic.c b/MagickCore/statistic.c index 31b56caf0..841833504 100644 --- a/MagickCore/statistic.c +++ b/MagickCore/statistic.c @@ -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); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % G e t I m a g e R a n g e % % % % % diff --git a/MagickCore/statistic.h b/MagickCore/statistic.h index b3dc676d9..b6bc80561 100644 --- a/MagickCore/statistic.h +++ b/MagickCore/statistic.h @@ -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 *), diff --git a/MagickCore/version.h b/MagickCore/version.h index c55cba3a3..42773b9a1 100644 --- a/MagickCore/version.h +++ b/MagickCore/version.h @@ -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"