large-image-source-tiff 1.30.5.dev8__tar.gz → 1.30.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/PKG-INFO +3 -3
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff/__init__.py +28 -15
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff/tiff_reader.py +35 -11
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/PKG-INFO +3 -3
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/requires.txt +2 -2
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/setup.py +1 -2
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/LICENSE +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/README.rst +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff/exceptions.py +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff/girder_source.py +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/SOURCES.txt +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/dependency_links.txt +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/entry_points.txt +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/large_image_source_tiff.egg-info/top_level.txt +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/pyproject.toml +0 -0
- {large_image_source_tiff-1.30.5.dev8 → large_image_source_tiff-1.30.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: large-image-source-tiff
|
3
|
-
Version: 1.30.
|
3
|
+
Version: 1.30.6
|
4
4
|
Summary: A TIFF tilesource for large_image.
|
5
5
|
Home-page: https://github.com/girder/large_image
|
6
6
|
Author: Kitware, Inc.
|
@@ -19,13 +19,13 @@ Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Requires-Python: >=3.8
|
20
20
|
Description-Content-Type: text/x-rst
|
21
21
|
License-File: LICENSE
|
22
|
-
Requires-Dist: large-image>=1.30.
|
22
|
+
Requires-Dist: large-image>=1.30.6
|
23
23
|
Requires-Dist: pylibtiff
|
24
24
|
Requires-Dist: tifftools>=1.2.0
|
25
25
|
Provides-Extra: all
|
26
26
|
Requires-Dist: pylibjpeg-openjpeg; extra == "all"
|
27
27
|
Provides-Extra: girder
|
28
|
-
Requires-Dist: girder-large-image>=1.30.
|
28
|
+
Requires-Dist: girder-large-image>=1.30.6; extra == "girder"
|
29
29
|
|
30
30
|
A TIFF tilesource for large_image.
|
31
31
|
|
@@ -141,7 +141,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
141
141
|
continue
|
142
142
|
# If a layer is a multiple of the tile size, the number of tiles
|
143
143
|
# should be a power of two rounded up from the primary.
|
144
|
-
if
|
144
|
+
if not (td.imageWidth % td.tileWidth) and not (td.imageHeight % td.tileHeight):
|
145
145
|
htw = highest.imageWidth // td.tileWidth
|
146
146
|
hth = highest.imageHeight // td.tileHeight
|
147
147
|
ttw = td.imageWidth // td.tileWidth
|
@@ -327,12 +327,19 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
327
327
|
self._info = info
|
328
328
|
frames = []
|
329
329
|
associated = [] # for now, a list of directories
|
330
|
+
used_subifd = False
|
330
331
|
for idx, ifd in enumerate(info['ifds']):
|
331
332
|
# if not tiles, add to associated images
|
332
333
|
if tifftools.Tag.tileWidth.value not in ifd['tags']:
|
333
|
-
associated.append(idx)
|
334
|
+
associated.append((idx, False))
|
334
335
|
continue
|
335
|
-
|
336
|
+
try:
|
337
|
+
level = self._levelFromIfd(ifd, info['ifds'][0])
|
338
|
+
except TileSourceError:
|
339
|
+
if idx and used_subifd:
|
340
|
+
associated.append((idx, True))
|
341
|
+
continue
|
342
|
+
raise
|
336
343
|
# if the same resolution as the main image, add a frame
|
337
344
|
if level == self.levels - 1:
|
338
345
|
frames.append({'dirs': [None] * self.levels})
|
@@ -371,9 +378,13 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
371
378
|
tifftools.Tag.TileOffsets.value not in subifds[0]['tags']):
|
372
379
|
msg = 'Subifd has no strip or tile offsets.'
|
373
380
|
raise TileSourceMalformedError(msg)
|
374
|
-
|
381
|
+
try:
|
382
|
+
level = self._levelFromIfd(subifds[0], info['ifds'][0])
|
383
|
+
except Exception:
|
384
|
+
break
|
375
385
|
if level < self.levels - 1 and frames[-1]['dirs'][level] is None:
|
376
386
|
frames[-1]['dirs'][level] = (idx, subidx + 1)
|
387
|
+
used_subifd = True
|
377
388
|
else:
|
378
389
|
msg = 'Tile layers are in a surprising order'
|
379
390
|
raise TileSourceError(msg)
|
@@ -407,8 +418,8 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
407
418
|
self._iccprofiles.append(ifd['tags'][
|
408
419
|
tifftools.Tag.ICCProfile.value]['data'])
|
409
420
|
self._associatedImages = {}
|
410
|
-
for dirNum in associated:
|
411
|
-
self._addAssociatedImage(dirNum)
|
421
|
+
for dirNum, isTiled in associated:
|
422
|
+
self._addAssociatedImage(dirNum, isTiled)
|
412
423
|
self._frames = frames
|
413
424
|
self._tiffDirectories = [
|
414
425
|
self.getTiffDir(
|
@@ -490,7 +501,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
490
501
|
frame.setdefault('frame', {})
|
491
502
|
frame['frame']['IndexC'] = idx
|
492
503
|
|
493
|
-
def _addAssociatedImage(self, directoryNum, mustBeTiled=False, topImage=None):
|
504
|
+
def _addAssociatedImage(self, directoryNum, mustBeTiled=False, topImage=None, imageId=None):
|
494
505
|
"""
|
495
506
|
Check if the specified TIFF directory contains an image with a sensible
|
496
507
|
image description that can be used as an ID. If so, and if the image
|
@@ -501,6 +512,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
501
512
|
untiled images.
|
502
513
|
:param topImage: if specified, add image-embedded metadata to this
|
503
514
|
image.
|
515
|
+
:param imageId: if specified, use this as the image name.
|
504
516
|
"""
|
505
517
|
try:
|
506
518
|
associated = self.getTiffDir(directoryNum, mustBeTiled)
|
@@ -514,6 +526,8 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
514
526
|
id = 'dir%d' % directoryNum
|
515
527
|
if not len(self._associatedImages):
|
516
528
|
id = 'macro'
|
529
|
+
if imageId:
|
530
|
+
id = imageId
|
517
531
|
if not id and not mustBeTiled:
|
518
532
|
id = {1: 'label', 9: 'macro'}.get(associated._tiffInfo.get('subfiletype'))
|
519
533
|
if not isinstance(id, str):
|
@@ -525,7 +539,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
525
539
|
associated._pixelInfo['width'] <= self._maxAssociatedImageSize and
|
526
540
|
associated._pixelInfo['height'] <= self._maxAssociatedImageSize and
|
527
541
|
id not in self._associatedImages):
|
528
|
-
image = associated.
|
542
|
+
image = associated.read_image()
|
529
543
|
# Optrascan scanners store xml image descriptions in a "tiled
|
530
544
|
# image". Check if this is the case, and, if so, parse such
|
531
545
|
# data
|
@@ -681,8 +695,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
681
695
|
except Exception:
|
682
696
|
if sparseFallback:
|
683
697
|
raise IOTiffError('Missing z level %d' % z)
|
684
|
-
|
685
|
-
raise
|
698
|
+
raise
|
686
699
|
else:
|
687
700
|
tile = dir.getTile(x, y, asarray=numpyAllowed == 'always')
|
688
701
|
format = 'JPEG'
|
@@ -765,7 +778,7 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
765
778
|
"""
|
766
779
|
imageList = set(self._associatedImages)
|
767
780
|
for td in self._tiffDirectories:
|
768
|
-
if td is not None:
|
781
|
+
if td is not None and td is not False:
|
769
782
|
imageList |= set(td._embeddedImages)
|
770
783
|
return sorted(imageList)
|
771
784
|
|
@@ -780,11 +793,11 @@ class TiffFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
|
|
780
793
|
# _associatedImages. There are some sample files where libtiff's
|
781
794
|
# read_image fails to read the _associatedImage properly because of
|
782
795
|
# separated jpeg information. For the samples we currently have,
|
783
|
-
# preferring the _embeddedImages is sufficient, but if find other
|
784
|
-
# with seemingly bad associated images, we may need to read them
|
785
|
-
# more complex process than read_image.
|
796
|
+
# preferring the _embeddedImages is sufficient, but if we find other
|
797
|
+
# files with seemingly bad associated images, we may need to read them
|
798
|
+
# with a more complex process than read_image.
|
786
799
|
for td in self._tiffDirectories:
|
787
|
-
if td is not None and imageKey in td._embeddedImages:
|
800
|
+
if td is not None and td is not False and imageKey in td._embeddedImages:
|
788
801
|
return PIL.Image.open(io.BytesIO(base64.b64decode(td._embeddedImages[imageKey])))
|
789
802
|
if imageKey in self._associatedImages:
|
790
803
|
return PIL.Image.fromarray(self._associatedImages[imageKey])
|
@@ -447,12 +447,11 @@ class TiledTiffDirectory:
|
|
447
447
|
|
448
448
|
if tileByteCountsLibtiffType == libtiff_ctypes.TIFFDataType.TIFF_LONG8:
|
449
449
|
return ctypes.c_uint64
|
450
|
-
|
450
|
+
if tileByteCountsLibtiffType == \
|
451
451
|
libtiff_ctypes.TIFFDataType.TIFF_SHORT:
|
452
452
|
return ctypes.c_uint16
|
453
|
-
|
454
|
-
|
455
|
-
'Invalid type for TIFFTAG_TILEBYTECOUNTS: %s' % tileByteCountsLibtiffType)
|
453
|
+
raise IOTiffError(
|
454
|
+
'Invalid type for TIFFTAG_TILEBYTECOUNTS: %s' % tileByteCountsLibtiffType)
|
456
455
|
|
457
456
|
def _getJpegFrameSize(self, tileNum):
|
458
457
|
"""
|
@@ -529,10 +528,10 @@ class TiledTiffDirectory:
|
|
529
528
|
if bytesRead == -1:
|
530
529
|
msg = 'Failed to read raw tile'
|
531
530
|
raise IOTiffError(msg)
|
532
|
-
|
531
|
+
if bytesRead < rawTileSize:
|
533
532
|
msg = 'Buffer underflow when reading tile'
|
534
533
|
raise IOTiffError(msg)
|
535
|
-
|
534
|
+
if bytesRead > rawTileSize:
|
536
535
|
# It's unlikely that this will ever occur, but incomplete reads will
|
537
536
|
# be checked for by looking for the JPEG end marker
|
538
537
|
msg = 'Buffer overflow when reading tile'
|
@@ -788,11 +787,13 @@ class TiledTiffDirectory:
|
|
788
787
|
|
789
788
|
if (not self._tiffInfo.get('istiled') or
|
790
789
|
self._tiffInfo.get('compression') not in {
|
791
|
-
libtiff_ctypes.COMPRESSION_JPEG, 33003, 33005, 34712} or
|
790
|
+
libtiff_ctypes.COMPRESSION_JPEG, 33003, 33004, 33005, 34712} or
|
792
791
|
self._tiffInfo.get('bitspersample') != 8 or
|
793
792
|
self._tiffInfo.get('sampleformat') not in {
|
794
793
|
None, libtiff_ctypes.SAMPLEFORMAT_UINT} or
|
795
|
-
(asarray and self._tiffInfo.get('compression') not in {
|
794
|
+
(asarray and self._tiffInfo.get('compression') not in {
|
795
|
+
33003, 33004, 33005, 34712,
|
796
|
+
} and (
|
796
797
|
self._tiffInfo.get('compression') != libtiff_ctypes.COMPRESSION_JPEG or
|
797
798
|
self._tiffInfo.get('photometric') != libtiff_ctypes.PHOTOMETRIC_YCBCR))):
|
798
799
|
return self._getUncompressedTile(tileNum)
|
@@ -811,7 +812,7 @@ class TiledTiffDirectory:
|
|
811
812
|
# Get the whole frame, which is in a JPEG or JPEG 2000 format
|
812
813
|
frame = self._getJpegFrame(tileNum, True)
|
813
814
|
# For JP2K, see if we can convert it faster than PIL
|
814
|
-
if self._tiffInfo.get('compression') in {33003, 33005}:
|
815
|
+
if self._tiffInfo.get('compression') in {33003, 33004, 33005, 34712}:
|
815
816
|
try:
|
816
817
|
import openjpeg
|
817
818
|
|
@@ -836,7 +837,7 @@ class TiledTiffDirectory:
|
|
836
837
|
self._embeddedImages = {}
|
837
838
|
|
838
839
|
if not meta:
|
839
|
-
return
|
840
|
+
return None
|
840
841
|
if not isinstance(meta, str):
|
841
842
|
meta = meta.decode(errors='ignore')
|
842
843
|
try:
|
@@ -858,7 +859,7 @@ class TiledTiffDirectory:
|
|
858
859
|
meta.split('|MPP = ', 1)[1].split('|')[0].strip()) * 0.001
|
859
860
|
except Exception:
|
860
861
|
pass
|
861
|
-
return
|
862
|
+
return None
|
862
863
|
try:
|
863
864
|
image = xml.find(
|
864
865
|
".//DataObject[@ObjectType='DPScannedImage']")
|
@@ -894,3 +895,26 @@ class TiledTiffDirectory:
|
|
894
895
|
except Exception:
|
895
896
|
pass
|
896
897
|
return True
|
898
|
+
|
899
|
+
def read_image(self):
|
900
|
+
"""
|
901
|
+
Use the underlying _tiffFile to read an image. But, if it is in a jp2k
|
902
|
+
encoding, read the raw data and convert it.
|
903
|
+
"""
|
904
|
+
if self._tiffInfo.get('compression') not in {33003, 33004, 33005, 34712}:
|
905
|
+
return self._tiffFile.read_image()
|
906
|
+
output = None
|
907
|
+
for yidx, y in enumerate(range(0, self.imageHeight, self.tileHeight)):
|
908
|
+
for xidx, x in enumerate(range(0, self.imageWidth, self.tileWidth)):
|
909
|
+
tile = self.getTile(xidx, yidx, asarray=True)
|
910
|
+
if len(tile.shape) == 2:
|
911
|
+
tile = tile[:, :, np.newaxis]
|
912
|
+
if output is None:
|
913
|
+
output = np.zeros(
|
914
|
+
(self.imageHeight, self.imageWidth, tile.shape[2]), dtype=tile.dtype)
|
915
|
+
if tile.shape[0] > self.imageHeight - y:
|
916
|
+
tile = tile[:self.imageHeight - y, :, :]
|
917
|
+
if tile.shape[1] > self.imageWidth - x:
|
918
|
+
tile = tile[:, :self.imageWidth - x, :]
|
919
|
+
output[y:y + tile.shape[0], x:x + tile.shape[1], :] = tile
|
920
|
+
return output
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: large-image-source-tiff
|
3
|
-
Version: 1.30.
|
3
|
+
Version: 1.30.6
|
4
4
|
Summary: A TIFF tilesource for large_image.
|
5
5
|
Home-page: https://github.com/girder/large_image
|
6
6
|
Author: Kitware, Inc.
|
@@ -19,13 +19,13 @@ Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Requires-Python: >=3.8
|
20
20
|
Description-Content-Type: text/x-rst
|
21
21
|
License-File: LICENSE
|
22
|
-
Requires-Dist: large-image>=1.30.
|
22
|
+
Requires-Dist: large-image>=1.30.6
|
23
23
|
Requires-Dist: pylibtiff
|
24
24
|
Requires-Dist: tifftools>=1.2.0
|
25
25
|
Provides-Extra: all
|
26
26
|
Requires-Dist: pylibjpeg-openjpeg; extra == "all"
|
27
27
|
Provides-Extra: girder
|
28
|
-
Requires-Dist: girder-large-image>=1.30.
|
28
|
+
Requires-Dist: girder-large-image>=1.30.6; extra == "girder"
|
29
29
|
|
30
30
|
A TIFF tilesource for large_image.
|
31
31
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|