Skip to content

Commit 526407c

Browse files
committed
Fix #53580: During resize gdImageCopyResampled cause colors change
We port the upstream fix[1], and also revert commit a3383ac[2] which is now obsolete, and also not part of libgd. Especially the change to gd.png.c was at best a half-baked optimization. [1] <libgd/libgd@a24e96f> [2] <a3383ac> Closes GH-7402.
1 parent 3677db6 commit 526407c

File tree

4 files changed

+43
-21
lines changed

4 files changed

+43
-21
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ PHP NEWS
88
(cmb)
99
. Fixed bug #73122 (Integer Overflow when concatenating strings). (cmb)
1010

11+
-GD:
12+
. Fixed bug #53580 (During resize gdImageCopyResampled cause colors change).
13+
(cmb)
14+
1115
- Opcache:
1216
. Fixed bug #81353 (segfault with preloading and statically bound closure).
1317
(Nikita)

ext/gd/libgd/gd.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,7 +2612,6 @@ void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, i
26122612
green /= spixels;
26132613
blue /= spixels;
26142614
alpha /= spixels;
2615-
alpha += 0.5;
26162615
}
26172616
if ( alpha_sum != 0.0f) {
26182617
if( contrib_sum != 0.0f) {
@@ -2622,20 +2621,12 @@ void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, i
26222621
green /= alpha_sum;
26232622
blue /= alpha_sum;
26242623
}
2625-
/* Clamping to allow for rounding errors above */
2626-
if (red > 255.0f) {
2627-
red = 255.0f;
2628-
}
2629-
if (green > 255.0f) {
2630-
green = 255.0f;
2631-
}
2632-
if (blue > 255.0f) {
2633-
blue = 255.0f;
2634-
}
2635-
if (alpha > gdAlphaMax) {
2636-
alpha = gdAlphaMax;
2637-
}
2638-
gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
2624+
/* Round up closest next channel value and clamp to max channel value */
2625+
red = red >= 255.5 ? 255 : red+0.5;
2626+
blue = blue >= 255.5 ? 255 : blue+0.5;
2627+
green = green >= 255.5 ? 255 : green+0.5;
2628+
alpha = alpha >= gdAlphaMax+0.5 ? 255 : alpha+0.5;
2629+
gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int)red, (int)green, (int)blue, (int)alpha));
26392630
}
26402631
}
26412632
}

ext/gd/libgd/gd_png.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -728,12 +728,7 @@ void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level, int basefilte
728728
*/
729729
a = gdTrueColorGetAlpha(thisPixel);
730730
/* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */
731-
if (a == 127) {
732-
*pOutputRow++ = 0;
733-
} else {
734-
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
735-
}
736-
731+
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
737732
}
738733
}
739734
}

ext/gd/tests/bug53580.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Bug #53580 (During resize gdImageCopyResampled cause colors change)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('gd')) die("skip gd extension not available");
6+
if (!GD_BUNDLED && version_compare(GD_VERSION, "2.3.2") <= 0) {
7+
die("skip test requires GD > 2.3.2");
8+
}
9+
?>
10+
--FILE--
11+
<?php
12+
$w0 = 100;
13+
$h0 = 100;
14+
$w1 = 150;
15+
$h1 = 150;
16+
$c0 = 0xffffff;
17+
18+
$im0 = imagecreatetruecolor($w0, $h0);
19+
imagefilledrectangle($im0, 0, 0, $w0 - 1, $h0 - 1, $c0);
20+
21+
$im1 = imagecreatetruecolor($w1, $h1);
22+
imagecopyresampled($im1, $im0, 0, 0, 0, 0, $w1, $h1, $w0, $h0);
23+
24+
for ($i = 0; $i < $w1; $i++) {
25+
for ($j = 0; $j < $h1; $j++) {
26+
if (($c1 = imagecolorat($im1, $i, $j)) !== $c0) {
27+
printf("%d,%d = %d\n", $i, $j, $c1);
28+
}
29+
}
30+
}
31+
?>
32+
--EXPECT--

0 commit comments

Comments
 (0)