Merge pull request #2387 from schuefflerlab/BestTiles

Introduced option maxTilesPerFrame
This commit is contained in:
Ian Gilman 2023-08-08 09:25:17 -07:00 committed by GitHub
commit cca81a37d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 24 deletions

View File

@ -290,6 +290,12 @@
* @property {Number} [rotationIncrement=90] * @property {Number} [rotationIncrement=90]
* The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated. * The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated.
* *
* @property {Number} [maxTilesPerFrame=1]
* The number of tiles loaded per frame. As the frame rate of the client's machine is usually high (e.g., 50 fps),
* one tile per frame should be a good choice. However, for large screens or lower frame rates, the number of
* loaded tiles per frame can be adjusted here. Reasonable values might be 2 or 3 tiles per frame.
* (Note that the actual frame rate is given by the client's browser and machine).
*
* @property {Number} [pixelsPerWheelLine=40] * @property {Number} [pixelsPerWheelLine=40]
* For pixel-resolution scrolling devices, the number of pixels equal to one scroll line. * For pixel-resolution scrolling devices, the number of pixels equal to one scroll line.
* *
@ -1288,6 +1294,7 @@ function OpenSeadragon( options ){
preserveImageSizeOnResize: false, // requires autoResize=true preserveImageSizeOnResize: false, // requires autoResize=true
minScrollDeltaTime: 50, minScrollDeltaTime: 50,
rotationIncrement: 90, rotationIncrement: 90,
maxTilesPerFrame: 1,
//DEFAULT CONTROL SETTINGS //DEFAULT CONTROL SETTINGS
showSequenceControl: true, //SEQUENCE showSequenceControl: true, //SEQUENCE

View File

@ -182,7 +182,8 @@ $.TiledImage = function( options ) {
opacity: $.DEFAULT_SETTINGS.opacity, opacity: $.DEFAULT_SETTINGS.opacity,
preload: $.DEFAULT_SETTINGS.preload, preload: $.DEFAULT_SETTINGS.preload,
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation, compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency,
maxTilesPerFrame: $.DEFAULT_SETTINGS.maxTilesPerFrame
}, options ); }, options );
this._preload = this.preload; this._preload = this.preload;
@ -1208,7 +1209,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
var levelsInterval = this._getLevelsInterval(); var levelsInterval = this._getLevelsInterval();
var lowestLevel = levelsInterval.lowestLevel; var lowestLevel = levelsInterval.lowestLevel;
var highestLevel = levelsInterval.highestLevel; var highestLevel = levelsInterval.highestLevel;
var bestTile = null; var bestTiles = [];
var haveDrawn = false; var haveDrawn = false;
var currentTime = $.now(); var currentTime = $.now();
@ -1253,7 +1254,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
); );
// Update the level and keep track of 'best' tile to load // Update the level and keep track of 'best' tile to load
bestTile = this._updateLevel( bestTiles = this._updateLevel(
haveDrawn, haveDrawn,
drawLevel, drawLevel,
level, level,
@ -1261,7 +1262,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
levelVisibility, levelVisibility,
drawArea, drawArea,
currentTime, currentTime,
bestTile bestTiles
); );
// Stop the loop if lower-res tiles would all be covered by // Stop the loop if lower-res tiles would all be covered by
@ -1274,9 +1275,13 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
// Perform the actual drawing // Perform the actual drawing
this._drawTiles(this.lastDrawn); this._drawTiles(this.lastDrawn);
// Load the new 'best' tile // Load the new 'best' n tiles
if (bestTile && !bestTile.context2D) { if (bestTiles && bestTiles.length > 0) {
this._loadTile(bestTile, currentTime); bestTiles.forEach(function (tile) {
if (tile && !tile.context2D) {
this._loadTile(tile, currentTime);
}
}, this);
this._needsDraw = true; this._needsDraw = true;
this._setFullyLoaded(false); this._setFullyLoaded(false);
} else { } else {
@ -1335,7 +1340,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @param {Number} levelVisibility * @param {Number} levelVisibility
* @param {OpenSeadragon.Rect} drawArea * @param {OpenSeadragon.Rect} drawArea
* @param {Number} currentTime * @param {Number} currentTime
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw. * @param {OpenSeadragon.Tile[]} best - The current "best" n tiles to draw.
*/ */
_updateLevel: function(haveDrawn, drawLevel, level, levelOpacity, _updateLevel: function(haveDrawn, drawLevel, level, levelOpacity,
levelVisibility, drawArea, currentTime, best) { levelVisibility, drawArea, currentTime, best) {
@ -1360,7 +1365,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @property {Object} topleft deprecated, use drawArea instead * @property {Object} topleft deprecated, use drawArea instead
* @property {Object} bottomright deprecated, use drawArea instead * @property {Object} bottomright deprecated, use drawArea instead
* @property {Object} currenttime * @property {Object} currenttime
* @property {Object} best * @property {Object[]} best
* @property {?Object} userData - Arbitrary subscriber-defined object. * @property {?Object} userData - Arbitrary subscriber-defined object.
*/ */
this.viewer.raiseEvent('update-level', { this.viewer.raiseEvent('update-level', {
@ -1449,7 +1454,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
* @param {OpenSeadragon.Point} viewportCenter * @param {OpenSeadragon.Point} viewportCenter
* @param {Number} numberOfTiles * @param {Number} numberOfTiles
* @param {Number} currentTime * @param {Number} currentTime
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw. * @param {OpenSeadragon.Tile[]} best - The current "best" tiles to draw.
*/ */
_updateTile: function( haveDrawn, drawLevel, x, y, level, levelOpacity, _updateTile: function( haveDrawn, drawLevel, x, y, level, levelOpacity,
levelVisibility, viewportCenter, numberOfTiles, currentTime, best){ levelVisibility, viewportCenter, numberOfTiles, currentTime, best){
@ -1538,7 +1543,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
// the tile is already in the download queue // the tile is already in the download queue
this._tilesLoading++; this._tilesLoading++;
} else if (!loadingCoverage) { } else if (!loadingCoverage) {
best = this._compareTiles( best, tile ); best = this._compareTiles( best, tile, this.maxTilesPerFrame );
} }
return best; return best;
@ -1912,28 +1917,49 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
/** /**
* @private * @private
* @inner * @inner
* Determines whether the 'last best' tile for the area is better than the * Determines the 'best tiles' from the given 'last best' tiles and the
* tile in question. * tile in question.
* *
* @param {OpenSeadragon.Tile} previousBest * @param {OpenSeadragon.Tile[]} previousBest The best tiles so far.
* @param {OpenSeadragon.Tile} tile * @param {OpenSeadragon.Tile} tile The new tile to consider.
* @returns {OpenSeadragon.Tile} The new best tile. * @param {Number} maxNTiles The max number of best tiles.
* @returns {OpenSeadragon.Tile[]} The new best tiles.
*/ */
_compareTiles: function( previousBest, tile ) { _compareTiles: function( previousBest, tile, maxNTiles ) {
if ( !previousBest ) { if ( !previousBest ) {
return tile; return [tile];
} }
previousBest.push(tile);
if ( tile.visibility > previousBest.visibility ) { this._sortTiles(previousBest);
return tile; if (previousBest.length > maxNTiles) {
} else if ( tile.visibility === previousBest.visibility ) { previousBest.pop();
if ( tile.squaredDistance < previousBest.squaredDistance ) {
return tile;
}
} }
return previousBest; return previousBest;
}, },
/**
* @private
* @inner
* Sorts tiles in an array according to distance and visibility.
*
* @param {OpenSeadragon.Tile[]} tiles The tiles.
*/
_sortTiles: function( tiles ) {
tiles.sort(function (a, b) {
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}
if (a.visibility === b.visibility) {
return (a.squaredDistance - b.squaredDistance);
} else {
return (a.visibility - b.visibility);
}
});
},
/** /**
* @private * @private
* @inner * @inner

View File

@ -1604,6 +1604,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
minZoomImageRatio: _this.minZoomImageRatio, minZoomImageRatio: _this.minZoomImageRatio,
wrapHorizontal: _this.wrapHorizontal, wrapHorizontal: _this.wrapHorizontal,
wrapVertical: _this.wrapVertical, wrapVertical: _this.wrapVertical,
maxTilesPerFrame: _this.maxTilesPerFrame,
immediateRender: _this.immediateRender, immediateRender: _this.immediateRender,
blendTime: _this.blendTime, blendTime: _this.blendTime,
alwaysBlend: _this.alwaysBlend, alwaysBlend: _this.alwaysBlend,

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>OpenSeadragon Zoomify Demo</title>
<script type="text/javascript" src='../../build/openseadragon/openseadragon.js'></script>
<script type="text/javascript" src='../lib/jquery-1.9.1.min.js'></script>
<style type="text/css">
.openseadragon1 {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div>
Simple demo page to show a default OpenSeadragon viewer with a Zoomify tile source.
</div>
<div id="contentDiv" class="openseadragon1"></div>
<script type="text/javascript">
var viewer = OpenSeadragon({
debugMode: true,
id: "contentDiv",
prefixUrl: "../../build/openseadragon/images/",
tileSources: "https://openseadragon.github.io/example-images/duomo/duomo.dzi",
showNavigator:true,
debugMode:true,
maxTilesPerFrame:3,
});
</script>
</body>
</html>