- Some support for dng:

- Read SubIFDs and tags, TODO: read image data in SubIFD
  - Read ExifIFDs and tags
- Maximize size of blocks in bar
- Properly read and print srationals
This commit is contained in:
Wim Pomp
2021-07-14 20:14:54 +02:00
parent bfea2501c9
commit 2cfd117cbf
3 changed files with 48 additions and 30 deletions

View File

@@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="tiffexplore",
packages=["tiffexplore"],
version="2021.06.2",
version="2021.07.0",
author="Wim Pomp",
author_email="wimpomp@gmail.com",
description="Explore a tiff structure.",

View File

@@ -131,14 +131,14 @@ class Bar(PaintBox):
self.drawText(qp, (0, value[0], 125, value[1]), ('_'.join(('{}',) * len(key))).format(*key).lower())
qp.end()
def get_bar(self):
min_size = 10
scale = 100
def get_bar(self, scale=100, min_size=10, max_size=1000):
bar = tiffread.assignments()
pos = 0
for item in self.tiff.addresses.get_assignments():
key, value = item[0]
size = value[1] // scale if value[1] // scale >= min_size else min_size
size = value[1] // scale
if not (min_size <= size <= max_size):
size = min_size if size < min_size else max_size
if not (key[0].lower() == 'empty' and value[1] == 1):
if key[0].lower() == 'empty':
bar[('empty', value[0] + value[1] // 2)] = (pos, size)
@@ -148,7 +148,6 @@ class Bar(PaintBox):
else:
bar[key] = (pos, size)
pos += size
bar.max_addr = pos
return bar
@@ -179,18 +178,21 @@ class Bar(PaintBox):
if key[0].lower() == 'ifd':
text.append(f'Number of tags: {self.tiff.nTags[key[1]]}\n')
text.extend([self.tiff.fmt_tag(k, v)+'\n' for k, v in self.tiff.tags[key[1]].items()])
if key[1] < len(self.tiff.offsets) - 1:
if not isinstance(key[1], str):
text.append(f'Next ifd offset: {self.tiff.offsets[key[1] + 1]}')
if key[0].lower() == 'tagdata':
text.append('\n' + self.tiff.fmt_tag(key[2], self.tiff.tags[key[1]][key[2]]))
if key[0].lower() == 'image':
im = self.tiff.asarray(key[1], key[2])
if im is not None:
text.append(f'\nStrip size: {im.shape}')
text.append(f'Data type: {im.dtype}')
text.append(f'Min, max: {im.min()}, {im.max()}')
text.append(f'Mean, std: {im.mean()}, {im.std()}')
self.parent.setImage(im)
try:
im = self.tiff.asarray(key[1], key[2])
if im is not None:
text.append(f'\nStrip size: {im.shape}')
text.append(f'Data type: {im.dtype}')
text.append(f'Min, max: {im.min()}, {im.max()}')
text.append(f'Mean, std: {im.mean()}, {im.std()}')
self.parent.setImage(im)
except Exception:
pass
else:
self.parent.setImage()
self.parent.properties.setText('\n'.join(text))
@@ -227,7 +229,7 @@ class App(QtWidgets.QMainWindow, UiMainWindow):
def openDialog(self):
file, _ = QtWidgets.QFileDialog.getOpenFileName(self,
"Open config file", "", "TIFF Files (*.tif *.tiff);;All Files (*)",
"Open config file", "", "TIFF Files (*.tif *.tiff);;DNG files (*.dng);;All Files (*)",
options=(QtWidgets.QFileDialog.Options() | QtWidgets.QFileDialog.DontUseNativeDialog))
self.open(file)

View File

@@ -3,6 +3,7 @@ import tifffile
import numpy as np
from traceback import format_exc
ifdcodes = {330: 'sub', 34665: 'exif', 34853: 'gps', 40965: 'inter'}
class tiff():
def __init__(self, file):
@@ -12,24 +13,39 @@ class tiff():
self.tiff = tifffile.TiffFile(self.file)
except Exception:
self.tiff = None
self.tags = []
self.tags = {}
self.get_file_len()
self.addresses = assignments(len(self))
self.offsets = []
self.nTags = []
self.nTags = {}
self.tagsread = set()
try:
self.offsets = [self.read_header()]
i = 0
idx = 0
while 0 < self.offsets[-1] < len(self):
self.offsets.append(self.read_ifd(self.offsets[-1], i))
i += 1
for i, tags in enumerate(self.tags):
if 273 in tags and 279 in tags:
for j, a in enumerate(zip(tags[273][-1], tags[279][-1])):
self.addresses[('image', i, j)] = a
self.offsets.append(self.read_ifd(self.offsets[-1], idx))
idx += 1
self.readtags()
except Exception:
print(format_exc())
def readtags(self):
while len(set(self.tags.keys()) - self.tagsread):
for idx in set(self.tags.keys()) - self.tagsread:
tags = self.tags[idx]
if idx not in self.tagsread:
if 273 in tags and 279 in tags:
for i, a in enumerate(zip(tags[273][-1], tags[279][-1])):
self.addresses[('image', idx, i)] = a
for code, id in ifdcodes.items():
if code in tags:
if len(tags[code][3]) == 1:
self.offsets.append(self.read_ifd(tags[code][3][0], f'{id}_{idx}'))
else:
for i, offset in enumerate(tags[code][3]):
self.offsets.append(self.read_ifd(offset, f'{id}_{idx}_{i}'))
self.tagsread.add(idx)
@staticmethod
def fmt_tag(code, value):
text = [f'Code: {code}']
@@ -42,8 +58,8 @@ class tiff():
pass
text.append(f'address: {value[1]}')
text.append(f'count: {value[2]}')
if value[0] == 5:
text.append(f'value: [{", ".join(["/".join([str(w) for w in v[::-1]]) for v in value[3]])}]')
if value[0] in (5, 10):
text.append(f'value: [{", ".join(["-" * (sum([w<0 for w in v]) % 2) + "/".join([str(abs(w)) for w in v[::-1]]) for v in value[3]])}]')
else:
text.append(f'value: {value[3]}')
return '\n'.join(text)
@@ -85,8 +101,8 @@ class tiff():
"""
self.fh.seek(offset)
nTags = struct.unpack(self.byteorder + self.tagnoformat, self.fh.read(struct.calcsize(self.tagnoformat)))[0]
self.nTags.append(nTags)
self.tags.append({})
self.nTags[idx] = nTags
self.tags[idx] = {}
assert nTags < 4096, 'Too many tags'
length = 8 if self.bigtiff else 2
@@ -115,7 +131,7 @@ class tiff():
value = self.fh.read(count)
elif ttype == 2:
value = self.fh.read(count).decode('ascii').rstrip('\x00')
elif ttype == 5:
elif ttype in (5, 10):
value = [struct.unpack(self.byteorder + dtype, self.fh.read(dtypelen)) for _ in range(count)]
else:
value = [struct.unpack(self.byteorder + dtype, self.fh.read(dtypelen))[0] for _ in range(count)]
@@ -124,7 +140,7 @@ class tiff():
self.fh.seek(cp)
except Exception:
print(format_exc())
self.tags[-1][code] = (ttype, caddr, dtypelen*count, value)
self.tags[idx][code] = (ttype, caddr, dtypelen*count, value)
self.fh.seek(offset + struct.calcsize(self.tagnoformat) + self.tagsize * nTags)
nifd = struct.unpack(self.byteorder + self.offsetformat, self.fh.read(self.offsetsize))[0]