From 20105aaa438206661922735235729500423e9663 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 5 Nov 2024 21:27:25 +1100 Subject: [PATCH] Allow loading of EMF images at a given DPI --- Tests/images/drawing_emf_ref_72_144.png | Bin 0 -> 984 bytes Tests/test_file_wmf.py | 16 +++++++++++++++- src/PIL/WmfImagePlugin.py | 22 +++++++++++++--------- 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 Tests/images/drawing_emf_ref_72_144.png diff --git a/Tests/images/drawing_emf_ref_72_144.png b/Tests/images/drawing_emf_ref_72_144.png new file mode 100644 index 0000000000000000000000000000000000000000..000377b6c7b1e05688fc17d5da09d163a18c5b4b GIT binary patch literal 984 zcmV;}11J26P) z+m?eM3`K+g|If}tT8An^fFxX!{W??4_QVUcOTu}cFoF=ms9ghq-o8T!`G3$n3L4r; z;S(Tv7 z*g4bg5BZ5u>}=ZTECjnbkG7~Y!fVc;t>BC>n)hm}IU`)=UE0dd2#a~U_7G>J-@H+K zpfl2G-l#p+8R@B^MO*Hfv6kjaTC`_~8fk9zYVCQVM%pr{(;j{$OVW@;o%V#z&{S20 z_H6APQ(GHVd(QU0sJ*sPwP$ulswyOD&)nWI^g2n}^GA))>lB$n90)P+vi2$+jt~Pc zYp>GbRTQ+>iW;HRT+m)IYD&#H?G>X&ik0WISBx4dR=(Q}jL56@x*d+>>wnc=x5JTq z{odpet9ST^cZ;<4>K$IhoBYcr9ge)XB(%5haPTI##a(-=6B|hx-L);8*x*fWiy!R` zPi*Aj^`mX%#D-XV+o%EHVdv+zC0yGQuDvz4pF4cCC;yEGJ66)Z;o6pP?cIql<_Flj zjDxAPV_e%3u5Ag|wuEb2!nG~o+Lo}TeT_YBX8{;W*E8=kK*&u$uPh z0#pg#mvPzBzHn_zxV9x++Y+vA3D>rSYg^&~0E0trLup^5PB5h%oqCm9%f69=AWL)}qDpk;FvW&-2%W_7m4ewmZF(V~zdOPTrXJ z*G{sz_SAfY3qS45;(n1@>+kbrKnL=A$hI8>3{A})shuAu$f!EHj>I!TPwG& zL#U6Wa@E!;18=CRere*`4+zs%Pqp@J*S59>Y+8SNnpSTPpm8WNL*NZpvWrIT;jP}| z3_SzSf##jg&^g{7V&3lz{nHG}<}A*@GP|N?&gBeTlS(?~j5kiUxinGpzU3_C`9IR4e2CH??qha)B=@Nu*N0000 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) + 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")) def test_save(ext: str, tmp_path: Path) -> None: diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index cad6c98d53f..487a57fbfa1 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -82,8 +82,6 @@ class WmfStubImageFile(ImageFile.StubImageFile): format_description = "Windows Metafile" def _open(self) -> None: - self._inch = None - # check placable header s = self.fp.read(80) @@ -91,7 +89,8 @@ def _open(self) -> None: # placeable windows metafile # get units per inch - self._inch = word(s, 14) + inch = word(s, 14) + self._inch: tuple[float, float] = inch, inch # get bounding box x0 = short(s, 6) @@ -102,8 +101,8 @@ def _open(self) -> None: # normalize size to 72 dots per inch self.info["dpi"] = 72 size = ( - (x1 - x0) * self.info["dpi"] // self._inch, - (y1 - y0) * self.info["dpi"] // self._inch, + (x1 - x0) * self.info["dpi"] // inch, + (y1 - y0) * self.info["dpi"] // inch, ) self.info["wmf_bbox"] = x0, y0, x1, y1 @@ -137,6 +136,7 @@ def _open(self) -> None: self.info["dpi"] = xdpi else: self.info["dpi"] = xdpi, ydpi + self._inch = xdpi, ydpi else: msg = "Unsupported file format" @@ -152,13 +152,17 @@ def _open(self) -> None: def _load(self) -> ImageFile.StubHandler | None: return _handler - def load(self, dpi: int | None = None) -> Image.core.PixelAccess | None: - if dpi is not None and self._inch is not None: + def load( + self, dpi: float | tuple[float, float] | None = None + ) -> Image.core.PixelAccess | None: + if dpi is not None: self.info["dpi"] = dpi x0, y0, x1, y1 = self.info["wmf_bbox"] + if not isinstance(dpi, tuple): + dpi = dpi, dpi self._size = ( - (x1 - x0) * self.info["dpi"] // self._inch, - (y1 - y0) * self.info["dpi"] // self._inch, + int((x1 - x0) * dpi[0] / self._inch[0]), + int((y1 - y0) * dpi[1] / self._inch[1]), ) return super().load()