Python code to read .bmp info from header (work on Desktop Python and MicroPython)

This exercise read header of bmp file to get information about the image, such as image width and height, number of bit per pixel, specially offset, such that we can get the bitmap image later. This help me understanding more about bmp file structure.

For the BMP file format, I reference https://en.wikipedia.org/wiki/BMP_file_format.


Exercise Code:

The Python code work on desktop Python and MicroPython, tested on:
- Python 3.13.0 on Windows 11
- MicroPython v1.24.0 on Raspberry Pi Pico2 with RP2350

py_bmp_info.py

"""
Python/MicroPython exercise to read bmp file and get the bmp info,
to understand the structure of bmp header.

Work on both:
- desktop Python (tested on Windows 11)
  .bmp image have to be save in 'images' directory under working directory.
- MicroPython (tested on Raspberry Pi Pico2 with RP2350 running MicroPython v1.24.0 on 2024-10-25
)
  .bmp files have to be saved in /images/ directory.

To prepare the bmp using GIMP:
-> Image > Mode > RGB
-> Export as .bmp
   Compatibility Options > Do not write color space information - checked
   Advanced Options > 16 bits > R5 G6 B5
                 or > 24 bits > R8 G8 B8
                 
ref: https://en.wikipedia.org/wiki/BMP_file_format
I follow the table of "Windows BITMAPINFOHEADER"

"""

import sys, platform

print("=============================================")
print("Running on: ", platform.platform())
print("=============================================")

if sys.implementation.name == 'cpython':
    # for desktop Python, images stored in 'images' folder under current folder
    img_path = 'images/'
else:
    # for MicroPython, images stored in 'images' folder under root
    img_path = '/images/'

bmp_file = img_path + 'img_01_240_RGB888.bmp'

def read_bmp(filename):
    print("Read:", filename)
    with open(filename, 'rb') as f:
        bmp_data = f.read()
    return bmp_data

def get_compression_method(num):
    switcher = {
        0: "BI_RGB",
        1: "BI_RLE8",
        2: "BI_RLE4",
        3: "BI_BITFIELDS",
        4: "BI_JPEG",
        5: "BI_PNG",
        6: "BI_ALPHABITFIELDS",
        11: "BI_CMYK",
        12: "BI_CMYKRLE8",
        13: "BI_CMYKRLE4",
        }
    
    return switcher.get(num, "unknown")

bmp_data = read_bmp(bmp_file)
#buffer = bytearray(bmp_data)
print("len(bmp_data)", type(bmp_data), len(bmp_data))
#print(bmp_data)
print("Signature:",chr(bmp_data[0]), chr(bmp_data[1]))

size_of_bmp_file = int.from_bytes(bmp_data[2:6], 'little')
print("--- size_of_bmp_file = ", size_of_bmp_file)

print("Reserved:", bmp_data[6], bmp_data[7])
print("Reserved:", bmp_data[8], bmp_data[9])

offset = int.from_bytes(bmp_data[10:14], 'little')
print("--- offset = ", offset)

size_of_header = int.from_bytes(bmp_data[14:18], 'little')
print("--- size_of_header:", size_of_header)

image_width = int.from_bytes(bmp_data[18:22], 'little')
print("--- image_width:", image_width)
image_height = int.from_bytes(bmp_data[22:26], 'little')
print("--- image_height:", image_height)

number_of_color_planes = int.from_bytes(bmp_data[26:28], 'little')
print("--- number_of_color_planes (must be 1):", number_of_color_planes)

num_of_bits_per_pixel = int.from_bytes(bmp_data[28:30], 'little')
print("--- num_of_bits_per_pixel:", num_of_bits_per_pixel)

compression_method = int.from_bytes(bmp_data[30:34], 'little')
print("--- compression_method:", compression_method, get_compression_method(compression_method))

image_size = int.from_bytes(bmp_data[34:38], 'little')
print("--- image_size:", image_size)

horizontal_resolution = int.from_bytes(bmp_data[38:42], 'little')
print("--- horizontal_resolution:", horizontal_resolution)
vertical_resolution = int.from_bytes(bmp_data[42:46], 'little')
print("--- vertical_resolution:", vertical_resolution)

number_of_colors = int.from_bytes(bmp_data[46:50], 'little')
print("--- number_of_colors:", number_of_colors)
number_of_important_colors = int.from_bytes(bmp_data[50:54], 'little')
print("--- number_of_important_colors:", number_of_important_colors)

print("=============================================")
print("What concerned are:")
print("Signature:",chr(bmp_data[0]), chr(bmp_data[1]))
print("offset:", offset)
print("image_width:", image_width)
print("image_height:", image_height)
print("num_of_bits_per_pixel:", num_of_bits_per_pixel)
print("=============================================")



Actually, it's prepare for my next exercise: Raspberry Pi Pico 2/MicroPython read bmp images and draw on ST7789 display pixel-by-pixel.

Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

Drive 320x240 ILI9341 SPI TFT using ESP32-S3 (NodeMCU ESP-S3-12K-Kit) using TFT_eSPI library, in Arduino Framework.