Skip to content

Commit

Permalink
Merge pull request #1407 from girder/speed-up-tile-output
Browse files Browse the repository at this point in the history
Speed up tile output.
  • Loading branch information
manthey authored Dec 15, 2023
2 parents e4da21e + 818b820 commit 29d8204
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
- Add a utility function for getting loggers ([#1403](../../pull/1403))
- Get bioformats jar version if bioformats was started ([#1405](../../pull/1405))
- Improve thread safety of concurrent first reads using bioformats ([#1406](../../pull/1406))
- Read more metadata from DICOMweb ([#1378](../../pull/1378))
- Remove logic for determining DICOMweb transfer syntax ([#1393](../../pull/1393))
- Speed up tile output ([#1407](../../pull/1407))

### Changes
- Use an enum for priority constants ([#1400](../../pull/1400))
Expand Down
9 changes: 5 additions & 4 deletions large_image/tilesource/tiledict.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,11 @@ def __getitem__(self, key, *args, **kwargs):
else:
tileData = self._retileTile()

pilData = _imageToPIL(tileData)

pilData = None
# resample if needed
if self.resample not in (False, None) and self.requestedScale:
pilData = _imageToPIL(tileData)

self['width'] = max(1, int(
pilData.size[0] / self.requestedScale))
self['height'] = max(1, int(
Expand Down Expand Up @@ -206,7 +207,7 @@ def __getitem__(self, key, *args, **kwargs):
tileData, _ = _imageToNumpy(tileData)
tileFormat = TILE_FORMAT_NUMPY
elif TILE_FORMAT_PIL in self.format:
tileData = pilData
tileData = pilData if pilData is not None else _imageToPIL(tileData)
tileFormat = TILE_FORMAT_PIL
elif TILE_FORMAT_IMAGE in self.format:
tileData, mimeType = _encodeImage(
Expand All @@ -217,7 +218,7 @@ def __getitem__(self, key, *args, **kwargs):
'Cannot yield tiles in desired format %r' % (
self.format, ))
else:
tileData = pilData
tileData = pilData if pilData is not None else _imageToPIL(tileData)
tileFormat = TILE_FORMAT_PIL

self['tile'] = tileData
Expand Down
17 changes: 15 additions & 2 deletions large_image/tilesource/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'GREEN': '#00ff00',
'BLUE': '#0000ff',
}
modesBySize = ['L', 'LA', 'RGB', 'RGBA']


class ImageBytes(bytes):
Expand Down Expand Up @@ -187,7 +188,7 @@ def _imageToPIL(image, setMode=None):
# Fallback for hyperspectral data to just use the first three bands
if image.shape[2] > 4:
image = image[:, :, :3]
mode = ['L', 'LA', 'RGB', 'RGBA'][image.shape[2] - 1]
mode = modesBySize[image.shape[2] - 1]
if len(image.shape) == 3 and image.shape[2] == 1:
image = np.resize(image, image.shape[:2])
if image.dtype == np.uint32:
Expand Down Expand Up @@ -220,6 +221,17 @@ def _imageToNumpy(image):
:param image: input image.
:returns: a numpy array and a target PIL image mode.
"""
if isinstance(image, np.ndarray) and len(image.shape) == 3 and 1 <= image.shape[2] <= 4:
return image, modesBySize[image.shape[2] - 1]
if (simplejpeg and isinstance(image, bytes) and image[:3] == b'\xff\xd8\xff' and
b'\xff\xc0' in image[:1024]):
idx = image.index(b'\xff\xc0')
if image[idx + 9:idx + 10] in {b'\x01', b'\x03'}:
try:
image = simplejpeg.decode_jpeg(
image, colorspace='GRAY' if image[idx + 9:idx + 10] == b'\x01' else 'RGB')
except Exception:
pass
if not isinstance(image, np.ndarray):
if not isinstance(image, PIL.Image.Image):
image = PIL.Image.open(io.BytesIO(image))
Expand All @@ -232,7 +244,8 @@ def _imageToNumpy(image):
image = np.asarray(image)
else:
if len(image.shape) == 3:
mode = ['L', 'LA', 'RGB', 'RGBA'][(image.shape[2] - 1) if image.shape[2] <= 4 else 3]
mode = modesBySize[(image.shape[2] - 1) if image.shape[2] <= 4 else 3]
return image, mode
else:
mode = 'L'
if len(image.shape) == 2:
Expand Down
2 changes: 1 addition & 1 deletion sources/dicom/large_image_source_dicom/dicom_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def extract_specimen_metadata(dataset):
for prep in getattr(specimen, 'SpecimenPreparationSequence', []):
steps = {}
for step in getattr(prep, 'SpecimenPreparationStepContentItemSequence', []):
# Only extract entires that have both a name and a value
# Only extract entries that have both a name and a value
if (len(getattr(step, 'ConceptCodeSequence', [])) > 0 and
len(getattr(step, 'ConceptNameCodeSequence', [])) > 0):
name = step.ConceptNameCodeSequence[0].CodeMeaning
Expand Down
1 change: 1 addition & 0 deletions sources/multi/large_image_source_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ def _addSourceToTile(self, tile, sourceEntry, corners, scale):
x = y = 0
# If there is no transform or the diagonals are positive and there is
# no sheer, use getRegion with an appropriate size (be wary of edges)
# TODO: when affine is generalized, only use this if scale is 1
if (transform is None or
transform[0][0] > 0 and transform[0][1] == 0 and
transform[1][0] == 0 and transform[1][1] > 0):
Expand Down

0 comments on commit 29d8204

Please sign in to comment.