Skip to content

ICO: Handle 0RGB format#3012

Open
RunDevelopment wants to merge 3 commits into
image-rs:mainfrom
RunDevelopment:ico-0rgb
Open

ICO: Handle 0RGB format#3012
RunDevelopment wants to merge 3 commits into
image-rs:mainfrom
RunDevelopment:ico-0rgb

Conversation

@RunDevelopment

Copy link
Copy Markdown
Member

While reviewing #3002, I realized that we don't decode 0RGB BMPs correctly.

See https://devblogs.microsoft.com/oldnewthing/20101021-00/?p=12483

To use an alpha-blended image, just drop in a ARGB 32bpp bitmap instead. When the window manager sees a 32bpp bitmap, it looks at the alpha channel. If it’s all zeroes, then it assumes that the image is in 0RGB format; otherwise it assumes it is in ARGB format. Everything else remains the same as for the non-alpha version. Note carefully that everything else remains the same.

Not only did we not apply the AND mask for 0RGB, we also didn't ignore the all-zero fourth channel.

This PR fixes this by (1) detecting 0RGB, (2) fixing up the alpha channel for 0RGB, and (3) applying the AND mask for 0RGB.

I added a test image for this that is either fully transparent or shows the word "BAD" when decoded incorrectly (depending on how incorrectly it is decoded) and a happy white smiley when decoded correctly.


I also added a reference for the image added in #3002, because our dumb test infra still doesn't detect this.

@197g

197g commented Jun 13, 2026

Copy link
Copy Markdown
Member

I don't understand that this alone is how it works, from the description.

In other words, the image format consists of a BITMAPINFOHEADER where the bmWidth is the width of the image and bmHeight is double the height of the image, followed by the bitmap color table, followed by the image pixels, followed by the mask pixels.

Rather, this seems to be the detection mechanism. Indeed, it is allowed but dubious to use an image color for a masked-away pixel as in the last line of the table:

mask image result operation
0 Q (screen AND 0) XOR Q = Q copy from icon
1 0 (screen AND 1) XOR 0 = screen nop
1 Q (screen AND 1) XOR Q = screen XOR Q dubious

@197g

197g commented Jun 13, 2026

Copy link
Copy Markdown
Member

That is: alpha-blended images are an evolution on 0RGB images and Windows has learned to interpret the 'dubious' row of the above table to do true blending but the mask for all of this would still follow in the mask. What's confusing to me here is that this only matters for compositing onto existing data. Or put another way: which of DI_NORMAL, DI_IMAGE, DI_MASK do we want to do?

@RunDevelopment

Copy link
Copy Markdown
Member Author

Ahh, I messed up. 0RGB has nothing to do with AND mask, so the detection should be done unconditionally.

I think this is also where your questions about the mask come from. To quote from part 2:

Supported color formats are 4bpp, 8bpp, 16bpp, and 0RGB 32bpp. Note that 24bpp is not supported; you’ll have to convert it to a 0RGB 32bpp bitmap.

So 0RGB is just a color format like R5G6B5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants