Demilade Sonuga's blog

All posts

A Few Things About Bitmap Images

2022-12-09

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:

BytesDescription
0..2This is used to identify the file as a BMP file. It will always be 0x42, 0x4d, which is BM in the ASCII encoding
2..6This is the size of the whole BMP file in bytes
6..10Reserved
10..14The 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:

BytesDescription
0..4The size of this DIB header
4..8The width of the image
8..12The height of the image
12..14A number that is always 1
14..16The 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..120Some fields we don't need to concern ourselves with
120..124Reserved

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