Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Tests/test_file_bufrstub.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_open() -> None:

# Dummy data from the stub
assert im.mode == "F"
assert im.size == (1, 1)
assert im.size == (0, 0)


def test_invalid_file() -> None:
Expand Down Expand Up @@ -58,6 +58,7 @@ class TestHandler(ImageFile.StubHandler):

def open(self, im: ImageFile.StubImageFile) -> None:
self.opened = True
im._size = (1, 1)

def load(self, im: ImageFile.StubImageFile) -> Image.Image:
self.loaded = True
Expand Down
3 changes: 2 additions & 1 deletion Tests/test_file_gribstub.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_open() -> None:

# Dummy data from the stub
assert im.mode == "F"
assert im.size == (1, 1)
assert im.size == (0, 0)


def test_invalid_file() -> None:
Expand Down Expand Up @@ -58,6 +58,7 @@ class TestHandler(ImageFile.StubHandler):

def open(self, im: Image.Image) -> None:
self.opened = True
im._size = (1, 1)

def load(self, im: ImageFile.ImageFile) -> Image.Image:
self.loaded = True
Expand Down
3 changes: 2 additions & 1 deletion Tests/test_file_hdf5stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_open() -> None:

# Dummy data from the stub
assert im.mode == "F"
assert im.size == (1, 1)
assert im.size == (0, 0)


def test_invalid_file() -> None:
Expand Down Expand Up @@ -60,6 +60,7 @@ class TestHandler(ImageFile.StubHandler):

def open(self, im: Image.Image) -> None:
self.opened = True
im._size = (1, 1)

def load(self, im: ImageFile.ImageFile) -> Image.Image:
self.loaded = True
Expand Down
5 changes: 4 additions & 1 deletion Tests/test_file_wmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,17 @@ def test_register_handler(tmp_path: Path) -> None:
class TestHandler(ImageFile.StubHandler):
methodCalled = False

def open(self, im: ImageFile.StubImageFile) -> None:
im._size = (1, 1)

def load(self, im: ImageFile.StubImageFile) -> Image.Image:
return Image.new("RGB", (1, 1))

def save(self, im: Image.Image, fp: IO[bytes], filename: str) -> None:
self.methodCalled = True

handler = TestHandler()
original_handler = WmfImagePlugin._handler
original_handler = WmfImagePlugin.WmfStubImageFile._handler
WmfImagePlugin.register_handler(handler)

im = hopper()
Expand Down
15 changes: 5 additions & 10 deletions src/PIL/BufrStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@

from . import Image, ImageFile

_handler = None


def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific BUFR image handler.

:param handler: Handler object.
"""
global _handler
_handler = handler
BufrStubImageFile._handler = handler


# --------------------------------------------------------------------
Expand All @@ -50,17 +47,15 @@ def _open(self) -> None:

# make something up
self._mode = "F"
self._size = 1, 1

def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
if BufrStubImageFile._handler is None or not hasattr(
BufrStubImageFile._handler, "save"
):
msg = "BUFR save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename)
BufrStubImageFile._handler.save(im, fp, filename)


# --------------------------------------------------------------------
Expand Down
15 changes: 5 additions & 10 deletions src/PIL/GribStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@

from . import Image, ImageFile

_handler = None


def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific GRIB image handler.

:param handler: Handler object.
"""
global _handler
_handler = handler
GribStubImageFile._handler = handler


# --------------------------------------------------------------------
Expand All @@ -50,17 +47,15 @@ def _open(self) -> None:

# make something up
self._mode = "F"
self._size = 1, 1

def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
if GribStubImageFile._handler is None or not hasattr(
GribStubImageFile._handler, "save"
):
msg = "GRIB save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename)
GribStubImageFile._handler.save(im, fp, filename)


# --------------------------------------------------------------------
Expand Down
15 changes: 5 additions & 10 deletions src/PIL/Hdf5StubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@

from . import Image, ImageFile

_handler = None


def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific HDF5 image handler.

:param handler: Handler object.
"""
global _handler
_handler = handler
HDF5StubImageFile._handler = handler


# --------------------------------------------------------------------
Expand All @@ -50,17 +47,15 @@ def _open(self) -> None:

# make something up
self._mode = "F"
self._size = 1, 1

def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
if HDF5StubImageFile._handler is None or not hasattr(
HDF5StubImageFile._handler, "save"
):
msg = "HDF5 save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename)
HDF5StubImageFile._handler.save(im, fp, filename)


# --------------------------------------------------------------------
Expand Down
24 changes: 12 additions & 12 deletions src/PIL/ImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,8 @@ def __init__(
try:
self._open()

if isinstance(self, StubImageFile):
if loader := self._load():
loader.open(self)
if isinstance(self, StubImageFile) and self._handler:
self._handler.open(self)
except (
IndexError, # end of data
TypeError, # end of data (ord)
Expand All @@ -163,7 +162,11 @@ def __init__(
) as v:
raise SyntaxError(v) from v

if not self.mode or self.size[0] <= 0 or self.size[1] <= 0:
if not self.mode or (
min(self.size) < 0
if isinstance(self, StubImageFile) and self._handler is None
else min(self.size) <= 0
):
msg = "not identified by this driver"
raise SyntaxError(msg)
except BaseException:
Expand Down Expand Up @@ -468,6 +471,7 @@ def _seek_check(self, frame: int) -> bool:


class StubHandler(abc.ABC):
@abc.abstractmethod
def open(self, im: StubImageFile) -> None:
pass

Expand All @@ -484,27 +488,23 @@ class StubImageFile(ImageFile, metaclass=abc.ABCMeta):
certain format, but relies on external code to load the file.
"""

_handler: StubHandler | None = None

@abc.abstractmethod
def _open(self) -> None:
pass

def load(self) -> Image.core.PixelAccess | None:
loader = self._load()
if loader is None:
if self._handler is None:
msg = f"cannot find loader for this {self.format} file"
raise OSError(msg)
image = loader.load(self)
image = self._handler.load(self)
assert image is not None
# become the other object (!)
self.__class__ = image.__class__ # type: ignore[assignment]
self.__dict__ = image.__dict__
return image.load()

@abc.abstractmethod
def _load(self) -> StubHandler | None:
"""(Hook) Find actual image loader."""
pass


class Parser:
"""
Expand Down
76 changes: 36 additions & 40 deletions src/PIL/WmfImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,6 @@
from ._binary import si16le as short
from ._binary import si32le as _long

_handler = None


def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific WMF image handler.

:param handler: Handler object.
"""
global _handler
_handler = handler


if hasattr(Image.core, "drawwmf"):
# install default handler (windows only)

class WmfHandler(ImageFile.StubHandler):
def open(self, im: ImageFile.StubImageFile) -> None:
self.bbox = im.info["wmf_bbox"]

def load(self, im: ImageFile.StubImageFile) -> Image.Image:
assert im.fp is not None
im.fp.seek(0) # rewind
return Image.frombytes(
"RGB",
im.size,
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
"raw",
"BGR",
(im.size[0] * 3 + 3) & -4,
-1,
)

register_handler(WmfHandler())

#
# --------------------------------------------------------------------
# Read WMF file
Expand Down Expand Up @@ -147,9 +112,6 @@ def _open(self) -> None:
self._mode = "RGB"
self._size = size

def _load(self) -> ImageFile.StubHandler | None:
return _handler

def load(
self, dpi: float | tuple[float, float] | None = None
) -> Image.core.PixelAccess | None:
Expand All @@ -166,10 +128,44 @@ def load(


def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
if WmfStubImageFile._handler is None or not hasattr(
WmfStubImageFile._handler, "save"
):
msg = "WMF save handler not installed"
raise OSError(msg)
_handler.save(im, fp, filename)
WmfStubImageFile._handler.save(im, fp, filename)


def register_handler(handler: ImageFile.StubHandler | None) -> None:
"""
Install application-specific WMF image handler.

:param handler: Handler object.
"""
WmfStubImageFile._handler = handler


if hasattr(Image.core, "drawwmf"):
# install default handler (windows only)

class WmfHandler(ImageFile.StubHandler):
def open(self, im: ImageFile.StubImageFile) -> None:
self.bbox = im.info["wmf_bbox"]

def load(self, im: ImageFile.StubImageFile) -> Image.Image:
assert im.fp is not None
im.fp.seek(0) # rewind
return Image.frombytes(
"RGB",
im.size,
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
"raw",
"BGR",
(im.size[0] * 3 + 3) & -4,
-1,
)

register_handler(WmfHandler())


#
Expand Down