Skip to content

Commit

Permalink
Fix #53580: During resize gdImageCopyResampled cause colors change
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cmb69 committed Aug 26, 2021
1 parent 3677db6 commit 526407c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 21 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ PHP NEWS
(cmb)
. Fixed bug #73122 (Integer Overflow when concatenating strings). (cmb)

-GD:
. Fixed bug #53580 (During resize gdImageCopyResampled cause colors change).
(cmb)

- Opcache:
. Fixed bug #81353 (segfault with preloading and statically bound closure).
(Nikita)
Expand Down
21 changes: 6 additions & 15 deletions ext/gd/libgd/gd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2612,7 +2612,6 @@ void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, i
green /= spixels;
blue /= spixels;
alpha /= spixels;
alpha += 0.5;
}
if ( alpha_sum != 0.0f) {
if( contrib_sum != 0.0f) {
Expand All @@ -2622,20 +2621,12 @@ void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, i
green /= alpha_sum;
blue /= alpha_sum;
}
/* Clamping to allow for rounding errors above */
if (red > 255.0f) {
red = 255.0f;
}
if (green > 255.0f) {
green = 255.0f;
}
if (blue > 255.0f) {
blue = 255.0f;
}
if (alpha > gdAlphaMax) {
alpha = gdAlphaMax;
}
gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
/* Round up closest next channel value and clamp to max channel value */
red = red >= 255.5 ? 255 : red+0.5;
blue = blue >= 255.5 ? 255 : blue+0.5;
green = green >= 255.5 ? 255 : green+0.5;
alpha = alpha >= gdAlphaMax+0.5 ? 255 : alpha+0.5;
gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int)red, (int)green, (int)blue, (int)alpha));
}
}
}
Expand Down
7 changes: 1 addition & 6 deletions ext/gd/libgd/gd_png.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,12 +728,7 @@ void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level, int basefilte
*/
a = gdTrueColorGetAlpha(thisPixel);
/* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */
if (a == 127) {
*pOutputRow++ = 0;
} else {
*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
}

*pOutputRow++ = 255 - ((a << 1) + (a >> 6));
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions ext/gd/tests/bug53580.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
Bug #53580 (During resize gdImageCopyResampled cause colors change)
--SKIPIF--
<?php
if (!extension_loaded('gd')) die("skip gd extension not available");
if (!GD_BUNDLED && version_compare(GD_VERSION, "2.3.2") <= 0) {
die("skip test requires GD > 2.3.2");
}
?>
--FILE--
<?php
$w0 = 100;
$h0 = 100;
$w1 = 150;
$h1 = 150;
$c0 = 0xffffff;

$im0 = imagecreatetruecolor($w0, $h0);
imagefilledrectangle($im0, 0, 0, $w0 - 1, $h0 - 1, $c0);

$im1 = imagecreatetruecolor($w1, $h1);
imagecopyresampled($im1, $im0, 0, 0, 0, 0, $w1, $h1, $w0, $h0);

for ($i = 0; $i < $w1; $i++) {
for ($j = 0; $j < $h1; $j++) {
if (($c1 = imagecolorat($im1, $i, $j)) !== $c0) {
printf("%d,%d = %d\n", $i, $j, $c1);
}
}
}
?>
--EXPECT--

0 comments on commit 526407c

Please sign in to comment.