Browse Source

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?
main
John-Mark Gurney 2 years ago
parent
commit
67d44c1e95
1 changed files with 26 additions and 34 deletions
  1. +26
    -34
      ui/medashare/metadata/crw.py

+ 26
- 34
ui/medashare/metadata/crw.py View File

@@ -15,7 +15,7 @@ import struct
# CRW: https://web.archive.org/web/20081230095207/http://xyrion.org/ciff/CIFFspecV1R04.pdf # 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/ # CR2: https://web.archive.org/web/20230404015346/http://lclevy.free.fr/cr2/
# JPEG: https://www.w3.org/Graphics/JPEG/itu-t81.pdf # 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: https://www.cipa.jp/std/documents/e/DC-X008-Translation-2019-E.pdf
# #
# Exif Tags: # Exif Tags:
@@ -407,11 +407,7 @@ class CanonMakerNote(enum.IntEnum):
PictureStylePC = 0x4009 PictureStylePC = 0x4009


canonmakernotehandlers = { 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 # Needed by Exif
class TIFFResolutionUnit(enum.IntEnum): class TIFFResolutionUnit(enum.IntEnum):
@@ -892,10 +888,16 @@ def tiff_bytes(endian, data):
return map(ord, data) return map(ord, data)


def tiff_ascii(endian, 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): def tiff_short(endian, data):
return struct.unpack(endian + 'H' * (len(data) // 2), data) return struct.unpack(endian + 'H' * (len(data) // 2), data)
@@ -922,10 +924,15 @@ tifftypes = {
4: (tiff_long, 4), 4: (tiff_long, 4),
5: (tiff_rational, 8), 5: (tiff_rational, 8),


#6: sbyte

# Exif Types # Exif Types
7: (lambda x, y: y, 1), # byte string 7: (lambda x, y: y, 1), # byte string
#8: sshort
9: (tiff_slong, 4), 9: (tiff_slong, 4),
10: (tiff_srational, 8), 10: (tiff_srational, 8),
#11: single float
#12: double float
} }


TIFF_IFD_CNT = 'H' TIFF_IFD_CNT = 'H'
@@ -942,6 +949,7 @@ def tiff_ifd(fh, endian, off):
for i in range(cnt): for i in range(cnt):
tag, ttype, length, valoff = entries[i * tag, ttype, length, valoff = entries[i *
TIFF_IFD_ENTRY_CNT:(i + 1) * TIFF_IFD_ENTRY_CNT] TIFF_IFD_ENTRY_CNT:(i + 1) * TIFF_IFD_ENTRY_CNT]
#print('t:', repr(tag), repr(ttype), repr(length), repr(valoff))
typefun, typequantum = tifftypes[ttype] typefun, typequantum = tifftypes[ttype]
blength = length * typequantum blength = length * typequantum
if blength <= 4: if blength <= 4:
@@ -1021,26 +1029,6 @@ def getendian(val):


return endian 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): def idcrw(fh):
fh.seek(0) fh.seek(0)
isjpeg = False isjpeg = False
@@ -1059,6 +1047,7 @@ def idcrw(fh):
while True: while True:
fh.seek(pos) fh.seek(pos)
data = fh.read(10) data = fh.read(10)
marklen = int.from_bytes(data[2:4], 'big')
if data == b'': if data == b'':
raise ValueError('unexpected end of file') 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': if data[:2] != b'\xff\xe1' or data[4:10] != b'Exif\x00\x00':
# Skip over marker # Skip over marker
pos += 2 + int.from_bytes(data[2:4], 'big')
pos += 2 + marklen
continue continue


# required due to coverage bug # required due to coverage bug
if True: #pragma: no cover if True: #pragma: no cover
break break


fh = fileoff(fh, fh.tell())
fh = BytesIO(fh.read(marklen - 8))
endian = getendian(fh.read(2)) endian = getendian(fh.read(2))
isjpeg = True isjpeg = True


@@ -1235,6 +1224,7 @@ class _TestCRW(unittest.TestCase):
self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.ExposureTime][0], Fraction(1, 200)) self.assertEqual(ci[0][TIFFTag.ExifIFDPointer][ExifTag.ExposureTime][0], Fraction(1, 200))


#print(repr(ci)) #print(repr(ci))
#print(repr(ci[0][TIFFTag.ExifIFDPointer][ExifTag.MakerNote][CanonMakerNote.SerialInfo]))


def test_jpegexif(self): def test_jpegexif(self):
with open(self.fixtures / 'exif.jpeg', 'rb') as fp: 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.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.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))

Loading…
Cancel
Save