I tried to create a 16-bit bitmap and searched for an online converter. I found https://online-converting.com/image/convert2bmp/, which can convert to RGB565. But the file produced by it couldn't be read by tinybmp: I got ParseError::UnexpectedEndOfFile. Because of that, I later converted to RGB565 using GIMP, which worked. But since the format produced by online-converting.com seems to be valid according to my inspection of it using ImHex, which can decode and visualize the bitmap struct fields, and because XnView can display it, I'm posting this issue.
How to create an RGB565 bitmap with online-converting.com:
- Go to https://online-converting.com/image/convert2bmp/.
- Deselect the checkbox "Automatically start" at the bottom of the form before uploading any file.
- In the "Color" drop-down box, choose "16 (5:6:5, RGB Hi color)".
- Upload a file.
- Click "Convert".
Here's an image I converted: 5x1px-16bpp-rgb565.bmp.
The file uses the BITMAPINFOHEADER. For it's biCompression member, which contains BI_BITFIELDS, Microsoft documents:
| Value |
Meaning |
| BI_RGB |
Uncompressed RGB. |
| BI_BITFIELDS |
Uncompressed RGB with color masks. Valid for 16-bpp and 32-bpp bitmaps. |
[...]
For 16-bpp bitmaps, if biCompression equals BI_RGB, the format is always RGB 555. If biCompression equals BI_BITFIELDS, the format is either RGB 555 or RGB 565. Use the subtype GUID in the AM_MEDIA_TYPE structure to determine the specific RGB type.
Since we're not decoding video and there's no AM_MEDIA_TYPE, this isn't very helpful. But there are hints about how to handle BI_BITFIELDS when only having BITMAPINFOHEADER:
- In an old Windows CE documentation for
BITMAPINFOHEADER, it says under biCompression:
| Value |
Description |
| BI_RGB |
An uncompressed format. |
| BI_BITFIELDS |
Specifies that the bitmap is not compressed and that the color table consists of three DWORD color masks that specify the red, green, and blue components of each pixel. This is valid when used with 16- and 32-bpp bitmaps. |
- In the "Color table" section of Wikipedia's "BMP file format" article, its says:
The color table (palette) occurs in the BMP image file directly after the BMP file header, the DIB header, and after the optional three or four bitmasks if the BITMAPINFOHEADER header with BI_BITFIELDS (12 bytes) or BI_ALPHABITFIELDS (16 bytes) option is used. Therefore, its offset is the size of the BITMAPFILEHEADER plus the size of the DIB header (plus optional 12-16 bytes for the three or four bit masks).
I didn't dive into your code in detail, but your src/header/dib_header.rs only knows HeaderType::Info and HeaderType::V3 and not HeaderType::V2, and it has this bit of code:
let (_dib_header_data, channel_masks) = if header_type.is_at_least(HeaderType::V3)
&& matches!(compression_method, CompressionMethod::Bitfields)
{
let (dib_header_data, mask_red) = try_const!(le_u32(dib_header_data));
let (dib_header_data, mask_green) = try_const!(le_u32(dib_header_data));
let (dib_header_data, mask_blue) = try_const!(le_u32(dib_header_data));
let (dib_header_data, mask_alpha) = try_const!(le_u32(dib_header_data));
(
dib_header_data,
Some(ChannelMasks {
red: mask_red,
green: mask_green,
blue: mask_blue,
alpha: mask_alpha,
}),
)
} else {
(dib_header_data, None)
};
But the "DIB header (bitmap information header)" section of the Wikipedia article also lists a BITMAPV2INFOHEADER, which only added "RGB bit masks," whereas, the BITMAPV3INFOHEADER added the single additional "alpha channel bit mask." So, it seems, tinybmp needs to differentiate between just interpreting the first 3 vs. the first 4 RGBQUADs from BITMAPINFO. Adding HeaderType::V2 seems to be incorrect, because your code reads dib_header_length, which would still be sizeof(BITMAPINFOHEADER). As a quick assessment, you'd need to remove the first part of the condition if header_type.is_at_least(HeaderType::V3) && matches!(compression_method, CompressionMethod::Bitfields) and then only retrieve mask_alpha, if header_type.is_at_least(HeaderType::V3) is true.
I tried to create a 16-bit bitmap and searched for an online converter. I found https://online-converting.com/image/convert2bmp/, which can convert to RGB565. But the file produced by it couldn't be read by
tinybmp: I gotParseError::UnexpectedEndOfFile. Because of that, I later converted to RGB565 using GIMP, which worked. But since the format produced by online-converting.com seems to be valid according to my inspection of it using ImHex, which can decode and visualize the bitmap struct fields, and because XnView can display it, I'm posting this issue.How to create an RGB565 bitmap with online-converting.com:
Here's an image I converted: 5x1px-16bpp-rgb565.bmp.
The file uses the
BITMAPINFOHEADER. For it'sbiCompressionmember, which containsBI_BITFIELDS, Microsoft documents:Since we're not decoding video and there's no
AM_MEDIA_TYPE, this isn't very helpful. But there are hints about how to handleBI_BITFIELDSwhen only havingBITMAPINFOHEADER:BITMAPINFOHEADER, it says underbiCompression:I didn't dive into your code in detail, but your
src/header/dib_header.rsonly knowsHeaderType::InfoandHeaderType::V3and notHeaderType::V2, and it has this bit of code:But the "DIB header (bitmap information header)" section of the Wikipedia article also lists a
BITMAPV2INFOHEADER, which only added "RGB bit masks," whereas, theBITMAPV3INFOHEADERadded the single additional "alpha channel bit mask." So, it seems,tinybmpneeds to differentiate between just interpreting the first 3 vs. the first 4RGBQUADs fromBITMAPINFO. AddingHeaderType::V2seems to be incorrect, because your code readsdib_header_length, which would still besizeof(BITMAPINFOHEADER). As a quick assessment, you'd need to remove the first part of the conditionif header_type.is_at_least(HeaderType::V3) && matches!(compression_method, CompressionMethod::Bitfields)and then only retrievemask_alpha, ifheader_type.is_at_least(HeaderType::V3)is true.