Last letter of name of GIMP brush missing, when created with Python - Stack Overflow

admin2025-04-17  1

I would like to create a (python) script, that takes an 2D-Array and converts it to a GIMP-brush in the .gbr format. I used the informations on the GIMP Developer Page to create a Bytestring that should be in the correct format, except the last caracter of the brush is always cut of. Other from that I can use the brush in Gimp without problems.

I used the following script:

def to_gbr(Image_array, name, spacing):
    # -- Create header
    #  header size 0-3
    header_size_int = len(name)+28
    header_size = int.to_bytes(header_size_int,4)

    #  version Type 4-7
    version_type = b"\x00\x00\x00\x02"

    #  Width 8-11
    width_int = Image_array.shape[1]
    width = int.to_bytes(width_int,4)

    #  height 12-15
    height_int = Image_array.shape[0]
    height = int.to_bytes(height_int,4)

    #  Color depth 16-19
    # 1 = greyscale, 4 = RGBA
    if Image_array.shape[2] == 1:
        color_depth = int.to_bytes(1,4)
    elif Image_array.shape[2] == 4:
        print("RGB is not implemented yet")
        return
    else:
        print("unknown Color depth")
        return

    #  Magic Number 20 - 23
    magic_number = b"GIMP"

    #  spacing 24-27
    spacing = int.to_bytes(int(spacing),4)

    #  name 28 - (header-size-1)
    name = bytes(name, encoding="utf-8")

    header = header_size + version_type + width + height + color_depth + magic_number + spacing + name

    # -- Read Data
    data = b""
    for y in range(height_int):
        for x in range(width_int):
            data = data + int.to_bytes(int(Image_array[y][x][0]))
    return header + data

I tried to change the header size (the saved value that tells GIMP the size, but increasing it resulting Gimp in not being able to read it, reducing it was shifting the brush.

Can anyone help me? I have no Idea what to do. Thanks in advance.

I would like to create a (python) script, that takes an 2D-Array and converts it to a GIMP-brush in the .gbr format. I used the informations on the GIMP Developer Page to create a Bytestring that should be in the correct format, except the last caracter of the brush is always cut of. Other from that I can use the brush in Gimp without problems.

I used the following script:

def to_gbr(Image_array, name, spacing):
    # -- Create header
    #  header size 0-3
    header_size_int = len(name)+28
    header_size = int.to_bytes(header_size_int,4)

    #  version Type 4-7
    version_type = b"\x00\x00\x00\x02"

    #  Width 8-11
    width_int = Image_array.shape[1]
    width = int.to_bytes(width_int,4)

    #  height 12-15
    height_int = Image_array.shape[0]
    height = int.to_bytes(height_int,4)

    #  Color depth 16-19
    # 1 = greyscale, 4 = RGBA
    if Image_array.shape[2] == 1:
        color_depth = int.to_bytes(1,4)
    elif Image_array.shape[2] == 4:
        print("RGB is not implemented yet")
        return
    else:
        print("unknown Color depth")
        return

    #  Magic Number 20 - 23
    magic_number = b"GIMP"

    #  spacing 24-27
    spacing = int.to_bytes(int(spacing),4)

    #  name 28 - (header-size-1)
    name = bytes(name, encoding="utf-8")

    header = header_size + version_type + width + height + color_depth + magic_number + spacing + name

    # -- Read Data
    data = b""
    for y in range(height_int):
        for x in range(width_int):
            data = data + int.to_bytes(int(Image_array[y][x][0]))
    return header + data

I tried to change the header size (the saved value that tells GIMP the size, but increasing it resulting Gimp in not being able to read it, reducing it was shifting the brush.

Can anyone help me? I have no Idea what to do. Thanks in advance.

Share asked Jan 31 at 2:49 Shadow of eagleShadow of eagle 114 bronze badges 3
  • It looks like the name is supposed to have a terminating null character, included in the length - and no, there's no way you could have told that from the documentation. Note that your code is broken for names containing non-ASCII characters - you're basing the header size on the len() of the string (in other words, the number of Unicode characters it contains), rather than the length of the UTF-8 encoded version of it. – jasonharper Commented Jan 31 at 3:19
  • pleae, when creating questions, try to input full stand alone minimally verifiable examples. In the case of this code, we don't see the part that records the GBR brush to disk, and don't know what kind of object Image_array is, nor which library it comes from (and then, no one can reproduce this). – jsbueno Commented Jan 31 at 21:21
  • I assumed that a minimal example would be prefered, so I removed parts not directly linked to the problem. But I will remember that for further questions. The writing happens at a different place and is just a standart with open(destination, 'wb') as f: f.write(gbr) and Image_Array is a 2D array containing values from 0 to 255 for the gbr file. Its creation takes multiple steps that would make this post quite large and unclear. – Shadow of eagle Commented Feb 1 at 0:01
Add a comment  | 

1 Answer 1

Reset to default 0

Thanks to jasonharper's comment I was able to solve the problem:
The string for the name has to end with a null caracter that counts into the length of the string. That caracter needs to be appended.

    name = bytes(name, encoding="utf-8") + b'\0'

and moving

    header_size_int = len(name_byte)+28
    header_size = int.to_bytes(header_size_int,4)

down after that solved the problem.

转载请注明原文地址:http://anycun.com/QandA/1744882725a88966.html