Demilade Sonuga's blog
All postsA Few Things About Bitmap Images
Soon, we'll finally start drawing images on the screen but before we do that, we first need to understand some things about the bitmap file format, which is the format we'll be dealing with.
There are quite a number of image file formats like png, jpeg, and gif, but their compression, although making them smaller and more efficient for transfer, makes them harder to work with. We're sticking with the BMP format here because they are not compressed (most of the time).
Let's begin by asking a question: What exactly is a bitmap? A bitmap is a representation of some object (in our case, images) with just bits. Now, what exactly is an image: An image, from our perspective, is a 2D array of colors. The first row of an image is made up of colors. The second row is the same. And it goes all the way down to the last row. The way the colors are represented may vary and that's why we have file formats: to know precisely what the bits in specific pre-defined areas of the file mean.
A BMP file starts with a bunch of bits called the Bitmap file header:
Bytes | Description |
---|---|
0..2 | This is used to identify the file as a BMP file. It will always be 0x42, 0x4d, which is BM in the ASCII encoding |
2..6 | This is the size of the whole BMP file in bytes |
6..10 | Reserved |
10..14 | The offset into the file of the starting byte of the bitmap pixel array |
This just gives some general information about the file and the location of the actual pixel array in the file, that is the bits that describe the colors of the pixels in the rows of the image.
The next segment of the BMP file is the DIB header. The BMP file format is an old image format that has been around since the 1990s, so unsurprisingly, there are different variants of it. This DIB header comes in a few different flavors, but the one we'll be looking at is the BITMAPV5HEADER.
In a BMP file, the number of bits used to represent the color of a single pixel can be 1, 4, 8, 16, 24 or 32. We'll only consider values of 8 here.
The DIB header:
Bytes | Description |
---|---|
0..4 | The size of this DIB header |
4..8 | The width of the image |
8..12 | The height of the image |
12..14 | A number that is always 1 |
14..16 | The number of bits used to define a single pixel. We're assuming this will always be 8. When this field is 8, the color value of a pixel, rather than representing the actual color, will be used as an index into a structure in the file called the color table, which will give the actual color description |
16..120 | Some fields we don't need to concern ourselves with |
120..124 | Reserved |
Immediately after the DIB header is a structure called the color table. This is an array of bitmap colors. Each color in the array is represented by 4 consecutive bytes: the blue intensity, the green intensity, the red intensity and an 8-bit reserved field. It looks like this:
#[repr(C)]
struct Color {
blue: u8,
green: u8,
red: u8,
reserved: u8
}
Each entry in the color table has a unique index, just like any normal array. The number of entries is at most 2^n, where n is the number of bits per pixel. This bits per pixel value can be found in the DIB header at offset 14..16. For this project, the bits per pixel are assumed to be 8 and the number of entries is assumed to always be 2^8 == 256.
The pixel array is the last component of the BMP file. This is an array that describes the image's colors from the last row to the first. So, the first row of pixels is the last in the actual image. The next is the second to the last, and so on.
This pixel array will be an array of 8-bit values (because our bits per pixel is 8), and each value is interpreted as an offset into the color table which will give the bits that describe the actual color of a pixel.
After parsing a BMP file, all that will be left to draw the image on the screen is to iterate over the pixel array from bottom to top (because the rows are upside down) use the values to index into the color table and from there interpret that color into the UEFI pixel format, then put those pixel instances into the video memory.
Take Away
- BMP is an image file format that stores images as arrays of pixels, along with some metadata to use to interpret those arrays.
- The BMP pixel array is upside down, that is, the first row of the image is represented by the last row of the pixel array, and so on.
- The color table is an array of structures that describe the red, blue, and green intensities of colors used in the bitmap
- In an 8-bit per pixel BMP file, the values in the pixel array are indexed into the color table.
In the Next Post
We'll draw some bitmaps on screen.
References
- https://en.wikipedia.org/wiki/BMP_file_format
- https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header