Web  Hopeful
Web Hopeful

Reputation: 761

How to use bitmap headers in Python?

I am attempting to convert a bitmap image file to grayscale and using the bitmap header method. I have the following code:

BMHEADER = bytearray([
66, 77,  # BM identifier
102, 117, 0, 0,  # size of file in bytes
0, 0, 0, 0,  # unused
54, 0, 0, 0,  # offset where the data can be found
40, 0, 0, 0,  # no. of bytes in DIB header from here
400, 0, 0, 0,  # bitmap width in pixels
296, 0, 0, 0,  # bitmap height in pixels
1, 0,  # number of colour planes
24, 0,  # number of bits per pixel (R=G=B=8 bits)
0, 0, 0, 0,  # no compression
48, 117, 0, 0,  # size of the raw data
18, 11, 0, 0,  # horizontal resolution
18, 11, 0, 0,  # vertical resolution
0, 0, 0, 0,  # number of colours in the palette
0, 0, 0, 0,  # all colours important
])
bmp = open(file, 'wb')
bmp.write(BMHEADER)  # write header
pixel = bytearray([0, 0, 255])  # blue, green, red
for x in range (400):
    for y in range (296):

I am trying to figure out how to setup the headers so that it works. I know I have the width and height correct but I am receiving the following error:

    0, 0, 0, 0,  # all colours important
ValueError: byte must be in range(0, 256)

Any ideas what values I should place on the line for this to work?

Upvotes: 1

Views: 1205

Answers (1)

Mark Ransom
Mark Ransom

Reputation: 308266

You have two values in your byte array that are greater than or equal to 256: 400 and 296. You must split them into their upper and lower byte. Instead of 400,0,0,0 you should use 144,1,0,0 and instead of 296,0,0,0 you should use 40,1,0,0.

If you want to derive those numbers instead of hardcoding them, use:

400&0xff, 400>>8, 0, 0,
296&0xff, 296>>8, 0, 0,

This works for values up to 65535. Anything larger than that and you have to use a more complicated expression for the upper bytes.

To do this in a safer fashion look into the struct module.

Upvotes: 1

Related Questions