Merge pull request #4837 from nulano/formats

Add formats parameter to open
This commit is contained in:
Andrew Murray 2020-09-05 20:49:59 +10:00 committed by GitHub
commit fac2d2781e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 5 deletions

View File

@ -87,6 +87,26 @@ class TestImage:
# with pytest.raises(MemoryError): # with pytest.raises(MemoryError):
# Image.new("L", (1000000, 1000000)) # Image.new("L", (1000000, 1000000))
def test_open_formats(self):
PNGFILE = "Tests/images/hopper.png"
JPGFILE = "Tests/images/hopper.jpg"
with pytest.raises(TypeError):
Image.open(PNGFILE, formats=123)
for formats in [["JPEG"], ("JPEG",)]:
with pytest.raises(UnidentifiedImageError):
Image.open(PNGFILE, formats=formats)
with Image.open(JPGFILE, formats=formats) as im:
assert im.mode == "RGB"
assert im.size == (128, 128)
for file in [PNGFILE, JPGFILE]:
with Image.open(file, formats=None) as im:
assert im.mode == "RGB"
assert im.size == (128, 128)
def test_width_height(self): def test_width_height(self):
im = Image.new("RGB", (1, 2)) im = Image.new("RGB", (1, 2))
assert im.width == 1 assert im.width == 1

View File

@ -50,6 +50,17 @@ Add MIME type to PsdImagePlugin
API Additions API Additions
============= =============
Image.open: add formats parameter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Added a new ``formats`` parameter to :py:func:`.Image.open`:
* A list or tuple of formats to attempt to load the file in.
This can be used to restrict the set of formats checked.
Pass ``None`` to try all supported formats. You can print the set of
available formats by running ``python -m PIL`` or using
the :py:func:`PIL.features.pilinfo` function.
ImageOps.autocontrast: add mask parameter ImageOps.autocontrast: add mask parameter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2837,7 +2837,7 @@ def _decompression_bomb_check(size):
) )
def open(fp, mode="r"): def open(fp, mode="r", formats=None):
""" """
Opens and identifies the given image file. Opens and identifies the given image file.
@ -2852,12 +2852,18 @@ def open(fp, mode="r"):
``file.seek``, and ``file.tell`` methods, ``file.seek``, and ``file.tell`` methods,
and be opened in binary mode. and be opened in binary mode.
:param mode: The mode. If given, this argument must be "r". :param mode: The mode. If given, this argument must be "r".
:param formats: A list or tuple of formats to attempt to load the file in.
This can be used to restrict the set of formats checked.
Pass ``None`` to try all supported formats. You can print the set of
available formats by running ``python -m PIL`` or using
the :py:func:`PIL.features.pilinfo` function.
:returns: An :py:class:`~PIL.Image.Image` object. :returns: An :py:class:`~PIL.Image.Image` object.
:exception FileNotFoundError: If the file cannot be found. :exception FileNotFoundError: If the file cannot be found.
:exception PIL.UnidentifiedImageError: If the image cannot be opened and :exception PIL.UnidentifiedImageError: If the image cannot be opened and
identified. identified.
:exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
instance is used for ``fp``. instance is used for ``fp``.
:exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
""" """
if mode != "r": if mode != "r":
@ -2868,6 +2874,11 @@ def open(fp, mode="r"):
"Binary data must be used instead." "Binary data must be used instead."
) )
if formats is None:
formats = ID
elif not isinstance(formats, (list, tuple)):
raise TypeError("formats must be a list or tuple")
exclusive_fp = False exclusive_fp = False
filename = "" filename = ""
if isinstance(fp, Path): if isinstance(fp, Path):
@ -2891,8 +2902,8 @@ def open(fp, mode="r"):
accept_warnings = [] accept_warnings = []
def _open_core(fp, filename, prefix): def _open_core(fp, filename, prefix, formats):
for i in ID: for i in formats:
try: try:
factory, accept = OPEN[i] factory, accept = OPEN[i]
result = not accept or accept(prefix) result = not accept or accept(prefix)
@ -2914,11 +2925,11 @@ def open(fp, mode="r"):
raise raise
return None return None
im = _open_core(fp, filename, prefix) im = _open_core(fp, filename, prefix, formats)
if im is None: if im is None:
if init(): if init():
im = _open_core(fp, filename, prefix) im = _open_core(fp, filename, prefix, formats)
if im: if im:
im._exclusive_fp = exclusive_fp im._exclusive_fp = exclusive_fp