diff --git a/setup.py b/setup.py index 6a0e47f..e45462f 100644 --- a/setup.py +++ b/setup.py @@ -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.", diff --git a/tiffexplore/__init__.py b/tiffexplore/__init__.py index 3c7094c..47a3a2c 100644 --- a/tiffexplore/__init__.py +++ b/tiffexplore/__init__.py @@ -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) diff --git a/tiffexplore/tiffread.py b/tiffexplore/tiffread.py index be51bea..57e3231 100644 --- a/tiffexplore/tiffread.py +++ b/tiffexplore/tiffread.py @@ -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]