New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix indices of colors read from GIMP Palette file #6640
base: main
Are you sure you want to change the base?
Changes from 10 commits
61b1eeb
d0837bd
681f77a
4642e02
1ed6039
a12389b
2f6467c
b471158
0d00d08
2eb6976
c345080
378471e
8979f0c
e007a0b
6893d1d
cefeab8
ea271be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
GIMP Palette | ||
Name: custompalette | ||
Columns: 4 | ||
# | ||
0 0 0 Index 3 | ||
65 38 30 Index 4 | ||
103 62 49 Index 6 | ||
79 73 72 Index 7 | ||
114 101 97 Index 8 | ||
208 127 100 Index 9 | ||
151 144 142 Index 10 | ||
221 207 199 Index 11 | ||
# 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 | ||
79 73 72 Index 3 | ||
114 101 97 Index 4 | ||
208 127 100 Index 5 | ||
151 144 142 Index 6 | ||
221 207 199 Index 7 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -15,6 +15,7 @@ | |||||
# | ||||||
|
||||||
import re | ||||||
import warnings | ||||||
|
||||||
from ._binary import o8 | ||||||
|
||||||
|
@@ -24,32 +25,44 @@ class GimpPaletteFile: | |||||
|
||||||
rawmode = "RGB" | ||||||
|
||||||
def __init__(self, fp): | ||||||
#: override if reading larger palettes is needed | ||||||
max_colors = 256 | ||||||
_max_line_size = 100 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're reading RGB data from each line. That's three integers. Under what circumstances would a user need to read more than 100 characters? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 4th Column contains the color name, though that is currently unused. And there might be a name with more than 100 characters - moving the number to an attribute just offers a chance of one working around an error imposed by an arbitrary, though reasonable, limit on an otherwise good file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (currently unused in PIL, that is: GIMP uses that name) |
||||||
_max_file_size = 2**20 | ||||||
|
||||||
self.palette = [o8(i) * 3 for i in range(256)] | ||||||
def __init__(self, fp): | ||||||
|
||||||
if fp.readline()[:12] != b"GIMP Palette": | ||||||
raise SyntaxError("not a GIMP palette file") | ||||||
|
||||||
for i in range(256): | ||||||
read = 0 | ||||||
|
||||||
s = fp.readline() | ||||||
self.palette = b"" | ||||||
while len(self.palette) < 3 * self.max_colors: | ||||||
|
||||||
s = fp.readline(self._max_file_size) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a mistake, where you've accidentally used the file size limit for the line size limit for the size argument. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no - "file" size is deliberate here - to avoid DoS only. Changing here for reading linesize would make the file break with long comments (as it did), and that makes no sense: if one has a python project in which Palettes with this format are used, there is no reason to impose an arbitrary limit on comments on that source code. Resilience against malicious files when those are input by 3rd parties are mitigated through the file-size check. |
||||||
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 = tuple(map(int, s.split()[:3])) | ||||||
if len(v) != 3: | ||||||
# 4th column is color name and may contain spaces. | ||||||
v = s.split(maxsplit=3) | ||||||
if len(v) < 3: | ||||||
raise ValueError("bad palette entry") | ||||||
|
||||||
self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2]) | ||||||
|
||||||
self.palette = b"".join(self.palette) | ||||||
for i in range(3): | ||||||
self.palette += o8(int(v[i])) | ||||||
|
||||||
def getpalette(self): | ||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an explanation of what is happening here - this isn't a random attribution. You're creating a comment that is over 100 characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments with >100 char lines long should not "break" the file. Even if we are reformatting here, the URL alone is wider than 100 chars in this case, so even breaking this in a functional way would still have lines wider than that.