From b366d0972680fe5806066888546f963bd0d48239 Mon Sep 17 00:00:00 2001 From: Lucas Cimon <925560+Lucas-C@users.noreply.github.com> Date: Sun, 13 Aug 2023 13:47:39 +0200 Subject: [PATCH] FPDF.image(), when provided a BytesIO instance, does not close it anymore - fix #881 --- CHANGELOG.md | 2 ++ fpdf/image_parsing.py | 13 ++++++++----- test/image/image_types/test_insert_images.py | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34028a387..a6b7ce3d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This can also be enabled programmatically with `warnings.simplefilter('default', ## [2.7.6] - Not released yet ### Added * [`FPDF.write_html()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write_html) now supports heading colors defined as attributes (_e.g._ `

...`) +### Fixed +* [`FPDF.image()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image), when provided a `BytesIO` instance, does not close it anymore - _cf._ issue [#881](https://github.com/py-pdf/fpdf2/issues/881) ## [2.7.5] - 2023-08-04 ### Added diff --git a/fpdf/image_parsing.py b/fpdf/image_parsing.py index b200cd42b..d79b4bb2f 100644 --- a/fpdf/image_parsing.py +++ b/fpdf/image_parsing.py @@ -14,7 +14,7 @@ RESAMPLE = Resampling.LANCZOS except ImportError: # For Pillow < 9.1.0 - # pylint: disable=no-member + # pylint: disable=no-member, useless-suppression RESAMPLE = Image.ANTIALIAS except ImportError: Image = None @@ -116,6 +116,7 @@ def get_img_info(filename, img=None, image_filter="AUTO", dims=None): raise EnvironmentError("Pillow not available - fpdf2 cannot insert images") is_pil_img = True + keep_bytes_io_open = False jpeg_inverted = False # flag to check whether a cmyk image is jpeg or not, if set to True the decode array is inverted in output.py img_raw_data = None if not img or isinstance(img, (Path, str)): @@ -123,9 +124,8 @@ def get_img_info(filename, img=None, image_filter="AUTO", dims=None): img = Image.open(img_raw_data) is_pil_img = False elif not isinstance(img, Image.Image): - if isinstance(img, bytes): - img = BytesIO(img) - img_raw_data = img + keep_bytes_io_open = isinstance(img, BytesIO) + img_raw_data = BytesIO(img) if isinstance(img, bytes) else img img = Image.open(img_raw_data) is_pil_img = False @@ -293,7 +293,10 @@ def get_img_info(filename, img=None, image_filter="AUTO", dims=None): dp = f"/BlackIs1 true /Columns {w} /K -1 /Rows {h}" if not is_pil_img: - img.close() + if keep_bytes_io_open: + img.fp = None # cf. issue #881 + else: + img.close() info.update( { diff --git a/test/image/image_types/test_insert_images.py b/test/image/image_types/test_insert_images.py index 983ce235e..be4b1ed6c 100644 --- a/test/image/image_types/test_insert_images.py +++ b/test/image/image_types/test_insert_images.py @@ -211,6 +211,7 @@ def test_insert_bytesio(tmp_path): img.save(img_bytes, "PNG") pdf.image(img_bytes, x=15, y=15, h=140) assert_pdf_equal(pdf, HERE / "image_types_insert_png.pdf", tmp_path) + assert not img_bytes.closed # cf. issue #881 def test_insert_bytes(tmp_path):