mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-22 05:06:09 +03:00
Support tile-less IIIF as per LegacyTileSource: Fix #737
This commit is contained in:
parent
0d43f7e01a
commit
f7c9585003
@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @class IIIFTileSource
|
* @class IIIFTileSource
|
||||||
* @classdesc A client implementation of the International Image Interoperability
|
* @classdesc A client implementation of the International Image Interoperability Framework
|
||||||
* Format: Image API 1.0 - 2.0
|
* Format: Image API 1.0 - 2.1
|
||||||
*
|
*
|
||||||
* @memberof OpenSeadragon
|
* @memberof OpenSeadragon
|
||||||
* @extends OpenSeadragon.TileSource
|
* @extends OpenSeadragon.TileSource
|
||||||
@ -83,7 +83,7 @@ $.IIIFTileSource = function( options ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if ( canBeTiled(options.profile) ) {
|
||||||
// use the largest of tileOptions that is smaller than the short dimension
|
// use the largest of tileOptions that is smaller than the short dimension
|
||||||
var shortDim = Math.min( this.height, this.width ),
|
var shortDim = Math.min( this.height, this.width ),
|
||||||
tileOptions = [256,512,1024],
|
tileOptions = [256,512,1024],
|
||||||
@ -101,13 +101,32 @@ $.IIIFTileSource = function( options ){
|
|||||||
// If we're smaller than 256, just use the short side.
|
// If we're smaller than 256, just use the short side.
|
||||||
options.tileSize = shortDim;
|
options.tileSize = shortDim;
|
||||||
}
|
}
|
||||||
|
} else if (this.sizes && this.sizes.length > 0) {
|
||||||
|
// This info.json can't be tiled, but we can still construct a legacy pyramid from the sizes array.
|
||||||
|
// In this mode, IIIFTileSource will call functions from the abstract baseTileSource or the
|
||||||
|
// LegacyTileSource instead of performing IIIF tiling.
|
||||||
|
this.emulateLegacyImagePyramid = true;
|
||||||
|
|
||||||
|
options.levels = constructLevels( this );
|
||||||
|
// use the largest available size to define tiles
|
||||||
|
$.extend( true, options, {
|
||||||
|
width: options.levels[ options.levels.length - 1 ].width,
|
||||||
|
height: options.levels[ options.levels.length - 1 ].height,
|
||||||
|
tileSize: Math.max( options.height, options.width ),
|
||||||
|
tileOverlap: 0,
|
||||||
|
minLevel: 0,
|
||||||
|
maxLevel: options.levels.length - 1
|
||||||
|
});
|
||||||
|
this.levels = options.levels;
|
||||||
|
} else {
|
||||||
|
$.console.error("Nothing in the info.json to construct image pyramids from");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !options.maxLevel ) {
|
if (!options.maxLevel && !this.emulateLegacyImagePyramid) {
|
||||||
if ( !this.scale_factors ) {
|
if (!this.scale_factors) {
|
||||||
options.maxLevel = Number( Math.ceil( Math.log( Math.max( this.width, this.height ), 2 ) ) );
|
options.maxLevel = Number(Math.ceil(Math.log(Math.max(this.width, this.height), 2)));
|
||||||
} else {
|
} else {
|
||||||
options.maxLevel = Math.floor( Math.pow( Math.max.apply(null, this.scale_factors), 0.5) );
|
options.maxLevel = Math.floor(Math.pow(Math.max.apply(null, this.scale_factors), 0.5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +211,11 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
* @param {Number} level
|
* @param {Number} level
|
||||||
*/
|
*/
|
||||||
getTileWidth: function( level ) {
|
getTileWidth: function( level ) {
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
return $.TileSource.prototype.getTileWidth.call(this, level);
|
||||||
|
}
|
||||||
|
|
||||||
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
||||||
|
|
||||||
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
||||||
@ -206,6 +230,11 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
* @param {Number} level
|
* @param {Number} level
|
||||||
*/
|
*/
|
||||||
getTileHeight: function( level ) {
|
getTileHeight: function( level ) {
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
return $.TileSource.prototype.getTileHeight.call(this, level);
|
||||||
|
}
|
||||||
|
|
||||||
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
||||||
|
|
||||||
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
||||||
@ -214,9 +243,61 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
return this._tileHeight;
|
return this._tileHeight;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
* @param {Number} level
|
||||||
|
*/
|
||||||
|
getLevelScale: function ( level ) {
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
var levelScale = NaN;
|
||||||
|
if (this.levels.length > 0 && level >= this.minLevel && level <= this.maxLevel) {
|
||||||
|
levelScale =
|
||||||
|
this.levels[level].width /
|
||||||
|
this.levels[this.maxLevel].width;
|
||||||
|
}
|
||||||
|
return levelScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.TileSource.prototype.getLevelScale.call(this, level);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for retreiving the url which will return an image for the
|
* @function
|
||||||
|
* @param {Number} level
|
||||||
|
*/
|
||||||
|
getNumTiles: function( level ) {
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
var scale = this.getLevelScale(level);
|
||||||
|
if (scale) {
|
||||||
|
return new $.Point(1, 1);
|
||||||
|
} else {
|
||||||
|
return new $.Point(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.TileSource.prototype.getNumTiles.call(this, level);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
* @param {Number} level
|
||||||
|
* @param {OpenSeadragon.Point} point
|
||||||
|
*/
|
||||||
|
getTileAtPoint: function( level, point ) {
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
return new $.Point(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.TileSource.prototype.getTileAtPoint.call(this, level, point);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for retrieving the url which will return an image for the
|
||||||
* region specified by the given x, y, and level components.
|
* region specified by the given x, y, and level components.
|
||||||
* @function
|
* @function
|
||||||
* @param {Number} level - z index
|
* @param {Number} level - z index
|
||||||
@ -226,6 +307,14 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
*/
|
*/
|
||||||
getTileUrl: function( level, x, y ){
|
getTileUrl: function( level, x, y ){
|
||||||
|
|
||||||
|
if(this.emulateLegacyImagePyramid) {
|
||||||
|
var url = null;
|
||||||
|
if ( this.levels.length > 0 && level >= this.minLevel && level <= this.maxLevel ) {
|
||||||
|
url = this.levels[ level ].url;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
//# constants
|
//# constants
|
||||||
var IIIF_ROTATION = '0',
|
var IIIF_ROTATION = '0',
|
||||||
//## get the scale (level as a decimal)
|
//## get the scale (level as a decimal)
|
||||||
@ -280,6 +369,40 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether arbitrary tile requests can be made against a service with the given profile
|
||||||
|
* @function
|
||||||
|
* @param {object} profile - IIIF profile object
|
||||||
|
* @throws {Error}
|
||||||
|
*/
|
||||||
|
function canBeTiled (profile ) {
|
||||||
|
var level0Profiles = [
|
||||||
|
"http://library.stanford.edu/iiif/image-api/compliance.html#level0",
|
||||||
|
"http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level0",
|
||||||
|
"http://iiif.io/api/image/2/level0.json"
|
||||||
|
];
|
||||||
|
var isLevel0 = (level0Profiles.indexOf(profile[0]) != -1);
|
||||||
|
return !isLevel0 || (profile.indexOf("sizeByW") != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the legacy pyramid URLs (one tile per level)
|
||||||
|
* @function
|
||||||
|
* @param {object} options - infoJson
|
||||||
|
* @throws {Error}
|
||||||
|
*/
|
||||||
|
function constructLevels(options) {
|
||||||
|
var levels = [];
|
||||||
|
for(var i=0; i<options.sizes.length; i++) {
|
||||||
|
levels.push({
|
||||||
|
url: options['@id'] + '/full/' + options.sizes[i].width + ',/0/default.jpg',
|
||||||
|
width: options.sizes[i].width,
|
||||||
|
height: options.sizes[i].height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return levels.sort(function(a,b){return a.width - b.width;});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function configureFromXml10(xmlDoc) {
|
function configureFromXml10(xmlDoc) {
|
||||||
//parse the xml
|
//parse the xml
|
||||||
@ -330,4 +453,5 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}( OpenSeadragon ));
|
}( OpenSeadragon ));
|
||||||
|
BIN
test/data/iiif_2_0_sizes/full/1600,/0/default.jpg
Normal file
BIN
test/data/iiif_2_0_sizes/full/1600,/0/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 208 KiB |
BIN
test/data/iiif_2_0_sizes/full/3200,/0/default.jpg
Normal file
BIN
test/data/iiif_2_0_sizes/full/3200,/0/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 678 KiB |
BIN
test/data/iiif_2_0_sizes/full/400,/0/default.jpg
Normal file
BIN
test/data/iiif_2_0_sizes/full/400,/0/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
test/data/iiif_2_0_sizes/full/6976,/0/default.jpg
Normal file
BIN
test/data/iiif_2_0_sizes/full/6976,/0/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 MiB |
BIN
test/data/iiif_2_0_sizes/full/800,/0/default.jpg
Normal file
BIN
test/data/iiif_2_0_sizes/full/800,/0/default.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
15
test/data/iiif_2_0_sizes/info.json
Normal file
15
test/data/iiif_2_0_sizes/info.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"@context": "http://iiif.io/api/image/2/context.json",
|
||||||
|
"@id": "http://localhost:8000/test/data/iiif_2_0_sizes",
|
||||||
|
"protocol": "http://iiif.io/api/image",
|
||||||
|
"width": 6976,
|
||||||
|
"height": 5074,
|
||||||
|
"profile": ["http://iiif.io/api/image/2/level0.json"],
|
||||||
|
"sizes" : [
|
||||||
|
{"width" : 400, "height" : 291},
|
||||||
|
{"width" : 800, "height" : 582},
|
||||||
|
{"width" : 1600, "height" : 1164},
|
||||||
|
{"width" : 3200, "height": 2328},
|
||||||
|
{"width" : 6976, "height": 5074}
|
||||||
|
]
|
||||||
|
}
|
51
test/demo/iiif-sizes.html
Normal file
51
test/demo/iiif-sizes.html
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenSeadragon Demo - IIIF emulation of legacy image pyramid</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: 800px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>Default OpenSeadragon viewer from IIIF Source</p>
|
||||||
|
<p>This allows IIIF even if you only have a handful of static image sizes.</p>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
legacy iiif
|
||||||
|
|
||||||
|
supports
|
||||||
|
configure
|
||||||
|
getTileWidth
|
||||||
|
getTileHeight
|
||||||
|
getLevelScale
|
||||||
|
getNumTiles
|
||||||
|
getTileAtPoint
|
||||||
|
getTileUrl getTileUrl
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<div id="contentDiv" class="openseadragon1"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var viewer = OpenSeadragon({
|
||||||
|
// debugMode: true,
|
||||||
|
id: "contentDiv",
|
||||||
|
prefixUrl: "../../build/openseadragon/images/",
|
||||||
|
tileSources: "../data/iiif_2_0_sizes/info.json",
|
||||||
|
showNavigator:true
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
34
test/demo/iiif.html
Normal file
34
test/demo/iiif.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenSeadragon Demo - IIIF Tiled</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: 800px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>Default OpenSeadragon viewer from IIIF Tile Source.</p>
|
||||||
|
<p>This depends on a remote server providing a IIIF Image API endpoint.</p>
|
||||||
|
</div>
|
||||||
|
<div id="contentDiv" class="openseadragon1"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var viewer = OpenSeadragon({
|
||||||
|
// debugMode: true,
|
||||||
|
id: "contentDiv",
|
||||||
|
prefixUrl: "../../build/openseadragon/images/",
|
||||||
|
tileSources: "http://wellcomelibrary.org/iiif-img/b11768265-0/a6801943-b8b4-4674-908c-7d5b27e70569/info.json",
|
||||||
|
showNavigator:true
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
56
test/demo/legacy.html
Normal file
56
test/demo/legacy.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OpenSeadragon Demo - Legacy image pyramid</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: 800px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
Use an array of full images at different sizes.
|
||||||
|
</div>
|
||||||
|
<div id="contentDiv" class="openseadragon1"></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var viewer = OpenSeadragon({
|
||||||
|
// debugMode: true,
|
||||||
|
id: "contentDiv",
|
||||||
|
prefixUrl: "../../build/openseadragon/images/",
|
||||||
|
tileSources: {
|
||||||
|
type: 'legacy-image-pyramid',
|
||||||
|
levels:[{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/400,/0/default.jpg',
|
||||||
|
height: 291,
|
||||||
|
width: 400
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/800,/0/default.jpg',
|
||||||
|
height: 582,
|
||||||
|
width: 800
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/1600,/0/default.jpg',
|
||||||
|
height: 1164,
|
||||||
|
width: 1600
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/3200,/0/default.jpg',
|
||||||
|
height: 2328,
|
||||||
|
width: 3200
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/6976,/0/default.jpg',
|
||||||
|
height: 5074,
|
||||||
|
width: 6976
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
showNavigator:true
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -114,6 +114,11 @@
|
|||||||
testOpenUrl('iiif_2_0_tiled/info.json');
|
testOpenUrl('iiif_2_0_tiled/info.json');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
asyncTest('IIIF 2.0 JSON, sizes array only', function() {
|
||||||
|
testOpenUrl('iiif_2_0_sizes/info.json');
|
||||||
|
});
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
asyncTest('IIIF 2.0 JSON String', function() {
|
asyncTest('IIIF 2.0 JSON String', function() {
|
||||||
testOpen(
|
testOpen(
|
||||||
@ -149,5 +154,38 @@
|
|||||||
url: "/test/data/A.png"
|
url: "/test/data/A.png"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ----------
|
||||||
|
asyncTest('Legacy Image Pyramid', function() {
|
||||||
|
// Although it is using image paths that happen to be in IIIF format, this is not a IIIFTileSource.
|
||||||
|
// The url values are opaque, just image locations.
|
||||||
|
// When emulating a legacy pyramid, IIIFTileSource calls functions from LegacyTileSource, so this
|
||||||
|
// adds a test for the legacy functionality too.
|
||||||
|
testOpen({
|
||||||
|
type: 'legacy-image-pyramid',
|
||||||
|
levels:[{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/400,/0/default.jpg',
|
||||||
|
height: 291,
|
||||||
|
width: 400
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/800,/0/default.jpg',
|
||||||
|
height: 582,
|
||||||
|
width: 800
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/1600,/0/default.jpg',
|
||||||
|
height: 1164,
|
||||||
|
width: 1600
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/3200,/0/default.jpg',
|
||||||
|
height: 2328,
|
||||||
|
width: 3200
|
||||||
|
},{
|
||||||
|
url: '/test/data/iiif_2_0_sizes/full/6976,/0/default.jpg',
|
||||||
|
height: 5074,
|
||||||
|
width: 6976
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user