mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge pull request #1882 from wiredfool/pr_1840
Fix Transparency for PNG images
This commit is contained in:
commit
a0602fb68c
|
@ -74,8 +74,7 @@ _MODES = {
|
|||
}
|
||||
|
||||
|
||||
_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
|
||||
|
@ -118,7 +117,7 @@ class ChunkStream(object):
|
|||
cid = s[4:]
|
||||
pos = self.fp.tell()
|
||||
length = i32(s)
|
||||
|
||||
|
||||
if not is_cid(cid):
|
||||
raise SyntaxError("broken PNG file (chunk %s)" % repr(cid))
|
||||
|
||||
|
@ -359,12 +358,14 @@ class PngStream(ChunkStream):
|
|||
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)
|
||||
|
|
|
@ -203,6 +203,7 @@ class TestFilePng(PillowTestCase):
|
|||
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")
|
||||
|
@ -215,16 +216,66 @@ class TestFilePng(PillowTestCase):
|
|||
in_file = "Tests/images/pil123p.png"
|
||||
im = Image.open(in_file)
|
||||
|
||||
# 'transparency' contains a byte string with the opacity for
|
||||
# each palette 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 unique alpha 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)
|
||||
|
|
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user