Repository navigation
Conversation
Gd\Image::paste() routed 0 < alpha < 100 through imagecopymerge(), which ignores the source's per-pixel alpha and resolves every touched destination pixel as fully opaque. Pasting an overlay over a base that has transparency therefore washed the transparent regions into an opaque block (near-white for a typical PNG whose transparent pixels are stored white). Fade the overlay's own alpha channel by the opacity factor and paste it at full opacity through the alpha-aware imagecopy() path instead, so the base's transparency survives. Mirrors the Imagick change in php-imagine#878. Add testPasteWithAlphaPreservesTransparentBase covering a transparent destination, companion to the existing opaque-base test.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GD counterpart of #878, which fixed the same thing for Imagick. Found it while pasting a watermark over a transparent PNG.
Problem:
Gd\Image::paste($image, $start, $alpha)sends0 < alpha < 100throughimagecopymerge(). That function only reads the source RGB (it ignores the source per-pixel alpha), and every destination pixel it touches ends up opaque. So when the base has transparency, the area under the overlay is forced opaque and its color gets pulled towards whatever RGB the transparent base stored, which is white for a normal PNG. You end up with an opaque near-white block where the paste happened. An opaque base (a JPEG) is fine, it only breaks when the base itself has transparency.Minimal repro:
Fix: fade the overlay's own alpha channel by the opacity factor, then paste at full opacity so it goes through the alpha-aware
imagecopy()path instead ofimagecopymerge(). I clone the overlay first so the caller's image is left untouched. Same approach as #878 did for Imagick (evaluateImage(MULTIPLY, factor, CHANNEL_ALPHA)then composite), and as Intervention/image#1489 did for GD. GD has no native equivalent of Imagick'sevaluateImage()on the alpha channel, so the overlay alpha is scaled pixel by pixel.Opaque bases behave exactly as before,
testPasteWithAlphaandtestPasteWithAlphaPreservesTransparencystill pass with the same values.Testing: I added
testPasteWithAlphaPreservesTransparentBasenext to the existing opaque-base test, inAbstractImageTestso every driver runs it. It fails on GD before the change, passes on Imagick, and is skipped on Gmagick (no alpha paste there). Full suite is green in the8.1-gd-imagickdocker image (GD bundled 2.1 compatible), 783 tests, and I also ran it against a newer GD (2.3.3) locally.