Bitmap file structure

# Bitmap Image Overview
Image files can be any type of extension like JPEG, PNG, SVG, TIFF, GIF, and BMP.

In terms of learning image-processing, Bitmap File (BMP) is the best selection because the file structure is the most simple format.

* **No compression of data**
* **Pixcel data are lined up in a liner sequence**

This article explains how a bitmap file is organized and what data exists in binary file.

# Color Image and Grayscale Image

There are two type of images to be handled:

* Color Image
* Grayscale Image

<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/45fb4cf7-e927-3199-2ea3-25f59749d3f1.png" alt="grayscale image" style="margin: 10px 10px">

<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/c011f162-80a8-3c5a-ce26-924da0a799a2.png" alt="color image" style="margin: 10px 10px">

In grayscale images, each pixcel value is called **brightness** or **gray value** in this article.

# Bit depth

To express each pixcel color or brightness, needs to determine how many bits one pixcel can have. 8-bit grayscale image, for example, can express from *0b'0000_0000* to *0b'1111_1111* value in binary number, which is equal to *0* to *255* in decimal number. This value *8* is exactly what we call **bit depth** or **bit count**.

In generally, 24 bits are assigned to a pixcel of color image, which can express 16,777,216

Furthermore, color images consist of three color values, **Red**, **Green**, and **Blue**. 24 bits are split into 8-bit Red, 8-bit Green, and 8-bit Blue information like below:

`rgb(255,0,0)` `rgb(0,255,0)`
`rgb(0,0,255)` `rgb(255,255,0)`
`rgb(255,0,255)` `rgb(0,255,255)`

Available bit depth in Bitmap is shown below:
| bit depth | color number | color table |
|:-:|:-:|:-:|
| 1 | 2  | required |
| 4 | 16 | required |
| 8 | 256 | required |
| 16 | 65,536  | optional|
| 24 | 16,777,216  | optional |

# Environment
To analyze bitmap file structure, i use [this image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/45fb4cf7-e927-3199-2ea3-25f59749d3f1.png) and you can also do it. However, this file will be downloaded as `png`.


So firstly, you need to convert this png into `bmp`. Refer to the article: [Convert any images into bitmap file](https://qiita.com/Jun2401/items/9a7aa04724db25265f7f) to convert png into bmp file.

To open the file's binary sequence, you need to open it with binary editor. This article uses **Hex Editor** as binary editor. This is [the article](https://qiita.com/Jun2401/items/38a5b555884c6a99b136) that guides you how to install it in VS code as extension.


# Bitmap Header

Most binary files have header compartment at the beginning of the file, which holds information like file size, file format, etc. Likely, Bitmap file must have following two header parts.

* **File header**
* **Info header**

Here is how the bitmap header looks like in Hex Editor. Initially, 1 row displays 16 bytes data. This bitmap file has 54 bytes of header parts.
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/cc154253-aa4a-0ca6-5a1e-4ae53da43362.jpeg">


## File Header
File Header has information that the file is images and its format is bitmap file, while Info Header has information about image details.
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/700f7d47-0e1f-1fdf-87a9-c37e5691884a.jpeg">

| property | size [byte] | value | meaning |
|:-:|:-|:-|:-|
| bfType | 2 | 0x 42 4D | "BM" in ascii code |
| bfSize | 4 | 0x 56 88 1B 00 | total file size |
| bfReserve1  | 2 | 0x 00 00  | area for future expansion (always 0)|
| bfReserve2  | 2 | 0x 00 00  | area for future expansion (always 0)|
| bfOffbits  | 4 | 0x 36 00 00 00  | offset size before emergence of data |

Numerical property is expressed in **Little Endian**. To calculate real value of bfSize, each byte needs to be reversed like this:

raw seqence: `0x 56 88 1B 00`
reveresed: `0x 00 1B 88 56`

These values are still hexadecimal number, so convert the value into decimal number:

`0x 00:` $0 \times 16 + 0 = 0$
`0x 1B:` $1 \times 16 + 11 = 27$
`0x 88:` $8 \times 16 + 8 = 136$
`0x 56:` $5 \times 16 + 6 = 86$

`0x 00 1B 88 56:` $27 \times 256^{2} + 136 \times 256^{1} + 86 = 1,804,374 $

Now you  know that bfSize value, which is total file size, is `1,804,374 [byte]`, which is approximately 1.72[MB]. You can also use windows' calculate to convert hexadecimal number into decimal number.

![header4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/38d50f63-098c-8c7c-d307-2587ea63fbf0.jpeg)

`bfOffbits` is also turned out that the value is `54 [byte]` in decimal number, which is equal to the entire header size of this bitmap. This means, after the end of header section, data section is coming soon afterwordly.

Please note relation between hexadecimal number and decimal number if needed:

| hex | dec | | hex | dec|| hex | dec|||dec|hex|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 0x00  | 0 || 0x08  | 8 || 0x10 | 16 |||0xf8|248|
| 0x01  | 1  || 0x09 | 9 || 0x11 | 17 |||0xf9|249|
| 0x02  | 2  || 0x0a | 10 || 0x12 | 18 |||0xfa|250|
| 0x03  | 3  || 0x0b | 11 || 0x13 | 19 |||0xfb|251|
| 0x04  | 4  || 0x0c | 12 || 0x14 | 20 |||0xfc|252|
| 0x05  | 5  || 0x0d | 13 || 0x15 | 21 |||0xfd|253|
| 0x06  | 6  || 0x0e | 14 || 0x16 | 22 |||0xfe|254|
| 0x07  | 7  || 0x0f | 15 || 0x17 | 23 |||0xff|255|
## Info Header
Regarding to info header, there are actually [4 types header](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmap-header-types) available. But this article only focuses on one header type, *BITMAPINFOHEADER*, whose size is fixed as **40 bytes** and supported by other standard application.

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/19314335-872f-cb06-b33b-6ba267d4267f.jpeg">


:::note info
Header Size
File header: 14 bytes
Info header: 40 bytes
Sum of  these: 54 bytes
:::

# Data Section

Since bit count is 24 bit, first 3 bytes is corresponding to 1 pixcel. To comlicated, **first byte is Blue, and last byte is Red**. The first pixcel of next images, for example, expresses `red: 0xff`, `green: 0xf7`, `blue: 0xb4` and this color looks like `rgb(255,247,180)`
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/bf4ae528-35e8-44fd-8f59-d675c0473e2a.jpeg">

But in what order pixcel are displayed on bitmap? This answer demonstrates next images. Beginning from left bottom pixcel, go right along width direction, then go one step up along hight direction.
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3567519/65940de0-8c8c-46b9-592b-7e2ba1e58cd2.jpeg" width="400">
This image is just expressing the order of appearance pixcel in binary file and its position on bitmap. In actual bitamp image, it can be possible that padding byte is existing on the leftside of images.