From 67d44c1e958b7c9ada9ef4f2836a8e60c3592c7d Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Fri, 5 May 2023 14:39:37 -0700 Subject: [PATCH] fix string to follow the standard, other minor fixes.. fixing strings let me drop some special handlers.. Use BytesIO instead of fileoff so less code to maintain.. Maybe want to just use bytes instead? --- ui/medashare/metadata/crw.py | 60 ++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/ui/medashare/metadata/crw.py b/ui/medashare/metadata/crw.py index b74de31..1700d6c 100644 --- a/ui/medashare/metadata/crw.py +++ b/ui/medashare/metadata/crw.py @@ -15,7 +15,7 @@ import struct # CRW: https://web.archive.org/web/20081230095207/http://xyrion.org/ciff/CIFFspecV1R04.pdf # CR2: https://web.archive.org/web/20230404015346/http://lclevy.free.fr/cr2/ # JPEG: https://www.w3.org/Graphics/JPEG/itu-t81.pdf -# JFIF: http://www.w3.org/Graphics/JPEG/jfif3.pdf +# JFIF: https://www.w3.org/Graphics/JPEG/jfif3.pdf # EXIF: https://www.cipa.jp/std/documents/e/DC-X008-Translation-2019-E.pdf # # Exif Tags: @@ -407,11 +407,7 @@ class CanonMakerNote(enum.IntEnum): PictureStylePC = 0x4009 canonmakernotehandlers = { - CanonMakerNote.FirmwareVersion: lambda fh, endian, res, off: - tuple(res.split(b'\x00', 1)), - CanonMakerNote.Lens: lambda fh, endian, res, off: - res.split(b'\x00', 1)[0], - } +} # Needed by Exif class TIFFResolutionUnit(enum.IntEnum): @@ -892,10 +888,16 @@ def tiff_bytes(endian, data): return map(ord, data) def tiff_ascii(endian, data): - if data[-1] != '\x00': - return data # XXX - Canon MakerNote requires this. - #raise ValueError, 'string does not terminate with NUL' - return data[:-1] + if data[-2:] == b'\x00\x00': + # multipl strings + return [ x.decode('ASCII') for x in data[:-2].split(b'\x00') ] + + if data[-1] != 0: + #print('d:', repr(data)) + #raise ValueError('string does not terminate with NUL') + return data + + return data[:-1].decode('ascii') def tiff_short(endian, data): return struct.unpack(endian + 'H' * (len(data) // 2), data) @@ -922,10 +924,15 @@ tifftypes = { 4: (tiff_long, 4), 5: (tiff_rational, 8), + #6: sbyte + # Exif Types 7: (lambda x, y: y, 1), # byte string + #8: sshort 9: (tiff_slong, 4), 10: (tiff_srational, 8), + #11: single float + #12: double float } TIFF_IFD_CNT = 'H' @@ -942,6 +949,7 @@ def tiff_ifd(fh, endian, off): for i in range(cnt): tag, ttype, length, valoff = entries[i * TIFF_IFD_ENTRY_CNT:(i + 1) * TIFF_IFD_ENTRY_CNT] + #print('t:', repr(tag), repr(ttype), repr(length), repr(valoff)) typefun, typequantum = tifftypes[ttype] blength = length * typequantum if blength <= 4: @@ -1021,26 +1029,6 @@ def getendian(val): return endian -class fileoff: - '''A wrapper around a file object that pretends it - starts at off. - ''' - - def __init__(self, fh, off): - self.fh = fh - self.off = off - - def seek(self, arg, whence=0): - if whence == 0: - arg += self.off - return self.fh.seek(arg, whence) - - def read(self, *args): - return self.fh.read(*args) - - def tell(self): - return self.th.tell() - self.off - def idcrw(fh): fh.seek(0) isjpeg = False @@ -1059,6 +1047,7 @@ def idcrw(fh): while True: fh.seek(pos) data = fh.read(10) + marklen = int.from_bytes(data[2:4], 'big') if data == b'': raise ValueError('unexpected end of file') @@ -1068,14 +1057,14 @@ def idcrw(fh): if data[:2] != b'\xff\xe1' or data[4:10] != b'Exif\x00\x00': # Skip over marker - pos += 2 + int.from_bytes(data[2:4], 'big') + pos += 2 + marklen continue # required due to coverage bug if True: #pragma: no cover break - fh = fileoff(fh, fh.tell()) + fh = BytesIO(fh.read(marklen - 8)) endian = getendian(fh.read(2)) isjpeg = True @@ -1235,6 +1224,7 @@ class _TestCRW(unittest.TestCase): self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.ExposureTime][0], Fraction(1, 200)) #print(repr(ci)) + #print(repr(ci[0][TIFFTag.ExifIFDPointer][ExifTag.MakerNote][CanonMakerNote.SerialInfo])) def test_jpegexif(self): with open(self.fixtures / 'exif.jpeg', 'rb') as fp: @@ -1242,5 +1232,7 @@ class _TestCRW(unittest.TestCase): self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.ISOSpeedRatings][0], 100) self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.UserComment], b'UNICODE\x00' + 'abc123สวัสดี'.encode('utf-16-be')) - self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.LensMake], b'Random Lens Maker\x00') - self.assertEqual(ci[0][TIFFTag.ImageDescription], b'Some comment\x00') + self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.LensMake], 'Random Lens Maker') + self.assertEqual(ci[0][TIFFTag.ImageDescription], 'Some comment') + + #print(repr(ci))