Skip to content

Commit

Permalink
Merge eb0f400 into 7938202
Browse files Browse the repository at this point in the history
  • Loading branch information
olt committed Apr 19, 2016
2 parents 7938202 + eb0f400 commit c0bb6c9
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 7 deletions.
11 changes: 6 additions & 5 deletions PIL/PngImagePlugin.py
Expand Up @@ -74,8 +74,7 @@
}


_simple_palette = re.compile(b'^\xff+\x00\xff*$')
_null_palette = re.compile(b'^\x00*$')
_simple_palette = re.compile(b'^\xff*\x00\xff*$')

# Maximum decompressed size for a iTXt or zTXt chunk.
# Eliminates decompression bombs where compressed chunks can expand 1000x
Expand Down Expand Up @@ -118,7 +117,7 @@ def read(self):
cid = s[4:]
pos = self.fp.tell()
length = i32(s)

if not is_cid(cid):
raise SyntaxError("broken PNG file (chunk %s)" % repr(cid))

Expand Down Expand Up @@ -359,12 +358,14 @@ def chunk_tRNS(self, pos, length):
s = ImageFile._safe_read(self.fp, length)
if self.im_mode == "P":
if _simple_palette.match(s):
# tRNS contains only one full-transparent entry,
# other entries are full opaque
i = s.find(b"\0")
if i >= 0:
self.im_info["transparency"] = i
elif _null_palette.match(s):
self.im_info["transparency"] = 0
else:
# otherwise, we have a byte string with one alpha value
# for each palette entry
self.im_info["transparency"] = s
elif self.im_mode == "L":
self.im_info["transparency"] = i16(s)
Expand Down
50 changes: 50 additions & 0 deletions Tests/test_file_png.py
Expand Up @@ -203,6 +203,7 @@ def test_load_transparent_p(self):
def test_load_transparent_rgb(self):
test_file = "Tests/images/rgb_trns.png"
im = Image.open(test_file)
self.assertEqual(im.info["transparency"], (0, 255, 52))

self.assert_image(im, "RGB", (64, 64))
im = im.convert("RGBA")
Expand All @@ -215,16 +216,65 @@ def test_save_p_transparent_palette(self):
in_file = "Tests/images/pil123p.png"
im = Image.open(in_file)

# 'transparency' contains a byte string with the opacity for each palett entry
self.assertEqual(len(im.info["transparency"]), 256)

test_file = self.tempfile("temp.png")
im.save(test_file)

# check if saved image contains same transparency
im = Image.open(test_file)
self.assertEqual(len(im.info["transparency"]), 256)

self.assert_image(im, "P", (162, 150))
im = im.convert("RGBA")
self.assert_image(im, "RGBA", (162, 150))

# image has 124 uniqe qlpha values
self.assertEqual(len(im.split()[3].getcolors()), 124)

def test_save_p_single_transparency(self):
in_file = "Tests/images/p_trns_single.png"
im = Image.open(in_file)

# pixel value 164 is full transparent
self.assertEqual(im.info["transparency"], 164)
self.assertEqual(im.getpixel((31, 31)), 164)

test_file = self.tempfile("temp.png")
im.save(test_file)

# check if saved image contains same transparency
im = Image.open(test_file)
self.assertEqual(im.info["transparency"], 164)
self.assertEqual(im.getpixel((31, 31)), 164)
self.assert_image(im, "P", (64, 64))
im = im.convert("RGBA")
self.assert_image(im, "RGBA", (64, 64))

self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0))

# image has 876 transparent pixels
self.assertEqual(im.split()[3].getcolors()[0][0], 876)

def test_save_p_transparent_black(self):
# check if solid black image with full transparency
# is supported (check for #1838)
im = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])

im = im.convert("P")
test_file = self.tempfile("temp.png")
im.save(test_file)

# check if saved image contains same transparency
im = Image.open(test_file)
self.assertEqual(len(im.info["transparency"]), 256)
self.assert_image(im, "P", (10, 10))
im = im.convert("RGBA")
self.assert_image(im, "RGBA", (10, 10))
self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))])

def test_save_l_transparency(self):
in_file = "Tests/images/l_trns.png"
im = Image.open(in_file)
Expand Down
12 changes: 10 additions & 2 deletions docs/handbook/image-file-formats.rst
Expand Up @@ -370,8 +370,13 @@ The :py:meth:`~PIL.Image.Image.open` method sets the following
Gamma, given as a floating point number.

**transparency**
Transparency color index. This key is omitted if the image is not a
transparent palette image.
For ``P`` images: Either the palette index for full transparent pixels,
or a byte string with alpha values for each palette entry.

For ``L`` and ``RGB`` images, the color that represents full transparent
pixels in this image.

This key is omitted if the image is not a transparent palette image.

``Open`` also sets ``Image.text`` to a list of the values of the
``tEXt``, ``zTXt``, and ``iTXt`` chunks of the PNG image. Individual
Expand All @@ -392,6 +397,9 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
For ``P``, ``L``, and ``RGB`` images, this option controls what
color image to mark as transparent.

For ``P`` images, this can be a either the palette index,
or a byte string with alpha values for each palette entry.

**dpi**
A tuple of two numbers corresponding to the desired dpi in each direction.

Expand Down

0 comments on commit c0bb6c9

Please sign in to comment.