user4780495
user4780495

Reputation: 2912

Gimp: How to export an image to BMP without the color space information using a python script?

I'm writing a python script for Gimp to export all the layers of an image to BMPs.

To export a given layer, I use the procedure file_bmp_save:

pdb.file_bmp_save(image, layer, filename, raw_filename)

But this function save the color space information in the BMP header.

When I export BMP manually (File > Export), there is an option

do not write color space information

See screen capture

I would like to reproduce this option in my python script.

Upvotes: 3

Views: 5510

Answers (1)

jsbueno
jsbueno

Reputation: 110440

So - I went to check it, and indeed - this option is not available programatically at all. The case is the chunk that is named as "color space information" on GIMP BMP export filter is actually the binary difference between a version 3 BMP file, and a version 4 bmp file, which was introduced as far back as Windows 95.

So, I beg you to rethink where you are using BMP files that need file versions as old as Pre-windows 95 files.

That said, at some point, someone with GIMP hacking capabilities felt that need, and added the option for these v3 files to the export GUI - but the same person did not bother adding a second PDB call for PDB save: the file_bmp_save call itself could not be changed to have the extra "dont_write_color_information" parameter - GIMP PDB calls are kept backwards compatible across major GIMP versions (which is like forever). And adding a second procedure circa 2004, 2005 to support saving a file version obsoleted in 1995, would be counterproductive.

Fortunatelly, it is just a matter of 68 bytes that are written at the end of the V4 header - and the different offsets are recorded in jus 3 points in the file. Therefore, it is easy to write a Python solution for converting these files to the format you need.

Should the conversion be more complicated, the path there would be to: file a bug with GIMP project so that a programmatic call could be made for the GUI exiting option, (and preferably code the patch for that and attach it to the bug, since GIMP is a volunteer only project) and wait for a new version of GIMP featuring the change. In the meantime, use an workaround with an external program which could make the needed image conversion (or your own patched version of GIMP).

As it is, though, the following Python function will convert the BMP version after it is exported by GIMP:

import struct

V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF  =  2
def strip_color_info(old_bmp_name, new_bmp_name=None):
    if new_bmp_name is None:
        new_bmp_name = old_bmp_name
    data = bytearray(open(old_bmp_name, "rb").read())
    header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
    if header_size == 108:
        # Remove 68  - the size for the extra data-chunk from both headers
        data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
        data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
            struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
        # Offset image data:
        data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] =  data[HEADER_OFF + header_size:]
        data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
    with open(new_bmp_name, "wb") as output_file:
        output_file.write(data)

(disclaimer: I've just tested this with an RGB 24bpp file - though it should work for other formats as well)

Upvotes: 4

Related Questions