Skip to content

Commit 86e1f0e

Browse files
committed
Fix #79676: imagescale adds black border with IMG_BICUBIC
We have to loop over all image pixels to avoid the black border. This is also done in external libgd in `_gdScaleOneAxis` and `_gdScalePass`.
1 parent 7ac0fb5 commit 86e1f0e

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ PHP NEWS
1111
- Filter:
1212
. Fixed bug #73527 (Invalid memory access in php_filter_strip). (cmb)
1313

14+
- GD:
15+
. Fixed bug #79676 (imagescale adds black border with IMG_BICUBIC). (cmb)
16+
1417
- OpenSSL:
1518
. Fixed bug #62890 (default_socket_timeout=-1 causes connection to timeout).
1619
(cmb)

ext/gd/libgd/gd_interpolation.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImage
931931
int *p_dst_row = dst->tpixels[row];
932932
unsigned int x;
933933

934-
for (x = 0; x < dst_width - 1; x++) {
934+
for (x = 0; x < dst_width; x++) {
935935
register unsigned char r = 0, g = 0, b = 0, a = 0;
936936
const int left = contrib->ContribRow[x].Left;
937937
const int right = contrib->ContribRow[x].Right;
@@ -967,7 +967,7 @@ static inline int _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigne
967967
return 0;
968968
}
969969
/* Scale each row */
970-
for (u = 0; u < dst_height - 1; u++) {
970+
for (u = 0; u < dst_height; u++) {
971971
_gdScaleRow(pSrc, src_width, pDst, dst_width, u, contrib);
972972
}
973973
_gdContributionsFree (contrib);
@@ -977,7 +977,7 @@ static inline int _gdScaleHoriz(gdImagePtr pSrc, unsigned int src_width, unsigne
977977
static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImagePtr pRes, unsigned int dst_width, unsigned int dst_height, unsigned int uCol, LineContribType *contrib)
978978
{
979979
unsigned int y;
980-
for (y = 0; y < dst_height - 1; y++) {
980+
for (y = 0; y < dst_height; y++) {
981981
register unsigned char r = 0, g = 0, b = 0, a = 0;
982982
const int iLeft = contrib->ContribRow[y].Left;
983983
const int iRight = contrib->ContribRow[y].Right;
@@ -1014,7 +1014,7 @@ static inline int _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_wi
10141014
return 0;
10151015
}
10161016
/* scale each column */
1017-
for (u = 0; u < dst_width - 1; u++) {
1017+
for (u = 0; u < dst_width; u++) {
10181018
_gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
10191019
}
10201020
_gdContributionsFree(contrib);

ext/gd/tests/bug79676.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug #79676 (imagescale adds black border with IMG_BICUBIC)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('gd')) die('skip gd extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
function test($image, $desc)
10+
{
11+
echo "$desc - Test Result: ",
12+
(imagecolorat($image, imagesx($image) - 1 , imagesy($image) - 1) != 0x000000 ? 'pass' : 'fail'),
13+
PHP_EOL;
14+
}
15+
16+
$size = 32;
17+
$src = imagecreatetruecolor($size, $size);
18+
imagefilledrectangle($src, 0, 0, $size - 1 , $size - 1, 0xff00ff);
19+
20+
test($src, 'No scaling');
21+
test(imagescale($src, $size * 2, $size * 2), 'Scale 200%, default mode');
22+
test(imagescale($src, $size / 2, $size / 2), 'Scale 50%, default mode');
23+
test(imagescale($src, $size * 2, $size * 2, IMG_BICUBIC), 'Scale 200%, IMG_BICUBIC mode');
24+
test(imagescale($src, $size / 2, $size / 2, IMG_BICUBIC), 'Scale 50%, IMG_BICUBIC mode');
25+
?>
26+
--EXPECT--
27+
No scaling - Test Result: pass
28+
Scale 200%, default mode - Test Result: pass
29+
Scale 50%, default mode - Test Result: pass
30+
Scale 200%, IMG_BICUBIC mode - Test Result: pass
31+
Scale 50%, IMG_BICUBIC mode - Test Result: pass

0 commit comments

Comments
 (0)