diff --git a/Tests/test_image.py b/Tests/test_image.py index 83da76b96..3cd754f99 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,3 +1,4 @@ +import io import os import shutil import tempfile @@ -91,6 +92,11 @@ class TestImage(PillowTestCase): def test_bad_mode(self): self.assertRaises(ValueError, Image.open, "filename", "bad mode") + def test_stringio(self): + with Image.open(io.StringIO("Tests/images/hopper.jpg")) as im: + self.assertEqual(im.mode, "RGB") + self.assertEqual(im.size, (128, 128)) + def test_pathlib(self): from PIL.Image import Path diff --git a/docs/reference/open_files.rst b/docs/reference/open_files.rst index ed0ab1a0c..d315b1cd1 100644 --- a/docs/reference/open_files.rst +++ b/docs/reference/open_files.rst @@ -3,10 +3,10 @@ File Handling in Pillow ======================= -When opening a file as an image, Pillow requires a filename, ``pathlib.Path`` -object, or a file-like object. Pillow uses the filename or ``Path`` to open a -file, so for the rest of this article, they will all be treated as a file-like -object. +When opening a file as an image, Pillow requires a filename, ``io.StringIO`` +object, ``pathlib.Path`` object, or a file-like object. Pillow uses the +filename, ``StringIO`` or ``Path`` to open a file, so for the rest of this +article, they will all be treated as a file-like object. The following are all equivalent:: @@ -17,6 +17,9 @@ The following are all equivalent:: with Image.open('test.jpg') as im: ... + with Image.open(io.StringIO('test.jpg')) as im2: + ... + with Image.open(pathlib.Path('test.jpg')) as im2: ... diff --git a/src/PIL/Image.py b/src/PIL/Image.py index ed90a26f7..16b84ab1d 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2674,8 +2674,8 @@ def open(fp, mode="r"): :py:meth:`~PIL.Image.Image.load` method). See :py:func:`~PIL.Image.new`. See :ref:`file-handling`. - :param fp: A filename (string), pathlib.Path object or a file object. - The file object must implement :py:meth:`~file.read`, + :param fp: A filename (string), io.StringIO object, pathlib.Path object + or a file object. The file object must implement :py:meth:`~file.read`, :py:meth:`~file.seek`, and :py:meth:`~file.tell` methods, and be opened in binary mode. :param mode: The mode. If given, this argument must be "r". @@ -2691,6 +2691,8 @@ def open(fp, mode="r"): filename = "" if isinstance(fp, Path): filename = str(fp.resolve()) + elif isinstance(fp, io.StringIO): + filename = fp.getvalue() elif isPath(fp): filename = fp