A pure python implementation of the GIMP XCF image format. Use this to interact with GIMP image formats

Overview

GitHub top language Repository size Issues License Commit activity Last commit PyPI Downloads PyPI Total Downloads PyPI Version

GimpFormats

Project Icon

Forked from https://github.com/TheHeadlessSourceMan/gimpFormats

A pure python implementation of the GIMP XCF image format. Use this to interact with GIMP image formats

Issues and contributions very much wanted/ needed 😄

Previously under gimpformats_unofficial now under gimpformats

Getting started

Read an image

from gimpformats.gimpXcfDocument import GimpDocument
project = GimpDocument("image.xcf")

Iterate the image and report the contents of each group followed by the first level children of the image

"""List data on groups followed by the direct children of a gimp xcf document
"""
layers = project.layers
index = 0
print("## Group info...")
while index < len(layers):
	layerOrGroup = layers[index]
	if layerOrGroup.isGroup:
		index += 1
		while layers[index].itemPath is not None:
			print("Group \"" + layerOrGroup.name + "\" contains Layer \"" + layers[index].name + "\"")
			layers.pop(index)
	else:
		index += 1

print("## Document direct children...")
for layerOrGroup in layers:
	print("\"" + layerOrGroup.name + "\" is a " + ("Group" if layerOrGroup.isGroup else "Layer"))

Example output:

## Group info...
Group "Layer Group" contains Layer "Layer"
Group "Layer Group" contains Layer "Layer2"
## Document direct children...
"bg #1" is a Layer
"bg" is a Layer
"bg #2" is a Layer
"Transformation" is a Layer
"Layer Group" is a Group
"Background" is a Layer

Next tasks (see below)

  • Saving

Currently supports

  • Loading xcf files (up to current GIMP version 2.10)
  • Getting image hierarchy and info
  • Getting image for each layer (PIL image)
  • .gbr brushes
  • .vbr brushes
  • .gpl palette files
  • .pat pattern files
  • .gtp tool presets
  • Generate a flattened image
  • Add new layers

In progress but results in crashes and tests failing

  • Saving
  • .ggr gradients - reads/saves fine, but I need to come up with a way to get the actual colours
  • .gih brush sets - BUG: seems to have more image data per brush than what's expected
  • .gpb brush - should work, but I need some test files

Not implemented

  • Exported paths in .svg format. - Reading should be easy enough, but I need to ensure I don't get a full-blown svg in the mix
  • Standard "parasites"

Documentation

See the Docs for more information.

Install With PIP

pip install gimpformats

Head to https://pypi.org/project/gimpformats/ for more info

Language information

Built for

This program has been written for Python 3 and has been tested with Python version 3.9.0 https://www.python.org/downloads/release/python-380/.

Install Python on Windows

Chocolatey

choco install python

Download

To install Python, go to https://www.python.org/ and download the latest version.

Install Python on Linux

Apt

sudo apt install python3.9

How to run

With VSCode

  1. Open the .py file in vscode
  2. Ensure a python 3.9 interpreter is selected (Ctrl+Shift+P > Python:Select Interpreter > Python 3.9)
  3. Run by pressing Ctrl+F5 (if you are prompted to install any modules, accept)

From the Terminal

./[file].py

Download Project

Clone

Using The Command Line

  1. Press the Clone or download button in the top right
  2. Copy the URL (link)
  3. Open the command line and change directory to where you wish to clone to
  4. Type 'git clone' followed by URL in step 2
$ git clone https://github.com/FHPythonUtils/GimpFormats

More information can be found at https://help.github.com/en/articles/cloning-a-repository

Using GitHub Desktop

  1. Press the Clone or download button in the top right
  2. Click open in desktop
  3. Choose the path for where you want and click Clone

More information can be found at https://help.github.com/en/desktop/contributing-to-projects/cloning-a-repository-from-github-to-github-desktop

Download Zip File

  1. Download this GitHub repository
  2. Extract the zip archive
  3. Copy/ move to the desired location

Community Files

Licence

LGPLv3 License (See the LICENSE for more information.)

Changelog

See the Changelog for more information.

Code of Conduct

Online communities include people from many backgrounds. The Project contributors are committed to providing a friendly, safe and welcoming environment for all. Please see the Code of Conduct for more information.

Contributing

Contributions are welcome, please see the Contributing Guidelines for more information.

Security

Thank you for improving the security of the project, please see the Security Policy for more information.

Support

Thank you for using this project, I hope it is of use to you. Please be aware that those involved with the project often do so for fun along with other commitments (such as work, family, etc). Please see the Support Policy for more information.

Rationale

The rationale acts as a guide to various processes regarding projects such as the versioning scheme and the programming styles used. Please see the Rationale for more information.

Comments
  • Bug: Layers with alpha translucency darker when flattened

    Bug: Layers with alpha translucency darker when flattened

    Describe the bug

    Using the head of the master branch, if layers have alpha channels, any alpha value less than 1 will end up darker than it should (based on the export from Gimp)

    variable-alpha.zip

    Expected outcome

    expected

    Actual outcome

    actual

    bug 
    opened by hemebond 5
  • Feature: Support group and layer masks when flattening

    Feature: Support group and layer masks when flattening

    Feature

    When flattening an XcfDocument with flattenAll it does not look the way it does when exported from GIMP. Masks seem to be ignored whether on a layer or on a group.

    Describe the solution you'd like

    flattenAll should result in the same image one would get if viewed in, or exported from, GIMP.

    Group masks should be applied to all layers inside the group. A layer mask should be applied to its layer.

    opened by hemebond 5
  • Feature: Add saving functionality to library

    Feature: Add saving functionality to library

    System info

    $ uname -a
    Linux 5.14.0-4-amd64 #1 SMP Debian 5.14.16-1 (2021-11-03) x86_64 GNU/Linux
    
    $ python3 --version
    Python 3.9.9
    
    $ pip freeze
    aenum==3.1.5
    binaryiotools==2021.0.3
    blendmodes==2021.3.3
    brackettree==0.2.5
    deprecation==2.1.0
    gimpformats==2021.1.3
    numpy==1.21.4
    packaging==21.3
    Pillow==8.4.0
    pyparsing==3.0.6
    

    Describe the bug

    Opening an XCF file and then saving, with either save or saveNew methods, results in a corrupt XCF file which can't be opened with gimpformats or Gimp. Test file attached test.zip.

    Expected outcome

    Creates an identical or at least valid XCF file.

    Actual outcome

    Python 3.9.9 (main, Nov 16 2021, 10:24:31) 
    [GCC 11.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from gimpformats.gimpXcfDocument import GimpDocument
    >>> d = GimpDocument('test.xcf')
    >>> d.saveNew('/tmp/test.xcf')
    >>> d = GimpDocument('/tmp/test.xcf')
    Traceback (most recent call last):
      File ".../lib/python3.9/site-packages/binaryiotools/__init__.py", line 118, in _read
        data = struct.unpack(fmt, self.data[self.index : self.index + size])[0]
    struct.error: unpack requires a buffer of 4 bytes
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File ".../lib/python3.9/site-packages/gimpformats/gimpXcfDocument.py", line 81, in __init__
        self.load(fileName)
      File ".../lib/python3.9/site-packages/gimpformats/gimpXcfDocument.py", line 89, in load
        self.decode(data)
      File ".../lib/python3.9/site-packages/gimpformats/gimpXcfDocument.py", line 134, in decode
        self._propertiesDecode(ioBuf)
      File ".../lib/python3.9/site-packages/gimpformats/GimpIOBase.py", line 669, in _propertiesDecode
        self._propertyDecode(propertyType, ioBuf.getBytes(dataLength))
      File ".../lib/python3.9/site-packages/gimpformats/GimpIOBase.py", line 383, in _propertyDecode
        self.blendMode = ioBuf.u32
      File ".../lib/python3.9/site-packages/binaryiotools/__init__.py", line 362, in u32
        return self.u32be
      File ".../lib/python3.9/site-packages/binaryiotools/__init__.py", line 515, in u32be
        return self._read(4, ">I")
      File ".../lib/python3.9/site-packages/binaryiotools/__init__.py", line 120, in _read
        raise Exception(
    Exception: >I 4 0 0 b''
    
    enhancement 
    opened by hemebond 4
  • Crash when merging XCF containing layer groups

    Crash when merging XCF containing layer groups

    To reproduce:

    1. Open GIMP, make a new image, add a layer group, drag the background layer into it, and save as test.xcf.
    2. Code:
    from gimpformats.gimpXcfDocument import GimpDocument
    
    img = GimpDocument('test.xcf')
    img.image.show()
    

    Result:

    Traceback (most recent call last):
      File "tst.py", line 4, in <module>
        img.image.show()
      File "venv/lib/python3.8/site-packages/gimpformats/gimpXcfDocument.py", line 335, in image
        while layers[index].itemPath is not None:
    IndexError: list index out of range
    
    

    Expected result: The merged image is displayed.

    File which causes the error: test.xcf.gz

    opened by ali1234 3
  • Bug instantiating gimp file with GimpDocument.  Seems like its an issue with changes to str and bytes.

    Bug instantiating gimp file with GimpDocument. Seems like its an issue with changes to str and bytes.

    from gimpformats.gimpXcfDocument import GimpDocument
    imagepath = 'borders.xcf'
    doc = GimpDocument(imagepath)
    

    Produces the follow dump:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/gimpXcfDocument.py", line 65, in __init__
        self.load(fileName)
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/gimpXcfDocument.py", line 82, in load
        self.decode(data)
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/gimpXcfDocument.py", line 121, in decode
        self._propertiesDecode(ioBuf)
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/GimpIOBase.py", line 703, in _propertiesDecode
        self._propertyDecode(propertyType, ioBuf.getBytes(dataLength))
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/GimpIOBase.py", line 441, in _propertyDecode
        self._guidelinesDecode(data)
      File "/home/ismael/miniconda3/lib/python3.7/site-packages/gimpformats/GimpIOBase.py", line 286, in _guidelinesDecode
        isVertical = struct.unpack(">B", data[index])[0] == 2
    TypeError: a bytes-like object is required, not 'int'
    

    It looks like it's likely caused by changes to bytes and str and between old and newer version of python. I'll update this "issue" as I get more detailed information. In the meantime, I'm sure you must already know or is this possibly a dead project?

    opened by ismaelharunid 2
  • I made a compatibility test suite

    I made a compatibility test suite

    See https://xcf.zerostem.io/

    This tool uses gimp scripting to generate xcf files with various combinations of layer blending. It exports each one as a png with gimp, gimpformats, layeredimage, and xcftools and compares the results. In gimpformats the conversion is done like this:

    img = GimpDocument(...)
    img.image.save(...)
    

    Then it compares the png files. If any channel value differs by more than 8 then the test fails.

    Of 648 tests, 550 failed.

    bug wontfix 
    opened by ali1234 1
  • Fix regression in flattenAll when using layer group masks

    Fix regression in flattenAll when using layer group masks

    • [ ] Documentation update
    • [X] Bug fix
    • [ ] New feature
    • [ ] Other, please explain:

    Changes

    • Fix mask property method to return the mask image data
    • Changes the image() property method to return nested lists for nested groups
    • Adjusts flattenLayerOrGroup() function to not apply offsets when rendering group layer
    • Adds unit tests for group masks (test/group_masks/test.py)

    Issue

    No issue raised. Appears to be a regression.

    opened by hemebond 1
  • Bug: unsupported operand type(s) on Python 3.9

    Bug: unsupported operand type(s) on Python 3.9

    System info

    • OS:
      Linux excession 5.14.0-2-amd64 #1 SMP Debian 5.14.9-2 (2021-10-03) x86_64 GNU/Linux
      
    • Version:
      $ python
      Python 3.9.8 (main, Nov  7 2021, 15:47:09) 
      [GCC 11.2.0] on linux
      

    Describe the bug

    When using Python 3.9 importing gimpformats results in a TypeError:

    >>> from gimpformats.gimpXcfDocument import GimpDocument
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File ".../gimpformats/gimpXcfDocument.py", line 23, in <module>
        from . import utils
      File ".../gimpformats/utils.py", line 6, in <module>
        def fileOpen(fileName: BytesIO | str) -> tuple[str, bytes]:
    TypeError: unsupported operand type(s) for |: 'type' and 'type'
    

    Using a pipe for writing union types is only supported from Python 3.10 (PEP604)

    bug 
    opened by hemebond 0
  • implement

    implement

    https://github.com/FHPythonUtils/GimpFormats/blob/7475dbce123519fb0498b9d4e52ae85fdec29890/test/test.py#L15-L20


    This issue was generated by todo based on a TODO comment in 7475dbce123519fb0498b9d4e52ae85fdec29890. It's been assigned to @FredHappyface because they committed the code.
    todo :spiral_notepad: 
    opened by todo[bot] 0
  • [ImgBot] Optimize images

    [ImgBot] Optimize images

    Beep boop. Your images are optimized!

    Your image file size has been reduced by 9% 🎉

    Details

    | File | Before | After | Percent reduction | |:--|:--|:--|:--| | /tests/exported_paths/lips.svg | 1.17kb | 0.77kb | 34.00% | | /tests/simple_xcf_read/testComplexImage_expected.png | 35.08kb | 25.25kb | 28.03% | | /tests/simple_xcf_read/testComplexImage.png | 36.40kb | 28.26kb | 22.36% | | /tests/gbr_brush/desiredOutput_pepper.png | 33.28kb | 31.87kb | 4.23% | | /tests/simple_xcf_read/testOneLayerWithTransparency.png | 101.91kb | 97.89kb | 3.95% | | /tests/simple_xcf_read/testOneLayerWithTransparency_expected.png | 101.91kb | 97.89kb | 3.95% | | /test_files/gimp-wilber.png | 11.31kb | 11.14kb | 1.57% | | | | | | | Total : | 321.06kb | 293.06kb | 8.72% |


    📝 docs | :octocat: repo | 🙋🏾 issues | 🏪 marketplace

    ~Imgbot - Part of Optimole family

    opened by imgbot[bot] 0
  • [ImgBot] Optimize images

    [ImgBot] Optimize images

    Beep boop. Your images are optimized!

    Your image file size has been reduced by 12% 🎉

    Details

    | File | Before | After | Percent reduction | |:--|:--|:--|:--| | /test/exportedPaths/lips.svg | 1.17kb | 0.77kb | 34.00% | | /test/simpleXcfRead/expected.png | 35.08kb | 25.25kb | 28.03% | | /test/simpleXcfRead/base24.png | 36.40kb | 28.26kb | 22.36% | | /test/simpleXcfRead/desiredOutput.png | 104.94kb | 98.94kb | 5.72% | | /test/gbrBrush/desiredOutput_pepper.png | 33.28kb | 31.87kb | 4.23% | | /gimp-wilber.png | 11.31kb | 11.14kb | 1.57% | | | | | | | Total : | 222.19kb | 196.23kb | 11.68% |


    Black Lives Matter | 💰 donate | 🎓 learn | ✍🏾 sign

    📝 docs | :octocat: repo | 🙋🏾 issues | 🏅 swag | 🏪 marketplace

    opened by imgbot[bot] 0
  • Call for contributors

    Call for contributors

    This project needs a heck of a lot of attention to whip it into shape. So if you find this useful then contributions are strongly encouraged.

    At the moment I simply don't have the time to dedicate to a rewrite (which is realistically what's needed) and so as things stand: when things break and cannot be easily fixed then the project will be deprecated.

    Tasks

    • Reduce duplication in this module and any existing modules (for instance investigate any rle implementations)
    • Improved binary read/ handling implementation over binaryutils

    These 2 changes alone should significantly improve the situation replacing hacked together code with more rigorously tested dependencies

    help wanted 
    opened by FredHappyface 2
Owner
FHPyhtonUtils
FredHappyface Python Libraries here
FHPyhtonUtils
Pure Python bindings for the pure C++11/OpenCL Qrack quantum computer simulator library

pyqrack Pure Python bindings for the pure C++11/OpenCL Qrack quantum computer simulator library (PyQrack is just pure Qrack.) IMPORTANT: You must buil

vm6502q 6 Jul 21, 2022
PSD (Photoshop, Krita, Gimp...) -> Godot.

limage v0.2.2 Features Getting Started Tags Settings Todo Customizer Changes Solutions WARNING: Requires Python to be installed PSD (Photoshop, Krita,

null 21 Nov 10, 2022
GIMP script to export bitmap as GRAPHICS 4 file (aka SCREEN 5)

gimpfu-msx-gr4.py GIMP script to export bitmap as GRAPHICS 4 file (aka SCREEN 5). GRAPHICS 4 specs are: 256x212 (or 256x192); 16 color palette (from 5

Pedro de Medeiros 4 Oct 17, 2022
Png2Jpg tool will help you convert from png image format to jpg images format.

PNG 2 JPG All codes assume running from root directory. Please update the sys path at the beginning of the codes before running. Over View Png2Jpg too

Nguyễn Trường Lâu 2 Dec 27, 2021
Pyconvert is a python script that you can use to convert image files to another image format! (eg. PNG to ICO)

Pyconvert is a python script that you can use to convert image files to another image format! (eg. PNG to ICO)

null 1 Jan 16, 2022
A proof-of-concept implementation of a parallel-decodable PNG format

mtpng A parallelized PNG encoder in Rust by Brion Vibber [email protected] Background Compressing PNG files is a relatively slow operation at large imag

Brion Vibber 193 Dec 16, 2022
Conversion of Image, video, text into ASCII format

asciju Python package that converts image to ascii Free software: MIT license

Aju Tamang 11 Aug 22, 2022
A Icon Maker GUI Made - Convert your image into icon ( .ico format ).

Icon-Maker-GUI A Icon Maker GUI Made Using Python 3.9.0 . It will take any image and convert it to ICO file, for web site favicon or Windows applicati

Insanecodes 12 Dec 15, 2021
Sombra is simple Raytracer written in pure Python.

Sombra Sombra is simple Raytracer written in pure Python. It's main purpose is to help understand how raytracing works with a clean code. If you are l

Hernaldo Jesus Henriquez Nuñez 10 Jul 16, 2022
New program to export a Blender model to the LBA2 model format.

LBA2 Blender to Model 2 This is a new program to export a Blender model to the LBA2 model format. This is also the first publicly released version of

null 2 Nov 30, 2022
Xmas-Tree-GIF-Tool - Convert any given animated gif file into an animation in GIFT CSV format

This repo is made to participate in Matt Parker's XmasTree 2021 event. Convert a

Aven Zitzelberger 2 Dec 30, 2021
Easy to use Python module to extract Exif metadata from digital image files.

Easy to use Python module to extract Exif metadata from digital image files.

ianaré sévi 719 Jan 5, 2023
Simple to use image handler for python sqlite3.

SQLite Image Handler Simple to use image handler for python sqlite3. Functions Function Name Parameters Returns init databasePath : str tableName : st

Mustafa Ozan Çetin 7 Sep 16, 2022
A quick and dirty QT Statusbar implementation for grabbing GIFs from Tenor, since there is no offical or unofficial one I found. This was intended for use under Linux, however it was also functional enough on MacOS.

Statusbar-TenorGIF App for Linux A quick and dirty QT Statusbar implementation for grabbing GIFs from Tenor, since there is no offical one and I didnt

Luigi DaVinci 1 Nov 1, 2021
Simple Python / ImageMagick script to package images into WAD3s for use as GoldSrc textures.

WADs Out For [The] Ladies Simple Python / ImageMagick script to package images into WAD3s for use as GoldSrc textures. Development mostly focused on L

null 5 Apr 9, 2022
A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos.

font2png A little Python tool to convert a TrueType (ttf/otf) font into a PNG for use in demos. To use from command line it expects python3 to be at /

Rich Elmes 3 Dec 22, 2021
An automated Comic Book downloader (cbr/cbz) for use with SABnzbd, NZBGet and torrents

Mylar Note that feature development has stopped as we have moved to Mylar3. EOL for this project is the end of 2020 and will no longer be supported. T

null 979 Dec 13, 2022
Photini - A free, easy to use, digital photograph metadata (Exif, IPTC, XMP) editing application for Linux, Windows and MacOS.

A free, easy to use, digital photograph metadata (Exif, IPTC, XMP) editing application for Linux, Windows and MacOS. "Metadata" is said to mea

Jim Easterbrook 120 Dec 20, 2022
Generate your own QR Code and scan it to see the results! Never use it for malicious purposes.

QR-Code-Generator-Python Choose the name of your generated QR .png file. If it happens to open the .py file (the application), there are specific comm

null 1 Dec 23, 2021