GbrImagePlugin.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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.
  26. from __future__ import annotations
  27. from . import Image, ImageFile
  28. from ._binary import i32be as i32
  29. def _accept(prefix):
  30. return len(prefix) >= 8 and i32(prefix, 0) >= 20 and i32(prefix, 4) in (1, 2)
  31. ##
  32. # Image plugin for the GIMP brush format.
  33. class GbrImageFile(ImageFile.ImageFile):
  34. format = "GBR"
  35. format_description = "GIMP brush file"
  36. def _open(self):
  37. header_size = i32(self.fp.read(4))
  38. if header_size < 20:
  39. msg = "not a GIMP brush"
  40. raise SyntaxError(msg)
  41. version = i32(self.fp.read(4))
  42. if version not in (1, 2):
  43. msg = f"Unsupported GIMP brush version: {version}"
  44. raise SyntaxError(msg)
  45. width = i32(self.fp.read(4))
  46. height = i32(self.fp.read(4))
  47. color_depth = i32(self.fp.read(4))
  48. if width <= 0 or height <= 0:
  49. msg = "not a GIMP brush"
  50. raise SyntaxError(msg)
  51. if color_depth not in (1, 4):
  52. msg = f"Unsupported GIMP brush color depth: {color_depth}"
  53. raise SyntaxError(msg)
  54. if version == 1:
  55. comment_length = header_size - 20
  56. else:
  57. comment_length = header_size - 28
  58. magic_number = self.fp.read(4)
  59. if magic_number != b"GIMP":
  60. msg = "not a GIMP brush, bad magic number"
  61. raise SyntaxError(msg)
  62. self.info["spacing"] = i32(self.fp.read(4))
  63. comment = self.fp.read(comment_length)[:-1]
  64. if color_depth == 1:
  65. self._mode = "L"
  66. else:
  67. self._mode = "RGBA"
  68. self._size = width, height
  69. self.info["comment"] = comment
  70. # Image might not be small
  71. Image._decompression_bomb_check(self.size)
  72. # Data is an uncompressed block of w * h * bytes/pixel
  73. self._data_size = width * height * color_depth
  74. def load(self):
  75. if not self.im:
  76. self.im = Image.core.new(self.mode, self.size)
  77. self.frombytes(self.fp.read(self._data_size))
  78. return Image.Image.load(self)
  79. #
  80. # registry
  81. Image.register_open(GbrImageFile.format, GbrImageFile, _accept)
  82. Image.register_extension(GbrImageFile.format, ".gbr")