From ced526b91b1a4c99a5d9769607d9340e9c981078 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Fri, 17 Feb 2023 13:04:04 -0500 Subject: [PATCH] Speed up some images handled with bioformats. Better find reduced resolution layers. --- CHANGELOG.md | 1 + .../large_image_source_bioformats/__init__.py | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef38218d..fc59ed489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Render item lists faster ([#1036](../../pull/1036)) - Reduce bioformats source memory usage ([#1038](../../pull/1038)) - Better pick the largest image from bioformats ([#1039](../../pull/1039), [#1040](../../pull/1040)) +- Speed up some images handled with bioformats ([#1063](../../pull/1063)) - Cache histogram thresholds ([#1042](../../pull/1042)) - Add `_repr_png_` for Jupyter ([#1058](../../pull/1058)) - Ignore bogus tifffile resolutions ([#1062](../../pull/1062)) diff --git a/sources/bioformats/large_image_source_bioformats/__init__.py b/sources/bioformats/large_image_source_bioformats/__init__.py index aa9dfce12..b26dd87b2 100644 --- a/sources/bioformats/large_image_source_bioformats/__init__.py +++ b/sources/bioformats/large_image_source_bioformats/__init__.py @@ -344,6 +344,8 @@ def _getSeriesStarts(self, rdr): # noqa key for key in seriesMetadata if key.startswith('Series ')): frameList = [[0]] nextSeriesNum = 1 + rdr.setSeries(0) + lastX, lastY = rdr.getSizeX(), rdr.getSizeY() for idx in range(1, self._metadata['seriesCount']): rdr.setSeries(idx) if (rdr.getSizeX() == self._metadata['sizeX'] and @@ -351,12 +353,23 @@ def _getSeriesStarts(self, rdr): # noqa frameList.append([idx]) if nextSeriesNum == idx: nextSeriesNum = idx + 1 + lastX, lastY = self._metadata['sizeX'], self._metadata['sizeY'] if (rdr.getSizeX() * rdr.getSizeY() > self._metadata['sizeX'] * self._metadata['sizeY']): frameList = [[idx]] nextSeriesNum = idx + 1 - self._metadata['sizeX'] = self.sizeX = rdr.getSizeX() - self._metadata['sizeY'] = self.sizeY = rdr.getSizeY() + self._metadata['sizeX'] = self.sizeX = lastX = rdr.getSizeX() + self._metadata['sizeY'] = self.sizeY = lastY = rdr.getSizeY() + if (lastX and lastY and + nearPowerOfTwo(rdr.getSizeX(), lastX) and rdr.getSizeX() < lastX and + nearPowerOfTwo(rdr.getSizeY(), lastY) and rdr.getSizeY() < lastY): + steps = int(round(math.log( + lastX * lastY / (rdr.getSizeX() * rdr.getSizeY())) / math.log(2) / 2)) + frameList[-1] += [None] * (steps - 1) + frameList[-1].append(idx) + lastX, lastY = rdr.getSizeX(), rdr.getSizeY() + if nextSeriesNum == idx: + nextSeriesNum = idx + 1 frameList = [fl for fl in frameList if len(fl)] self._metadata['frameSeries'] = [{ 'series': fl, @@ -385,6 +398,8 @@ def _checkSeries(self, rdr): validate = None for frame in self._metadata['frameSeries']: for level in range(len(frame['series'])): + if level and frame['series'][level] is None: + continue rdr.setSeries(frame['series'][level]) self._metadataForCurrentSeries(rdr) info = { @@ -400,6 +415,9 @@ def _checkSeries(self, rdr): not nearPowerOfTwo(frame['sizeY'], info['sizeY'])): frame['series'] = frame['series'][:level] validate = True + break + rdr.setSeries(frame['series'][0]) + self._metadataForCurrentSeries(rdr) if validate is None: validate = False rdr.setSeries(0) @@ -545,7 +563,7 @@ def getTile(self, x, y, z, pilImageAllowed=False, numpyAllowed=False, **kwargs): fseries = self._metadata['frameSeries'][fxy] seriesLevel = self.levels - 1 - z scale = 1 - while seriesLevel >= len(fseries['series']): + while seriesLevel >= len(fseries['series']) or fseries['series'][seriesLevel] is None: seriesLevel -= 1 scale *= 2 offsetx = x * self.tileWidth * scale