Skip to content

Commit 6d42449

Browse files
authored
Allow loading of EMF images at a given DPI (#8536)
Co-authored-by: Andrew Murray <[email protected]>
1 parent 2579973 commit 6d42449

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed
984 Bytes
Loading

Tests/test_file_wmf.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,20 @@ def test_load_set_dpi() -> None:
9797

9898
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref_144.png", 2.1)
9999

100+
with Image.open("Tests/images/drawing.emf") as im:
101+
assert im.size == (1625, 1625)
102+
103+
if not hasattr(Image.core, "drawwmf"):
104+
return
105+
im.load(im.info["dpi"])
106+
assert im.size == (1625, 1625)
107+
108+
with Image.open("Tests/images/drawing.emf") as im:
109+
im.load((72, 144))
110+
assert im.size == (82, 164)
111+
112+
assert_image_equal_tofile(im, "Tests/images/drawing_emf_ref_72_144.png")
113+
100114

101115
@pytest.mark.parametrize("ext", (".wmf", ".emf"))
102116
def test_save(ext: str, tmp_path: Path) -> None:

src/PIL/WmfImagePlugin.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,18 @@ class WmfStubImageFile(ImageFile.StubImageFile):
8080
format_description = "Windows Metafile"
8181

8282
def _open(self) -> None:
83-
self._inch = None
84-
8583
# check placable header
8684
s = self.fp.read(80)
8785

8886
if s.startswith(b"\xd7\xcd\xc6\x9a\x00\x00"):
8987
# placeable windows metafile
9088

9189
# get units per inch
92-
self._inch = word(s, 14)
93-
if self._inch == 0:
90+
inch = word(s, 14)
91+
if inch == 0:
9492
msg = "Invalid inch"
9593
raise ValueError(msg)
94+
self._inch: tuple[float, float] = inch, inch
9695

9796
# get bounding box
9897
x0 = short(s, 6)
@@ -103,8 +102,8 @@ def _open(self) -> None:
103102
# normalize size to 72 dots per inch
104103
self.info["dpi"] = 72
105104
size = (
106-
(x1 - x0) * self.info["dpi"] // self._inch,
107-
(y1 - y0) * self.info["dpi"] // self._inch,
105+
(x1 - x0) * self.info["dpi"] // inch,
106+
(y1 - y0) * self.info["dpi"] // inch,
108107
)
109108

110109
self.info["wmf_bbox"] = x0, y0, x1, y1
@@ -138,6 +137,7 @@ def _open(self) -> None:
138137
self.info["dpi"] = xdpi
139138
else:
140139
self.info["dpi"] = xdpi, ydpi
140+
self._inch = xdpi, ydpi
141141

142142
else:
143143
msg = "Unsupported file format"
@@ -153,13 +153,17 @@ def _open(self) -> None:
153153
def _load(self) -> ImageFile.StubHandler | None:
154154
return _handler
155155

156-
def load(self, dpi: int | None = None) -> Image.core.PixelAccess | None:
157-
if dpi is not None and self._inch is not None:
156+
def load(
157+
self, dpi: float | tuple[float, float] | None = None
158+
) -> Image.core.PixelAccess | None:
159+
if dpi is not None:
158160
self.info["dpi"] = dpi
159161
x0, y0, x1, y1 = self.info["wmf_bbox"]
162+
if not isinstance(dpi, tuple):
163+
dpi = dpi, dpi
160164
self._size = (
161-
(x1 - x0) * self.info["dpi"] // self._inch,
162-
(y1 - y0) * self.info["dpi"] // self._inch,
165+
int((x1 - x0) * dpi[0] / self._inch[0]),
166+
int((y1 - y0) * dpi[1] / self._inch[1]),
163167
)
164168
return super().load()
165169

0 commit comments

Comments
 (0)