Edit report at https://bugs.php.net/bug.php?id=55034&edit=1
ID: 55034
Comment by: php at heavyconsulting dot net
Reported by: php at mrphlip dot com
Summary: ImageCopyResampled doesn't calculate colours
properly with alpha
Status: Open
Type: Bug
Package: GD related
Operating System: Ubuntu Natty
PHP Version: 5.3.6
Block user comment: N
Private report: N
New Comment:
I have this problem on a new server running
Debian Squeeze with php5-gd 5.3.3-7+squeeze8.
I do not have this problem on my older server
running CentOS with php-gd-5.1.6-24.el5_4.5.
The test-script produces the expected result on the old CentOS server, and the
wrong result on the new Debian server.
My application uses imagecopyresampled to rescale and place simple white images
with alpha channel on top of a background image.
This works great on the old server, but on the new one it results in a black
border around the edge of the white graphic.
Previous Comments:
------------------------------------------------------------------------
[2011-06-13 06:38:18] php at mrphlip dot com
Hmm... I've just tried this on a different machine, and it works correctly
there.
I notice that the two machines link to GD differently... on my machine (where
the bug happens), I don't have ImageAntiAlias, but on the other machine (where
it works), I do... which I know is related to how GD is compiled. I'm not sure
whether this is related, but I figure more information can't hurt.
------------------------------------------------------------------------
[2011-06-11 15:53:31] php at mrphlip dot com
Changed summary to be more accurate... it calculates the alpha fine, it's the
colours it doesn't calculate correctly in the presence of an alpha channel.
------------------------------------------------------------------------
[2011-06-11 15:48:17] php at mrphlip dot com
Description:
------------
It appears that ImageCopyResampled uses a naive averaging, which isn't correct
when there is an alpha channel involved. It should instead use a weighted
average for the colour channel, weighting each input pixel according to its
opacity (so a more opaque input pixel has more weight in the average).
This comes up particularly if you have eg a solid white shape against a solid
black-but-transparent background. The original image, every pixel is either
white or transparent. But shrink it down, and the object will have a thin dark
halo around the edge, because of averaging those black pixels into the result.
The expected result would fade from full opacity white, to half opacity white,
to transparent any-colour... but the actual result fades from full opacity
white, to half opacity *grey*, to transparent black.
Test script:
---------------
# create an image with an almost-transparent white pixel and an almost-opaque
black pixel
$img1 = ImageCreateTrueColor(2, 1);
ImageAlphaBlending($img1, FALSE);
ImageSetPixel($img1, 0, 0, ImageColorAllocateAlpha($img1, 255, 255, 255, 0x70));
ImageSetPixel($img1, 1, 0, ImageColorAllocateAlpha($img1, 0, 0, 0, 0x10));
# scale the image down to a single pixel - make it mix the two together
$img2 = ImageCreateTrueColor(1, 1);
ImageAlphaBlending($img2, FALSE);
ImageCopyResampled($img2, $img1, 0, 0, 0, 0, 1, 1, 2, 1);
# find out what colour the resulting pixel is
$col = ImageColorAt($img2, 0, 0);
print "R: " . (($col >> 16) & 0xFF) . "<br>";
print "G: " . (($col >> 8) & 0xFF) . "<br>";
print "B: " . ($col & 0xFF) . "<br>";
print "A: " . (($col >> 24) & 0xFF) . "<br>";
# clean up
ImageDestroy($img1);
ImageDestroy($img2);
Expected result:
----------------
R: 30
G: 30
B: 30
A: 64
Each of the colour channels has been weighted in the average... the
almost-transparent white pixel with a weight of 0xF (0x7F - 0x70), and the
almost-opaque black pixel with a weight of 0x6F (0x7F - 0x10), giving a
weighted average of (255 * 0xF + 0 * 0x6F) / (0xF + 0x6F) == 30. The alpha
channel is averaged in the normal way.
Actual result:
--------------
R: 127
G: 127
B: 127
A: 64
Each channel has been averaged separately, with no regard for the alpha channel.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=55034&edit=1