From 8ae1edfd480b5b476cc206f797e3c86cb3eb0eb9 Mon Sep 17 00:00:00 2001 From: Lutz Helm Date: Tue, 17 Dec 2019 16:22:48 +0100 Subject: [PATCH] Add support for IIIF Image API 3.0 beta --- src/iiiftilesource.js | 76 ++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/src/iiiftilesource.js b/src/iiiftilesource.js index 49fbc1e9..33e26d72 100644 --- a/src/iiiftilesource.js +++ b/src/iiiftilesource.js @@ -59,6 +59,8 @@ $.IIIFTileSource = function( options ){ this.tileFormat = this.tileFormat || 'jpg'; + this.version = options.version; + // N.B. 2.0 renamed scale_factors to scaleFactors if ( this.tile_width && this.tile_height ) { options.tileWidth = this.tile_width; @@ -88,7 +90,7 @@ $.IIIFTileSource = function( options ){ } } } - } else if ( canBeTiled(options.profile) ) { + } else if ( canBeTiled(options) ) { // use the largest of tileOptions that is smaller than the short dimension var shortDim = Math.min( this.height, this.width ), tileOptions = [256, 512, 1024], @@ -201,11 +203,42 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea var options = configureFromXml10( data ); options['@context'] = "http://iiif.io/api/image/1.0/context.json"; options['@id'] = url.replace('/info.xml', ''); + options.version = 1; return options; } else { if ( !data['@context'] ) { data['@context'] = 'http://iiif.io/api/image/1.0/context.json'; data['@id'] = url.replace('/info.json', ''); + data.version = 1; + } else { + var context = data['@context']; + if (Array.isArray(context)) { + for (var i = 0; i < context.length; i++) { + if (typeof context[i] === 'string' && + ( /^http:\/\/iiif\.io\/api\/image\/[0-2]\/context\.json$/.test(context[i]) || + context[i] === 'http://library.stanford.edu/iiif/image-api/1.1/context.json' ) ) { + context = context[i]; + break; + } + } + } + switch (data['@context']) { + case 'http://iiif.io/api/image/1/context.json': + case 'http://library.stanford.edu/iiif/image-api/1.1/context.json': + data.version = 1; + break; + case 'http://iiif.io/api/image/2/context.json': + data.version = 2; + break; + case 'http://iiif.io/api/image/3/context.json': + data.version = 3; + break; + default: + // unexpected context + } + } + if ( !data['@id'] && data['id'] ) { + data['@id'] = data['id']; } if(data.preferredFormats) { for (var f = 0; f < data.preferredFormats.length; f++ ) { @@ -350,25 +383,22 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea iiifTileH, iiifSize, iiifSizeW, + iiifSizeH, iiifQuality, - uri, - isv1; + uri; tileWidth = this.getTileWidth(level); tileHeight = this.getTileHeight(level); iiifTileSizeWidth = Math.ceil( tileWidth / scale ); iiifTileSizeHeight = Math.ceil( tileHeight / scale ); - isv1 = ( this['@context'].indexOf('/1.0/context.json') > -1 || - this['@context'].indexOf('/1.1/context.json') > -1 || - this['@context'].indexOf('/1/context.json') > -1 ); - if (isv1) { + if (this.version === 1) { iiifQuality = "native." + this.tileFormat; } else { iiifQuality = "default." + this.tileFormat; } if ( levelWidth < tileWidth && levelHeight < tileHeight ){ - if ( isv1 || levelWidth !== this.width ) { - iiifSize = levelWidth + ","; + if ( this.version === 1 || levelWidth !== this.width ) { + iiifSize = levelWidth + "," + ( this.version === 3 ? levelHeight : "" ); } else { iiifSize = "max"; } @@ -384,10 +414,11 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea iiifRegion = [ iiifTileX, iiifTileY, iiifTileW, iiifTileH ].join( ',' ); } iiifSizeW = Math.ceil( iiifTileW * scale ); - if ( (!isv1) && iiifSizeW === this.width ) { + iiifSizeH = Math.ceil( iiifTileH * scale ); + if ( this.version !== 1 && iiifSizeW === this.width && ( this.version !== 3 || iiifSizeH === this.height ) ) { iiifSize = "max"; } else { - iiifSize = iiifSizeW + ","; + iiifSize = iiifSizeW + "," + ( this.version === 3 ? iiifSizeH : "" ); } } uri = [ this['@id'], iiifRegion, iiifSize, IIIF_ROTATION, iiifQuality ].join( '/' ); @@ -403,18 +434,23 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea * @param {array} profile - IIIF profile array * @throws {Error} */ - function canBeTiled ( profile ) { + function canBeTiled ( options ) { 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" + "http://iiif.io/api/image/2/level0.json", + "level0", + "https://iiif.io/api/image/3/level0.json" ]; - var isLevel0 = (level0Profiles.indexOf(profile[0]) !== -1); - var hasSizeByW = false; - if ( profile.length > 1 && profile[1].supports ) { - hasSizeByW = profile[1].supports.indexOf( "sizeByW" ) !== -1; + var isLevel0 = (level0Profiles.indexOf(options.profile[0]) !== -1); + var hasCanoncicalSizeFeature = false; + if ( options.version === 2 && options.profile.length > 1 && options.profile[1].supports ) { + hasCanoncicalSizeFeature = options.profile[1].supports.indexOf( "sizeByW" ) !== -1; } - return !isLevel0 || hasSizeByW; + if ( options.version === 3 && options.extraFeatures ) { + hasCanoncicalSizeFeature = options.extraFeatures.indexOf( "sizeByWh" ) !== -1; + } + return !isLevel0 || hasCanoncicalSizeFeature; } /** @@ -427,7 +463,9 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea var levels = []; for(var i = 0; i < options.sizes.length; i++) { levels.push({ - url: options['@id'] + '/full/' + options.sizes[i].width + ',/0/default.' + options.tileFormat, + url: options['@id'] + '/full/' + options.sizes[i].width + ',' + + (options.version === 3 ? options.sizes[i].height : '') + + '/0/default.' + options.tileFormat, width: options.sizes[i].width, height: options.sizes[i].height });