diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7acd026..75e5df4ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## 1.27.5 +### Features +- Zarr tile sink ([#1446](../../pull/1446)) + +### Improvements +- Prioritize tile sinks ([#1478](../../pull/1478)) + ### Bug Fixes - Fix an issue with single band on multi source with non uniform sources ([#1474](../../pull/1474)) - Allow alternate name axes in the multi source schema ([#1476](../../pull/1476)) diff --git a/large_image/tilesource/__init__.py b/large_image/tilesource/__init__.py index 503cee457..bdd271e4a 100644 --- a/large_image/tilesource/__init__.py +++ b/large_image/tilesource/__init__.py @@ -86,11 +86,14 @@ def getSortedSourceList( properties = { '_geospatial_source': isGeospatial(pathOrUri), } + isNew = str(pathOrUri).startswith(NEW_IMAGE_PATH_FLAG) sourceList = [] for sourceName in availableSources: sourceExtensions = availableSources[sourceName].extensions priority = sourceExtensions.get(None, SourcePriority.MANUAL) fallback = True + if isNew and getattr(availableSources[sourceName], 'newPriority', None): + priority = min(priority, availableSources[sourceName].newPriority) if (mimeType and getattr(availableSources[sourceName], 'mimeTypes', None) and mimeType in availableSources[sourceName].mimeTypes): fallback = False @@ -130,7 +133,8 @@ def getSourceNameFromDict( there is no such source. """ sourceList = getSortedSourceList(availableSources, pathOrUri, mimeType, *args, **kwargs) - for _clash, _fallback, _priority, sourceName in sorted(sourceList): + for entry in sorted(sourceList): + sourceName = entry[-1] if availableSources[sourceName].canRead(pathOrUri, *args, **kwargs): return sourceName return None @@ -217,7 +221,8 @@ def canReadList( sourceList = getSortedSourceList( AvailableTileSources, pathOrUri, mimeType, *args, **kwargs) result = [] - for _clash, _fallback, _priority, sourceName in sorted(sourceList): + for entry in sorted(sourceList): + sourceName = entry[-1] result.append((sourceName, AvailableTileSources[sourceName].canRead( pathOrUri, *args, **kwargs))) return result diff --git a/large_image/tilesource/base.py b/large_image/tilesource/base.py index 7c9b898f6..af92cc0ce 100644 --- a/large_image/tilesource/base.py +++ b/large_image/tilesource/base.py @@ -57,6 +57,10 @@ class TileSource(IPyLeafletMixin): nameMatches: Dict[str, SourcePriority] = { } + # If a source supports creating new tiled images, specify its basic + # priority based on expected feature set + newPriority: Optional[SourcePriority] = None + # When getting tiles for otherwise empty levels (missing powers of two), we # composite the tile from higher resolution levels. This can use excessive # memory if there are too many missing levels. For instance, if there are diff --git a/sources/vips/large_image_source_vips/__init__.py b/sources/vips/large_image_source_vips/__init__.py index 65ecbea2a..e747c7133 100644 --- a/sources/vips/large_image_source_vips/__init__.py +++ b/sources/vips/large_image_source_vips/__init__.py @@ -50,6 +50,7 @@ class VipsFileTileSource(FileTileSource, metaclass=LruCacheMetaclass): mimeTypes = { None: SourcePriority.FALLBACK, } + newPriority = SourcePriority.MEDIUM _tileSize = 256 diff --git a/sources/zarr/large_image_source_zarr/__init__.py b/sources/zarr/large_image_source_zarr/__init__.py index 620bc682c..61e3d8234 100644 --- a/sources/zarr/large_image_source_zarr/__init__.py +++ b/sources/zarr/large_image_source_zarr/__init__.py @@ -40,6 +40,7 @@ class ZarrFileTileSource(FileTileSource, metaclass=LruCacheMetaclass): 'zattrs': SourcePriority.PREFERRED, 'db': SourcePriority.MEDIUM, } + newPriority = SourcePriority.HIGH _tileSize = 512 _minTileSize = 128 diff --git a/test/test_source_vips.py b/test/test_source_vips.py index 1d3e57a95..9ef56e808 100644 --- a/test/test_source_vips.py +++ b/test/test_source_vips.py @@ -169,8 +169,7 @@ def testNewAndWriteMinSize(): def testNewAndWriteJPEG(): imagePath = datastore.fetch('sample_image.ptif') source = large_image.open(imagePath) - # Update this if it doesn't direct to vips source - out = large_image.new() + out = large_image_source_vips.new() for tile in source.tileIterator( format=large_image.constants.TILE_FORMAT_NUMPY, region=dict(right=4000, bottom=2000),