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