Interpret/Display BMP File Header

Links

BMP File Format (Wikipedia)

How to Read BMP File Header in Python

What is a BMP file?

THE BMP FILE FORMAT

Code Example

#!/usr/bin/python3 # ================================================================ # interpret/display BMP file header information # ================================================================ # ---------------------------------------------------------------- # ---- DIB header name # ---------------------------------------------------------------- def dib_header_name(dib_header_size:int) -> str: match dib_header_size: case 12: return 'BITMAPCOREHEADER' case 64: return 'OS22XBITMAPHEADER' case 16: return 'OS22XBITMAPHEADER' case 40: return 'BITMAPINFOHEADER' case 52: return 'BITMAPV2INFOHEADER' case 56: return 'BITMAPV3INFOHEADER' case 108: return 'BITMAPV4HEADER' case 124: return 'BITMAPV5HEADER' return 'unknown' # ---------------------------------------------------------------- # ---- DIB bits per pixel (palette entry information) # ---------------------------------------------------------------- def dib_bits_per_pixel(bits_per_pixel:int) -> str: match bits_per_pixel: case 1: return 'monochrome palette. NumColors = 1' case 4: return '4bit palletized. NumColors = 16' case 8: return '8bit palletized. NumColors = 256' case 16: return '16bit RGB. NumColors = 65536' case 24: return '24bit RGB. NumColors = 16M' return 'unknown' # ---------------------------------------------------------------- # ---- DIB compression method # ---------------------------------------------------------------- def dib_compression_method(compression_method:int) -> str: match compression_method: case 0: return 'BI_RGB - no compression' case 1: return 'BI_RLE8 8bit RLE encoding' case 2: return 'BI_RLE4 4bit RLE encoding' return 'unknown' # ---------------------------------------------------------------- # ---- DIB important colors # ---------------------------------------------------------------- def dib_important_colors(important_colors:int) -> str: if important_colors == 0: return 'all' return f'{important_colors} important colors' # ---------------------------------------------------------------- # ---- display BMP file header # ---- # ---- the common DIB format is the BITMAPINFOHEADER header # ---------------------------------------------------------------- def display_bmp_header(file_path:str,bmp_bytes:bytearray) -> None: print('---- BMP Header -------------------------------') char1 = chr(int.from_bytes(bmp_bytes[0:1],'little')) char2 = chr(int.from_bytes(bmp_bytes[1:2],'little')) width = int.from_bytes(bmp_bytes[18:22],'little') height = int.from_bytes(bmp_bytes[22:26],'little') file_size = int.from_bytes(bmp_bytes[2:6],'little') offset = int.from_bytes(bmp_bytes[10:14],'little') print(f'file = {file_path}') print(f'file type = {char1}{char2}') print(f'width = {width}') print(f'height = {height}') print(f'file size = {file_size}') print(f'pixels offset = {offset}') print('---- DIB Header -------------------------------') dib_header_size = int.from_bytes(bmp_bytes[14:18], 'little') dib_width = int.from_bytes(bmp_bytes[18:22], 'little') dib_height = int.from_bytes(bmp_bytes[22:26], 'little') color_planes = int.from_bytes(bmp_bytes[26:28], 'little') bits_per_pixel = int.from_bytes(bmp_bytes[28:30], 'little') compression_method = int.from_bytes(bmp_bytes[30:34], 'little') raw_image_size = int.from_bytes(bmp_bytes[34:38], 'little') horizontal_resolution = int.from_bytes(bmp_bytes[38:42], 'little',signed=True) vertical_resolution = int.from_bytes(bmp_bytes[42:46], 'little',signed=True) number_of_colors = int.from_bytes(bmp_bytes[46:50], 'little') important_colors = int.from_bytes(bmp_bytes[50:54], 'little') compression = dib_compression_method(compression_method) header_name = dib_header_name(dib_header_size) num_important_colors = dib_important_colors(important_colors) pixel_bits = dib_bits_per_pixel(bits_per_pixel) print(f'DIB header size = {dib_header_size}') print(f'DIB header name = {header_name}') print(f'DIB width = {dib_width}') print(f'DIB height = {dib_height}') print(f'color planes = {color_planes}') print(f'bits per pixel = {bits_per_pixel}') print(f' {pixel_bits}') print(f'compression method = {compression_method}') print(f' {compression}') print(f'raw image size = {raw_image_size}') print(f'horizontal res = {horizontal_resolution}') print(f'vertical res = {vertical_resolution}') print(f'number of colors = {number_of_colors}') print(f'important colors = {important_colors}') print(f' {num_important_colors}') if bits_per_pixel < 8: print('---- Color Table ------------------------------') print('bits per pixel ({bits_per_pixel}) < 8') red_intensity = int.from_bytes(bmp_bytes[55:56], 'little') green_intensity = int.from_bytes(bmp_bytes[56:57], 'little') blue_intensity = int.from_bytes(bmp_bytes[57:58], 'little') print(f'red intensity {red_intensity}') print(f'green intensity {green_intensity}') print(f'blue intensity {blue_intensity}') # ---------------------------------------------------------------- # ---- open bmp and read it directly into a byte array # ---- # ---- It is not necessary to read in the complete file # ---- if you are only accessing the headers. For example, # ---- read the first 1000 bytes? # ---- # ---- def load_bmp_to_array(bmp_file_path:str) -> bytearray: # ---- f = open(bmp_file_path,'rb') # ---- bmp_bytes = f.read(1000) # ---- close(f) # ---- return bmp_bytes # ---- # ---------------------------------------------------------------- def load_bmp_to_array(bmp_file_path:str) -> bytearray: with open(bmp_file_path,'rb') as file: bmp_bytes = file.read() return bmp_bytes # ---------------------------------------------------------------- # ---- main # ---------------------------------------------------------------- if __name__ == '__main__': bmp_file_paths = [bmp_all_red.bmp, ##'mona_lisa_1.bmp', 'mona_lisa_original.bmp', ##'bmp_test_file_1.bmp','bmp_test_file_2.bmp', ##'bmp_test_file_3.bmp' ] for file_path in bmp_file_paths: print() bmp_bytes = load_bmp_to_array(file_path) display_bmp_header(file_path,bmp_bytes) print()