Fix BitmapXLib::GetPixel mistagging 32-bit pixels as RGB colorspace - #12
Open
ElCruncharino wants to merge 1 commit into
Open
ElCruncharino wants to merge 1 commit into
ElCruncharino wants to merge 1 commit into
Conversation
The alpha byte was OR'd into a Long returned as a Color that defaults to the RGB colorspace tag when constructed from a bare Long, even though it carries real alpha data. Color::ConvertTo(RGB) trusts that tag and returns RGB-space colors unchanged, so any comparison against an alpha-stripped color (e.g. Bitmap::ReplaceColor matching a mask color) silently failed for every pixel with non-zero alpha - exactly the ones that are visible.
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.
Problem
For 32-bit (RGBA) bitmaps,
BitmapXLib::GetPixel()builds its return value like this:The
Color(r, g, b, colorSpace)constructor packsr/g/binto the low 24 bits but does not encode the passedcolorSpaceinto the packedLongvalue at all - it's tracked separately as an object member. Once thisColorgets implicitly converted toLong(viaoperator Long()) and OR'd with the alpha byte, the result is a plainLong, which is then implicitly converted back to aColorviaColor(Long, ColorSpace = RGB)- defaulting to the RGB colorspace tag, even though the value carries real alpha data in its high byte.Color::ConvertTo(RGB)trusts this tag: for an already-RGB-tagged color it just returns the object unchanged (assuming no alpha content), instead of stripping the alpha bits. So any code that comparesGetPixel(...).ConvertTo(RGB)against a reference color (e.g.Bitmap::ReplaceColor, which matches pixels by RGB while preserving their alpha) silently fails to match any pixel with non-zero alpha - i.e. every visible pixel in a typical antialiased icon/mask image. Only fully transparent pixels (alpha == 0) happen to compare equal by coincidence.Fix
Construct the
Longvalue directly and passColor::RGBAexplicitly to theColor(Long, ColorSpace)constructor, so the returned color is correctly tagged andConvertTo(RGB)properly strips the alpha bits as intended.Impact
This affects any caller on Linux/X11 that reads back pixel colors from a 32-bit bitmap and expects alpha-aware comparisons to work correctly - most notably
Bitmap::ReplaceColor(), which is the documented way to recolor a monochrome icon (solid color + alpha mask) at runtime, e.g. for theme-adaptive icon tinting. Before this fix,ReplaceColor()silently did nothing on any bitmap loaded through this backend.