mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge pull request #6176 from radarhere/gif_transparency
Improve transparency handling when saving GIF
This commit is contained in:
commit
27f5c4d8fb
|
@ -639,7 +639,8 @@ def test_dispose2_background(tmp_path):
|
||||||
assert im.getpixel((0, 0)) == (255, 0, 0)
|
assert im.getpixel((0, 0)) == (255, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_transparency_in_second_frame():
|
def test_transparency_in_second_frame(tmp_path):
|
||||||
|
out = str(tmp_path / "temp.gif")
|
||||||
with Image.open("Tests/images/different_transparency.gif") as im:
|
with Image.open("Tests/images/different_transparency.gif") as im:
|
||||||
assert im.info["transparency"] == 0
|
assert im.info["transparency"] == 0
|
||||||
|
|
||||||
|
@ -649,6 +650,14 @@ def test_transparency_in_second_frame():
|
||||||
|
|
||||||
assert_image_equal_tofile(im, "Tests/images/different_transparency_merged.png")
|
assert_image_equal_tofile(im, "Tests/images/different_transparency_merged.png")
|
||||||
|
|
||||||
|
im.save(out, save_all=True)
|
||||||
|
|
||||||
|
with Image.open(out) as reread:
|
||||||
|
reread.seek(reread.tell() + 1)
|
||||||
|
assert_image_equal_tofile(
|
||||||
|
reread, "Tests/images/different_transparency_merged.png"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_no_transparency_in_second_frame():
|
def test_no_transparency_in_second_frame():
|
||||||
with Image.open("Tests/images/iss634.gif") as img:
|
with Image.open("Tests/images/iss634.gif") as img:
|
||||||
|
@ -660,6 +669,22 @@ def test_no_transparency_in_second_frame():
|
||||||
assert img.histogram()[255] == 0
|
assert img.histogram()[255] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_remapped_transparency(tmp_path):
|
||||||
|
out = str(tmp_path / "temp.gif")
|
||||||
|
|
||||||
|
im = Image.new("P", (1, 2))
|
||||||
|
im2 = im.copy()
|
||||||
|
|
||||||
|
# Add transparency at a higher index
|
||||||
|
# so that it will be optimized to a lower index
|
||||||
|
im.putpixel((0, 1), 5)
|
||||||
|
im.info["transparency"] = 5
|
||||||
|
im.save(out, save_all=True, append_images=[im2])
|
||||||
|
|
||||||
|
with Image.open(out) as reloaded:
|
||||||
|
assert reloaded.info["transparency"] == reloaded.getpixel((0, 1))
|
||||||
|
|
||||||
|
|
||||||
def test_duration(tmp_path):
|
def test_duration(tmp_path):
|
||||||
duration = 1000
|
duration = 1000
|
||||||
|
|
||||||
|
|
|
@ -609,6 +609,20 @@ class TestImage:
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
im.remap_palette(None)
|
im.remap_palette(None)
|
||||||
|
|
||||||
|
def test_remap_palette_transparency(self):
|
||||||
|
im = Image.new("P", (1, 2))
|
||||||
|
im.putpixel((0, 1), 1)
|
||||||
|
im.info["transparency"] = 0
|
||||||
|
|
||||||
|
im_remapped = im.remap_palette([1, 0])
|
||||||
|
assert im_remapped.info["transparency"] == 1
|
||||||
|
|
||||||
|
# Test unused transparency
|
||||||
|
im.info["transparency"] = 2
|
||||||
|
|
||||||
|
im_remapped = im.remap_palette([1, 0])
|
||||||
|
assert "transparency" not in im_remapped.info
|
||||||
|
|
||||||
def test__new(self):
|
def test__new(self):
|
||||||
im = hopper("RGB")
|
im = hopper("RGB")
|
||||||
im_p = hopper("P")
|
im_p = hopper("P")
|
||||||
|
|
|
@ -574,10 +574,14 @@ def _write_multiple_frames(im, fp, palette):
|
||||||
im_frame = _normalize_mode(im_frame.copy())
|
im_frame = _normalize_mode(im_frame.copy())
|
||||||
if frame_count == 0:
|
if frame_count == 0:
|
||||||
for k, v in im_frame.info.items():
|
for k, v in im_frame.info.items():
|
||||||
|
if k == "transparency":
|
||||||
|
continue
|
||||||
im.encoderinfo.setdefault(k, v)
|
im.encoderinfo.setdefault(k, v)
|
||||||
im_frame = _normalize_palette(im_frame, palette, im.encoderinfo)
|
|
||||||
|
|
||||||
encoderinfo = im.encoderinfo.copy()
|
encoderinfo = im.encoderinfo.copy()
|
||||||
|
im_frame = _normalize_palette(im_frame, palette, encoderinfo)
|
||||||
|
if "transparency" in im_frame.info:
|
||||||
|
encoderinfo.setdefault("transparency", im_frame.info["transparency"])
|
||||||
if isinstance(duration, (list, tuple)):
|
if isinstance(duration, (list, tuple)):
|
||||||
encoderinfo["duration"] = duration[frame_count]
|
encoderinfo["duration"] = duration[frame_count]
|
||||||
elif duration is None and "duration" in im_frame.info:
|
elif duration is None and "duration" in im_frame.info:
|
||||||
|
|
|
@ -1909,6 +1909,13 @@ class Image:
|
||||||
m_im.putpalette(new_palette_bytes)
|
m_im.putpalette(new_palette_bytes)
|
||||||
m_im.palette = ImagePalette.ImagePalette("RGB", palette=palette_bytes)
|
m_im.palette = ImagePalette.ImagePalette("RGB", palette=palette_bytes)
|
||||||
|
|
||||||
|
if "transparency" in self.info:
|
||||||
|
try:
|
||||||
|
m_im.info["transparency"] = dest_map.index(self.info["transparency"])
|
||||||
|
except ValueError:
|
||||||
|
if "transparency" in m_im.info:
|
||||||
|
del m_im.info["transparency"]
|
||||||
|
|
||||||
return m_im
|
return m_im
|
||||||
|
|
||||||
def _get_safe_box(self, size, resample, box):
|
def _get_safe_box(self, size, resample, box):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user