mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-09 14:54:46 +03:00
webp: handle ImageFile.LOAD_TRUNCATED_IMAGES
When set, don't raise an error on truncated content.
This commit is contained in:
parent
b4fcc44eb9
commit
3b736c5a0f
|
@ -7,6 +7,11 @@ _VALID_WEBP_MODES = ("RGB", "RGBA")
|
|||
|
||||
_VP8_MODES_BY_IDENTIFIER = (b"VP8 ", b"VP8X", b"VP8L")
|
||||
|
||||
_INFO_CHUNKS = {
|
||||
b'EXIF': 'exif',
|
||||
b'ICCP': 'icc_profile',
|
||||
}
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
is_riff_file_format = prefix[:4] == b"RIFF"
|
||||
|
@ -96,9 +101,8 @@ class WebPImageFile(ImageFile.ImageFile):
|
|||
while True:
|
||||
|
||||
chunk_header = self.fp.read(8)
|
||||
if 8 != len(chunk_header):
|
||||
if first_chunk:
|
||||
raise SyntaxError("not a WebP file")
|
||||
if len(chunk_header) < 8:
|
||||
# EOF.
|
||||
break
|
||||
|
||||
chunk_fourcc = chunk_header[0:4]
|
||||
|
@ -125,26 +129,19 @@ class WebPImageFile(ImageFile.ImageFile):
|
|||
elif b'ALPH' == chunk_fourcc:
|
||||
mode = 'RGBA'
|
||||
|
||||
elif b'EXIF' == chunk_fourcc:
|
||||
exif = self.fp.read(chunk_size)
|
||||
if chunk_size != len(exif):
|
||||
raise SyntaxError("bad EXIF chunk")
|
||||
self.info["exif"] = exif
|
||||
elif chunk_fourcc in _INFO_CHUNKS:
|
||||
data = self.fp.read(chunk_size)
|
||||
if len(data) < chunk_size:
|
||||
if ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
# Simulate EOF.
|
||||
break
|
||||
msg = "image file is truncated: incomplete %s chunk" % chunk_fourcc
|
||||
raise IOError(msg)
|
||||
self.info[_INFO_CHUNKS[chunk_fourcc]] = data
|
||||
chunk_size = 0
|
||||
|
||||
elif b'ICCP' == chunk_fourcc:
|
||||
icc_profile = self.fp.read(chunk_size)
|
||||
if chunk_size != len(icc_profile):
|
||||
raise SyntaxError("bad ICCP chunk")
|
||||
self.info["icc_profile"] = icc_profile
|
||||
chunk_size = 0
|
||||
|
||||
if chunk_size > 0:
|
||||
# Skip to next chunk.
|
||||
pos = self.fp.tell()
|
||||
self.fp.seek(chunk_size, os.SEEK_CUR)
|
||||
if self.fp.tell() != (pos + chunk_size):
|
||||
raise SyntaxError("not a WebP file")
|
||||
# Skip to next chunk.
|
||||
self.fp.seek(chunk_size, os.SEEK_CUR)
|
||||
|
||||
first_chunk = False
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from helper import unittest, PillowTestCase, hopper
|
||||
|
||||
from PIL import Image
|
||||
from PIL import Image, ImageFile
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
try:
|
||||
from PIL import _webp
|
||||
|
@ -72,6 +74,40 @@ class TestFileWebp(PillowTestCase):
|
|||
target = hopper("RGB")
|
||||
self.assert_image_similar(image, target, 12)
|
||||
|
||||
def test_truncated(self):
|
||||
assert False == ImageFile.LOAD_TRUNCATED_IMAGES
|
||||
with open('Tests/images/flower.webp', 'rb') as fp:
|
||||
full_data = fp.read()
|
||||
# Truncate in the middle (VP8 chunk).
|
||||
half_data = full_data[:len(full_data)//2]
|
||||
im = Image.open(BytesIO(half_data))
|
||||
self.assertRaises(IOError, im.load)
|
||||
im = Image.open(BytesIO(half_data))
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
try:
|
||||
im.load()
|
||||
finally:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
original = Image.open(BytesIO(full_data))
|
||||
width, height = original.size
|
||||
# Check we decoded at least part of the image (top).
|
||||
top_area = (0, 0, width-1, 31)
|
||||
self.assert_image_equal(im.crop(top_area), original.crop(top_area))
|
||||
# Bottom should be blank.
|
||||
bottom_area = (width-33, height-33, width-1, height-1)
|
||||
self.assert_image_equal(im.crop(bottom_area), Image.new(original.mode, (32, 32)))
|
||||
# Truncate at the end (EXIF chunk).
|
||||
most_data = full_data[:-4*1024]
|
||||
self.assertRaises(IOError, Image.open, BytesIO(most_data))
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
try:
|
||||
im = Image.open(BytesIO(most_data))
|
||||
finally:
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
im.load()
|
||||
# Check we decoded the whole image.
|
||||
self.assert_image_equal(im, original)
|
||||
|
||||
def test_info_compression(self):
|
||||
for name, compression in (
|
||||
('flower2' , 'lossy'),
|
||||
|
|
Loading…
Reference in New Issue
Block a user