Skip to content

Commit

Permalink
Merge pull request #5554 from radarhere/tag_group_data
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Jun 28, 2021
2 parents 5030223 + dd28af0 commit 2251be1
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
14 changes: 14 additions & 0 deletions Tests/test_file_tiff_metadata.py
Expand Up @@ -378,6 +378,20 @@ def test_too_many_entries():
pytest.warns(UserWarning, lambda: ifd[277])


def test_tag_group_data():
base_ifd = TiffImagePlugin.ImageFileDirectory_v2()
interop_ifd = TiffImagePlugin.ImageFileDirectory_v2(group=40965)
for ifd in (base_ifd, interop_ifd):
ifd[2] = "test"
ifd[256] = 10

assert base_ifd.tagtype[256] == 4
assert interop_ifd.tagtype[256] != base_ifd.tagtype[256]

assert interop_ifd.tagtype[2] == 7
assert base_ifd.tagtype[2] != interop_ifd.tagtype[256]


def test_empty_subifd(tmp_path):
out = str(tmp_path / "temp.jpg")

Expand Down
16 changes: 10 additions & 6 deletions src/PIL/TiffImagePlugin.py
Expand Up @@ -468,7 +468,7 @@ class ImageFileDirectory_v2(MutableMapping):
"""

def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None):
def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None, group=None):
"""Initialize an ImageFileDirectory.
To construct an ImageFileDirectory from a real file, pass the 8-byte
Expand All @@ -488,6 +488,7 @@ def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None):
self._endian = "<"
else:
raise SyntaxError("not a TIFF IFD")
self.group = group
self.tagtype = {}
""" Dictionary of tag types """
self.reset()
Expand Down Expand Up @@ -519,7 +520,10 @@ def named(self):
Returns the complete tag dictionary, with named tags where possible.
"""
return {TiffTags.lookup(code).name: value for code, value in self.items()}
return {
TiffTags.lookup(code, self.group).name: value
for code, value in self.items()
}

def __len__(self):
return len(set(self._tagdata) | set(self._tags_v2))
Expand All @@ -544,7 +548,7 @@ def __setitem__(self, tag, value):
def _setitem(self, tag, value, legacy_api):
basetypes = (Number, bytes, str)

info = TiffTags.lookup(tag)
info = TiffTags.lookup(tag, self.group)
values = [value] if isinstance(value, basetypes) else value

if tag not in self.tagtype:
Expand Down Expand Up @@ -761,7 +765,7 @@ def load(self, fp):
for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
tag, typ, count, data = self._unpack("HHL4s", self._ensure_read(fp, 12))

tagname = TiffTags.lookup(tag).name
tagname = TiffTags.lookup(tag, self.group).name
typname = TYPES.get(typ, "unknown")
msg = f"tag: {tagname} ({tag}) - type: {typname} ({typ})"

Expand Down Expand Up @@ -828,7 +832,7 @@ def tobytes(self, offset=0):
ifh = b"II\x2A\x00\x08\x00\x00\x00"
else:
ifh = b"MM\x00\x2A\x00\x00\x00\x08"
ifd = ImageFileDirectory_v2(ifh)
ifd = ImageFileDirectory_v2(ifh, group=tag)
values = self._tags_v2[tag]
for ifd_tag, ifd_value in values.items():
ifd[ifd_tag] = ifd_value
Expand All @@ -837,7 +841,7 @@ def tobytes(self, offset=0):
values = value if isinstance(value, tuple) else (value,)
data = self._write_dispatch[typ](self, *values)

tagname = TiffTags.lookup(tag).name
tagname = TiffTags.lookup(tag, self.group).name
typname = "ifd" if is_ifd else TYPES.get(typ, "unknown")
msg = f"save: {tagname} ({tag}) - type: {typname} ({typ})"
msg += " - value: " + (
Expand Down
25 changes: 23 additions & 2 deletions src/PIL/TiffTags.py
Expand Up @@ -33,7 +33,7 @@ def cvt_enum(self, value):
return self.enum.get(value, value) if self.enum else value


def lookup(tag):
def lookup(tag, group=None):
"""
:param tag: Integer tag number
:returns: Taginfo namedtuple, From the TAGS_V2 info if possible,
Expand All @@ -42,7 +42,11 @@ def lookup(tag):
"""

return TAGS_V2.get(tag, TagInfo(tag, TAGS.get(tag, "unknown")))
if group is not None:
info = TAGS_V2_GROUPS[group].get(tag) if group in TAGS_V2_GROUPS else None
else:
info = TAGS_V2.get(tag)
return info or TagInfo(tag, TAGS.get(tag, "unknown"))


##
Expand Down Expand Up @@ -213,6 +217,19 @@ def lookup(tag):
50838: ("ImageJMetaDataByteCounts", LONG, 0), # Can be more than one
50839: ("ImageJMetaData", UNDEFINED, 1), # see Issue #2006
}
TAGS_V2_GROUPS = {
# ExifIFD
34665: {
36864: ("ExifVersion", UNDEFINED, 1),
40960: ("FlashPixVersion", UNDEFINED, 1),
40965: ("InteroperabilityIFD", LONG, 1),
41730: ("CFAPattern", UNDEFINED, 1),
},
# GPSInfoIFD
34853: {},
# InteroperabilityIFD
40965: {1: ("InteropIndex", ASCII, 1), 2: ("InteropVersion", UNDEFINED, 1)},
}

# Legacy Tags structure
# these tags aren't included above, but were in the previous versions
Expand Down Expand Up @@ -371,6 +388,10 @@ def _populate():

TAGS_V2[k] = TagInfo(k, *v)

for group, tags in TAGS_V2_GROUPS.items():
for k, v in tags.items():
tags[k] = TagInfo(k, *v)


_populate()
##
Expand Down

0 comments on commit 2251be1

Please sign in to comment.