mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-11 04:07:21 +03:00
Merge pull request #3 from radarhere/fix_get_optimize
Optimise palettes with more than 128 colors
This commit is contained in:
commit
7c839d8d81
|
@ -158,6 +158,9 @@ def test_optimize_correctness():
|
|||
assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
|
||||
|
||||
# These do optimize the palette
|
||||
check(256, 511, 256)
|
||||
check(255, 511, 255)
|
||||
check(129, 511, 129)
|
||||
check(128, 511, 128)
|
||||
check(64, 511, 64)
|
||||
check(4, 511, 4)
|
||||
|
@ -167,11 +170,6 @@ def test_optimize_correctness():
|
|||
check(64, 513, 256)
|
||||
check(4, 513, 256)
|
||||
|
||||
# Other limits that don't optimize the palette
|
||||
check(129, 511, 256)
|
||||
check(255, 511, 256)
|
||||
check(256, 511, 256)
|
||||
|
||||
|
||||
def test_optimize_full_l():
|
||||
im = Image.frombytes("L", (16, 16), bytes(range(256)))
|
||||
|
@ -182,17 +180,15 @@ def test_optimize_full_l():
|
|||
|
||||
def test_optimize_if_palette_can_be_reduced_by_half():
|
||||
with Image.open("Tests/images/test.colors.gif") as im:
|
||||
# Reduce because original is too big for _get_optimize()
|
||||
# Reduce dimensions because original is too big for _get_optimize()
|
||||
im = im.resize((591, 443))
|
||||
imrgb = im.convert("RGB")
|
||||
im_rgb = im.convert("RGB")
|
||||
|
||||
for (optimize, colors) in ((False, 256), (True, 8)):
|
||||
out = BytesIO()
|
||||
imrgb.save(out, "GIF", optimize=False)
|
||||
im_rgb.save(out, "GIF", optimize=optimize)
|
||||
with Image.open(out) as reloaded:
|
||||
assert len(reloaded.palette.palette) // 3 == 256
|
||||
out = BytesIO()
|
||||
imrgb.save(out, "GIF", optimize=True)
|
||||
with Image.open(out) as reloaded:
|
||||
assert len(reloaded.palette.palette) // 3 == 8
|
||||
assert len(reloaded.palette.palette) // 3 == colors
|
||||
|
||||
|
||||
def test_roundtrip(tmp_path):
|
||||
|
@ -997,8 +993,8 @@ def test_append_images(tmp_path):
|
|||
def test_transparent_optimize(tmp_path):
|
||||
# From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
|
||||
# transparency.
|
||||
# Need a palette that isn't using the 0 color, and one that's > 128 items where the
|
||||
# transparent color is actually the top palette entry to trigger the bug.
|
||||
# Need a palette that isn't using the 0 color,
|
||||
# where the transparent color is actually the top palette entry to trigger the bug.
|
||||
|
||||
data = bytes(range(1, 254))
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
|
@ -1008,10 +1004,10 @@ def test_transparent_optimize(tmp_path):
|
|||
im.putpalette(palette)
|
||||
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, transparency=253)
|
||||
with Image.open(out) as reloaded:
|
||||
im.save(out, transparency=im.getpixel((252, 0)))
|
||||
|
||||
assert reloaded.info["transparency"] == 253
|
||||
with Image.open(out) as reloaded:
|
||||
assert reloaded.info["transparency"] == reloaded.getpixel((252, 0))
|
||||
|
||||
|
||||
def test_rgb_transparency(tmp_path):
|
||||
|
|
|
@ -824,17 +824,18 @@ def _get_optimize(im, info):
|
|||
if count:
|
||||
used_palette_colors.append(i)
|
||||
|
||||
num_palette_colors = (
|
||||
len(im.palette.palette) // 4
|
||||
if im.palette.mode == "RGBA"
|
||||
else len(im.palette.palette) // 3
|
||||
if optimise or max(used_palette_colors) >= len(used_palette_colors):
|
||||
return used_palette_colors
|
||||
|
||||
num_palette_colors = len(im.palette.palette) // Image.getmodebands(
|
||||
im.palette.mode
|
||||
)
|
||||
# Round up to power of 2 but at least 4
|
||||
num_palette_colors = max(4, 1 << (num_palette_colors - 1).bit_length())
|
||||
if optimise or (
|
||||
len(used_palette_colors) <= 128
|
||||
and max(used_palette_colors) >= len(used_palette_colors)
|
||||
or len(used_palette_colors) <= num_palette_colors // 2
|
||||
current_palette_size = 1 << (num_palette_colors - 1).bit_length()
|
||||
if (
|
||||
# check that the palette would become smaller when saved
|
||||
len(used_palette_colors) <= current_palette_size // 2
|
||||
# check that the palette is not already the smallest possible size
|
||||
and current_palette_size > 2
|
||||
):
|
||||
return used_palette_colors
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user