Skip to content

Instantly share code, notes, and snippets.

@DevStefIt
Created June 2, 2023 14:08
Show Gist options
  • Save DevStefIt/36b99717ed1effc3ce2ef5c323c77b94 to your computer and use it in GitHub Desktop.
Save DevStefIt/36b99717ed1effc3ce2ef5c323c77b94 to your computer and use it in GitHub Desktop.
BMP File Format programs used in the video
import random
from PIL import Image
def create_random_image(width, height):
# Create a new blank image with RGB mode
image = Image.new('RGB', (width, height))
# Create a pixel map
pixels = image.load()
for y in range(height):
for x in range(width):
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
pixels[x, y] = (r, g, b)
return image
width = 8
height = 8
image = create_random_image(width, height)
image.save('random_image.bmp')
from tkinter import Tk
from tkinter.filedialog import askopenfilename
from pathlib import Path
def parse_bmp(file_path):
with open(file_path, 'rb') as f:
# Read BMP header
signature = f.read(2).decode('ascii')
file_size = int.from_bytes(f.read(4), 'little')
reserved_1 = int.from_bytes(f.read(2), 'little')
reserved_2 = int.from_bytes(f.read(2), 'little')
pixel_data_offset = int.from_bytes(f.read(4), 'little')
# Read DIB header
dib_header_size = int.from_bytes(f.read(4), 'little')
width = int.from_bytes(f.read(4), 'little', signed=True)
height = int.from_bytes(f.read(4), 'little', signed=True)
color_planes = int.from_bytes(f.read(2), 'little')
bit_depth = int.from_bytes(f.read(2), 'little')
compression_method = int.from_bytes(f.read(4), 'little')
image_size = int.from_bytes(f.read(4), 'little')
horizontal_resolution = int.from_bytes(f.read(4), 'little')
vertical_resolution = int.from_bytes(f.read(4), 'little')
colors_in_palette = int.from_bytes(f.read(4), 'little')
important_colors = int.from_bytes(f.read(4), 'little')
# Process pixel data
f.seek(pixel_data_offset)
# Calculate row padding
row_size = ((bit_depth * width + 31) // 32) * 4
padding = row_size - ((bit_depth * width) // 8)
pixel_data = []
for _ in range(abs(height)):
row = []
for _ in range(width):
if bit_depth == 24:
blue = ord(f.read(1))
green = ord(f.read(1))
red = ord(f.read(1))
row.append((red, green, blue))
elif bit_depth == 32:
blue = ord(f.read(1))
green = ord(f.read(1))
red = ord(f.read(1))
alpha = ord(f.read(1))
row.append((red, green, blue, alpha))
else:
raise ValueError("Unsupported bit depth")
f.read(padding) # Skip padding bytes
pixel_data.append(row)
# Create list of field information
bmp_info = [
('Signature', 0, 2, signature.encode('ascii').hex(), signature),
('File Size', 2, 4, chr(file_size), file_size),
('Reserved 1', 6, 2, hex(reserved_1), reserved_1),
('Reserved 2', 8, 2, hex(reserved_2), reserved_2),
('Pixel Data Offset', 10, 4, hex(pixel_data_offset), pixel_data_offset),
('DIB Header Size', 14, 4, hex(dib_header_size), dib_header_size),
('Width', 18, 4, hex(width), width),
('Height', 22, 4, hex(height), height),
('Color Planes', 26, 2, hex(color_planes), color_planes),
('Bit Depth', 28, 2, hex(bit_depth), bit_depth),
('Compression Method', 30, 4, hex(compression_method), compression_method),
('Image Size', 34, 4, hex(image_size), image_size),
('Horizontal Resolution', 38, 4, hex(horizontal_resolution), horizontal_resolution),
('Vertical Resolution', 42, 4, hex(vertical_resolution), vertical_resolution),
('Colors in Palette', 46, 4, hex(colors_in_palette), colors_in_palette),
('Important Colors', 50, 4, hex(important_colors), important_colors)
]
# Print field information as tab-separated values
print("field_name,offset,size,value,hex")
for field_info in bmp_info:
field_name, offset, size, hex_value, value = field_info
if isinstance(value, str):
hex_value = ' '.join(f"{byte:02X}" for byte in value.encode())
else:
hex_value = ' '.join(f"{byte:02X}" for byte in value.to_bytes(size, 'little'))
print(f"{field_name},{hex(offset)},{size},{value},{hex_value}")
return pixel_data
root=Tk()
root.withdraw()
bmp_file_path = Path(askopenfilename(title='Select a bitmap file', initialdir='bmp_parser', filetypes=[('Bitmap files', '*.bmp'),('All files', '*.*')])) # shows dialog box and return the path
bmp_info = parse_bmp(bmp_file_path)
#print(f"Pixel Data: {pixel_data}")
field_name offset size value hex
Signature 0x0 2 BM 42 4D
File Size 0x2 4 246 F6 00 00 00
Reserved 1 0x6 2 0 00 00
Reserved 2 0x8 2 0 00 00
Pixel Data Offset 0xa 4 54 36 00 00 00
DIB Header Size 0xe 4 40 28 00 00 00
Width 0x12 4 8 08 00 00 00
Height 0x16 4 8 08 00 00 00
Color Planes 0x1a 2 1 01 00
Bit Depth 0x1c 2 24 18 00
Compression Method 0x1e 4 0 00 00 00 00
Image Size 0x22 4 192 C0 00 00 00
Horizontal Resolution 0x26 4 3780 C4 0E 00 00
Vertical Resolution 0x2a 4 3780 C4 0E 00 00
Colors in Palette 0x2e 4 0 00 00 00 00
Important Colors 0x32 4 0 00 00 00 00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment