mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	Merge pull request #8180 from radarhere/skip_truncated_mask
This commit is contained in:
		
						commit
						eb1dbbf787
					
				|  | @ -6,7 +6,7 @@ from pathlib import Path | ||||||
| 
 | 
 | ||||||
| import pytest | import pytest | ||||||
| 
 | 
 | ||||||
| from PIL import IcoImagePlugin, Image, ImageDraw | from PIL import IcoImagePlugin, Image, ImageDraw, ImageFile | ||||||
| 
 | 
 | ||||||
| from .helper import assert_image_equal, assert_image_equal_tofile, hopper | from .helper import assert_image_equal, assert_image_equal_tofile, hopper | ||||||
| 
 | 
 | ||||||
|  | @ -241,3 +241,29 @@ def test_draw_reloaded(tmp_path: Path) -> None: | ||||||
| 
 | 
 | ||||||
|     with Image.open(outfile) as im: |     with Image.open(outfile) as im: | ||||||
|         assert_image_equal_tofile(im, "Tests/images/hopper_draw.ico") |         assert_image_equal_tofile(im, "Tests/images/hopper_draw.ico") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_truncated_mask() -> None: | ||||||
|  |     # 1 bpp | ||||||
|  |     with open("Tests/images/hopper_mask.ico", "rb") as fp: | ||||||
|  |         data = fp.read() | ||||||
|  | 
 | ||||||
|  |     ImageFile.LOAD_TRUNCATED_IMAGES = True | ||||||
|  |     data = data[:-3] | ||||||
|  | 
 | ||||||
|  |     try: | ||||||
|  |         with Image.open(io.BytesIO(data)) as im: | ||||||
|  |             with Image.open("Tests/images/hopper_mask.png") as expected: | ||||||
|  |                 assert im.mode == "1" | ||||||
|  | 
 | ||||||
|  |         # 32 bpp | ||||||
|  |         output = io.BytesIO() | ||||||
|  |         expected = hopper("RGBA") | ||||||
|  |         expected.save(output, "ico", bitmap_format="bmp") | ||||||
|  | 
 | ||||||
|  |         data = output.getvalue()[:-1] | ||||||
|  | 
 | ||||||
|  |         with Image.open(io.BytesIO(data)) as im: | ||||||
|  |             assert im.mode == "RGB" | ||||||
|  |     finally: | ||||||
|  |         ImageFile.LOAD_TRUNCATED_IMAGES = False | ||||||
|  |  | ||||||
|  | @ -243,6 +243,7 @@ class IcoFile: | ||||||
|                 alpha_bytes = self.buf.read(im.size[0] * im.size[1] * 4)[3::4] |                 alpha_bytes = self.buf.read(im.size[0] * im.size[1] * 4)[3::4] | ||||||
| 
 | 
 | ||||||
|                 # convert to an 8bpp grayscale image |                 # convert to an 8bpp grayscale image | ||||||
|  |                 try: | ||||||
|                     mask = Image.frombuffer( |                     mask = Image.frombuffer( | ||||||
|                         "L",  # 8bpp |                         "L",  # 8bpp | ||||||
|                         im.size,  # (w, h) |                         im.size,  # (w, h) | ||||||
|  | @ -250,6 +251,11 @@ class IcoFile: | ||||||
|                         "raw",  # raw decoder |                         "raw",  # raw decoder | ||||||
|                         ("L", 0, -1),  # 8bpp inverted, unpadded, reversed |                         ("L", 0, -1),  # 8bpp inverted, unpadded, reversed | ||||||
|                     ) |                     ) | ||||||
|  |                 except ValueError: | ||||||
|  |                     if ImageFile.LOAD_TRUNCATED_IMAGES: | ||||||
|  |                         mask = None | ||||||
|  |                     else: | ||||||
|  |                         raise | ||||||
|             else: |             else: | ||||||
|                 # get AND image from end of bitmap |                 # get AND image from end of bitmap | ||||||
|                 w = im.size[0] |                 w = im.size[0] | ||||||
|  | @ -267,6 +273,7 @@ class IcoFile: | ||||||
|                 mask_data = self.buf.read(total_bytes) |                 mask_data = self.buf.read(total_bytes) | ||||||
| 
 | 
 | ||||||
|                 # convert raw data to image |                 # convert raw data to image | ||||||
|  |                 try: | ||||||
|                     mask = Image.frombuffer( |                     mask = Image.frombuffer( | ||||||
|                         "1",  # 1 bpp |                         "1",  # 1 bpp | ||||||
|                         im.size,  # (w, h) |                         im.size,  # (w, h) | ||||||
|  | @ -274,10 +281,16 @@ class IcoFile: | ||||||
|                         "raw",  # raw decoder |                         "raw",  # raw decoder | ||||||
|                         ("1;I", int(w / 8), -1),  # 1bpp inverted, padded, reversed |                         ("1;I", int(w / 8), -1),  # 1bpp inverted, padded, reversed | ||||||
|                     ) |                     ) | ||||||
|  |                 except ValueError: | ||||||
|  |                     if ImageFile.LOAD_TRUNCATED_IMAGES: | ||||||
|  |                         mask = None | ||||||
|  |                     else: | ||||||
|  |                         raise | ||||||
| 
 | 
 | ||||||
|                 # now we have two images, im is XOR image and mask is AND image |                 # now we have two images, im is XOR image and mask is AND image | ||||||
| 
 | 
 | ||||||
|             # apply mask image as alpha channel |             # apply mask image as alpha channel | ||||||
|  |             if mask: | ||||||
|                 im = im.convert("RGBA") |                 im = im.convert("RGBA") | ||||||
|                 im.putalpha(mask) |                 im.putalpha(mask) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user