This rather quick – and possibly dirty – Python program will read a 32bpp BMP image, assert it is indeed 32 bpp, and if so convert it to a 16-bit ARGB image and write out to a new file.
import sys, struct
def convertBmp(filename):
with open(filename, 'rb') as in_file:
data = in_file.read()
type1,type2,size,reserved1,reserved2,offset,dib,wide,high,planes,bpp = struct.unpack('<ccIHHIIIIHH',data[:30])
if type1 != b'B' or type2 != b'M':
raise ValueError('Not a BMP image')
if planes != 1 or bpp != 32:
raise ValueError('Not a 32bpp BMP image')
header = bytearray(data[:offset])
data = bytearray(data[offset:])
# process data
newdata = bytearray()
for y in range(high):
for x in range(wide):
b,g,r,a = data[4*wide*y+4*x:4*wide*y+4*x+4]
a = 32768 if a < 127 else 0
r >>= 3
g >>= 3
b >>= 3
newdata += struct.pack('<H',a+(r<<10)+(g<<5)+b)
# add row padding
if wide & 1:
newdata += b'\x00\x00'
# update total size
header[2:6] = struct.pack('<I',len(header)+len(newdata))
# update bpp
header[28] = 16
# update planes
header[30] = 0
# update raw image size
header[34:38] = struct.pack('<I',len(newdata))
return header+newdata
if len(sys.argv) != 3:
print ('usage: python convbmp.py input.bmp output.bmp')
else:
image = convertBmp(sys.argv[1])
with open(sys.argv[1], 'wb') as out_file:
out_file.write (image)
It should only touch the BMP data fields that are actually changed for the conversion and leave the rest alone. Testing was a bit troublesome as I don't appear to have any software to view the resulting ARGB; both Photoshop and Apple's Preview (again!) let me down by not showing if this one-bit alpha channel actually worked. Photoshop always seems to import the alpha channel as if everything is set. (If alpha does not work for you, experiment with the value of the setting of that a
variable; its logic may need inverting.)
This should cover the basics. Expanding it to be able to accept multiple arguments or loop over an entire folder of data, is left as an implementation detail.