Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/PIL/IptcImagePlugin.py: 13%

125 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1# 

2# The Python Imaging Library. 

3# $Id$ 

4# 

5# IPTC/NAA file handling 

6# 

7# history: 

8# 1995-10-01 fl Created 

9# 1998-03-09 fl Cleaned up and added to PIL 

10# 2002-06-18 fl Added getiptcinfo helper 

11# 

12# Copyright (c) Secret Labs AB 1997-2002. 

13# Copyright (c) Fredrik Lundh 1995. 

14# 

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

16# 

17import os 

18import tempfile 

19 

20from . import Image, ImageFile 

21from ._binary import i8 

22from ._binary import i16be as i16 

23from ._binary import i32be as i32 

24from ._binary import o8 

25 

26COMPRESSION = {1: "raw", 5: "jpeg"} 

27 

28PAD = o8(0) * 4 

29 

30 

31# 

32# Helpers 

33 

34 

35def i(c): 

36 return i32((PAD + c)[-4:]) 

37 

38 

39def dump(c): 

40 for i in c: 

41 print("%02x" % i8(i), end=" ") 

42 print() 

43 

44 

45## 

46# Image plugin for IPTC/NAA datastreams. To read IPTC/NAA fields 

47# from TIFF and JPEG files, use the <b>getiptcinfo</b> function. 

48 

49 

50class IptcImageFile(ImageFile.ImageFile): 

51 

52 format = "IPTC" 

53 format_description = "IPTC/NAA" 

54 

55 def getint(self, key): 

56 return i(self.info[key]) 

57 

58 def field(self): 

59 # 

60 # get a IPTC field header 

61 s = self.fp.read(5) 

62 if not len(s): 

63 return None, 0 

64 

65 tag = s[1], s[2] 

66 

67 # syntax 

68 if s[0] != 0x1C or tag[0] < 1 or tag[0] > 9: 

69 raise SyntaxError("invalid IPTC/NAA file") 

70 

71 # field size 

72 size = s[3] 

73 if size > 132: 

74 raise OSError("illegal field length in IPTC/NAA file") 

75 elif size == 128: 

76 size = 0 

77 elif size > 128: 

78 size = i(self.fp.read(size - 128)) 

79 else: 

80 size = i16(s, 3) 

81 

82 return tag, size 

83 

84 def _open(self): 

85 

86 # load descriptive fields 

87 while True: 

88 offset = self.fp.tell() 

89 tag, size = self.field() 

90 if not tag or tag == (8, 10): 

91 break 

92 if size: 

93 tagdata = self.fp.read(size) 

94 else: 

95 tagdata = None 

96 if tag in self.info: 

97 if isinstance(self.info[tag], list): 

98 self.info[tag].append(tagdata) 

99 else: 

100 self.info[tag] = [self.info[tag], tagdata] 

101 else: 

102 self.info[tag] = tagdata 

103 

104 # mode 

105 layers = i8(self.info[(3, 60)][0]) 

106 component = i8(self.info[(3, 60)][1]) 

107 if (3, 65) in self.info: 

108 id = i8(self.info[(3, 65)][0]) - 1 

109 else: 

110 id = 0 

111 if layers == 1 and not component: 

112 self.mode = "L" 

113 elif layers == 3 and component: 

114 self.mode = "RGB"[id] 

115 elif layers == 4 and component: 

116 self.mode = "CMYK"[id] 

117 

118 # size 

119 self._size = self.getint((3, 20)), self.getint((3, 30)) 

120 

121 # compression 

122 try: 

123 compression = COMPRESSION[self.getint((3, 120))] 

124 except KeyError as e: 

125 raise OSError("Unknown IPTC image compression") from e 

126 

127 # tile 

128 if tag == (8, 10): 

129 self.tile = [ 

130 ("iptc", (compression, offset), (0, 0, self.size[0], self.size[1])) 

131 ] 

132 

133 def load(self): 

134 

135 if len(self.tile) != 1 or self.tile[0][0] != "iptc": 

136 return ImageFile.ImageFile.load(self) 

137 

138 type, tile, box = self.tile[0] 

139 

140 encoding, offset = tile 

141 

142 self.fp.seek(offset) 

143 

144 # Copy image data to temporary file 

145 o_fd, outfile = tempfile.mkstemp(text=False) 

146 o = os.fdopen(o_fd) 

147 if encoding == "raw": 

148 # To simplify access to the extracted file, 

149 # prepend a PPM header 

150 o.write("P5\n%d %d\n255\n" % self.size) 

151 while True: 

152 type, size = self.field() 

153 if type != (8, 10): 

154 break 

155 while size > 0: 

156 s = self.fp.read(min(size, 8192)) 

157 if not s: 

158 break 

159 o.write(s) 

160 size -= len(s) 

161 o.close() 

162 

163 try: 

164 with Image.open(outfile) as _im: 

165 _im.load() 

166 self.im = _im.im 

167 finally: 

168 try: 

169 os.unlink(outfile) 

170 except OSError: 

171 pass 

172 

173 

174Image.register_open(IptcImageFile.format, IptcImageFile) 

175 

176Image.register_extension(IptcImageFile.format, ".iim") 

177 

178 

179def getiptcinfo(im): 

180 """ 

181 Get IPTC information from TIFF, JPEG, or IPTC file. 

182 

183 :param im: An image containing IPTC data. 

184 :returns: A dictionary containing IPTC information, or None if 

185 no IPTC information block was found. 

186 """ 

187 import io 

188 

189 from . import JpegImagePlugin, TiffImagePlugin 

190 

191 data = None 

192 

193 if isinstance(im, IptcImageFile): 

194 # return info dictionary right away 

195 return im.info 

196 

197 elif isinstance(im, JpegImagePlugin.JpegImageFile): 

198 # extract the IPTC/NAA resource 

199 photoshop = im.info.get("photoshop") 

200 if photoshop: 

201 data = photoshop.get(0x0404) 

202 

203 elif isinstance(im, TiffImagePlugin.TiffImageFile): 

204 # get raw data from the IPTC/NAA tag (PhotoShop tags the data 

205 # as 4-byte integers, so we cannot use the get method...) 

206 try: 

207 data = im.tag.tagdata[TiffImagePlugin.IPTC_NAA_CHUNK] 

208 except (AttributeError, KeyError): 

209 pass 

210 

211 if data is None: 

212 return None # no properties 

213 

214 # create an IptcImagePlugin object without initializing it 

215 class FakeImage: 

216 pass 

217 

218 im = FakeImage() 

219 im.__class__ = IptcImageFile 

220 

221 # parse the IPTC information chunk 

222 im.info = {} 

223 im.fp = io.BytesIO(data) 

224 

225 try: 

226 im._open() 

227 except (IndexError, KeyError): 

228 pass # expected failure 

229 

230 return im.info