mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-21 20:56: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
|
||||
* @classdesc A client implementation of the International Image Interoperability
|
||||
* Format: Image API 1.0 - 2.0
|
||||
* @classdesc A client implementation of the International Image Interoperability Framework
|
||||
* Format: Image API 1.0 - 2.1
|
||||
*
|
||||
* @memberof OpenSeadragon
|
||||
* @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
|
||||
var shortDim = Math.min( this.height, this.width ),
|
||||
tileOptions = [256,512,1024],
|
||||
@ -101,13 +101,32 @@ $.IIIFTileSource = function( options ){
|
||||
// If we're smaller than 256, just use the short side.
|
||||
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 ( !this.scale_factors ) {
|
||||
options.maxLevel = Number( Math.ceil( Math.log( Math.max( this.width, this.height ), 2 ) ) );
|
||||
if (!options.maxLevel && !this.emulateLegacyImagePyramid) {
|
||||
if (!this.scale_factors) {
|
||||
options.maxLevel = Number(Math.ceil(Math.log(Math.max(this.width, this.height), 2)));
|
||||
} 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
|
||||
*/
|
||||
getTileWidth: function( level ) {
|
||||
|
||||
if(this.emulateLegacyImagePyramid) {
|
||||
return $.TileSource.prototype.getTileWidth.call(this, level);
|
||||
}
|
||||
|
||||
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
||||
|
||||
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
||||
@ -206,6 +230,11 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
||||
* @param {Number} level
|
||||
*/
|
||||
getTileHeight: function( level ) {
|
||||
|
||||
if(this.emulateLegacyImagePyramid) {
|
||||
return $.TileSource.prototype.getTileHeight.call(this, level);
|
||||
}
|
||||
|
||||
var scaleFactor = Math.pow(2, this.maxLevel - level);
|
||||
|
||||
if (this.tileSizePerScaleFactor && this.tileSizePerScaleFactor[scaleFactor]) {
|
||||
@ -214,9 +243,61 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
||||
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.
|
||||
* @function
|
||||
* @param {Number} level - z index
|
||||
@ -226,6 +307,14 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
||||
*/
|
||||
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
|
||||
var IIIF_ROTATION = '0',
|
||||
//## 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) {
|
||||
//parse the xml
|
||||
@ -330,4 +453,5 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
||||
}
|
||||
|
||||
|
||||
|
||||
}( 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');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('IIIF 2.0 JSON, sizes array only', function() {
|
||||
testOpenUrl('iiif_2_0_sizes/info.json');
|
||||
});
|
||||
|
||||
// ----------
|
||||
asyncTest('IIIF 2.0 JSON String', function() {
|
||||
testOpen(
|
||||
@ -149,5 +154,38 @@
|
||||
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