From 41e9f7eb2676cf975ded22cb7f2d573b3b315dd8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 12:16:58 +0100 Subject: [PATCH 1/9] Use type declarations instead of doc-block annotations --- ext/gd/tests/func.inc | 10 ++-------- ext/gd/tests/similarity.inc | 25 +++++-------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/ext/gd/tests/func.inc b/ext/gd/tests/func.inc index 0f10aa7d83dee..9873d532c9f74 100644 --- a/ext/gd/tests/func.inc +++ b/ext/gd/tests/func.inc @@ -128,11 +128,8 @@ function test_image_equals_image(GdImage $expected, GdImage $actual, bool $save_ /** * Returns the truecolor version of an image. - * - * @param resource $image - * @return resource */ -function test_to_truecolor($image) +function test_to_truecolor(GdImage $image): GdImage { if (imageistruecolor($image)) { return $image; @@ -150,11 +147,8 @@ function test_to_truecolor($image) * * The image is saved right beside the temporary .php test file with the * extension .out.png. - * - * @param resource $image - * @return void */ -function save_actual_image($image) +function save_actual_image(GdImage $image): void { $pathinfo = pathinfo($_SERVER['SCRIPT_FILENAME']); $filename = "{$pathinfo['dirname']}/{$pathinfo['filename']}.out.png"; diff --git a/ext/gd/tests/similarity.inc b/ext/gd/tests/similarity.inc index cb0dba77f2064..c4c3988fcac22 100644 --- a/ext/gd/tests/similarity.inc +++ b/ext/gd/tests/similarity.inc @@ -7,15 +7,8 @@ /** * Gets the individual components of an RGB value. - * - * @param int $color - * @param int $red - * @param int $green - * @param int $blue - * - * @return void */ -function get_rgb($color, &$red, &$green, &$blue) +function get_rgb(int $color, &$red, &$green, &$blue): void { // assumes $color is an RGB value $red = ($color >> 16) & 0xFF; @@ -25,13 +18,8 @@ function get_rgb($color, &$red, &$green, &$blue) /** * Calculates the euclidean distance of two RGB values. - * - * @param int $color1 - * @param int $color2 - * - * @return int */ -function calc_pixel_distance($color1, $color2) +function calc_pixel_distance(int $color1, int $color2): float { get_rgb($color1, $red1, $green1, $blue1); get_rgb($color2, $red2, $green2, $blue2); @@ -43,13 +31,10 @@ function calc_pixel_distance($color1, $color2) /** * Calculates dissimilarity of two images. * - * @param resource $image1 - * @param resource $image2 - * - * @return int The dissimilarity. 0 means the images are identical. The higher - * the value, the more dissimilar are the images. + * The dissimilarity. 0 means the images are identical. The higher + * the value, the more dissimilar are the images. */ -function calc_image_dissimilarity($image1, $image2) +function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float { // assumes image1 and image2 have same width and height $dissimilarity = 0; From b5234c739fa8d580786cb43dabb96702a906a511 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 12:25:56 +0100 Subject: [PATCH 2/9] Inline the terrible get_rgb() function --- ext/gd/tests/similarity.inc | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/ext/gd/tests/similarity.inc b/ext/gd/tests/similarity.inc index c4c3988fcac22..2caba5796b68b 100644 --- a/ext/gd/tests/similarity.inc +++ b/ext/gd/tests/similarity.inc @@ -5,26 +5,15 @@ * mainly useful for checking lossy compression. */ -/** - * Gets the individual components of an RGB value. - */ -function get_rgb(int $color, &$red, &$green, &$blue): void -{ - // assumes $color is an RGB value - $red = ($color >> 16) & 0xFF; - $green = ($color >> 8) & 0xFF; - $blue = $color & 0xFF; -} - /** * Calculates the euclidean distance of two RGB values. */ function calc_pixel_distance(int $color1, int $color2): float { - get_rgb($color1, $red1, $green1, $blue1); - get_rgb($color2, $red2, $green2, $blue2); return sqrt( - pow($red1 - $red2, 2) + pow($green1 - $green2, 2) + pow($blue1 - $blue2, 2) + ((($color1 >> 16) & 0xFF) - (($color2 >> 16) & 0xFF)) ** 2 + + ((($color1 >> 8) & 0xFF) - (($color2 >> 8) & 0xFF)) ** 2 + + ((($color1 >> 0) & 0xFF) - (($color2 >> 0) & 0xFF)) ** 2 ); } From 93c8b7053045a4a5de6720e641ef4a1a67c9b26f Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 12:41:37 +0100 Subject: [PATCH 3/9] Always traverse pixels in Z order libgd stores the pixel as an array of rows, so we should use row-major- order traversal to improve caching. --- ext/gd/tests/similarity.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/gd/tests/similarity.inc b/ext/gd/tests/similarity.inc index 2caba5796b68b..c0b7ef86f366f 100644 --- a/ext/gd/tests/similarity.inc +++ b/ext/gd/tests/similarity.inc @@ -27,8 +27,8 @@ function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float { // assumes image1 and image2 have same width and height $dissimilarity = 0; - for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { - for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { + for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { + for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { $color1 = imagecolorat($image1, $i, $j); $color2 = imagecolorat($image2, $i, $j); $dissimilarity += calc_pixel_distance($color1, $color2); From 518474fdd4daecf3b7f8f5db7d08e68da05a6714 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 14:08:12 +0100 Subject: [PATCH 4/9] Add assertions to avoid misuse of the functions The assertion regarding the image dimensions won't break any tests, and we had it already as a comment. However, asserting that the images are truecolor images is important for `calc_image_dissimilarity()` which otherwise would calculate nonsense, and not unreasonable for `test_image_equals_image()` which otherwise is overspecified (for our purposes, it doesn't matter which palette entry a pixel refers to, but rather whether the actual colors referred by a palette color match). Since the truecolor assertions break two tests, we fix these by converting to truecolor. That should likely be backported to lower branches. --- ext/gd/tests/bug43475.phpt | 1 + ext/gd/tests/bug43475.png | Bin 4697 -> 11430 bytes ext/gd/tests/func.inc | 1 + ext/gd/tests/gd276.phpt | 2 ++ ext/gd/tests/similarity.inc | 3 ++- 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/gd/tests/bug43475.phpt b/ext/gd/tests/bug43475.phpt index 454d2daad0f1a..a5b4ac6d22885 100644 --- a/ext/gd/tests/bug43475.phpt +++ b/ext/gd/tests/bug43475.phpt @@ -60,6 +60,7 @@ imageline($im, 700, 100, 700, 600, IMG_COLOR_STYLED); imageline($im, 700, 600, 200, 100, IMG_COLOR_STYLED); $ex = imagecreatefrompng(__DIR__ . '/bug43475.png'); +imagepalettetotruecolor($im); var_dump(calc_image_dissimilarity($ex, $im) < 1e-5); ?> --EXPECT-- diff --git a/ext/gd/tests/bug43475.png b/ext/gd/tests/bug43475.png index 774270f63db86efd053f126ab9d66a9e50569768..d53a9a3322ae6aab3ce1840db001f63cd2360295 100644 GIT binary patch literal 11430 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 M^SoTj#Qxj=2jQFG2LJ#7 literal 4697 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 WgTe{iOXy|@=DuZzTQ%)K;(q~-Qc&{% diff --git a/ext/gd/tests/func.inc b/ext/gd/tests/func.inc index 9873d532c9f74..65332ff441ce3 100644 --- a/ext/gd/tests/func.inc +++ b/ext/gd/tests/func.inc @@ -95,6 +95,7 @@ function test_image_equals_file(string $filename, GdImage $actual): void */ function test_image_equals_image(GdImage $expected, GdImage $actual, bool $save_actual = false): void { + assert(imageistruecolor($expected) && imageistruecolor($actual)); $exp_x = imagesx($expected); $exp_y = imagesy($expected); $act_x = imagesx($actual); diff --git a/ext/gd/tests/gd276.phpt b/ext/gd/tests/gd276.phpt index a12bce3983049..ad7b6343f520d 100644 --- a/ext/gd/tests/gd276.phpt +++ b/ext/gd/tests/gd276.phpt @@ -15,6 +15,8 @@ $filename = __DIR__ . "/gd276.bmp"; imagebmp($orig, $filename, true); $saved = imagecreatefrombmp($filename); var_dump($saved !== false); +imagepalettetotruecolor($orig); +imagepalettetotruecolor($saved); test_image_equals_image($orig, $saved); ?> --EXPECT-- diff --git a/ext/gd/tests/similarity.inc b/ext/gd/tests/similarity.inc index c0b7ef86f366f..7654e6ff31fad 100644 --- a/ext/gd/tests/similarity.inc +++ b/ext/gd/tests/similarity.inc @@ -25,7 +25,8 @@ function calc_pixel_distance(int $color1, int $color2): float */ function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float { - // assumes image1 and image2 have same width and height + assert(imageistruecolor($image1) && imageistruecolor($image2)); + assert(imagesx($image1) === imagesx($image2) && imagesy($image1) === imagesy($image2)); $dissimilarity = 0; for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { From 8464a45bbfe0c669f862a0352f8fe28cda34d7fd Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 15:03:48 +0100 Subject: [PATCH 5/9] Drop implicit conversion to truecolor Conversion to truecolor is a relatively expensive operation, and as such should not be implicit; instead test authors are encouraged to use truecolor images in the first place where possible, or to even find better ways to verify expectations than doing a full image comparison. --- ext/gd/tests/bug52070.phpt | 1 + ext/gd/tests/bug52070.png | Bin 2223 -> 8724 bytes ext/gd/tests/bug72913.phpt | 14 +++++++++++--- ext/gd/tests/bug72913.png | Bin 147 -> 0 bytes ext/gd/tests/func.inc | 18 ------------------ ext/gd/tests/imagebmp_basic.phpt | 2 +- ext/gd/tests/imagebmp_basic.png | Bin 141 -> 584 bytes ext/gd/tests/imagecolorset_basic.phpt | 1 + ext/gd/tests/imagecolorset_basic.png | Bin 99 -> 434 bytes ext/gd/tests/imagecreatefromstring_bmp.phpt | 2 +- ext/gd/tests/imagecreatefromstring_bmp.png | Bin 126 -> 134 bytes .../tests/imagegammacorrect_variation1.phpt | 2 +- ext/gd/tests/imagegammacorrect_variation1.png | Bin 199 -> 686 bytes .../tests/imagegammacorrect_variation2.phpt | 3 +++ .../tests/imagetruecolortopalette_basic.phpt | 2 +- .../tests/imagetruecolortopalette_basic.png | Bin 208 -> 709 bytes .../tests/test_image_equals_file_palette.phpt | 3 +++ 17 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 ext/gd/tests/bug72913.png diff --git a/ext/gd/tests/bug52070.phpt b/ext/gd/tests/bug52070.phpt index 6bbe2363a650b..8bc653ae95ef8 100644 --- a/ext/gd/tests/bug52070.phpt +++ b/ext/gd/tests/bug52070.phpt @@ -20,6 +20,7 @@ imagedashedline($im, 800, 400, 500, 800, $color); imagedashedline($im, 800, 400, 600, 800, $color); imagedashedline($im, 800, 400, 700, 800, $color); imagedashedline($im, 800, 400, 800, 800, $color); +imagepalettetotruecolor($im); include_once __DIR__ . '/func.inc'; test_image_equals_file(__DIR__ . '/bug52070.png', $im); ?> diff --git a/ext/gd/tests/bug52070.png b/ext/gd/tests/bug52070.png index 5ce54b121bc2ed6f250dd98505cfafb50e48b9fc..a6f9a3b875d560724e5f91744c15fe31fd835422 100644 GIT binary patch literal 8724 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 literal 2223 zcmcIm`#TeCA6I%)dPwD1nCi*-EQA=b9I7GXozs@B(J+!j$jBqogcsQ!vcxd8p|KGa zZ-|srPSY6WRI^5H&Zj-=y1akFd;f6X*ZsY(>vMgs&*$^K@B4up*ilOIxTKhvn3S`V z!&Nb{eJ{ks#MSnQiz)~8588>A{ce{bAWcn8p-{*=vY9I;cHp|RgB>Kch&SrqTlP{e zEkH8|=tnOteAR?IZxvBSRU>%!xK{`6@dkMnw3>C?eWpE-*|$zwEkGMaT}r6UKCIm& zEyDeOj5Y71b*}3X-j?T^8yb}xb)xAwLwtzM5KqtnTiLRKAS=5b9m!C!srr<;&u{umSTeXDN5G2{#|?eZLgy~#<6 zq&*ooDR>KAd-MrD1PraOy7P^U{obAbdR(_-z8Jd`W-v1Jtyl-Gga4HIo?K{06Qk~T*~8k2g$(upEJ`>*S^ zvpH&g(3EG;wVf~#h#{uUjYlfa1w@|mpe=ZeNlJLo_A1nQXQcKiZiBYl0>_$MF*;%P zL6jMkk8>n#qo1=lf`|@y-ij!EfQmZJM{^&(>Zu=2by+PLeFyHk4N{}YQi_Gn|Q56RdH!{?8%+C#2~DvoG(yI>W&_ooP^APt=cCb zGd9ePQ6;T)+3VPW+u0Z$Vt2cXA2>)`-X>s4VL7|^`dDG`xWTLb=olB+l+W=D)1INB z8S;ZjVgWP{T`>^vlfKKUv0IAIzB(@eh?nsl;qWb^qg)*#*@lLz`1tc;yOJm-#KkED zI9eW-Q>v)`Udt~?YhpzM&4iYh2LVvtACb`Ueb?aCYN6j+AtLzd5t?l)9W&cducq2#6 zC%~-LVfKt?)-JvB4&JYIHExQ&g=OVDQ$n29%-4*Bkd(IEd331JW=UGlp>)d>y$0F z^7K+lq7@|D^X6cQ(~UpnCyX{SEE8C@%z6Z7ljF8vr;s&pzSk!<(a+VMHg*1;I)L1l zO1g3HGfn`ZK8NX&PUN`y20i*$Se8Lnt=01!f}`H{LZvd7qSy&@KgfK-*-aQAE5Z)R zDF1i4=Dp80>{L=J^cRTOlzh1JTu>8Dbr#eugOr-p`$C6|f=%0D+M#fm)48l!PzdEd z08W>GYzJ?2%VbQoM&y6Gp!+&-Ng;ZRj;h9#H?4eqIq{eNlQL9M=GqT>X&|B;?Q+GY z=V^upS|w29%3yGSCqjvxp1`t1`m;yYhMj{or1(2!Piu&>NNiR0)rLxPNY~1)%h_al z*|RTm%<{9+b$4nrG?t+pkafdefGc`n31K}#(6YsuQWy7Xbc1+j?SJ%ucuc}k*XfN~ zVowSjUY}=a2XBF7FuqQq^R8OU!+tA?Wz~+<&lRrxqO+6riRJD^RZHV>S2EiRgV14o z!Jkc0cznRhoHvV#;X*H(pDM2J9mUrhB}U>?B9UXA0OHvE;a(S7vl%n8<=jJN+OJ(T zi+cs7y`}_s!GK}+&NF>tG_uEFeq18Kvahb<7?<|O2#C!x4HfQPbJD*-Rzw&m&?hJU z6Q$Zs-HW?~fALR%h3l08MJ1 zKY+&N-pcC}e4k6EOM2vJpc`IGA$J9ZGwavbwpkLq*9T~Tvx9)cvIqij#l!g((NR4z;vk~`4whp|Z2Bv$QkJ>F+U@U&j&r`lB> zvBDSNqfKQ(3P|N$1|A%~lh3_p-gA|;t(aZ&NnS%0Yag6oS%tAGC1$}TNfyD%Awo3e zhf?@nSm)NR|9vD>0O5lUjCc!+pC9y7MZfcb4S^(n#?iZd$DsMHzO#`8s6DSH*&cM# ziXn3cbaIn*rHe$15oizJ$0iE2FNuGj91lHC`7rBls)PL~PimvE^kGsN>V4v`7^KKJTH7jPe*jU;Q`$Yhi zMXvH>#uopST=`$u8|&ihHJka%T7-)hvAMo!+BBR(bmR86v95ZxKXsm5HEf>&wcmz| z$)S!|Rmt2z9ogK#c&CY;vYOjJpGGz$y+N$5E{2Erq_MXYz2TRNn^U9qfye z+C;_DH~oz8ho**P`?Q!|7G4(is5}FWAvt8D@nwGtdkJm=YPb89^XpFTT+;-Dmkhp3WMAW;Km`Xj_FVEgt->`ke?U64xB9f{Y`KNfgP$ZT>I-E D7F$KO diff --git a/ext/gd/tests/bug72913.phpt b/ext/gd/tests/bug72913.phpt index 9eb9c24653530..eea77b6ed56b1 100644 --- a/ext/gd/tests/bug72913.phpt +++ b/ext/gd/tests/bug72913.phpt @@ -23,8 +23,16 @@ imagesavealpha($dst, true); imagecopy($dst, $src, 0,0, 0,0, 50,50); -include_once __DIR__ . '/func.inc'; -test_image_equals_file(__DIR__ . '/bug72913.png', $dst); +var_dump(imagecolorsforindex($dst, imagecolorat($dst, 0, 0))); ?> --EXPECT-- -The images are equal. +array(4) { + ["red"]=> + int(255) + ["green"]=> + int(255) + ["blue"]=> + int(255) + ["alpha"]=> + int(127) +} diff --git a/ext/gd/tests/bug72913.png b/ext/gd/tests/bug72913.png deleted file mode 100644 index 83eeb81fb16acb3131c987d331ebeb53962ccb1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_{3?x-PN__%SYymzYuK$66f#G%3^T|LF#*!ev zU diff --git a/ext/gd/tests/imagebmp_basic.png b/ext/gd/tests/imagebmp_basic.png index 26fc7d0afcf9fc37dc565ce1ffa7c08f83f0d2b6..d52dd04fb0987c6d654fa5ae11d41ae6770a1bd5 100644 GIT binary patch delta 571 zcmeBWJi#(SqMn0|fq|jm(bNzi#aZAHS1x;9MWM=*s&K)-F?a&8@Fm*&Ve0ay(Gv<)!rX8c%oE@Ch!>aph}UG-dS- z&)6wOqOx;4iuOL*tP{8{GU&Q)zN@)G3aN~hH8qQ4z z_Glb#Ixt7Wx%ohi#^L4zF&e=Q2W&JhHyn`B2yQ&^L*sJefg2jZO$T;pTy8orLnFBP zK!wKT<^vHL-VFyVG)^}hkkIgMbg(;Bq%fhkev=BvlSMk*OfxmSn;qm%eNvdvs&pb; zQ={q5)CQ#!>#G)Xd|EP3qiN3y@h*k`SD0NVm~V9xOmWu@WVsosE#k;`g~@e7^Hn#& zCoZOeES8bFB93|?KvmsS-2|67s0OlVhG>d7a)kj^9g1}oT;dcSz_Rj6q==(d8Jp{b rQ?e$mHyi%#*8euyA2rHgF*rZn{?j3OsYYPxU|{fc^>bP0l+XkKkY@Jw delta 105 zcmX@X(#tqOLYk48fq}tGhg}>zqS`xb9`n5Bb%mN$g*%|g2=_nlD(7v@q!5e&51$Y@*eK-@r&<@O1TaS?83{1ORKWio*Z^ delta 81 zcmdnQoIF9on~|A;fr0J({AM7<9N-h;%E0iytKw2PkSp!!;uzx5`SxHVki&3z!O!6P e4_HDOf$Z}P{5A}XzJg(@AQ?|rKbLh*2~7Z&1Qt{P diff --git a/ext/gd/tests/imagecreatefromstring_bmp.phpt b/ext/gd/tests/imagecreatefromstring_bmp.phpt index 34db04297e3aa..746e566fdbfea 100644 --- a/ext/gd/tests/imagecreatefromstring_bmp.phpt +++ b/ext/gd/tests/imagecreatefromstring_bmp.phpt @@ -22,7 +22,7 @@ $bmp = "\x42\x4D\x3E\x00\x00\x00\x00\x00\x00\x00\x3E\x00\x00\x00\x28\x00" . "\x01\x00\x05\x00\x00\x00\x02\x00\x01\x01\x01\x00\x06\x00\x00\x00" . "\x0A\x00\x00\x00\x0A\x00\x00\x00\x00\x01"; $im = imagecreatefromstring($bmp); - +imagepalettetotruecolor($im); include_once __DIR__ . '/func.inc'; test_image_equals_file(__DIR__ . '/imagecreatefromstring_bmp.png', $im); ?> diff --git a/ext/gd/tests/imagecreatefromstring_bmp.png b/ext/gd/tests/imagecreatefromstring_bmp.png index 04ffc83c468e3066d4214f06698547c2ba7ed74f..a9ae65fdc9827c0d0b56752782658283fb3376dc 100644 GIT binary patch delta 116 zcmbX?_wfUrhf)<`Gjv*3LlT#8Bew=q; zNl^k)S|3_(_@DnFabc7prUHu`FyhCt$(wcb(mq{#Ne^J!fD8O2VG5MAV-}6h; RdVppyc)I$ztaD0e0swT2DDeOQ delta 88 zcmZo;teYSq&B)Baz_9&K>^~sI7T^=&3Z(!4|G)I+{JRqsC5+`fT^vI=W+o>vFtf6; pF|x7ov9XD diff --git a/ext/gd/tests/imagegammacorrect_variation1.png b/ext/gd/tests/imagegammacorrect_variation1.png index f9718890968a2eae8faad02ef6a536ddb3000ec5..8b0e80c5ea0345cade6f903a41a4613b8b1f16ea 100644 GIT binary patch literal 686 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7Cr(}oCO|{#S9F5M?jcysy3fA0|Qfn zr;B4q#hkadFXl=c3OG2bdI-O|BD=fiNq0k{!bXALkumptSXJH^`U@?P*VotIpa0=# zon1BK9M1@q7FVYsN7UI?Gs^G0|Nea3p>1*T@$>h#?7vl)^tPtr{FdK4bL7R0IlEgn zcyK_7BOM#c{%8HYt2XC&$A%g1AkQZGL+)l%l(S T|609(36R0l)z4*}Q$iB}bm|H* delta 183 zcmV;o07(C?1;+u97=Hl+00006&*Py0000J1OjJd9czBVKkv6>FPyhe`d`Uz>R7i>K z(Y+0TAP|OO2!*9?z$lESqcI92SXvnT37-kMBe}-H$i3y000$VOX_}_}vjgSIX4w7# z3$X1a^RQL05talSU{Np!TLiN(Q^&ukZGm04ZJu5C89It)`7n58m`p6NW6KLBVvf83 lHl*9#i|Nv diff --git a/ext/gd/tests/imagetruecolortopalette_basic.png b/ext/gd/tests/imagetruecolortopalette_basic.png index 7d042f2ac3da278c8ebeedd18665cdbae49e86d4..79e14eef35908f66237035ea8e7b8e6af6357b00 100644 GIT binary patch literal 709 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7Cr(}oCO|{#S9F5M?jcysy3fA0|QgJ zr;B4q#hkad4gHiI1spE2P0W9g@V?&0sYu0aQ_9*Kq6&7GP3zvX+A+hm=Gy5Fk2&g{dZs4+{@b%*KU1( zp={&lnr(dDJGb#?KQDhev26b7Z;6JNJ2sTnm;c+s`B_5nT9k3yPvK=}5`7}F&q`*c zUi$0adQ^sg`tj4ZFSh^as{Xb5#uDFB)3Rh=nQ!4fd!OIfaBY_Lm;PBb`!6Q0HLd>f z-}rCbJ=b)_>fIc#uT7jd*LGQSx%joK{%mFbjxkA89ZJ6T-G@yGywo>bt(h^ delta 192 zcmV;x06+i51<(PI7=Hl+00006&*Py0000J1OjJb^0uu!O{2_F>GXMYpg-Jv~R7i>K z&@m2xAPhj!8U{zb0Y~9za5Rs?5f~ka8Y68A9SDhu4*laBXeofEY1&KK6H8>tWxiTl#!@;pKBgW!j usPkgP^I&Yui09xwO=<~Xm85B!_M --EXPECT-- From a0f26996b650b5cc8502be5974fe690f90984e30 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 15:18:14 +0100 Subject: [PATCH 6/9] Merge similarity.inc into func.inc There is no particular reason to have a separate file for similarity comparisons. --- ext/gd/tests/avif_decode_encode.phpt | 2 +- ext/gd/tests/bug43475.phpt | 2 +- ext/gd/tests/bug64641.phpt | 2 +- ext/gd/tests/func.inc | 37 ++++++++++++++++++++++++++ ext/gd/tests/similarity.inc | 39 ---------------------------- ext/gd/tests/webp_basic.phpt | 2 +- 6 files changed, 41 insertions(+), 43 deletions(-) delete mode 100644 ext/gd/tests/similarity.inc diff --git a/ext/gd/tests/avif_decode_encode.phpt b/ext/gd/tests/avif_decode_encode.phpt index cb7f1ce95a67c..010ad82629891 100644 --- a/ext/gd/tests/avif_decode_encode.phpt +++ b/ext/gd/tests/avif_decode_encode.phpt @@ -14,7 +14,7 @@ gd --FILE-- --FILE-- --FILE-- > 16) & 0xFF) - (($color2 >> 16) & 0xFF)) ** 2 + + ((($color1 >> 8) & 0xFF) - (($color2 >> 8) & 0xFF)) ** 2 + + ((($color1 >> 0) & 0xFF) - (($color2 >> 0) & 0xFF)) ** 2 + ); +} + +/** + * Calculates dissimilarity of two images. + * + * The dissimilarity. 0 means the images are identical. The higher + * the value, the more dissimilar are the images. + */ +function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float +{ + assert(imageistruecolor($image1) && imageistruecolor($image2)); + assert(imagesx($image1) === imagesx($image2) && imagesy($image1) === imagesy($image2)); + $dissimilarity = 0; + for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { + for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { + $color1 = imagecolorat($image1, $i, $j); + $color2 = imagecolorat($image2, $i, $j); + $dissimilarity += calc_pixel_distance($color1, $color2); + } + } + return $dissimilarity; +} diff --git a/ext/gd/tests/similarity.inc b/ext/gd/tests/similarity.inc deleted file mode 100644 index 7654e6ff31fad..0000000000000 --- a/ext/gd/tests/similarity.inc +++ /dev/null @@ -1,39 +0,0 @@ -> 16) & 0xFF) - (($color2 >> 16) & 0xFF)) ** 2 + - ((($color1 >> 8) & 0xFF) - (($color2 >> 8) & 0xFF)) ** 2 + - ((($color1 >> 0) & 0xFF) - (($color2 >> 0) & 0xFF)) ** 2 - ); -} - -/** - * Calculates dissimilarity of two images. - * - * The dissimilarity. 0 means the images are identical. The higher - * the value, the more dissimilar are the images. - */ -function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float -{ - assert(imageistruecolor($image1) && imageistruecolor($image2)); - assert(imagesx($image1) === imagesx($image2) && imagesy($image1) === imagesy($image2)); - $dissimilarity = 0; - for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { - for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { - $color1 = imagecolorat($image1, $i, $j); - $color2 = imagecolorat($image2, $i, $j); - $dissimilarity += calc_pixel_distance($color1, $color2); - } - } - return $dissimilarity; -} diff --git a/ext/gd/tests/webp_basic.phpt b/ext/gd/tests/webp_basic.phpt index 97b0451c09b8d..2e074c23ef5ed 100644 --- a/ext/gd/tests/webp_basic.phpt +++ b/ext/gd/tests/webp_basic.phpt @@ -12,7 +12,7 @@ if (!function_exists('imagewebp') || !function_exists('imagecreatefromwebp')) ?> --FILE-- Date: Tue, 31 Dec 2024 16:43:25 +0100 Subject: [PATCH 7/9] Simplify bug43475.phpt and bug64641.phpt `calc_image_dissimilarity()` calculates the sum of the euclidean distance of the RGB channels of all pixels. The euclidean distance is either zero or greater than or equal to one (but never in ]0, 1[). The sum of these values also has this property, so it doesn't make sense to check for less than 1e-5. Thus we just call `test_image_equals_file()` instead. --- ext/gd/tests/bug43475.phpt | 5 ++--- ext/gd/tests/bug64641.phpt | 12 ++---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/ext/gd/tests/bug43475.phpt b/ext/gd/tests/bug43475.phpt index 9d3931bd5d737..4d3db399a30e2 100644 --- a/ext/gd/tests/bug43475.phpt +++ b/ext/gd/tests/bug43475.phpt @@ -59,9 +59,8 @@ imageline($im, 200, 100, 700, 100, IMG_COLOR_STYLED); imageline($im, 700, 100, 700, 600, IMG_COLOR_STYLED); imageline($im, 700, 600, 200, 100, IMG_COLOR_STYLED); -$ex = imagecreatefrompng(__DIR__ . '/bug43475.png'); imagepalettetotruecolor($im); -var_dump(calc_image_dissimilarity($ex, $im) < 1e-5); +test_image_equals_file(__DIR__ . '/bug43475.png', $im); ?> --EXPECT-- -bool(true) +The images are equal. diff --git a/ext/gd/tests/bug64641.phpt b/ext/gd/tests/bug64641.phpt index c2676b77817a4..d2e51817b9b48 100644 --- a/ext/gd/tests/bug64641.phpt +++ b/ext/gd/tests/bug64641.phpt @@ -31,15 +31,7 @@ $points = array( ); imagefilledpolygon($im, $points, 0xFFFF00); -$ex = imagecreatefrompng(__DIR__ . '/bug64641.png'); -if (($diss = calc_image_dissimilarity($ex, $im)) < 1e-5) { - echo "IDENTICAL"; -} else { - echo "DISSIMILARITY: $diss"; -} -imagedestroy($ex); - -imagedestroy($im); +test_image_equals_file(__DIR__ . '/bug64641.png', $im); ?> --EXPECT-- -IDENTICAL +The images are equal. From 9efc96f665f2c700a5a3a6d470da77b74382285e Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 31 Dec 2024 16:52:29 +0100 Subject: [PATCH 8/9] Replace calc_image_dissimilarity() with the well-known mse() `calc_image_dissimilarity()` has the drawback that it did sum up the pixel differences, so for large images the result could be way larger than for small images. It also has the drawback that it likely is not as well understood as the mean squared error. Thus we replace it with the latter, and calculate the mean squared error of the individual RGB channels (to be precise). The result is always in range 0..255**2 what makes reasoning about thresholds easier. --- ext/gd/tests/avif_decode_encode.phpt | 6 ++--- ext/gd/tests/func.inc | 37 ++++++++-------------------- ext/gd/tests/webp_basic.phpt | 4 +-- 3 files changed, 15 insertions(+), 32 deletions(-) diff --git a/ext/gd/tests/avif_decode_encode.phpt b/ext/gd/tests/avif_decode_encode.phpt index 010ad82629891..b73f61a537b50 100644 --- a/ext/gd/tests/avif_decode_encode.phpt +++ b/ext/gd/tests/avif_decode_encode.phpt @@ -58,8 +58,8 @@ gd // Note we could also forgive a certain number of pixel differences. // With the current test image, we just didn't need to. - echo 'How many pixels are different in the two images? '; - print_r(calc_image_dissimilarity($img, $img_from_avif)); + echo 'What is the mean squared error of the two images? '; + print_r(mse($img, $img_from_avif)); unlink($outfile); @@ -79,4 +79,4 @@ Encoding AVIF with illegal quality: imageavif(): Argument #3 ($quality) must be Encoding AVIF with illegal speed: imageavif(): Argument #4 ($speed) must be between -1 and 10 Encoding AVIF losslessly... ok Decoding the AVIF we just wrote... -How many pixels are different in the two images? 0 +What is the mean squared error of the two images? 0 diff --git a/ext/gd/tests/func.inc b/ext/gd/tests/func.inc index 445f844ec55ab..0668742d2b8a7 100644 --- a/ext/gd/tests/func.inc +++ b/ext/gd/tests/func.inc @@ -156,39 +156,22 @@ function trycatch_dump(...$tests) { } /** - * A very simple algorithm for finding the dissimilarity between images, - * mainly useful for checking lossy compression. + * Calculate the mean squared error (in range 0..255**2) */ - -/** - * Calculates the euclidean distance of two RGB values. - */ -function calc_pixel_distance(int $color1, int $color2): float -{ - return sqrt( - ((($color1 >> 16) & 0xFF) - (($color2 >> 16) & 0xFF)) ** 2 + - ((($color1 >> 8) & 0xFF) - (($color2 >> 8) & 0xFF)) ** 2 + - ((($color1 >> 0) & 0xFF) - (($color2 >> 0) & 0xFF)) ** 2 - ); -} - -/** - * Calculates dissimilarity of two images. - * - * The dissimilarity. 0 means the images are identical. The higher - * the value, the more dissimilar are the images. - */ -function calc_image_dissimilarity(GdImage $image1, GdImage $image2): float +function mse(GdImage $image1, GdImage $image2): float { assert(imageistruecolor($image1) && imageistruecolor($image2)); assert(imagesx($image1) === imagesx($image2) && imagesy($image1) === imagesy($image2)); - $dissimilarity = 0; + $e = $count = 0; for ($j = 0, $m = imagesy($image1); $j < $m; $j++) { for ($i = 0, $n = imagesx($image1); $i < $n; $i++) { - $color1 = imagecolorat($image1, $i, $j); - $color2 = imagecolorat($image2, $i, $j); - $dissimilarity += calc_pixel_distance($color1, $color2); + $c1 = imagecolorat($image1, $i, $j); + $c2 = imagecolorat($image2, $i, $j); + $e += ((($c1 >> 16) & 255) - (($c2 >> 16) & 255)) ** 2 + + ((($c1 >> 8) & 255) - (($c2 >> 8) & 255)) ** 2 + + ((($c1 >> 0) & 255) - (($c2 >> 0) & 255)) ** 2; + $count += 3; } } - return $dissimilarity; + return $e / $count; } diff --git a/ext/gd/tests/webp_basic.phpt b/ext/gd/tests/webp_basic.phpt index 2e074c23ef5ed..ef2fae8652560 100644 --- a/ext/gd/tests/webp_basic.phpt +++ b/ext/gd/tests/webp_basic.phpt @@ -30,12 +30,12 @@ imagewebp($im1, $filename); $im2 = imagecreatefromwebp($filename); imagewebp($im2, $filename); echo 'Is lossy conversion close enough? '; -var_dump(calc_image_dissimilarity($im1, $im2) < 10e5); +var_dump(mse($im1, $im2) < 500); imagewebp($im1, $filename, IMG_WEBP_LOSSLESS); $im_lossless = imagecreatefromwebp($filename); echo 'Does lossless conversion work? '; -var_dump(calc_image_dissimilarity($im1, $im_lossless) == 0); +var_dump(mse($im1, $im_lossless) == 0); try { imagewebp($im1, $filename, -10); From 2f1d25f9f16f308297b7849d127fafc12edc363a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 2 Jan 2025 14:28:29 +0100 Subject: [PATCH 9/9] review --- ext/gd/tests/avif_decode_encode.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/gd/tests/avif_decode_encode.phpt b/ext/gd/tests/avif_decode_encode.phpt index b73f61a537b50..054eb52467637 100644 --- a/ext/gd/tests/avif_decode_encode.phpt +++ b/ext/gd/tests/avif_decode_encode.phpt @@ -58,8 +58,8 @@ gd // Note we could also forgive a certain number of pixel differences. // With the current test image, we just didn't need to. - echo 'What is the mean squared error of the two images? '; - print_r(mse($img, $img_from_avif)); + echo 'What is the mean squared error of the two images? ', + mse($img, $img_from_avif); unlink($outfile);