diff --git a/CHANGELOG.md b/CHANGELOG.md index 854db6445..aa7f6f592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Remove logic for determining DICOMweb transfer syntax ([#1393](../../pull/1393)) - Speed up tile output ([#1407](../../pull/1407)) - Speed up import time ([#1408](../../pull/1408)) +- Speed up some tile iteration by reducing the chance of multiple image decodes ([#1410](../../pull/1410)) ### Changes - Use an enum for priority constants ([#1400](../../pull/1400)) diff --git a/large_image/tilesource/base.py b/large_image/tilesource/base.py index 334ddd63a..4396a3cc0 100644 --- a/large_image/tilesource/base.py +++ b/large_image/tilesource/base.py @@ -2186,8 +2186,12 @@ def getRegion(self, format=(TILE_FORMAT_IMAGE, ), **kwargs): y0 = 0 subimage = subimage[:min(subimage.shape[0], regionHeight - y0), :min(subimage.shape[1], regionWidth - x0)] - image = self._addRegionTileToImage( - image, subimage, x0, y0, regionWidth, regionHeight, tiled, tile, **kwargs) + if tiled: + image = self._addRegionTileToTiled( + image, subimage, x0, y0, regionWidth, regionHeight, tile, **kwargs) + else: + image = self._addRegionTileToImage( + image, subimage, x0, y0, regionWidth, regionHeight, **kwargs) # Scale if we need to outWidth = int(math.floor(outWidth)) outHeight = int(math.floor(outHeight)) @@ -2209,7 +2213,7 @@ def getRegion(self, format=(TILE_FORMAT_IMAGE, ), **kwargs): return _encodeImage(image, format=format, **kwargs) def _addRegionTileToImage( - self, image, subimage, x, y, width, height, tiled=False, tile=None, **kwargs): + self, image, subimage, x, y, width, height, tile=None, **kwargs): """ Add a subtile to a larger image. @@ -2221,12 +2225,8 @@ def _addRegionTileToImage( the output image. :param width: the output image size. :param height: the output image size. - :param tiled: true to generate a tiled output image. - :param tile: the original tile record with the current scale, etc. :returns: the output image record. """ - if tiled: - return self._addRegionTileToTiled(image, subimage, x, y, width, height, tile, **kwargs) if image is None: if (x, y, width, height) == (0, 0, subimage.shape[1], subimage.shape[0]): return subimage @@ -2473,9 +2473,12 @@ def tileFrames(self, format=(TILE_FORMAT_IMAGE, ), frameList=None, self.logger.debug( 'Tiling frame %d (%d/%d), offset %dx%d', frame, idx, len(frameList), offsetX, offsetY) - image = self._addRegionTileToImage( - image, subimage, offsetX, offsetY, outWidth, outHeight, tiled, - tile=tile, **kwargs) + if tiled: + image = self._addRegionTileToTiled( + image, subimage, offsetX, offsetY, outWidth, outHeight, tile, **kwargs) + else: + image = self._addRegionTileToImage( + image, subimage, offsetX, offsetY, outWidth, outHeight, **kwargs) if tiled: return self._encodeTiledImage(image, outWidth, outHeight, iterInfo, **kwargs) return _encodeImage(image, format=format, **kwargs) diff --git a/large_image/tilesource/tiledict.py b/large_image/tilesource/tiledict.py index f85a535b0..a6f9fb13d 100644 --- a/large_image/tilesource/tiledict.py +++ b/large_image/tilesource/tiledict.py @@ -165,7 +165,8 @@ def __getitem__(self, key, *args, **kwargs): if not self.retile: tileData = self.source.getTile( self.x, self.y, self.level, - pilImageAllowed=True, numpyAllowed=True, + pilImageAllowed=True, + numpyAllowed='always' if TILE_FORMAT_NUMPY in self.format else True, sparseFallback=True, frame=self.frame) if self.crop: tileData, _ = _imageToNumpy(tileData) @@ -217,6 +218,10 @@ def __getitem__(self, key, *args, **kwargs): raise exceptions.TileSourceError( 'Cannot yield tiles in desired format %r' % ( self.format, )) + elif (TILE_FORMAT_PIL not in self.format and TILE_FORMAT_NUMPY in self.format and + not isinstance(tileData, PIL.Image.Image)): + tileData, _ = _imageToNumpy(tileData) + tileFormat = TILE_FORMAT_NUMPY else: tileData = pilData if pilData is not None else _imageToPIL(tileData) tileFormat = TILE_FORMAT_PIL