Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pillow-10.4.0-py3.8-linux-x86_64.egg/PIL/WmfImagePlugin.py: 28%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

74 statements  

1# 

2# The Python Imaging Library 

3# $Id$ 

4# 

5# WMF stub codec 

6# 

7# history: 

8# 1996-12-14 fl Created 

9# 2004-02-22 fl Turned into a stub driver 

10# 2004-02-23 fl Added EMF support 

11# 

12# Copyright (c) Secret Labs AB 1997-2004. All rights reserved. 

13# Copyright (c) Fredrik Lundh 1996. 

14# 

15# See the README file for information on usage and redistribution. 

16# 

17# WMF/EMF reference documentation: 

18# https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf 

19# http://wvware.sourceforge.net/caolan/index.html 

20# http://wvware.sourceforge.net/caolan/ora-wmf.html 

21from __future__ import annotations 

22 

23from typing import IO 

24 

25from . import Image, ImageFile 

26from ._binary import i16le as word 

27from ._binary import si16le as short 

28from ._binary import si32le as _long 

29 

30_handler = None 

31 

32 

33def register_handler(handler: ImageFile.StubHandler | None) -> None: 

34 """ 

35 Install application-specific WMF image handler. 

36 

37 :param handler: Handler object. 

38 """ 

39 global _handler 

40 _handler = handler 

41 

42 

43if hasattr(Image.core, "drawwmf"): 

44 # install default handler (windows only) 

45 

46 class WmfHandler(ImageFile.StubHandler): 

47 def open(self, im: ImageFile.StubImageFile) -> None: 

48 im._mode = "RGB" 

49 self.bbox = im.info["wmf_bbox"] 

50 

51 def load(self, im: ImageFile.StubImageFile) -> Image.Image: 

52 im.fp.seek(0) # rewind 

53 return Image.frombytes( 

54 "RGB", 

55 im.size, 

56 Image.core.drawwmf(im.fp.read(), im.size, self.bbox), 

57 "raw", 

58 "BGR", 

59 (im.size[0] * 3 + 3) & -4, 

60 -1, 

61 ) 

62 

63 register_handler(WmfHandler()) 

64 

65# 

66# -------------------------------------------------------------------- 

67# Read WMF file 

68 

69 

70def _accept(prefix: bytes) -> bool: 

71 return ( 

72 prefix[:6] == b"\xd7\xcd\xc6\x9a\x00\x00" or prefix[:4] == b"\x01\x00\x00\x00" 

73 ) 

74 

75 

76## 

77# Image plugin for Windows metafiles. 

78 

79 

80class WmfStubImageFile(ImageFile.StubImageFile): 

81 format = "WMF" 

82 format_description = "Windows Metafile" 

83 

84 def _open(self) -> None: 

85 self._inch = None 

86 

87 # check placable header 

88 s = self.fp.read(80) 

89 

90 if s[:6] == b"\xd7\xcd\xc6\x9a\x00\x00": 

91 # placeable windows metafile 

92 

93 # get units per inch 

94 self._inch = word(s, 14) 

95 

96 # get bounding box 

97 x0 = short(s, 6) 

98 y0 = short(s, 8) 

99 x1 = short(s, 10) 

100 y1 = short(s, 12) 

101 

102 # normalize size to 72 dots per inch 

103 self.info["dpi"] = 72 

104 size = ( 

105 (x1 - x0) * self.info["dpi"] // self._inch, 

106 (y1 - y0) * self.info["dpi"] // self._inch, 

107 ) 

108 

109 self.info["wmf_bbox"] = x0, y0, x1, y1 

110 

111 # sanity check (standard metafile header) 

112 if s[22:26] != b"\x01\x00\t\x00": 

113 msg = "Unsupported WMF file format" 

114 raise SyntaxError(msg) 

115 

116 elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF": 

117 # enhanced metafile 

118 

119 # get bounding box 

120 x0 = _long(s, 8) 

121 y0 = _long(s, 12) 

122 x1 = _long(s, 16) 

123 y1 = _long(s, 20) 

124 

125 # get frame (in 0.01 millimeter units) 

126 frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36) 

127 

128 size = x1 - x0, y1 - y0 

129 

130 # calculate dots per inch from bbox and frame 

131 xdpi = 2540.0 * (x1 - y0) / (frame[2] - frame[0]) 

132 ydpi = 2540.0 * (y1 - y0) / (frame[3] - frame[1]) 

133 

134 self.info["wmf_bbox"] = x0, y0, x1, y1 

135 

136 if xdpi == ydpi: 

137 self.info["dpi"] = xdpi 

138 else: 

139 self.info["dpi"] = xdpi, ydpi 

140 

141 else: 

142 msg = "Unsupported file format" 

143 raise SyntaxError(msg) 

144 

145 self._mode = "RGB" 

146 self._size = size 

147 

148 loader = self._load() 

149 if loader: 

150 loader.open(self) 

151 

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

153 return _handler 

154 

155 def load(self, dpi=None): 

156 if dpi is not None and self._inch is not None: 

157 self.info["dpi"] = dpi 

158 x0, y0, x1, y1 = self.info["wmf_bbox"] 

159 self._size = ( 

160 (x1 - x0) * self.info["dpi"] // self._inch, 

161 (y1 - y0) * self.info["dpi"] // self._inch, 

162 ) 

163 return super().load() 

164 

165 

166def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None: 

167 if _handler is None or not hasattr(_handler, "save"): 

168 msg = "WMF save handler not installed" 

169 raise OSError(msg) 

170 _handler.save(im, fp, filename) 

171 

172 

173# 

174# -------------------------------------------------------------------- 

175# Registry stuff 

176 

177 

178Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept) 

179Image.register_save(WmfStubImageFile.format, _save) 

180 

181Image.register_extensions(WmfStubImageFile.format, [".wmf", ".emf"])