3
3
from PIL import features
4
4
from PIL ._util import py3
5
5
6
+ from collections import namedtuple
6
7
from ctypes import c_float
7
8
import io
8
9
import logging
@@ -235,12 +236,39 @@ def test_additional_metadata(self):
235
236
TiffImagePlugin .WRITE_LIBTIFF = False
236
237
237
238
def test_custom_metadata (self ):
239
+ tc = namedtuple ("test_case" , "value,type,supported_by_default" )
238
240
custom = {
239
- 37000 : [4 , TiffTags .SHORT ],
240
- 37001 : [4.2 , TiffTags .RATIONAL ],
241
- 37002 : ["custom tag value" , TiffTags .ASCII ],
242
- 37003 : [u"custom tag value" , TiffTags .ASCII ],
243
- 37004 : [b"custom tag value" , TiffTags .BYTE ],
241
+ 37000 + k : v
242
+ for k , v in enumerate (
243
+ [
244
+ tc (4 , TiffTags .SHORT , True ),
245
+ tc (123456789 , TiffTags .LONG , True ),
246
+ tc (- 4 , TiffTags .SIGNED_BYTE , False ),
247
+ tc (- 4 , TiffTags .SIGNED_SHORT , False ),
248
+ tc (- 123456789 , TiffTags .SIGNED_LONG , False ),
249
+ tc (TiffImagePlugin .IFDRational (4 , 7 ), TiffTags .RATIONAL , True ),
250
+ tc (4.25 , TiffTags .FLOAT , True ),
251
+ tc (4.25 , TiffTags .DOUBLE , True ),
252
+ tc ("custom tag value" , TiffTags .ASCII , True ),
253
+ tc (u"custom tag value" , TiffTags .ASCII , True ),
254
+ tc (b"custom tag value" , TiffTags .BYTE , True ),
255
+ tc ((4 , 5 , 6 ), TiffTags .SHORT , True ),
256
+ tc ((123456789 , 9 , 34 , 234 , 219387 , 92432323 ), TiffTags .LONG , True ),
257
+ tc ((- 4 , 9 , 10 ), TiffTags .SIGNED_BYTE , False ),
258
+ tc ((- 4 , 5 , 6 ), TiffTags .SIGNED_SHORT , False ),
259
+ tc (
260
+ (- 123456789 , 9 , 34 , 234 , 219387 , - 92432323 ),
261
+ TiffTags .SIGNED_LONG ,
262
+ False ,
263
+ ),
264
+ tc ((4.25 , 5.25 ), TiffTags .FLOAT , True ),
265
+ tc ((4.25 , 5.25 ), TiffTags .DOUBLE , True ),
266
+ # array of TIFF_BYTE requires bytes instead of tuple for backwards
267
+ # compatibility
268
+ tc (bytes ([4 ]), TiffTags .BYTE , True ),
269
+ tc (bytes ((4 , 9 , 10 )), TiffTags .BYTE , True ),
270
+ ]
271
+ )
244
272
}
245
273
246
274
libtiff_version = TiffImagePlugin ._libtiff_version ()
@@ -263,8 +291,13 @@ def check_tags(tiffinfo):
263
291
reloaded = Image .open (out )
264
292
for tag , value in tiffinfo .items ():
265
293
reloaded_value = reloaded .tag_v2 [tag ]
266
- if isinstance (reloaded_value , TiffImagePlugin .IFDRational ):
267
- reloaded_value = float (reloaded_value )
294
+ if (
295
+ isinstance (reloaded_value , TiffImagePlugin .IFDRational )
296
+ and libtiff
297
+ ):
298
+ # libtiff does not support real RATIONALS
299
+ self .assertAlmostEqual (float (reloaded_value ), float (value ))
300
+ continue
268
301
269
302
if libtiff and isinstance (value , bytes ):
270
303
value = value .decode ()
@@ -274,12 +307,19 @@ def check_tags(tiffinfo):
274
307
# Test with types
275
308
ifd = TiffImagePlugin .ImageFileDirectory_v2 ()
276
309
for tag , tagdata in custom .items ():
277
- ifd [tag ] = tagdata [ 0 ]
278
- ifd .tagtype [tag ] = tagdata [ 1 ]
310
+ ifd [tag ] = tagdata . value
311
+ ifd .tagtype [tag ] = tagdata . type
279
312
check_tags (ifd )
280
313
281
- # Test without types
282
- check_tags ({tag : tagdata [0 ] for tag , tagdata in custom .items ()})
314
+ # Test without types. This only works for some types, int for example are
315
+ # always encoded as LONG and not SIGNED_LONG.
316
+ check_tags (
317
+ {
318
+ tag : tagdata .value
319
+ for tag , tagdata in custom .items ()
320
+ if tagdata .supported_by_default
321
+ }
322
+ )
283
323
TiffImagePlugin .WRITE_LIBTIFF = False
284
324
285
325
def test_int_dpi (self ):
0 commit comments