|
|
@@ -619,6 +619,7 @@ class IFD(object): |
|
|
|
if tag is None: |
|
|
|
nextptr.append(res) |
|
|
|
break |
|
|
|
|
|
|
|
tag = self.getEnum(tag) |
|
|
|
if tag in taghandlers: |
|
|
|
res = taghandlers[tag](fh, endian, res, off) |
|
|
@@ -639,7 +640,7 @@ class IFD(object): |
|
|
|
def getEnum(self, key): |
|
|
|
try: |
|
|
|
return self.__enum(key) |
|
|
|
except KeyError: |
|
|
|
except ValueError: |
|
|
|
return key |
|
|
|
|
|
|
|
def __repr__(self): |
|
|
@@ -919,6 +920,7 @@ def tiff_srational(endian, data): |
|
|
|
return rational_dcomp(tiff_slong(endian, data)) |
|
|
|
|
|
|
|
tifftypes = { |
|
|
|
# function to decode, length of an element |
|
|
|
1: (tiff_bytes, 1), |
|
|
|
2: (tiff_ascii, 1), |
|
|
|
3: (tiff_short, 2), |
|
|
@@ -1083,7 +1085,7 @@ def idcrw(fh): |
|
|
|
|
|
|
|
if hlen == 0x2a: |
|
|
|
#TIFF/CR2 |
|
|
|
hoff, idstr, ver, hlen = readstruct(fh, endian + "I2sHI") |
|
|
|
hoff, idstr, ver, rawifdoff = readstruct(fh, endian + "I2sHI") |
|
|
|
if not isjpeg and (hoff != 0x10 or idstr != b'CR' or ver != 2): |
|
|
|
raise ValueError('normal TIFF, not a CR2') |
|
|
|
nextoff = [ hoff ] |
|
|
@@ -1180,6 +1182,64 @@ class _TestCRW(unittest.TestCase): |
|
|
|
l.sort() |
|
|
|
set(l) |
|
|
|
|
|
|
|
@staticmethod |
|
|
|
def ifd_builder(endian, off, entries): |
|
|
|
'''Build an IFD. It is assumed to be rooted at off, but |
|
|
|
will be returned as a bare string. To locate it properly, |
|
|
|
something like: |
|
|
|
file = b'\x00' * off + ifd_builder('<', off) |
|
|
|
|
|
|
|
needs to be used. Obviously the prefix above is wrong and will |
|
|
|
need to be a proper TIFF header and/or other IFDs. |
|
|
|
|
|
|
|
The data will be added at the end. |
|
|
|
|
|
|
|
entires is a list of tuples: |
|
|
|
(tag, type, count, value) |
|
|
|
|
|
|
|
Return value is a tuple of bytes, and offset of nextifd. |
|
|
|
''' |
|
|
|
|
|
|
|
entries = list(entries) |
|
|
|
cnt = len(entries) |
|
|
|
|
|
|
|
r = [] |
|
|
|
|
|
|
|
r.append(struct.pack(endian + 'H', cnt)) |
|
|
|
|
|
|
|
# offset + count + ifd entries + nextifd |
|
|
|
extra = off + 2 + cnt * 12 + 4 |
|
|
|
sextra = extra |
|
|
|
e = [] # extra values |
|
|
|
|
|
|
|
for tag, _type, count, value in entries: |
|
|
|
if len(value) <= 4: |
|
|
|
r.append(struct.pack(endian + 'HHI', tag, _type, count) + value + b'\x00' * (4 - len(value))) |
|
|
|
else: |
|
|
|
r.append(struct.pack(endian + 'HHII', tag, _type, count, extra)) |
|
|
|
e.append(value) |
|
|
|
extra += len(value) |
|
|
|
|
|
|
|
r = b''.join(r) |
|
|
|
|
|
|
|
nextoff = len(r) + off |
|
|
|
|
|
|
|
assert len(r) + 4 == sextra - off |
|
|
|
|
|
|
|
return r + b'\x00' * 4 + b''.join(e), len(r) |
|
|
|
|
|
|
|
def test_unknown(self): |
|
|
|
endian = '<' |
|
|
|
off = 10 |
|
|
|
|
|
|
|
ifd, nextoff = self.ifd_builder(endian, off, [ |
|
|
|
(65000, 1, 4, b'\x10' * 4), |
|
|
|
(65001, 1, 10, b'\x20' * 10) |
|
|
|
]) |
|
|
|
fh = BytesIO(b'\x00' * 10 + ifd) |
|
|
|
|
|
|
|
r = IFD(ExifTag, {}, fh, endian, off) |
|
|
|
|
|
|
|
def test_bogus(self): |
|
|
|
# make sure various bogus "files" raise an error |
|
|
|
|
|
|
|