You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(imageops): premultiply alpha in blur to prevent color bleed - #3107
Problem:DynamicImage::blur convolves RGBA subpixels without premultiplying alpha, so fully-transparent pixels bleed their color into opaque neighbors (#2324). A white rectangle on a transparent-red background picks up a red tint at its edges.
Fix: premultiply by alpha before the Gaussian convolution and unpremultiply after, mirroring what resize already does (added in #2639). The existing premultiply_alpha/unpremultiply_alpha/has_constant_alpha helpers in resize.rs are reused (made pub(crate)); premultiplication is skipped when the alpha channel is constant.
Tests: added blur_does_not_bleed_color_from_transparent_pixels; verified it fails without the fix. cargo fmt, clippy, and the imageops suite are green.
The cargo-deny red is a pre-existing duplicate in the dependency tree — miniz_oxide 0.8.9 and 0.9.1 are pulled in by different transitive dependencies. This PR is source-only (two files under src/imageops/) and doesn't touch any dependency, so it isn't introduced by this change. Let me know if you'd like anything adjusted.
The failing cargo-deny check is unrelated to this PR. It's the [bans] multiple-versions rule firing on miniz_oxide (0.8.9 via exr/png vs 0.9.1 via flate2) — both pre-existing transitive deps. This change only touches src/imageops/{sample,resize}.rs and adds no dependency (no Cargo.toml/Cargo.lock diff), so it can't introduce or resolve the duplicate. Resolving it (a skip entry in deny.toml, or converging the miniz_oxide requirement) seems like a separate maintainer decision, out of scope for this color-bleed fix.
I also added a small deny.toml hunk to unblock the cargo-deny check: png/exr still pin miniz_oxide 0.8 while flate2 pulls 0.9, so the duplicate is unavoidable from this crate until png bumps. I skipped it the same way syn is already skipped. Happy to drop that hunk if you'd rather handle the dedup separately from this blur fix.
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
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.
Problem:
DynamicImage::blurconvolves RGBA subpixels without premultiplying alpha, so fully-transparent pixels bleed their color into opaque neighbors (#2324). A white rectangle on a transparent-red background picks up a red tint at its edges.Fix: premultiply by alpha before the Gaussian convolution and unpremultiply after, mirroring what
resizealready does (added in #2639). The existingpremultiply_alpha/unpremultiply_alpha/has_constant_alphahelpers inresize.rsare reused (madepub(crate)); premultiplication is skipped when the alpha channel is constant.Tests: added
blur_does_not_bleed_color_from_transparent_pixels; verified it fails without the fix.cargo fmt,clippy, and theimageopssuite are green.Closes #2324