Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify thumbnail generation. #593

Merged
merged 1 commit into from
Apr 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions girder/test_girder/test_tiles_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,14 +836,6 @@ def testGetTileSource(server, admin, fsAssetstore):
image, mime = source.getThumbnail(encoding='JPEG', width=200)
assert image[:len(utilities.JPEGHeader)] == utilities.JPEGHeader

# Test the level0 thumbnail code path
image, mime = source.getThumbnail(
encoding='PNG', width=200, height=100, levelZero=True, fill='blue')
assert image[:len(utilities.PNGHeader)] == utilities.PNGHeader
(width, height) = struct.unpack('!LL', image[16:24])
assert width == 200
assert height == 100


@pytest.mark.usefixtures('unbindLargeImage')
@pytest.mark.plugin('large_image')
Expand Down
40 changes: 7 additions & 33 deletions large_image/tilesource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1694,17 +1694,16 @@ def getTileMimeType(self):
return TileOutputMimeTypes.get(self.encoding, 'image/jpeg')

@methodcache()
def getThumbnail(self, width=None, height=None, levelZero=False, **kwargs):
def getThumbnail(self, width=None, height=None, **kwargs):
"""
Get a basic thumbnail from the current tile source. Aspect ratio is
preserved. If neither width nor height is given, a default value is
used. If both are given, the thumbnail will be no larger than either
size.
size. A thumbnail has the same options as a region except that it
always includes the entire image and has a default size of 256 x 256.

:param width: maximum width in pixels.
:param height: maximum height in pixels.
:param levelZero: if true, always use the level zero tile. Otherwise,
the thumbnail is generated so that it is never upsampled.
:param kwargs: optional arguments. Some options are encoding,
jpegQuality, jpegSubsampling, and tiffCompression.
:returns: thumbData, thumbMime: the image data and the mime type.
Expand All @@ -1714,35 +1713,10 @@ def getThumbnail(self, width=None, height=None, levelZero=False, **kwargs):
raise ValueError('Invalid width or height. Minimum value is 2.')
if width is None and height is None:
width = height = 256
# There are two code paths for generating thumbnails. If
# alwaysUseLevelZero is True, then the the thumbnail is generated more
# swiftly, but may look poor. We may want to add a parameter for this
# option, or only use the high-quality results.
if not levelZero:
params = dict(kwargs)
params['output'] = {'maxWidth': width, 'maxHeight': height}
params.pop('region', None)
return self.getRegion(**params)
metadata = self.getMetadata()
tileData = self.getTile(0, 0, 0)
image = _imageToPIL(tileData)
imageWidth = int(math.floor(
metadata['sizeX'] * 2 ** -(metadata['levels'] - 1)))
imageHeight = int(math.floor(
metadata['sizeY'] * 2 ** -(metadata['levels'] - 1)))
image = image.crop((0, 0, imageWidth, imageHeight))

if width or height:
maxWidth, maxHeight = width, height
width, height, calcScale = self._calculateWidthHeight(
width, height, imageWidth, imageHeight)

image = image.resize(
(width, height),
PIL.Image.BICUBIC if width > imageWidth else PIL.Image.LANCZOS)
if kwargs.get('fill') and maxWidth and maxHeight:
image = _letterboxImage(image, maxWidth, maxHeight, kwargs['fill'])
return _encodeImage(image, **kwargs)
params = dict(kwargs)
params['output'] = {'maxWidth': width, 'maxHeight': height}
params.pop('region', None)
return self.getRegion(**params)

def getPreferredLevel(self, level):
"""
Expand Down
10 changes: 5 additions & 5 deletions sources/gdal/large_image_source_gdal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -879,17 +879,17 @@ def _getRegionBounds(self, metadata, left=None, top=None, right=None,
metadata, left, top, right, bottom, width, height, units, **kwargs)

@methodcache()
def getThumbnail(self, width=None, height=None, levelZero=False, **kwargs):
def getThumbnail(self, width=None, height=None, **kwargs):
"""
Get a basic thumbnail from the current tile source. Aspect ratio is
preserved. If neither width nor height is given, a default value is
used. If both are given, the thumbnail will be no larger than either
size.
size. A thumbnail has the same options as a region except that it
always includes the entire image if there is no projection and has a
default size of 256 x 256.

:param width: maximum width in pixels.
:param height: maximum height in pixels.
:param levelZero: if true, always use the level zero tile. Otherwise,
the thumbnail is generated so that it is never upsampled.
:param kwargs: optional arguments. Some options are encoding,
jpegQuality, jpegSubsampling, and tiffCompression.
:returns: thumbData, thumbMime: the image data and the mime type.
Expand All @@ -904,7 +904,7 @@ def getThumbnail(self, width=None, height=None, levelZero=False, **kwargs):
params['output'] = {'maxWidth': width, 'maxHeight': height}
params['region'] = {'units': 'projection'}
return self.getRegion(**params)
return super().getThumbnail(width, height, levelZero, **kwargs)
return super().getThumbnail(width, height, **kwargs)

def toNativePixelCoordinates(self, x, y, proj=None, roundResults=True):
"""
Expand Down