Provide way to load big palettes;

This commit is contained in:
João S. O. Bueno 2022-10-06 11:35:41 -03:00
parent 1ed6039c85
commit a12389bf35
3 changed files with 50 additions and 6 deletions

View File

@ -1,7 +1,7 @@
GIMP Palette
Name: custompalette
Columns: 4
#
# Original written by David Wetz in https://stackoverflow.com/questions/815836/im-creating-a-program-that-generates-a-palette-from-a-true-color-image-need-hel/815855#815855
0 0 0 Index 0
65 38 30 Index 1
103 62 49 Index 2

View File

@ -20,6 +20,21 @@ def test_sanity():
GimpPaletteFile(fp)
def test_large_file_is_truncated():
import warnings
from unittest.mock import patch
try:
original_value = GimpPaletteFile._max_file_size
GimpPaletteFile._max_file_size = 100
with warnings.catch_warnings():
warnings.simplefilter("error")
with pytest.raises(UserWarning):
with open("Tests/images/custom_gimp_palette.gpl", "rb") as fp:
palette_file = GimpPaletteFile(fp)
finally:
GimpPaletteFile._max_file_size = original_value
def test_get_palette():
# Arrange
with open("Tests/images/custom_gimp_palette.gpl", "rb") as fp:
@ -43,3 +58,13 @@ def test_get_palette():
expected_palette += bytes(color)
assert palette == expected_palette
assert mode == "RGB"
def test_n_colors():
# Arrange
with open("Tests/images/custom_gimp_palette.gpl", "rb") as fp:
palette_file = GimpPaletteFile(fp)
palette, _ = palette_file.getpalette()
assert len(palette) == 24
assert palette_file.n_colors == 8

View File

@ -15,6 +15,7 @@
#
import re
import warnings
from ._binary import o8
@ -24,25 +25,39 @@ class GimpPaletteFile:
rawmode = "RGB"
#: override if reading larger palettes is needed
max_colors = 256
_max_line_size = 100
_max_file_size = 2 ** 20
def __init__(self, fp):
if fp.readline()[:12] != b"GIMP Palette":
raise SyntaxError("not a GIMP palette file")
self.palette = b""
while len(self.palette) < 768:
read = 0
s = fp.readline()
self.palette = b""
while len(self.palette) < 3 * self.max_colors:
s = fp.readline(self._max_file_size)
if not s:
break
read += len(s)
if read >= self._max_file_size:
warnings.warn(
f"Palette file truncated at {self._max_file_size - len(s)} bytes")
break
# skip fields and comment lines
if re.match(rb"\w+:|#", s):
continue
if len(s) > 100:
if len(s) > self._max_line_size:
raise SyntaxError("bad palette file")
v = s.split()
# 4th column is color name and may contain spaces.
v = s.split(None, 4)
if len(v) < 3:
raise ValueError("bad palette entry")
for i in range(3):
@ -51,3 +66,7 @@ class GimpPaletteFile:
def getpalette(self):
return self.palette, self.rawmode
@property
def n_colors(self):
return len(self.palette) / 3