Allow loading of EMF images at a given DPI

This commit is contained in:
Andrew Murray 2024-11-05 21:27:25 +11:00
parent 7fe56d62c6
commit 20105aaa43
3 changed files with 28 additions and 10 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

View File

@ -8,7 +8,7 @@ import pytest
from PIL import Image, ImageFile, WmfImagePlugin from PIL import Image, ImageFile, WmfImagePlugin
from .helper import assert_image_similar_tofile, hopper from .helper import assert_image_equal_tofile, assert_image_similar_tofile, hopper
def test_load_raw() -> None: def test_load_raw() -> None:
@ -79,6 +79,20 @@ def test_load_set_dpi() -> None:
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref_144.png", 2.1) assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref_144.png", 2.1)
with Image.open("Tests/images/drawing.emf") as im:
assert im.size == (1625, 1625)
if not hasattr(Image.core, "drawwmf"):
return
im.load(im.info["dpi"])
assert im.size == (1625, 1625)
with Image.open("Tests/images/drawing.emf") as im:
im.load((72, 144))
assert im.size == (82, 164)
assert_image_equal_tofile(im, "Tests/images/drawing_emf_ref_72_144.png")
@pytest.mark.parametrize("ext", (".wmf", ".emf")) @pytest.mark.parametrize("ext", (".wmf", ".emf"))
def test_save(ext: str, tmp_path: Path) -> None: def test_save(ext: str, tmp_path: Path) -> None:

View File

@ -82,8 +82,6 @@ class WmfStubImageFile(ImageFile.StubImageFile):
format_description = "Windows Metafile" format_description = "Windows Metafile"
def _open(self) -> None: def _open(self) -> None:
self._inch = None
# check placable header # check placable header
s = self.fp.read(80) s = self.fp.read(80)
@ -91,7 +89,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# placeable windows metafile # placeable windows metafile
# get units per inch # get units per inch
self._inch = word(s, 14) inch = word(s, 14)
self._inch: tuple[float, float] = inch, inch
# get bounding box # get bounding box
x0 = short(s, 6) x0 = short(s, 6)
@ -102,8 +101,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# normalize size to 72 dots per inch # normalize size to 72 dots per inch
self.info["dpi"] = 72 self.info["dpi"] = 72
size = ( size = (
(x1 - x0) * self.info["dpi"] // self._inch, (x1 - x0) * self.info["dpi"] // inch,
(y1 - y0) * self.info["dpi"] // self._inch, (y1 - y0) * self.info["dpi"] // inch,
) )
self.info["wmf_bbox"] = x0, y0, x1, y1 self.info["wmf_bbox"] = x0, y0, x1, y1
@ -137,6 +136,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
self.info["dpi"] = xdpi self.info["dpi"] = xdpi
else: else:
self.info["dpi"] = xdpi, ydpi self.info["dpi"] = xdpi, ydpi
self._inch = xdpi, ydpi
else: else:
msg = "Unsupported file format" msg = "Unsupported file format"
@ -152,13 +152,17 @@ class WmfStubImageFile(ImageFile.StubImageFile):
def _load(self) -> ImageFile.StubHandler | None: def _load(self) -> ImageFile.StubHandler | None:
return _handler return _handler
def load(self, dpi: int | None = None) -> Image.core.PixelAccess | None: def load(
if dpi is not None and self._inch is not None: self, dpi: float | tuple[float, float] | None = None
) -> Image.core.PixelAccess | None:
if dpi is not None:
self.info["dpi"] = dpi self.info["dpi"] = dpi
x0, y0, x1, y1 = self.info["wmf_bbox"] x0, y0, x1, y1 = self.info["wmf_bbox"]
if not isinstance(dpi, tuple):
dpi = dpi, dpi
self._size = ( self._size = (
(x1 - x0) * self.info["dpi"] // self._inch, int((x1 - x0) * dpi[0] / self._inch[0]),
(y1 - y0) * self.info["dpi"] // self._inch, int((y1 - y0) * dpi[1] / self._inch[1]),
) )
return super().load() return super().load()