-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BmpImagePlugin - Unsupported 32bpp DIBs with Alpha #8594
Comments
Sorry to bother you all with such a niche problem. 😅 For context, the attached bitmap (DIB) comes from one of the themes in Windows XP - I am trying to look into writing a general tool for converting .MSSTYLES based themes to various Linux toolkits. I pinpointed this line of interest in Removing this check for 22 byte header does resolve the issue for me, however it breaks the 32bpp bitmap test case. Unfortunately it seems like the alpha channel behaviour is undocumented, at least I cannot find anything. Both images use the 40-byte BITMAPINFOHEADER, and the only real difference is I don't think this is something easily solvable via parsing the format alone, so I have a fork of Pillow to include I'll submit a corresponding PR, though my solution might be rubbish - I don't use Python all that much. 😝 |
For context, #1125 is the PR that introduced that line of code. Can I ask - how do you know the image should be RGBA? Googling, I found https://jumpshare.com/viewer/bmp, and it showed no transparency when given the file. |
I found https://learn.microsoft.com/en-us/windows/win32/wmdm/-bitmapinfoheader, which describes 32 bitcount as
So it sounds like RGB is the intention. |
Because this DIB comes directly from the resource file Here's a comparison between the current read and what is intended: I know the documentation does not say anything about it, I'm not sure if it was ever formally documented or whether it's just modern MSDN missing stuff. From searching around there's old forum posts and pages on CodeProject (RIP) about these 32bpp bitmaps. I think potentially it is possible to create them in Photoshop, but I'm not sure if that's still the case in newer versions. |
The question I was trying to ask is - what program are you using to view this file that shows transparency? Should I understand your response to mean that you're not viewing them in a program, and your expectation is based on the fact that Windows loads this data and then you see the result in the OS? Not just the transparent corners, but also a transparent inside under some circumstances? |
You caught me just before I finished writing this update. 😛 In that post I compared between |
Hmm. I'm concerned about interpreting data that the documentation says to ignore, because that's what third-party software would follow when creating images, and it's possible that what they write to this fourth channel may not actually work as an alpha channel. So it might fix your image, but it might also break others. What do you think of this code, that will work with Pillow as-is to read your image as RGBA? from PIL import Image, _binary, BmpImagePlugin
filename = "BLUE_RADIOBUTTON25_BMP.bmp"
im = Image.open(filename)
if im.format == "DIB" and im.info["compression"] == BmpImagePlugin.BmpImageFile.COMPRESSIONS["RAW"]:
bits = None
with open(filename, "rb") as fp:
header_size = _binary.i32le(fp.read(4))
if header_size == 40:
header_data = fp.read(header_size - 4)
bits = _binary.i16le(header_data, 10)
if bits == 32:
im._mode = "RGBA"
args = list(im.tile[0].args)
args[0] = "BGRA"
im.tile = [im.tile[0]._replace(args=tuple(args))]
im.save("out.png") |
This was why I opted to add the extra formats to act as 'hints', rather than trying to guess what the interpretation should be - so it cannot break existing images: rozniak@79683d3
It works perfectly. 😄 I mean it's up to you really, I suppose it might not be a very common type of bitmap for people to read so I don't mind working with this snippet in my own project. I did try to keep the change minimal and to avoid breaking any existing images according to spec, depends whether you think it's worth having or not. I suppose there is always this issue thread for future reference otherwise. 😛 |
I've created #8602 as a suggestion - it will retain the current Pillow behaviour by default, but if you run from PIL import BmpImagePlugin
BmpImagePlugin.USE_RAW_ALPHA = True first, then the fourth channel will be read. |
Really appreciate you being so helpful with this problem, I didn't expect much at all considering it's an undocumented use of a niche variant of the file format so I wanted to express my thanks. 😁 |
What did you do?
Attempted to read the attached 32bpp DIB with
Image.open()
(I've plopped it in a ZIP because GitHub doesn't like me just chucking the DIB itself in here)
sampledib.zip
What did you expect to happen?
The image reads as
RGBA
What actually happened?
The image reads as
RGB
What are your OS, Python and Pillow versions?
Locally built Pillow from d66c51a
The text was updated successfully, but these errors were encountered: