From d38b499165db0dc9a1682f0e23baf9884cc2f10c Mon Sep 17 00:00:00 2001 From: David Manthey Date: Wed, 25 Sep 2024 12:15:17 -0400 Subject: [PATCH] Fix styling images with empty tile layers --- CHANGELOG.md | 4 ++++ large_image/tilesource/base.py | 9 +++++---- sources/tiff/large_image_source_tiff/__init__.py | 6 ++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 608c6b470..b09dd6197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Better handle images without enough tile layers ([#1648](../../pull/1648)) - Add users option to config files; have a default config file ([#1649](../../pull/1649)) +### Bug Fixes + +- Fix styling images with empty tile layers ([#1650](../../pull/1650)) + ## 1.29.11 ### Changes diff --git a/large_image/tilesource/base.py b/large_image/tilesource/base.py index aa3276246..ea02dfce8 100644 --- a/large_image/tilesource/base.py +++ b/large_image/tilesource/base.py @@ -1535,7 +1535,7 @@ def _getTileFromEmptyLevel(self, x: int, y: int, z: int, **kwargs) -> Tuple[ 'Compositing tile from higher resolution tiles x=%d y=%d z=%d', x * scale + newX, y * scale + newY, z) lastlog = time.time() - subtile = self.getTile( + subtile = getattr(self, '_unstyledInstance', self).getTile( x * scale + newX, y * scale + newY, z, pilImageAllowed=False, numpyAllowed='always', sparseFallback=True, edge=False, frame=kwargs.get('frame')) @@ -1559,7 +1559,7 @@ def _getTileFromEmptyLevel(self, x: int, y: int, z: int, **kwargs) -> Tuple[ 'Compositing tile from higher resolution tiles x=%d y=%d z=%d', x * scale + newX, y * scale + newY, z) lastlog = time.time() - subtile = self.getTile( + subtile = getattr(self, '_unstyledInstance', self).getTile( x * scale + newX, y * scale + newY, z, pilImageAllowed=True, numpyAllowed=False, sparseFallback=True, edge=False, frame=kwargs.get('frame')) @@ -1815,7 +1815,8 @@ def getRegion(self, format: Union[str, Tuple[str]] = (TILE_FORMAT_IMAGE, ), **kw cast(Dict[str, Any], tiledimage), outWidth, outHeight, tileIter.info, **kwargs) if outWidth != regionWidth or outHeight != regionHeight: dtype = cast(np.ndarray, image).dtype - if dtype == np.uint8 or resample is not None: + if dtype == np.uint8 or (resample is not None and ( + dtype != np.uint16 or cast(np.ndarray, image).shape[-1] != 1)): image = _imageToPIL(cast(np.ndarray, image), mode).resize( (outWidth, outHeight), getattr(PIL.Image, 'Resampling', PIL.Image).NEAREST @@ -1828,7 +1829,7 @@ def getRegion(self, format: Union[str, Tuple[str]] = (TILE_FORMAT_IMAGE, ), **kw else: cols = [int(idx * regionWidth / outWidth) for idx in range(outWidth)] rows = [int(idx * regionHeight / outHeight) for idx in range(outHeight)] - image = np.take(np.take(image, rows, axis=0), cols, axis=1) + image = np.take(np.take(cast(np.ndarray, image), rows, axis=0), cols, axis=1) maxWidth = kwargs.get('output', {}).get('maxWidth') maxHeight = kwargs.get('output', {}).get('maxHeight') if kwargs.get('fill') and maxWidth and maxHeight: diff --git a/sources/tiff/large_image_source_tiff/__init__.py b/sources/tiff/large_image_source_tiff/__init__.py index ca6c92ec7..d84de6a2a 100644 --- a/sources/tiff/large_image_source_tiff/__init__.py +++ b/sources/tiff/large_image_source_tiff/__init__.py @@ -664,7 +664,6 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, else: dir = self._tiffDirectories[z] try: - allowStyle = True if dir is None: try: if not kwargs.get('inSparseFallback'): @@ -676,7 +675,6 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, raise IOTiffError('Missing z level %d' % z) else: raise - allowStyle = False else: tile = dir.getTile(x, y, asarray=numpyAllowed == 'always') format = 'JPEG' @@ -685,7 +683,7 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, if isinstance(tile, np.ndarray): format = TILE_FORMAT_NUMPY return self._outputTile(tile, format, x, y, z, pilImageAllowed, - numpyAllowed, applyStyle=allowStyle, **kwargs) + numpyAllowed, **kwargs) except InvalidOperationTiffError as e: raise TileSourceError(e.args[0]) except IOTiffError as e: @@ -734,7 +732,7 @@ def getTileIOTiffError(self, x, y, z, pilImageAllowed=False, else: image = PIL.Image.new('RGBA', (self.tileWidth, self.tileHeight)) return self._outputTile(image, TILE_FORMAT_PIL, x, y, z, pilImageAllowed, - numpyAllowed, applyStyle=False, **kwargs) + numpyAllowed, **kwargs) raise TileSourceError('Internal I/O failure: %s' % exception.args[0]) def _nonemptyLevelsList(self, frame=0):