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
# (This code is for uncompressed, 24-bit pixel BMP files)
# ================================================================
# ----------------------------------------------------------------
# ---- 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()