From fae9afe35164c35aa1799e8a326d10601c12d586 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 25 Apr 2021 14:21:00 +1000 Subject: [PATCH] Replace sys.stdout with sys.stdout.buffer when saving --- Tests/test_file_png.py | 19 +++++++++++++++++++ src/PIL/Image.py | 2 ++ src/PIL/ImageFile.py | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index a1234b46a..35c82a4fb 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -1,4 +1,5 @@ import re +import sys import zlib from io import BytesIO @@ -10,6 +11,7 @@ from .helper import ( PillowLeakTestCase, assert_image, assert_image_equal, + assert_image_equal_tofile, hopper, is_big_endian, is_win32, @@ -711,6 +713,23 @@ class TestFilePng: with pytest.raises(EOFError): im.seek(1) + def test_save_stdout(self): + old_stdout = sys.stdout.buffer + + class MyStdOut: + buffer = BytesIO() + + sys.stdout = mystdout = MyStdOut() + + with Image.open(TEST_PNG_FILE) as im: + im.save(sys.stdout, "PNG") + + # Reset stdout + sys.stdout = old_stdout + + reloaded = Image.open(mystdout.buffer) + assert_image_equal_tofile(reloaded, TEST_PNG_FILE) + @pytest.mark.skipif(is_win32(), reason="Requires Unix or macOS") @skip_unless_feature("zlib") diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 6529db2be..105dbb34d 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2135,6 +2135,8 @@ class Image: elif isinstance(fp, Path): filename = str(fp) open_fp = True + elif fp == sys.stdout: + fp = sys.stdout.buffer if not filename and hasattr(fp, "name") and isPath(fp.name): # only set the name for metadata purposes filename = fp.name diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 0258a2ec1..6917e09a2 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -493,7 +493,7 @@ def _save(im, fp, tile, bufsize=0): # But, it would need at least the image size in most cases. RawEncode is # a tricky case. bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4) # see RawEncode.c - if fp == sys.stdout: + if fp == sys.stdout.buffer: fp.flush() return try: