Added SupportsArrayInterface

This commit is contained in:
Andrew Murray 2024-04-03 20:00:40 +11:00
parent 5d19151cd3
commit e85a84baa7
3 changed files with 27 additions and 7 deletions

View File

@ -91,6 +91,16 @@ def test_fromarray() -> None:
Image.fromarray(wrapped)
def test_fromarray_strides_without_tobytes() -> None:
class Wrapper:
def __init__(self, arr_params: dict[str, Any]) -> None:
self.__array_interface__ = arr_params
with pytest.raises(ValueError):
wrapped = Wrapper({"shape": (1, 1), "strides": (1, 1)})
Image.fromarray(wrapped, "L")
def test_fromarray_palette() -> None:
# Arrange
i = im.convert("L")

View File

@ -78,6 +78,8 @@ Constructing images
^^^^^^^^^^^^^^^^^^^
.. autofunction:: new
.. autoclass:: SupportsArrayInterface
:show-inheritance:
.. autofunction:: fromarray
.. autofunction:: frombytes
.. autofunction:: frombuffer

View File

@ -41,7 +41,7 @@ import warnings
from collections.abc import Callable, MutableMapping
from enum import IntEnum
from types import ModuleType
from typing import IO, TYPE_CHECKING, Any
from typing import IO, TYPE_CHECKING, Any, Protocol
# VERSION was removed in Pillow 6.0.0.
# PILLOW_VERSION was removed in Pillow 9.0.0.
@ -3013,7 +3013,7 @@ def frombytes(mode, size, data, decoder_name="raw", *args) -> Image:
return im
def frombuffer(mode, size, data, decoder_name="raw", *args):
def frombuffer(mode, size, data, decoder_name="raw", *args) -> Image:
"""
Creates an image memory referencing pixel data in a byte buffer.
@ -3069,10 +3069,15 @@ def frombuffer(mode, size, data, decoder_name="raw", *args):
return frombytes(mode, size, data, decoder_name, args)
def fromarray(
obj, # type: numpy.typing.ArrayLike
mode: str | None = None,
) -> Image:
class SupportsArrayInterface(Protocol):
"""
An object that has an ``__array_interface__`` dictionary.
"""
__array_interface__: dict[str, Any]
def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:
"""
Creates an image memory from an object exporting the array interface
(using the buffer protocol)::
@ -3151,8 +3156,11 @@ def fromarray(
if strides is not None:
if hasattr(obj, "tobytes"):
obj = obj.tobytes()
else:
elif hasattr(obj, "tostring"):
obj = obj.tostring()
else:
msg = "'strides' requires either tobytes() or tostring()"
raise ValueError(msg)
return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)