Commit 3fea455d9 for imagemagick.org
commit 3fea455d9fd697ad4a8cb234f9d391d2eb1baa24
Author: Cristy <urban-warrior@imagemagick.org>
Date: Tue Jun 2 20:28:12 2026 -0400
https://github.com/ImageMagick/ImageMagick/issues/8766
diff --git a/MagickCore/compare.c b/MagickCore/compare.c
index 2973d7df3..a6a6407bd 100644
--- a/MagickCore/compare.c
+++ b/MagickCore/compare.c
@@ -1909,8 +1909,6 @@ static MagickBooleanType GetPSNRSimilarity(const Image *image,
static MagickBooleanType GetPHASHSimilarity(const Image *image,
const Image *reconstruct_image,double *similarity,ExceptionInfo *exception)
{
-#define PHASHNormalizationFactor 389.373723242
-
ChannelPerceptualHash
*channel_phash,
*reconstruct_phash;
@@ -1919,7 +1917,7 @@ static MagickBooleanType GetPHASHSimilarity(const Image *image,
*artifact;
ssize_t
- k;
+ i;
/*
Compute the perceptual hash similarity.
@@ -1934,64 +1932,60 @@ static MagickBooleanType GetPHASHSimilarity(const Image *image,
channel_phash);
return(MagickFalse);
}
- for (k=0; k < MaxPixelChannels; k++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
double
- difference;
+ difference = 0.0;
ssize_t
- i;
+ j;
- PixelChannel channel = GetPixelChannelChannel(image,k);
+ PixelChannel channel = GetPixelChannelChannel(image,i);
PixelTrait traits = GetPixelChannelTraits(image,channel);
PixelTrait reconstruct_traits = GetPixelChannelTraits(reconstruct_image,
channel);
if (((traits & UpdatePixelTrait) == 0) ||
((reconstruct_traits & UpdatePixelTrait) == 0))
continue;
- difference=0.0;
- for (i=0; i < MaximumNumberOfImageMoments; i++)
+ for (j=0; j < (ssize_t) channel_phash[0].number_colorspaces; j++)
{
double
alpha,
beta;
ssize_t
- j;
+ k;
- for (j=0; j < (ssize_t) channel_phash[0].number_colorspaces; j++)
+ for (k=0; k < MaximumNumberOfPerceptualHashes; k++)
{
double
error;
- alpha=channel_phash[k].phash[j][i];
- beta=reconstruct_phash[k].phash[j][i];
+ alpha=channel_phash[i].phash[j][k];
+ beta=reconstruct_phash[i].phash[j][k];
error=beta-alpha;
if (IsNaN(error) != 0)
error=0.0;
- difference+=error*error/PHASHNormalizationFactor;
+ difference+=error*error;
}
}
- similarity[k]+=difference;
+ similarity[i]+=difference;
similarity[CompositePixelChannel]+=difference;
}
similarity[CompositePixelChannel]/=(double) GetImageChannels(image);
artifact=GetImageArtifact(image,"phash:normalize");
if (IsStringTrue(artifact) != MagickFalse)
{
- ssize_t
- j;
-
- for (j=0; j < (ssize_t) GetPixelChannels(image); j++)
+ for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
- PixelChannel channel = GetPixelChannelChannel(image,j);
+ PixelChannel channel = GetPixelChannelChannel(image,i);
PixelTrait traits = GetPixelChannelTraits(image,channel);
PixelTrait reconstruct_traits = GetPixelChannelTraits(reconstruct_image,
channel);
if (((traits & UpdatePixelTrait) == 0) ||
((reconstruct_traits & UpdatePixelTrait) == 0))
continue;
- similarity[j]=sqrt(similarity[j]/channel_phash[0].number_colorspaces);
+ similarity[i]=sqrt(similarity[i]/channel_phash[0].number_colorspaces);
}
similarity[CompositePixelChannel]=sqrt(similarity[CompositePixelChannel]/
channel_phash[0].number_colorspaces);
diff --git a/MagickCore/statistic.c b/MagickCore/statistic.c
index 7b14927fb..65cf99bb4 100644
--- a/MagickCore/statistic.c
+++ b/MagickCore/statistic.c
@@ -1792,7 +1792,7 @@ MagickExport ChannelPerceptualHash *GetImagePerceptualHash(const Image *image,
if (moments == (ChannelMoments *) NULL)
break;
for (channel=0; channel <= MaxPixelChannels; channel++)
- for (j=0; j < MaximumNumberOfImageMoments; j++)
+ for (j=0; j < MaximumNumberOfPerceptualHashes; j++)
perceptual_hash[channel].phash[i][j]=(-MagickSafeLog10(fabs(
moments[channel].invariant[j])));
moments=(ChannelMoments *) RelinquishMagickMemory(moments);
diff --git a/MagickCore/statistic.h b/MagickCore/statistic.h
index 07805e9d7..d69b11fb1 100644
--- a/MagickCore/statistic.h
+++ b/MagickCore/statistic.h
@@ -73,8 +73,8 @@ typedef struct _ChannelMoments
typedef struct _ChannelPerceptualHash
{
double
- srgb_hu_phash[MaximumNumberOfImageMoments+1],
- hclp_hu_phash[MaximumNumberOfImageMoments+1];
+ srgb_hu_phash[MaximumNumberOfPerceptualHashes+2],
+ hclp_hu_phash[MaximumNumberOfPerceptualHashes+2];
size_t
number_colorspaces;
@@ -83,7 +83,7 @@ typedef struct _ChannelPerceptualHash
colorspace[MaximumNumberOfPerceptualColorspaces+1];
double
- phash[MaximumNumberOfPerceptualColorspaces+1][MaximumNumberOfImageMoments+1];
+ phash[MaximumNumberOfPerceptualColorspaces+1][MaximumNumberOfPerceptualHashes+2];
size_t
number_channels;
diff --git a/MagickWand/compare.c b/MagickWand/compare.c
index e4dcd6260..21d752e83 100644
--- a/MagickWand/compare.c
+++ b/MagickWand/compare.c
@@ -1281,6 +1281,7 @@ WandExport MagickBooleanType CompareImagesCommand(ImageInfo *image_info,
}
case PerceptualHashErrorMetric:
{
+ scale=1.0;
if (subimage_search == MagickFalse)
{
double