From 6b168a3e2bafe1c957de8e9705ec9a17dd62fd84 Mon Sep 17 00:00:00 2001 From: Yay295 Date: Tue, 6 Aug 2024 21:02:46 -0500 Subject: [PATCH] add EPS test for image with ImageData and BoundingBox (atend) --- Tests/images/eps/1_atend.eps | Bin 0 -> 45867 bytes Tests/test_file_eps.py | 40 +++++++++++++-------- src/PIL/EpsImagePlugin.py | 65 ++++++++++++++++++++++------------- 3 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 Tests/images/eps/1_atend.eps diff --git a/Tests/images/eps/1_atend.eps b/Tests/images/eps/1_atend.eps new file mode 100644 index 0000000000000000000000000000000000000000..08f8c4681a90908a2ca3d7695d19f150a5787816 GIT binary patch literal 45867 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 None: EpsImagePlugin.EpsImageFile(data) +@pytest.mark.parametrize("prefix", (b"", simple_binary_header)) +def test_simple_eps_file(prefix: bytes) -> None: + data = io.BytesIO(prefix + b"\n".join(simple_eps_file)) + with Image.open(data) as img: + assert img.mode == "RGB" + assert img.size == (100, 100) + assert img.format == "EPS" + + @pytest.mark.parametrize("prefix", (b"", simple_binary_header)) def test_missing_version_comment(prefix: bytes) -> None: data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_version)) @@ -142,23 +151,19 @@ def test_missing_boundingbox_comment(prefix: bytes) -> None: @pytest.mark.parametrize("prefix", (b"", simple_binary_header)) -def test_invalid_boundingbox_comment(prefix: bytes) -> None: - data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox)) +@pytest.mark.parametrize( + "file_lines", + ( + simple_eps_file_with_invalid_boundingbox, + simple_eps_file_with_invalid_boundingbox_valid_imagedata, + ), +) +def test_invalid_boundingbox_comment(prefix: bytes, file_lines: list[bytes]) -> None: + data = io.BytesIO(prefix + b"\n".join(file_lines)) with pytest.raises(OSError, match="cannot determine EPS bounding box"): EpsImagePlugin.EpsImageFile(data) -@pytest.mark.parametrize("prefix", (b"", simple_binary_header)) -def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix: bytes) -> None: - data = io.BytesIO( - prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox_valid_imagedata) - ) - with Image.open(data) as img: - assert img.mode == "RGB" - assert img.size == (100, 100) - assert img.format == "EPS" - - @pytest.mark.parametrize("prefix", (b"", simple_binary_header)) def test_ascii_comment_too_long(prefix: bytes) -> None: data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_ascii_comment)) @@ -247,8 +252,13 @@ def test_bytesio_object() -> None: @pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available") -def test_1() -> None: - with Image.open("Tests/images/eps/1.eps") as im: +@pytest.mark.parametrize( + # These images have an "ImageData" descriptor. + "filename", + ("Tests/images/eps/1.eps", "Tests/images/eps/1_atend.eps"), +) +def test_1(filename: str) -> None: + with Image.open(filename) as im: assert_image_equal_tofile(im, "Tests/images/eps/1.bmp") diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index cbf48de18..ce8e54908 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -194,6 +194,11 @@ class EpsImageFile(ImageFile.ImageFile): self._mode = "RGB" + # When reading header comments, the first comment is used. + # When reading trailer comments, the last comment is used. + bounding_box: list[int] | None = None + imagedata_size: tuple[int, int] | None = None + byte_arr = bytearray(255) bytes_mv = memoryview(byte_arr) bytes_read = 0 @@ -214,8 +219,8 @@ class EpsImageFile(ImageFile.ImageFile): msg = 'EPS header missing "%%BoundingBox" comment' raise SyntaxError(msg) - def _read_comment(s: str) -> bool: - nonlocal reading_trailer_comments + def read_comment(s: str) -> bool: + nonlocal bounding_box, reading_trailer_comments try: m = split.match(s) except re.error as e: @@ -230,18 +235,12 @@ class EpsImageFile(ImageFile.ImageFile): if k == "BoundingBox": if v == "(atend)": reading_trailer_comments = True - elif not self.tile or (trailer_reached and reading_trailer_comments): + elif not bounding_box or (trailer_reached and reading_trailer_comments): try: # Note: The DSC spec says that BoundingBox # fields should be integers, but some drivers # put floating point values there anyway. - box = [int(float(i)) for i in v.split()] - self._size = box[2] - box[0], box[3] - box[1] - self.tile = [ - ImageFile._Tile( - "eps", (0, 0) + self.size, offset, (length, box) - ) - ] + bounding_box = [int(float(i)) for i in v.split()] except Exception: pass return True @@ -292,7 +291,7 @@ class EpsImageFile(ImageFile.ImageFile): continue s = str(bytes_mv[:bytes_read], "latin-1") - if not _read_comment(s): + if not read_comment(s): m = field.match(s) if m: k = m.group(1) @@ -326,32 +325,50 @@ class EpsImageFile(ImageFile.ImageFile): int(value) for value in image_data_values[:4] ) - if bit_depth == 1: - self._mode = "1" - elif bit_depth == 8: - try: - self._mode = self.mode_map[mode_id] - except ValueError: - break - else: - break + if not imagedata_size: + imagedata_size = columns, rows - self._size = columns, rows - return + if bit_depth == 1: + self._mode = "1" + elif bit_depth == 8: + try: + self._mode = self.mode_map[mode_id] + except ValueError: + pass elif bytes_mv[:5] == b"%%EOF": break elif trailer_reached and reading_trailer_comments: # Load EPS trailer s = str(bytes_mv[:bytes_read], "latin-1") - _read_comment(s) + read_comment(s) elif bytes_mv[:9] == b"%%Trailer": trailer_reached = True bytes_read = 0 - if not self.tile: + # A "BoundingBox" is always required, + # even if an "ImageData" descriptor size exists. + if not bounding_box: msg = "cannot determine EPS bounding box" raise OSError(msg) + # An "ImageData" size takes precedence over the "BoundingBox". + if imagedata_size: + self._size = imagedata_size + else: + self._size = ( + bounding_box[2] - bounding_box[0], + bounding_box[3] - bounding_box[1], + ) + + self.tile = [ + ImageFile._Tile( + codec_name="eps", + extents=(0, 0) + self._size, + offset=offset, + args=(length, bounding_box), + ) + ] + def _find_offset(self, fp: IO[bytes]) -> tuple[int, int]: s = fp.read(4)