From 6d42449788e4c05a76cc7c9c81a7c8b2a40d099e Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Sun, 30 Mar 2025 03:25:13 +1100 Subject: [PATCH] Allow loading of EMF images at a given DPI (#8536) Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com> --- Tests/images/drawing_emf_ref_72_144.png | Bin 0 -> 984 bytes Tests/test_file_wmf.py | 14 ++++++++++++++ src/PIL/WmfImagePlugin.py | 24 ++++++++++++++---------- 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)<h;3K|Lk000e1NJLTq002?|005*20ssI2i-qpU000A@Nkl<Zc%1E> z+m?eM3`K+g|If}tT8An^fFxX!{W??4_QVUcOTu}cFoF=ms9ghq-o8T!`G3$n3L4r; z;S(Tv7<A-iwPWGpZsMaLEia{w!p)n;Lm(%ANNhBOaCSHY0Dio9IcSDC?aq)B8w3D> 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_YBX<r-$2issb?a>8{;W*E8=kK*&u$uPh z0#pg#mvPzBzHn_zxV9x++Y+vA3D>rSYg^&~0E0trLup^5PB5h%<Jy*RZA*N#x4(zQ zmvOM3wl!Sa66UoBE>oqCm9%f69=AWL)}qDpk;FvW&-2%W_7m4ewmZF(V~zdOPTrXJ z*G{sz_S<MWrM=PV{r2d&dD?HdcFY!io|z`wIql4t^8FpgGNnwy`#X#m@AG_Y+ctSV zw(Q&Jxl2)_Sb6qs^vm{nvGUSN6MUtpL8-a4(!_#+Q)=G!l9q?Cc#c99d=RT8ES|Ge zpA)O4tq0auiW>AfY3qS45;(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(?~j5kiUxinGpz<tZ)oI(^b z$KK|BMq-{hMRP9sz<NIaY+2|@6W`C(vuPn=L~5QK+Y)1^hkyOQs58i={lA0MQbgA- zlSf2hs3WfZ*$r(SCbhAhlJ<SC-=i>U3_C`9IR4e2CH??qha)B=@Nu*N0000<MNUMn GLSTaTnENdN literal 0 HcmV?d00001 diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py index 928493a0f..a752f8013 100644 --- a/Tests/test_file_wmf.py +++ b/Tests/test_file_wmf.py @@ -97,6 +97,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 04abd52f0..f709d026b 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -80,8 +80,6 @@ class WmfStubImageFile(ImageFile.StubImageFile): format_description = "Windows Metafile" def _open(self) -> None: - self._inch = None - # check placable header s = self.fp.read(80) @@ -89,10 +87,11 @@ class WmfStubImageFile(ImageFile.StubImageFile): # placeable windows metafile # get units per inch - self._inch = word(s, 14) - if self._inch == 0: + inch = word(s, 14) + if inch == 0: msg = "Invalid inch" raise ValueError(msg) + self._inch: tuple[float, float] = inch, inch # get bounding box x0 = short(s, 6) @@ -103,8 +102,8 @@ class WmfStubImageFile(ImageFile.StubImageFile): # 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 @@ -138,6 +137,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): self.info["dpi"] = xdpi else: self.info["dpi"] = xdpi, ydpi + self._inch = xdpi, ydpi else: msg = "Unsupported file format" @@ -153,13 +153,17 @@ class WmfStubImageFile(ImageFile.StubImageFile): 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()