Skip to content

Commit

Permalink
Limit the range of tile sizes the openjpeg source can produce.
Browse files Browse the repository at this point in the history
Tiles that are too large or small are inefficient.

For the Leaflet and SlideAtlas viewers, show an error if the tile size
is larger than 256, as neither of those viewers works properly in that
case.
  • Loading branch information
manthey committed Oct 8, 2019
1 parent 6357f70 commit e621dcc
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
25 changes: 24 additions & 1 deletion server/tilesource/openjpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class OpenjpegFileTileSource(FileTileSource):
}
_xmlTag = b'mxl '

_minTileSize = 256
_maxTileSize = 512

def __init__(self, path, **kwargs):
"""
Initialize the tile class. See the base class for other available
Expand All @@ -99,10 +102,24 @@ def __init__(self, path, **kwargs):
except IndexError:
raise TileSourceException('File cannot be opened via Glymur and OpenJPEG.')
self.levels = self._openjpeg.codestream.segment[2].num_res + 1
self._minlevel = 0
self.tileWidth = self.tileHeight = 2 ** int(math.ceil(max(
math.log(float(self.sizeX)) / math.log(2) - self.levels + 1,
math.log(float(self.sizeY)) / math.log(2) - self.levels + 1)))
# read associated images and metadata from boxes
# Small and large tiles are both inefficient. Large tiles don't work
# with some viewers (leaflet and Slide Atlas, for instance)
if self.tileWidth < self._minTileSize or self.tileWidth > self._maxTileSize:
self.tileWidth = self.tileHeight = min(
self._maxTileSize, max(self._minTileSize, self.tileWidth))
self.levels = math.ceil(math.log(float(max(
self.sizeX, self.sizeY)) / self.tileWidth) / math.log(2)) + 1
self._minlevel = self.levels - self._openjpeg.codestream.segment[2].num_res - 1
self._getAssociatedImages()

def _getAssociatedImages(self):
"""
Read associated images and metadata from boxes.
"""
self._associatedImages = {}
for box in self._openjpeg.box:
if box.box_id == self._xmlTag or box.box_id in self._boxToTag:
Expand Down Expand Up @@ -203,6 +220,10 @@ def getTile(self, x, y, z, pilImageAllowed=False, **kwargs):
raise TileSourceException('x is outside layer')
if y < 0 or y0 >= self.sizeY:
raise TileSourceException('y is outside layer')
scale = None
if z < self._minlevel:
scale = 2 ** (self._minlevel - z)
step = 2 ** (self.levels - 1 - self._minlevel)
# possible open the file multiple times so multiple threads can access
# it concurrently.
with self._openjpegLock:
Expand All @@ -218,6 +239,8 @@ def getTile(self, x, y, z, pilImageAllowed=False, **kwargs):
if len(tile.shape) == 3:
mode = ['L', 'LA', 'RGB', 'RGBA'][tile.shape[2] - 1]
tile = PIL.Image.frombytes(mode, (tile.shape[1], tile.shape[0]), tile)
if scale:
tile = tile.resize((tile.size[0] // scale, tile.size[1] // scale), PIL.Image.LANCZOS)
if tile.size != (self.tileWidth, self.tileHeight):
wrap = PIL.Image.new(mode, (self.tileWidth, self.tileHeight))
wrap.paste(tile, (0, 0))
Expand Down
11 changes: 10 additions & 1 deletion web_client/views/imageViewerWidget/leaflet.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var LeafletImageViewerWidget = ImageViewerWidget.extend({
},

render: function () {
var errmsg;
// If script or metadata isn't loaded, then abort
if (!window.L || !this.tileWidth || !this.tileHeight || this.deleted) {
return this;
Expand All @@ -34,7 +35,15 @@ var LeafletImageViewerWidget = ImageViewerWidget.extend({
}

if (this.tileWidth !== this.tileHeight) {
console.error('The Leaflet viewer only supports square tiles.');
errmsg = 'The Leaflet viewer only supports square tiles.';
}
if (this.tileWidth > 256) {
errmsg = 'The Leaflet viewer does not support tiles wider than 256 pixels.';
}
if (errmsg) {
this.viewer = $('<div/>').text(errmsg);
this.$el.append(this.viewer);
console.error(errmsg);
return this;
}

Expand Down
11 changes: 10 additions & 1 deletion web_client/views/imageViewerWidget/slideatlas.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var SlideAtlasImageViewerWidget = ImageViewerWidget.extend({
},

render: function () {
var errmsg;
// If script or metadata isn't loaded, then abort
if (!window.SA || !this.tileWidth || !this.tileHeight || this.deleted) {
return this;
Expand All @@ -36,7 +37,15 @@ var SlideAtlasImageViewerWidget = ImageViewerWidget.extend({
}

if (this.tileWidth !== this.tileHeight) {
console.error('The SlideAtlas viewer only supports square tiles.');
errmsg = 'The SlideAtlas viewer only supports square tiles.';
}
if (this.tileWidth > 256) {
errmsg = 'The SlideAtlas viewer does not support tiles wider than 256 pixels.';
}
if (errmsg) {
this.viewer = $('<div/>').text(errmsg);
this.$el.append(this.viewer);
console.error(errmsg);
return this;
}

Expand Down

0 comments on commit e621dcc

Please sign in to comment.