mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14: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,13 +243,19 @@ 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
|
||||||
mask = Image.frombuffer(
|
try:
|
||||||
"L", # 8bpp
|
mask = Image.frombuffer(
|
||||||
im.size, # (w, h)
|
"L", # 8bpp
|
||||||
alpha_bytes, # source chars
|
im.size, # (w, h)
|
||||||
"raw", # raw decoder
|
alpha_bytes, # source chars
|
||||||
("L", 0, -1), # 8bpp inverted, unpadded, reversed
|
"raw", # raw decoder
|
||||||
)
|
("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,19 +273,26 @@ 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
|
||||||
mask = Image.frombuffer(
|
try:
|
||||||
"1", # 1 bpp
|
mask = Image.frombuffer(
|
||||||
im.size, # (w, h)
|
"1", # 1 bpp
|
||||||
mask_data, # source chars
|
im.size, # (w, h)
|
||||||
"raw", # raw decoder
|
mask_data, # source chars
|
||||||
("1;I", int(w / 8), -1), # 1bpp inverted, padded, reversed
|
"raw", # raw decoder
|
||||||
)
|
("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
|
||||||
im = im.convert("RGBA")
|
if mask:
|
||||||
im.putalpha(mask)
|
im = im.convert("RGBA")
|
||||||
|
im.putalpha(mask)
|
||||||
|
|
||||||
return im
|
return im
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user