0

I need to save an image as Windows Bitmap BMP A1R5G5B5 16bpp.
Source files are 32bpp image files (PNG and/or Windows Bitmap).

Preview saves BMP images at 32bpp.

XnConvert saves BMP images at 24bpp.

Imagemagick, Acorn, GraphicConverter do not support saving at 16bpp.

Photoshop can do it, but I don't own it.

Any ideas? GUI or command line is fine for me.

7
  • 1
    16bpp as in R5G6B5? Or 16bpp as in 48 bpp, meaning a full 16 bits for each of the individual channels? Also, what is your input file format, and what is the desired output format? (I know, 'bmp' suggests a Windows Bitmap, but I'd like to see that confirmed.)
    – Jongware
    Commented Dec 17, 2018 at 21:40
  • 1
    just came back to state its actually A1R5G5B5 Windows bitmap. Commented Dec 17, 2018 at 21:44
  • 1
    Can you handle a Python script?
    – Jongware
    Commented Dec 17, 2018 at 21:48
  • Yes I certainly can Commented Dec 17, 2018 at 21:49
  • 1
    (cracks knuckles) Gimme a mo'.
    – Jongware
    Commented Dec 17, 2018 at 22:08

1 Answer 1

1

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.

8
  • I'm getting "Not a BMP image" with this file I saved using Preview: 0x0.st/skxy.bmp and in fact python convbmp.py with no files gives me that error also Commented Dec 17, 2018 at 23:42
  • 1
    @MattSephton: hm. It worked for me... It's late at nite over here, will run some tests with that image later.
    – Jongware
    Commented Dec 17, 2018 at 23:43
  • FWIW in GIMP, I picked X1R5G5B5 which is the same format with unused alpha? I'll check back tomorrow, it's late here too. Thanks! Commented Dec 17, 2018 at 23:44
  • This is what I get running the python script: imgur.com/Xc0c5G6 Commented Dec 18, 2018 at 16:34
  • 1
    @MattSephton: I, sir, am an Idiot. ... I ran it from within an IDE and tested with a hardcoded command line. But when run from a terminal, the first argument is actually the script itself. Sorry for that!
    – Jongware
    Commented Dec 19, 2018 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.