How do I create a BMP file with pure Python?

Taras Bilynskyi picture Taras Bilynskyi · Jan 4, 2012 · Viewed 20.4k times · Source

I need to create a black and white BMP file with pure Python.

I read an article on wikipedia, BMP file format, but I am not good at low level programming and want to fill this gap in my knowledge.

So the question is, how do I create a black and white BMP file having a matrix of pixels? I need to do this with pure Python, not using any modules like PIL. It is just for my education.

Answer

LionKimbro picture LionKimbro · Jan 16, 2014

This is a complete answer for monochrome bitmaps.

import math, struct

mult4 = lambda n: int(math.ceil(n/4))*4
mult8 = lambda n: int(math.ceil(n/8))*8
lh = lambda n: struct.pack("<h", n)
li = lambda n: struct.pack("<i", n)

def bmp(rows, w):
    h, wB = len(rows), int(mult8(w)/8)
    s, pad = li(mult4(wB)*h+0x20), [0]*(mult4(wB)-wB)
    s = li(mult4(w)*h+0x20)
    return (b"BM" + s + b"\x00\x00\x00\x00\x20\x00\x00\x00\x0C\x00\x00\x00" +
            lh(w) + lh(h) + b"\x01\x00\x01\x00\xff\xff\xff\x00\x00\x00" +
            b"".join([bytes(row+pad) for row in reversed(rows)]))

For example:

FF XXXXXXXX
81 X......X
A5 X.X..X.X
81 X......X
A5 X.X..X.X
BD X.XXXX.X
81 X......X
FF XXXXXXXX

So, encoding this as a series of rows:

smile = [[0xFF], [0x81], [0xA5], [0x81], [0xA5], [0xBD], [0x81], [0xFF]]

Render it with:

bmp(smile, 8)

Note that it is the programmer's responsibility to ensure that the required number of bytes are present in each row supplied.

The black color is specified in the \xff \xff \xff and the white color is specified in the following \x00 \x00 \x00, should you want to change them.