def test_ifd_unsigned_rational(self): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() max_long = 2**32 - 1 # 4 bytes unsigned long numerator = max_long info[41493] = TiffImagePlugin.IFDRational(numerator, 1) out = self.tempfile("temp.tiff") im.save(out, tiffinfo=info, compression="raw") reloaded = Image.open(out) self.assertEqual(max_long, reloaded.tag_v2[41493].numerator) self.assertEqual(1, reloaded.tag_v2[41493].denominator) # out of bounds of 4 byte unsigned long numerator = max_long + 1 info[41493] = TiffImagePlugin.IFDRational(numerator, 1) out = self.tempfile("temp.tiff") im.save(out, tiffinfo=info, compression="raw") reloaded = Image.open(out) self.assertEqual(max_long, reloaded.tag_v2[41493].numerator) self.assertEqual(1, reloaded.tag_v2[41493].denominator)
def test_ifd_unsigned_rational(tmp_path): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() max_long = 2**32 - 1 # 4 bytes unsigned long numerator = max_long info[41493] = TiffImagePlugin.IFDRational(numerator, 1) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert max_long == reloaded.tag_v2[41493].numerator assert 1 == reloaded.tag_v2[41493].denominator # out of bounds of 4 byte unsigned long numerator = max_long + 1 info[41493] = TiffImagePlugin.IFDRational(numerator, 1) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert max_long == reloaded.tag_v2[41493].numerator assert 1 == reloaded.tag_v2[41493].denominator
def test_additional_metadata(self, tmp_path): # these should not crash. Seriously dummy data, most of it doesn't make # any sense, so we're running up against limits where we're asking # libtiff to do stupid things. # Get the list of the ones that we should be able to write core_items = { tag: info for tag, info in ((s, TiffTags.lookup(s)) for s in TiffTags.LIBTIFF_CORE) if info.type is not None } # Exclude ones that have special meaning # that we're already testing them with Image.open("Tests/images/hopper_g4.tif") as im: for tag in im.tag_v2: try: del core_items[tag] except KeyError: pass del core_items[320] # colormap is special, tested below # Type codes: # 2: "ascii", # 3: "short", # 4: "long", # 5: "rational", # 12: "double", # Type: dummy value values = { 2: "test", 3: 1, 4: 2**20, 5: TiffImagePlugin.IFDRational(100, 1), 12: 1.05, } new_ifd = TiffImagePlugin.ImageFileDirectory_v2() for tag, info in core_items.items(): if info.length == 1: new_ifd[tag] = values[info.type] if info.length == 0: new_ifd[tag] = tuple(values[info.type] for _ in range(3)) else: new_ifd[tag] = tuple(values[info.type] for _ in range(info.length)) # Extra samples really doesn't make sense in this application. del new_ifd[338] out = str(tmp_path / "temp.tif") TiffImagePlugin.WRITE_LIBTIFF = True im.save(out, tiffinfo=new_ifd) TiffImagePlugin.WRITE_LIBTIFF = False
def test_additional_metadata(self): # these should not crash. Seriously dummy data, most of it doesn't make # any sense, so we're running up against limits where we're asking # libtiff to do stupid things. # Get the list of the ones that we should be able to write core_items = dict((tag, info) for tag, info in [(s, TiffTags.lookup(s)) for s in TiffTags.LIBTIFF_CORE] if info.type is not None) # Exclude ones that have special meaning # that we're already testing them im = Image.open('Tests/images/hopper_g4.tif') for tag in im.tag_v2.keys(): try: del (core_items[tag]) except: pass # Type codes: # 2: "ascii", # 3: "short", # 4: "long", # 5: "rational", # 12: "double", # type: dummy value values = { 2: 'test', 3: 1, 4: 2**20, 5: TiffImagePlugin.IFDRational(100, 1), 12: 1.05 } new_ifd = TiffImagePlugin.ImageFileDirectory_v2() for tag, info in core_items.items(): if info.length == 1: new_ifd[tag] = values[info.type] if info.length == 0: new_ifd[tag] = tuple(values[info.type] for _ in range(3)) else: new_ifd[tag] = tuple(values[info.type] for _ in range(info.length)) # Extra samples really doesn't make sense in this application. del (new_ifd[338]) out = self.tempfile("temp.tif") TiffImagePlugin.WRITE_LIBTIFF = True im.save(out, tiffinfo=new_ifd) TiffImagePlugin.WRITE_LIBTIFF = False
def test_exif_div_zero(self): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() info[41988] = TiffImagePlugin.IFDRational(0, 0) out = self.tempfile('temp.tiff') im.save(out, tiffinfo=info, compression='raw') reloaded = Image.open(out) self.assertEqual(0, reloaded.tag_v2[41988][0].numerator) self.assertEqual(0, reloaded.tag_v2[41988][0].denominator)
def test_exif_div_zero(tmp_path): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() info[41988] = TiffImagePlugin.IFDRational(0, 0) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert 0 == reloaded.tag_v2[41988].numerator assert 0 == reloaded.tag_v2[41988].denominator
def test_ifd_signed_rational(self): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() # pair of 4 byte signed longs numerator = 2**31 - 1 denominator = -(2**31) info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = self.tempfile("temp.tiff") im.save(out, tiffinfo=info, compression="raw") reloaded = Image.open(out) self.assertEqual(numerator, reloaded.tag_v2[37380].numerator) self.assertEqual(denominator, reloaded.tag_v2[37380].denominator) numerator = -(2**31) denominator = 2**31 - 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = self.tempfile("temp.tiff") im.save(out, tiffinfo=info, compression="raw") reloaded = Image.open(out) self.assertEqual(numerator, reloaded.tag_v2[37380].numerator) self.assertEqual(denominator, reloaded.tag_v2[37380].denominator) # out of bounds of 4 byte signed long numerator = -(2**31) - 1 denominator = 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = self.tempfile("temp.tiff") im.save(out, tiffinfo=info, compression="raw") reloaded = Image.open(out) self.assertEqual(2**31 - 1, reloaded.tag_v2[37380].numerator) self.assertEqual(-1, reloaded.tag_v2[37380].denominator)
def test_ifd_signed_rational(tmp_path): im = hopper() info = TiffImagePlugin.ImageFileDirectory_v2() # pair of 4 byte signed longs numerator = 2**31 - 1 denominator = -(2**31) info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert numerator == reloaded.tag_v2[37380].numerator assert denominator == reloaded.tag_v2[37380].denominator numerator = -(2**31) denominator = 2**31 - 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert numerator == reloaded.tag_v2[37380].numerator assert denominator == reloaded.tag_v2[37380].denominator # out of bounds of 4 byte signed long numerator = -(2**31) - 1 denominator = 1 info[37380] = TiffImagePlugin.IFDRational(numerator, denominator) out = str(tmp_path / "temp.tiff") im.save(out, tiffinfo=info, compression="raw") with Image.open(out) as reloaded: assert 2**31 - 1 == reloaded.tag_v2[37380].numerator assert -1 == reloaded.tag_v2[37380].denominator
def test_custom_metadata(self, tmp_path): tc = namedtuple("test_case", "value,type,supported_by_default") custom = { 37000 + k: v for k, v in enumerate( [ tc(4, TiffTags.SHORT, True), tc(123456789, TiffTags.LONG, True), tc(-4, TiffTags.SIGNED_BYTE, False), tc(-4, TiffTags.SIGNED_SHORT, False), tc(-123456789, TiffTags.SIGNED_LONG, False), tc(TiffImagePlugin.IFDRational(4, 7), TiffTags.RATIONAL, True), tc(4.25, TiffTags.FLOAT, True), tc(4.25, TiffTags.DOUBLE, True), tc("custom tag value", TiffTags.ASCII, True), tc(b"custom tag value", TiffTags.BYTE, True), tc((4, 5, 6), TiffTags.SHORT, True), tc((123456789, 9, 34, 234, 219387, 92432323), TiffTags.LONG, True), tc((-4, 9, 10), TiffTags.SIGNED_BYTE, False), tc((-4, 5, 6), TiffTags.SIGNED_SHORT, False), tc( (-123456789, 9, 34, 234, 219387, -92432323), TiffTags.SIGNED_LONG, False, ), tc((4.25, 5.25), TiffTags.FLOAT, True), tc((4.25, 5.25), TiffTags.DOUBLE, True), # array of TIFF_BYTE requires bytes instead of tuple for backwards # compatibility tc(bytes([4]), TiffTags.BYTE, True), tc(bytes((4, 9, 10)), TiffTags.BYTE, True), ] ) } libtiffs = [False] if Image.core.libtiff_support_custom_tags: libtiffs.append(True) for libtiff in libtiffs: TiffImagePlugin.WRITE_LIBTIFF = libtiff def check_tags(tiffinfo): im = hopper() out = str(tmp_path / "temp.tif") im.save(out, tiffinfo=tiffinfo) with Image.open(out) as reloaded: for tag, value in tiffinfo.items(): reloaded_value = reloaded.tag_v2[tag] if ( isinstance(reloaded_value, TiffImagePlugin.IFDRational) and libtiff ): # libtiff does not support real RATIONALS assert ( round(abs(float(reloaded_value) - float(value)), 7) == 0 ) continue assert reloaded_value == value # Test with types ifd = TiffImagePlugin.ImageFileDirectory_v2() for tag, tagdata in custom.items(): ifd[tag] = tagdata.value ifd.tagtype[tag] = tagdata.type check_tags(ifd) # Test without types. This only works for some types, int for example are # always encoded as LONG and not SIGNED_LONG. check_tags( { tag: tagdata.value for tag, tagdata in custom.items() if tagdata.supported_by_default } ) TiffImagePlugin.WRITE_LIBTIFF = False