Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
GbrImagePlugin.py104 linesDownload Raw Back to PIL
1#
2# The Python Imaging Library
3#
4# load a GIMP brush file
5#
6# History:
7#       96-03-14 fl     Created
8#       16-01-08 es     Version 2
9#
10# Copyright (c) Secret Labs AB 1997.
11# Copyright (c) Fredrik Lundh 1996.
12# Copyright (c) Eric Soroos 2016.
13#
14# See the README file for information on usage and redistribution.
15#
16#
17# See https://github.com/GNOME/gimp/blob/mainline/devel-docs/gbr.txt for
18# format documentation.
19#
20# This code Interprets version 1 and 2 .gbr files.
21# Version 1 files are obsolete, and should not be used for new
22#   brushes.
23# Version 2 files are saved by GIMP v2.8 (at least)
24# Version 3 files have a format specifier of 18 for 16bit floats in
25#   the color depth field. This is currently unsupported by Pillow.
26from __future__ import annotations
27
28from . import Image, ImageFile
29from ._binary import i32be as i32
30
31
32def _accept(prefix: bytes) -> bool:
33    return len(prefix) >= 8 and i32(prefix, 0) >= 20 and i32(prefix, 4) in (1, 2)
34
35
36##
37# Image plugin for the GIMP brush format.
38
39
40class GbrImageFile(ImageFile.ImageFile):
41    format = "GBR"
42    format_description = "GIMP brush file"
43
44    def _open(self) -> None:
45        assert self.fp is not None
46        header_size = i32(self.fp.read(4))
47        if header_size < 20:
48            msg = "not a GIMP brush"
49            raise SyntaxError(msg)
50        version = i32(self.fp.read(4))
51        if version not in (1, 2):
52            msg = f"Unsupported GIMP brush version: {version}"
53            raise SyntaxError(msg)
54
55        width = i32(self.fp.read(4))
56        height = i32(self.fp.read(4))
57        color_depth = i32(self.fp.read(4))
58        if width == 0 or height == 0:
59            msg = "not a GIMP brush"
60            raise SyntaxError(msg)
61        if color_depth not in (1, 4):
62            msg = f"Unsupported GIMP brush color depth: {color_depth}"
63            raise SyntaxError(msg)
64
65        if version == 1:
66            comment_length = header_size - 20
67        else:
68            comment_length = header_size - 28
69            magic_number = self.fp.read(4)
70            if magic_number != b"GIMP":
71                msg = "not a GIMP brush, bad magic number"
72                raise SyntaxError(msg)
73            self.info["spacing"] = i32(self.fp.read(4))
74
75        self.info["comment"] = self.fp.read(comment_length)[:-1]
76
77        if color_depth == 1:
78            self._mode = "L"
79        else:
80            self._mode = "RGBA"
81
82        self._size = width, height
83
84        # Image might not be small
85        Image._decompression_bomb_check(self.size)
86
87        # Data is an uncompressed block of w * h * bytes/pixel
88        self._data_size = width * height * color_depth
89
90    def load(self) -> Image.core.PixelAccess | None:
91        if self._im is None:
92            assert self.fp is not None
93            self.im = Image.core.new(self.mode, self.size)
94            self.frombytes(self.fp.read(self._data_size))
95        return Image.Image.load(self)
96
97
98#
99# registry
100
101
102Image.register_open(GbrImageFile.format, GbrImageFile, _accept)
103Image.register_extension(GbrImageFile.format, ".gbr")
104 
codekingpro/portable-devtools · Team Ai