Refactor IIIFInfo and add tests
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ const layer = new TileLayer(),
|
|||||||
function refreshMap(imageInfoUrl) {
|
function refreshMap(imageInfoUrl) {
|
||||||
fetch(imageInfoUrl).then(function(response) {
|
fetch(imageInfoUrl).then(function(response) {
|
||||||
response.json().then(function(imageInfo) {
|
response.json().then(function(imageInfo) {
|
||||||
const options = new IIIFInfo().readOptionsFromJson(imageInfo);
|
const options = new IIIFInfo(imageInfo).getTileSourceOptions();
|
||||||
if (options === undefined || options.version === undefined) {
|
if (options === undefined || options.version === undefined) {
|
||||||
notifyDiv.textContent = 'Data seems to be no valid IIIF image information.';
|
notifyDiv.textContent = 'Data seems to be no valid IIIF image information.';
|
||||||
return;
|
return;
|
||||||
|
|||||||
+259
-182
@@ -13,11 +13,19 @@ import {assert} from '../asserts.js';
|
|||||||
* indicates support for that quality.
|
* indicates support for that quality.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SupportedFeatures
|
||||||
|
* @property {Array<string>} [supports] Supported IIIF image size and region
|
||||||
|
* calculation features.
|
||||||
|
* @property {Array<string>} [formats] Supported image formats.
|
||||||
|
* @property {Array<string>} [qualities] Supported IIIF image qualities.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported image formats, qualities and supported region / size calculation features
|
* Supported image formats, qualities and supported region / size calculation features
|
||||||
* for different image API versions and compliance levels
|
* for different image API versions and compliance levels
|
||||||
* @const
|
* @const
|
||||||
* @type {Object<string, Object<string, Array<string>>>}
|
* @type {Object<string, Object<string, SupportedFeatures>}
|
||||||
*/
|
*/
|
||||||
const IIIF_PROFILE_VALUES = {
|
const IIIF_PROFILE_VALUES = {
|
||||||
version1: {
|
version1: {
|
||||||
@@ -90,178 +98,9 @@ export const Versions = {
|
|||||||
VERSION3: 'version3'
|
VERSION3: 'version3'
|
||||||
};
|
};
|
||||||
|
|
||||||
function getComplianceLevelOfImageInfoForVersion(imageInfo, version) {
|
const COMPLIANCE_VERSION1 = new RegExp('^https?\:\/\/library\.stanford\.edu\/iiif\/image-api\/(1\.1\/)?compliance\.html#level[0-2]$');
|
||||||
switch (version) {
|
const COMPLIANCE_VERSION2 = new RegExp('^https?\:\/\/iiif\.io\/api\/image\/2\/level[0-2](\.json)?$');
|
||||||
case Versions.VERSION1:
|
const COMPLIANCE_VERSION3 = new RegExp('(^https?\:\/\/iiif\.io\/api\/image\/3\/level[0-2](\.json)?$)|(^level[0-2]$)');
|
||||||
case Versions.VERSION3:
|
|
||||||
return imageInfo.profile;
|
|
||||||
case Versions.VERSION2:
|
|
||||||
if (typeof imageInfo.profile === 'string') {
|
|
||||||
return imageInfo.profile;
|
|
||||||
}
|
|
||||||
if (Array.isArray(imageInfo.profile) && imageInfo.profile.length > 0
|
|
||||||
&& typeof imageInfo.profile[0] === 'string') {
|
|
||||||
return imageInfo.profile[0];
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVersionOfImageInfo(imageInfo) {
|
|
||||||
const context = imageInfo['@context'] || undefined;
|
|
||||||
switch (context) {
|
|
||||||
case 'http://library.stanford.edu/iiif/image-api/1.1/context.json':
|
|
||||||
case 'http://iiif.io/api/image/1/context.json':
|
|
||||||
return Versions.VERSION1;
|
|
||||||
case 'http://iiif.io/api/image/2/context.json':
|
|
||||||
return Versions.VERSION2;
|
|
||||||
case 'http://iiif.io/api/image/3/context.json':
|
|
||||||
return Versions.VERSION3;
|
|
||||||
case undefined:
|
|
||||||
// Image API 1.0 has no '@context'
|
|
||||||
if (getComplianceLevelOfImageInfoForVersion(imageInfo, Versions.VERSION1)) {
|
|
||||||
return Versions.VERSION1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
assert(false, 61);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLevelProfileForImageInfo(imageInfo) {
|
|
||||||
const version = getVersionOfImageInfo(imageInfo),
|
|
||||||
complianceLevel = getComplianceLevelOfImageInfoForVersion(imageInfo, version);
|
|
||||||
let level;
|
|
||||||
if (version === undefined || complianceLevel === undefined) {
|
|
||||||
return IIIF_PROFILE_VALUES.none;
|
|
||||||
}
|
|
||||||
level = complianceLevel.match(/level[0-2](\.json)?$/g);
|
|
||||||
level = Array.isArray(level) ? level[0].replace('.json', '') : 'none';
|
|
||||||
return IIIF_PROFILE_VALUES[version][level];
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateVersion1Options(imageInfo) {
|
|
||||||
const levelProfile = getLevelProfileForImageInfo(imageInfo);
|
|
||||||
return {
|
|
||||||
url: imageInfo['@id'].replace(/\/?(info.json)?$/g, ''),
|
|
||||||
supports: levelProfile.supports,
|
|
||||||
formats: [...levelProfile.formats, imageInfo.formats === undefined ?
|
|
||||||
[] : imageInfo.formats
|
|
||||||
],
|
|
||||||
qualities: [...levelProfile.qualities, imageInfo.qualities === undefined ?
|
|
||||||
[] : imageInfo.qualities
|
|
||||||
],
|
|
||||||
resolutions: imageInfo.scale_factors,
|
|
||||||
tileSize: imageInfo.tile_width !== undefined ? imageInfo.tile_height != undefined ?
|
|
||||||
[imageInfo.tile_width, imageInfo.tile_height] : [imageInfo.tile_width, imageInfo.tile_width] :
|
|
||||||
imageInfo.tile_height != undefined ? [imageInfo.tile_height, imageInfo.tile_height] : undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateVersion2Options(imageInfo) {
|
|
||||||
const levelProfile = getLevelProfileForImageInfo(imageInfo),
|
|
||||||
additionalProfile = Array.isArray(imageInfo.profile) && imageInfo.profile.length > 1,
|
|
||||||
profileSupports = additionalProfile && imageInfo.profile[1].supports ? imageInfo.profile[1].supports : [],
|
|
||||||
profileFormats = additionalProfile && imageInfo.profile[1].formats ? imageInfo.profile[1].formats : [],
|
|
||||||
profileQualities = additionalProfile && imageInfo.profile[1].qualities ? imageInfo.profile[1].qualities : [],
|
|
||||||
attributions = [];
|
|
||||||
if (imageInfo.attribution !== undefined) {
|
|
||||||
// TODO potentially dangerous
|
|
||||||
attributions.push(imageInfo.attribution);
|
|
||||||
}
|
|
||||||
if (imageInfo.license !== undefined) {
|
|
||||||
let license = imageInfo.license;
|
|
||||||
if (license.match(/^http(s)?:\/\//g)) {
|
|
||||||
license = '<a href="' + encodeURI(license) + '"/>' + encodeURI(license) + '</a>';
|
|
||||||
}
|
|
||||||
// TODO potentially dangerous
|
|
||||||
attributions.push(license);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
url: imageInfo['@id'].replace(/\/?(info.json)?$/g, ''),
|
|
||||||
sizes: imageInfo.sizes === undefined ? undefined : imageInfo.sizes.map(function(size) {
|
|
||||||
return [size.width, size.height];
|
|
||||||
}),
|
|
||||||
tileSize: imageInfo.tiles === undefined ? undefined : [
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.width;
|
|
||||||
})[0],
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.height;
|
|
||||||
})[0]
|
|
||||||
],
|
|
||||||
resolutions: imageInfo.tiles === undefined ? undefined :
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.scaleFactors;
|
|
||||||
})[0],
|
|
||||||
supports: [...levelProfile.supports, ...profileSupports],
|
|
||||||
formats: [...levelProfile.formats, ...profileFormats],
|
|
||||||
qualities: [...levelProfile.qualities, ...profileQualities],
|
|
||||||
attributions: attributions.length == 0 ? undefined : attributions
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateVersion3Options(imageInfo) {
|
|
||||||
const levelProfile = getLevelProfileForImageInfo(imageInfo);
|
|
||||||
return {
|
|
||||||
url: imageInfo['id'],
|
|
||||||
sizes: imageInfo.sizes === undefined ? undefined : imageInfo.sizes.map(function(size) {
|
|
||||||
return [size.width, size.height];
|
|
||||||
}),
|
|
||||||
tileSize: imageInfo.tiles === undefined ? undefined : [
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.width;
|
|
||||||
})[0],
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.height;
|
|
||||||
})[0]
|
|
||||||
],
|
|
||||||
resolutions: imageInfo.tiles === undefined ? undefined :
|
|
||||||
imageInfo.tiles.map(function(tile) {
|
|
||||||
return tile.scaleFactors;
|
|
||||||
})[0],
|
|
||||||
supports: imageInfo.extraFeatures === undefined ? levelProfile.supports :
|
|
||||||
[...levelProfile.supports, ...imageInfo.extraFeatures],
|
|
||||||
formats: imageInfo.extraFormats === undefined ? levelProfile.formats :
|
|
||||||
[...levelProfile.formats, ...imageInfo.extraFormats],
|
|
||||||
qualities: imageInfo.extraQualities === undefined ? levelProfile.qualities :
|
|
||||||
[...levelProfile.extraQualities, ...imageInfo.extraQualities],
|
|
||||||
maxWidth: undefined,
|
|
||||||
maxHeight: undefined,
|
|
||||||
maxArea: undefined,
|
|
||||||
attributions: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionFunctions = {};
|
|
||||||
versionFunctions[Versions.VERSION1] = generateVersion1Options;
|
|
||||||
versionFunctions[Versions.VERSION2] = generateVersion2Options;
|
|
||||||
versionFunctions[Versions.VERSION3] = generateVersion3Options;
|
|
||||||
|
|
||||||
function getOptionsForImageInformation(imageInfo, preferredOptions) {
|
|
||||||
const options = preferredOptions || {},
|
|
||||||
version = getVersionOfImageInfo(imageInfo),
|
|
||||||
imageOptions = version === undefined ? undefined : versionFunctions[version](imageInfo);
|
|
||||||
if (imageOptions === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
url: imageOptions.url,
|
|
||||||
version: version,
|
|
||||||
size: [imageInfo.width, imageInfo.height],
|
|
||||||
sizes: imageOptions.sizes,
|
|
||||||
format: imageOptions.formats.includes(options.format) ? options.format : 'jpg',
|
|
||||||
supports: imageOptions.supports,
|
|
||||||
quality: options.quality && imageOptions.qualities.includes(options.quality) ?
|
|
||||||
options.quality : imageOptions.qualities.includes('native') ? 'native' : 'default',
|
|
||||||
resolutions: Array.isArray(imageOptions.resolutions) ? imageOptions.resolutions.sort(function(a, b) {
|
|
||||||
return b - a;
|
|
||||||
}) : undefined,
|
|
||||||
tileSize: imageOptions.tileSize,
|
|
||||||
attributions: imageOptions.attributions
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
@@ -270,25 +109,263 @@ function getOptionsForImageInformation(imageInfo, preferredOptions) {
|
|||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
// TODO at the moment, this does not need to be a class.
|
|
||||||
class IIIFInfo {
|
class IIIFInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} imageInfo Deserialized image information JSON response object
|
* @param {Object|string} imageInfo Deserialized image information JSON response
|
||||||
* @param {PreferredOptions} opt_preferredOptions Optional options for preferred format and quality.
|
* object or JSON response as string
|
||||||
* @returns {import("../source/IIIF.js").Options} IIIF tile source ready constructor options.
|
|
||||||
*/
|
*/
|
||||||
readOptionsFromJson(imageInfo, opt_preferredOptions) {
|
constructor(imageInfo) {
|
||||||
return getOptionsForImageInformation(imageInfo, opt_preferredOptions);
|
this.setImageInfo(imageInfo);
|
||||||
|
this.versionFunctions = {};
|
||||||
|
this.versionFunctions[Versions.VERSION1] = this.generateVersion1Options.bind(this);
|
||||||
|
this.versionFunctions[Versions.VERSION2] = this.generateVersion2Options.bind(this);
|
||||||
|
this.versionFunctions[Versions.VERSION3] = this.generateVersion3Options.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object|string} imageInfo Deserialized image information JSON response
|
||||||
|
* object or JSON response as string
|
||||||
|
*/
|
||||||
|
setImageInfo(imageInfo) {
|
||||||
|
if (typeof imageInfo == 'string') {
|
||||||
|
this.imageInfo = JSON.parse(imageInfo);
|
||||||
|
} else {
|
||||||
|
this.imageInfo = imageInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Versions} Major IIIF version.
|
||||||
|
*/
|
||||||
|
getImageApiVersion() {
|
||||||
|
if (this.imageInfo === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const context = this.imageInfo['@context'] || undefined;
|
||||||
|
switch (context) {
|
||||||
|
case 'http://library.stanford.edu/iiif/image-api/1.1/context.json':
|
||||||
|
case 'http://iiif.io/api/image/1/context.json':
|
||||||
|
return Versions.VERSION1;
|
||||||
|
case 'http://iiif.io/api/image/2/context.json':
|
||||||
|
return Versions.VERSION2;
|
||||||
|
case 'http://iiif.io/api/image/3/context.json':
|
||||||
|
return Versions.VERSION3;
|
||||||
|
case undefined:
|
||||||
|
// Image API 1.0 has no '@context'
|
||||||
|
if (this.getComplianceLevelEntryFromProfile(Versions.VERSION1) && this.imageInfo.identifier) {
|
||||||
|
return Versions.VERSION1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
assert(false, 61);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Versions} version Optional IIIF image API version
|
||||||
|
* @returns {string} Compliance level as it appears in the IIIF image information
|
||||||
|
* response.
|
||||||
|
*/
|
||||||
|
getComplianceLevelEntryFromProfile(version) {
|
||||||
|
if (this.imageInfo === undefined || this.imageInfo.profile === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (version === undefined) {
|
||||||
|
version = this.getImageApiVersion();
|
||||||
|
}
|
||||||
|
switch (version) {
|
||||||
|
case Versions.VERSION1:
|
||||||
|
if (COMPLIANCE_VERSION1.test(this.imageInfo.profile)) {
|
||||||
|
return this.imageInfo.profile;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Versions.VERSION3:
|
||||||
|
if (COMPLIANCE_VERSION3.test(this.imageInfo.profile)) {
|
||||||
|
return this.imageInfo.profile;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Versions.VERSION2:
|
||||||
|
if (typeof this.imageInfo.profile === 'string' && COMPLIANCE_VERSION2.test(this.imageInfo.profile)) {
|
||||||
|
return this.imageInfo.profile;
|
||||||
|
}
|
||||||
|
if (Array.isArray(this.imageInfo.profile) && this.imageInfo.profile.length > 0
|
||||||
|
&& typeof this.imageInfo.profile[0] === 'string' && COMPLIANCE_VERSION2.test(this.imageInfo.profile[0])) {
|
||||||
|
return this.imageInfo.profile[0];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Versions} version Optional IIIF image API version
|
||||||
|
* @returns {string} Compliance level, on of 'level0', 'level1' or 'level2' or undefined
|
||||||
|
*/
|
||||||
|
getComplianceLevelFromProfile(version) {
|
||||||
|
const complianceLevel = this.getComplianceLevelEntryFromProfile(version);
|
||||||
|
if (complianceLevel === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const level = complianceLevel.match(/level[0-2](\.json)?$/g);
|
||||||
|
return Array.isArray(level) ? level[0].replace('.json', '') : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {SupportedFeatures} Image formats, qualities and region / size calculation
|
||||||
|
* methods that are supported by the IIIF service.
|
||||||
|
*/
|
||||||
|
getComplianceLevelSupportedFeatures() {
|
||||||
|
if (this.imageInfo === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const version = this.getImageApiVersion();
|
||||||
|
const level = this.getComplianceLevelFromProfile(version);
|
||||||
|
if (level === undefined) {
|
||||||
|
return IIIF_PROFILE_VALUES.none;
|
||||||
|
}
|
||||||
|
return IIIF_PROFILE_VALUES[version][level];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} imageInfo Image information JSON response as string serialization.
|
|
||||||
* @param {PreferredOptions} opt_preferredOptions Optional options for preferred format and quality.
|
* @param {PreferredOptions} opt_preferredOptions Optional options for preferred format and quality.
|
||||||
* @returns {import("../source/IIIF.js").Options} IIIF tile source ready constructor options.
|
* @returns {import("../source/IIIF.js").Options} IIIF tile source ready constructor options.
|
||||||
*/
|
*/
|
||||||
readOptionsFromJsonString(imageInfo, opt_preferredOptions) {
|
getTileSourceOptions(opt_preferredOptions) {
|
||||||
return getOptionsForImageInformation(JSON.parse(imageInfo), opt_preferredOptions);
|
const options = opt_preferredOptions || {},
|
||||||
|
version = this.getImageApiVersion();
|
||||||
|
if (version === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const imageOptions = version === undefined ? undefined : this.versionFunctions[version]();
|
||||||
|
if (imageOptions === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
url: imageOptions.url,
|
||||||
|
version: version,
|
||||||
|
size: [this.imageInfo.width, this.imageInfo.height],
|
||||||
|
sizes: imageOptions.sizes,
|
||||||
|
format: imageOptions.formats.includes(options.format) ? options.format : 'jpg',
|
||||||
|
supports: imageOptions.supports,
|
||||||
|
quality: options.quality && imageOptions.qualities.includes(options.quality) ?
|
||||||
|
options.quality : imageOptions.qualities.includes('native') ? 'native' : 'default',
|
||||||
|
resolutions: Array.isArray(imageOptions.resolutions) ? imageOptions.resolutions.sort(function(a, b) {
|
||||||
|
return b - a;
|
||||||
|
}) : undefined,
|
||||||
|
tileSize: imageOptions.tileSize,
|
||||||
|
attributions: imageOptions.attributions
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @returns {object} Available options
|
||||||
|
*/
|
||||||
|
generateVersion1Options() {
|
||||||
|
let levelProfile = this.getComplianceLevelSupportedFeatures();
|
||||||
|
// Version 1.0 and 1.1 do not require a profile.
|
||||||
|
if (levelProfile === undefined) {
|
||||||
|
levelProfile = IIIF_PROFILE_VALUES.version1.level0;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
url: this.imageInfo['@id'] === undefined ? undefined : this.imageInfo['@id'].replace(/\/?(info.json)?$/g, ''),
|
||||||
|
supports: levelProfile.supports,
|
||||||
|
formats: [...levelProfile.formats, this.imageInfo.formats === undefined ?
|
||||||
|
[] : this.imageInfo.formats
|
||||||
|
],
|
||||||
|
qualities: [...levelProfile.qualities, this.imageInfo.qualities === undefined ?
|
||||||
|
[] : this.imageInfo.qualities
|
||||||
|
],
|
||||||
|
resolutions: this.imageInfo.scale_factors,
|
||||||
|
tileSize: this.imageInfo.tile_width !== undefined ? this.imageInfo.tile_height != undefined ?
|
||||||
|
[this.imageInfo.tile_width, this.imageInfo.tile_height] : [this.imageInfo.tile_width, this.imageInfo.tile_width] :
|
||||||
|
this.imageInfo.tile_height != undefined ? [this.imageInfo.tile_height, this.imageInfo.tile_height] : undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @returns {object} Available options
|
||||||
|
*/
|
||||||
|
generateVersion2Options() {
|
||||||
|
const levelProfile = this.getComplianceLevelSupportedFeatures(),
|
||||||
|
additionalProfile = Array.isArray(this.imageInfo.profile) && this.imageInfo.profile.length > 1,
|
||||||
|
profileSupports = additionalProfile && this.imageInfo.profile[1].supports ? this.imageInfo.profile[1].supports : [],
|
||||||
|
profileFormats = additionalProfile && this.imageInfo.profile[1].formats ? this.imageInfo.profile[1].formats : [],
|
||||||
|
profileQualities = additionalProfile && this.imageInfo.profile[1].qualities ? this.imageInfo.profile[1].qualities : [],
|
||||||
|
attributions = [];
|
||||||
|
if (this.imageInfo.attribution !== undefined) {
|
||||||
|
// TODO potentially dangerous
|
||||||
|
attributions.push(this.imageInfo.attribution);
|
||||||
|
}
|
||||||
|
if (this.imageInfo.license !== undefined) {
|
||||||
|
let license = this.imageInfo.license;
|
||||||
|
if (license.match(/^http(s)?:\/\//g)) {
|
||||||
|
license = '<a href="' + encodeURI(license) + '"/>' + encodeURI(license) + '</a>';
|
||||||
|
}
|
||||||
|
// TODO potentially dangerous
|
||||||
|
attributions.push(license);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
url: this.imageInfo['@id'].replace(/\/?(info.json)?$/g, ''),
|
||||||
|
sizes: this.imageInfo.sizes === undefined ? undefined : this.imageInfo.sizes.map(function(size) {
|
||||||
|
return [size.width, size.height];
|
||||||
|
}),
|
||||||
|
tileSize: this.imageInfo.tiles === undefined ? undefined : [
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.width;
|
||||||
|
})[0],
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.height;
|
||||||
|
})[0]
|
||||||
|
],
|
||||||
|
resolutions: this.imageInfo.tiles === undefined ? undefined :
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.scaleFactors;
|
||||||
|
})[0],
|
||||||
|
supports: [...levelProfile.supports, ...profileSupports],
|
||||||
|
formats: [...levelProfile.formats, ...profileFormats],
|
||||||
|
qualities: [...levelProfile.qualities, ...profileQualities],
|
||||||
|
attributions: attributions.length == 0 ? undefined : attributions
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
* @private
|
||||||
|
* @returns {object} Available options
|
||||||
|
*/
|
||||||
|
generateVersion3Options() {
|
||||||
|
const levelProfile = this.getComplianceLevelSupportedFeatures();
|
||||||
|
return {
|
||||||
|
url: this.imageInfo['id'],
|
||||||
|
sizes: this.imageInfo.sizes === undefined ? undefined : this.imageInfo.sizes.map(function(size) {
|
||||||
|
return [size.width, size.height];
|
||||||
|
}),
|
||||||
|
tileSize: this.imageInfo.tiles === undefined ? undefined : [
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.width;
|
||||||
|
})[0],
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.height;
|
||||||
|
})[0]
|
||||||
|
],
|
||||||
|
resolutions: this.imageInfo.tiles === undefined ? undefined :
|
||||||
|
this.imageInfo.tiles.map(function(tile) {
|
||||||
|
return tile.scaleFactors;
|
||||||
|
})[0],
|
||||||
|
supports: this.imageInfo.extraFeatures === undefined ? levelProfile.supports :
|
||||||
|
[...levelProfile.supports, ...this.imageInfo.extraFeatures],
|
||||||
|
formats: this.imageInfo.extraFormats === undefined ? levelProfile.formats :
|
||||||
|
[...levelProfile.formats, ...this.imageInfo.extraFormats],
|
||||||
|
qualities: this.imageInfo.extraQualities === undefined ? levelProfile.qualities :
|
||||||
|
[...levelProfile.extraQualities, ...this.imageInfo.extraQualities],
|
||||||
|
maxWidth: undefined,
|
||||||
|
maxHeight: undefined,
|
||||||
|
maxArea: undefined,
|
||||||
|
attributions: undefined
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,278 @@
|
|||||||
|
import IIIFInfo from '../../../../src/ol/format/IIIFInfo.js';
|
||||||
|
import {Versions} from '../../../../src/ol/format/IIIFInfo.js';
|
||||||
|
|
||||||
|
describe('ol.format.IIIF', function() {
|
||||||
|
|
||||||
|
const iiifInfo = new IIIFInfo(),
|
||||||
|
imageInfoVersion1_0Level0 = {
|
||||||
|
identifier: 'identifier-version-1.0',
|
||||||
|
width: 2000,
|
||||||
|
height: 1500,
|
||||||
|
profile: 'http://library.stanford.edu/iiif/image-api/compliance.html#level0'
|
||||||
|
},
|
||||||
|
imageInfoVersion2Level1 = {
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'@id': 'http://iiif.test/version2/id',
|
||||||
|
width: 2000,
|
||||||
|
height: 1500,
|
||||||
|
profile: [
|
||||||
|
'http://iiif.io/api/image/2/level1.json'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
imageInfoVersion2Level2 = {
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'@id': 'http://iiif.test/version2/id',
|
||||||
|
width: 2000,
|
||||||
|
height: 1500,
|
||||||
|
profile: [
|
||||||
|
'http://iiif.io/api/image/2/level2.json'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('constructor', function() {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setImageInfo', function() {
|
||||||
|
|
||||||
|
it('can handle image info JSON as object or as string serialization', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'@id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION3);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo('{"@context": "http://iiif.io/api/image/2/context.json","@id":"http://iiif.test/id"}');
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION2);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getImageApiVersion', function() {
|
||||||
|
|
||||||
|
it('provides the correct Image API version', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(function() {
|
||||||
|
iiifInfo.getImageApiVersion();
|
||||||
|
}).to.throwException();
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'identifier': 'http://iiif.test/id',
|
||||||
|
'profile': 'this is no valid profile'
|
||||||
|
});
|
||||||
|
expect(function() {
|
||||||
|
iiifInfo.getImageApiVersion();
|
||||||
|
}).to.throwException();
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'this is no valid context',
|
||||||
|
'@id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(function() {
|
||||||
|
iiifInfo.getImageApiVersion();
|
||||||
|
}).to.throwException();
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'identifier': 'http://iiif.test/id',
|
||||||
|
profile: 'http://library.stanford.edu/iiif/image-api/compliance.html#level0'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION1);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://library.stanford.edu/iiif/image-api/1.1/context.json',
|
||||||
|
'@id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION1);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/1/context.json',
|
||||||
|
'identifier': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION1);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'@id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION2);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'id': 'http://iiif.test/id'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getImageApiVersion()).to.be(Versions.VERSION3);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getComplianceLevelFromProfile', function() {
|
||||||
|
|
||||||
|
it('detects the correct compliance level', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'profile': 'level0'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'profile': 'http://iiif.io/api/image/level3.json'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'profile': 'level1'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'profile': 'http://iiif.io/api/image/2/level2.json'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be('level2');
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'profile': ['http://iiif.io/api/image/2/level1.json']
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be('level1');
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'profile': 'level4'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'profile': 'http://iiif.io/api/image/3/level3.json'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'profile': 'http://iiif.io/api/image/2/level1.json'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be(undefined);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'profile': 'level2'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be('level2');
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://iiif.io/api/image/3/context.json',
|
||||||
|
'profile': 'http://iiif.io/api/image/3/level1.json'
|
||||||
|
});
|
||||||
|
expect(iiifInfo.getComplianceLevelFromProfile()).to.be('level1');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getComplianceLevelSupportedFeatures', function() {
|
||||||
|
|
||||||
|
it('provides the correct features for given versions and compliance levels', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo({
|
||||||
|
'@context': 'http://library.stanford.edu/iiif/image-api/1.1/context.json',
|
||||||
|
'profile': 'http://library.stanford.edu/iiif/image-api/compliance.html#level0'
|
||||||
|
});
|
||||||
|
expect();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getTileSourceOptions', function() {
|
||||||
|
|
||||||
|
it('produces options from minimal information responses', function() {
|
||||||
|
|
||||||
|
let imageInfo = {
|
||||||
|
width: 2000,
|
||||||
|
height: 1500
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
iiifInfo.setImageInfo(imageInfo);
|
||||||
|
iiifInfo.getTileSourceOptions();
|
||||||
|
}).to.throwException();
|
||||||
|
|
||||||
|
imageInfo = {
|
||||||
|
identifier: 'id',
|
||||||
|
profile: 'http://library.stanford.edu/iiif/image-api/compliance.html#level0'
|
||||||
|
};
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo(imageInfo);
|
||||||
|
let options = iiifInfo.getTileSourceOptions(imageInfo);
|
||||||
|
|
||||||
|
expect(options).to.be.an('object');
|
||||||
|
expect(options).to.have.property('version', Versions.VERSION1);
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo(imageInfoVersion1_0Level0);
|
||||||
|
options = iiifInfo.getTileSourceOptions();
|
||||||
|
|
||||||
|
expect(options).to.not.be(undefined);
|
||||||
|
expect(options).to.not.be(null);
|
||||||
|
expect(options).to.have.property('version', Versions.VERSION1);
|
||||||
|
expect(options).to.have.property('size');
|
||||||
|
expect(options.size).to.be.an('array');
|
||||||
|
expect(options.size.length).to.be(2);
|
||||||
|
expect(options.size[0]).to.be(2000);
|
||||||
|
expect(options.size[1]).to.be(1500);
|
||||||
|
expect(options.quality).to.be('native');
|
||||||
|
expect(options.url).to.be(undefined);
|
||||||
|
expect(options.sizes).to.be(undefined);
|
||||||
|
expect(options.tileSize).to.be(undefined);
|
||||||
|
expect(options.format).to.be('jpg');
|
||||||
|
expect(options.supports).to.be.empty();
|
||||||
|
|
||||||
|
imageInfo = {
|
||||||
|
'@context': 'http://iiif.io/api/image/2/context.json',
|
||||||
|
'@id': 'http://iiif.test/version2/id'
|
||||||
|
};
|
||||||
|
iiifInfo.setImageInfo(imageInfo);
|
||||||
|
options = iiifInfo.getTileSourceOptions();
|
||||||
|
|
||||||
|
expect(options).to.be.an('object');
|
||||||
|
expect(options).to.have.property('version', Versions.VERSION2);
|
||||||
|
expect(options).to.have.property('url', 'http://iiif.test/version2/id');
|
||||||
|
expect(options).to.have.property('format', 'jpg');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses preferred options if applicable', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo(imageInfoVersion2Level2);
|
||||||
|
const options = iiifInfo.getTileSourceOptions({
|
||||||
|
quality: 'bitonal',
|
||||||
|
format: 'png'
|
||||||
|
});
|
||||||
|
expect(options).to.have.property('quality', 'bitonal');
|
||||||
|
expect(options).to.have.property('format', 'png');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores preferred options that are not supported', function() {
|
||||||
|
|
||||||
|
iiifInfo.setImageInfo(imageInfoVersion2Level1);
|
||||||
|
const options = iiifInfo.getTileSourceOptions({
|
||||||
|
quality: 'bitonal',
|
||||||
|
format: 'png'
|
||||||
|
});
|
||||||
|
expect(options).to.have.property('quality', 'default');
|
||||||
|
expect(options).to.have.property('format', 'jpg');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user