From: Operating system: Ubuntu Natty PHP version: 5.3.6 Package: GD related Bug Type: Bug Bug description:ImageCopyResampled doesn't calculate alpha properly
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 bug report at http://bugs.php.net/bug.php?id=55034&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=55034&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=55034&r=trysnapshot53 Try a snapshot (trunk): http://bugs.php.net/fix.php?id=55034&r=trysnapshottrunk Fixed in SVN: http://bugs.php.net/fix.php?id=55034&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=55034&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=55034&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=55034&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=55034&r=needscript Try newer version: http://bugs.php.net/fix.php?id=55034&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=55034&r=support Expected behavior: http://bugs.php.net/fix.php?id=55034&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=55034&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=55034&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=55034&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=55034&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=55034&r=dst IIS Stability: http://bugs.php.net/fix.php?id=55034&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=55034&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=55034&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=55034&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=55034&r=mysqlcfg
