Merge pull request #2898 from wiredfool/pr_2790

Add support for sRGB and cHRM chunks, permit sRGB when no iCCP chunk
This commit is contained in:
wiredfool 2017-12-27 12:12:57 +00:00 committed by GitHub
commit bd5f99f19d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 14 deletions

View File

@ -387,12 +387,31 @@ class PngStream(ChunkStream):
return s
def chunk_gAMA(self, pos, length):
# gamma setting
s = ImageFile._safe_read(self.fp, length)
self.im_info["gamma"] = i32(s) / 100000.0
return s
def chunk_cHRM(self, pos, length):
# chromaticity, 8 unsigned ints, actual value is scaled by 100,000
# WP x,y, Red x,y, Green x,y Blue x,y
s = ImageFile._safe_read(self.fp, length)
raw_vals = struct.unpack('>%dI' % (len(s) // 4), s)
self.im_info['chromaticity'] = tuple(elt/100000.0 for elt in raw_vals)
return s
def chunk_sRGB(self, pos, length):
# srgb rendering intent, 1 byte
# 0 perceptual
# 1 relative colorimetric
# 2 saturation
# 3 absolute colorimetric
s = ImageFile._safe_read(self.fp, length)
self.im_info['srgb'] = i8(s)
return s
def chunk_pHYs(self, pos, length):
# pixels per unit
@ -731,7 +750,9 @@ def _save(im, fp, filename, chunk=putchunk):
name = b"ICC Profile"
data = name + b"\0\0" + zlib.compress(icc)
chunk(fp, b"iCCP", data)
else:
# You must either have sRGB or iCCP.
# Disallow sRGB chunks when an iCCP-chunk has been emitted.
chunks.remove(b"sRGB")
info = im.encoderinfo.get("pnginfo")

View File

@ -49,6 +49,21 @@ class TestFilePng(PillowTestCase):
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
self.skipTest("zip/deflate support not available")
def get_chunks(self, filename):
chunks = []
with open(filename, "rb") as fp:
fp.read(8)
with PngImagePlugin.PngStream(fp) as png:
while True:
cid, pos, length = png.read()
chunks.append(cid)
try:
s = png.call(cid, pos, length)
except EOFError:
break
png.crc(cid, s)
return chunks
def test_sanity(self):
# internal version number
@ -501,18 +516,7 @@ class TestFilePng(PillowTestCase):
test_file = self.tempfile("temp.png")
im.convert("P").save(test_file, dpi=(100, 100))
chunks = []
with open(test_file, "rb") as fp:
fp.read(8)
with PngImagePlugin.PngStream(fp) as png:
while True:
cid, pos, length = png.read()
chunks.append(cid)
try:
s = png.call(cid, pos, length)
except EOFError:
break
png.crc(cid, s)
chunks = self.get_chunks(test_file)
# https://www.w3.org/TR/PNG/#5ChunkOrdering
# IHDR - shall be first

View File

@ -408,9 +408,22 @@ PIL identifies, reads, and writes PNG files containing ``1``, ``L``, ``P``,
The :py:meth:`~PIL.Image.Image.open` method sets the following
:py:attr:`~PIL.Image.Image.info` properties, when appropriate:
**chromaticity**
The chromaticity points, as an 8 tuple of floats. (``White Point
X``, ``White Point Y``, ``Red X``, ``Red Y``, ``Green X``, ``Green
Y``, ``Blue X``, ``Blue Y``)
**gamma**
Gamma, given as a floating point number.
**srgb**
The sRGB rendering intent as an integer.
* 0 Perceptual
* 1 Relative Colorimetric
* 2 Saturation
* 3 Absolute Colorimetric
**transparency**
For ``P`` images: Either the palette index for full transparent pixels,
or a byte string with alpha values for each palette entry.