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