@allmaps/iiif-parser
Version:
Allmaps IIIF parser
145 lines (144 loc) • 5.73 kB
JavaScript
import { image1ProfileUriRegex, Image1ContextString, Image1ContextStringIncorrect } from '../schemas/image.1.js';
import { image2ProfileUriRegex, Image2ContextString } from '../schemas/image.2.js';
const anyRegionAndSizeFeatures = ['regionByPx', 'sizeByWh'];
function parseImage1ProfileUri(uri) {
const match = uri.match(image1ProfileUriRegex);
if (match && match.groups) {
const level = parseInt(match.groups.level);
return level;
}
}
function parseImage2ProfileUri(uri) {
const match = uri.match(image2ProfileUriRegex);
if (match && match.groups) {
const level = parseInt(match.groups.level);
return level;
}
}
function parseImage2ProfileDescription(parsedProfileDescription) {
return {
maxWidth: parsedProfileDescription?.maxWidth,
maxHeight: parsedProfileDescription?.maxHeight,
maxArea: parsedProfileDescription?.maxArea,
supportsAnyRegionAndSize: anyRegionAndSizeFeatures.every((feature) => parsedProfileDescription?.supports &&
parsedProfileDescription?.supports?.includes(feature))
};
}
export function getMajorIiifVersionFromImageService(imageService) {
if ('type' in imageService && imageService.type === 'ImageService3') {
return 3;
}
else if (('type' in imageService && imageService.type === 'ImageService2') ||
('@type' in imageService && imageService['@type'] === 'ImageService2') ||
('@context' in imageService &&
imageService['@context'] === Image2ContextString)) {
return 2;
}
else if ('@context' in imageService &&
(imageService['@context'] === Image1ContextString ||
imageService['@context'] === Image1ContextStringIncorrect)) {
return 1;
}
else if ('profile' in imageService) {
let profile;
if (Array.isArray(imageService.profile)) {
profile = imageService.profile[0];
}
else {
profile = imageService.profile;
}
if (profile.match(image1ProfileUriRegex)) {
return 1;
}
else if (profile.match(image2ProfileUriRegex)) {
return 2;
}
else {
return 3;
}
}
else {
throw new Error('Unsupported IIIF Image Service');
}
}
export function getProfileProperties(parsedImage) {
// TODO: this function is very messy and needs cleaning up.
// Probably also needs a better way to keep ImageService and ImageInfo apart.
if ('type' in parsedImage || '@type' in parsedImage) {
const profile = parsedImage.profile;
let supportsAnyRegionAndSize = false;
if (profile === 'level0' ||
(typeof profile === 'string' && profile.endsWith('level0.json'))) {
if ('extraFeatures' in parsedImage) {
supportsAnyRegionAndSize = anyRegionAndSizeFeatures.every((feature) => parsedImage.extraFeatures &&
parsedImage.extraFeatures.includes(feature));
}
}
else {
supportsAnyRegionAndSize = true;
}
return {
maxWidth: 'maxWidth' in parsedImage ? parsedImage.maxWidth : undefined,
maxHeight: 'maxHeight' in parsedImage ? parsedImage.maxHeight : undefined,
maxArea: 'maxArea' in parsedImage ? parsedImage.maxArea : undefined,
supportsAnyRegionAndSize
};
}
else if (Array.isArray(parsedImage.profile)) {
let supportsAnyRegionAndSize = false;
let maxHeight = Number.NEGATIVE_INFINITY;
let maxWidth = Number.NEGATIVE_INFINITY;
let maxArea = Number.NEGATIVE_INFINITY;
parsedImage.profile.forEach((profile) => {
if (typeof profile === 'string') {
const profileLevel = parseImage2ProfileUri(profile);
if (profileLevel) {
supportsAnyRegionAndSize =
supportsAnyRegionAndSize || profileLevel >= 1;
}
}
else {
const { maxWidth: profileMaxWidth, maxHeight: profileMaxHeight, maxArea: profileMaxArea, supportsAnyRegionAndSize: profileSupportsAnyRegionAndSize } = parseImage2ProfileDescription(profile);
if (profileMaxWidth !== undefined) {
maxWidth = Math.max(profileMaxWidth, maxWidth);
}
if (profileMaxHeight !== undefined) {
maxHeight = Math.max(profileMaxHeight, maxHeight);
}
if (profileMaxArea !== undefined) {
maxArea = Math.max(profileMaxArea, maxArea);
}
supportsAnyRegionAndSize =
supportsAnyRegionAndSize || profileSupportsAnyRegionAndSize;
}
});
return {
maxWidth: maxWidth >= 0 ? maxWidth : undefined,
maxHeight: maxHeight >= 0 ? maxHeight : undefined,
maxArea: maxArea >= 0 ? maxArea : undefined,
supportsAnyRegionAndSize
};
}
else if ('profile' in parsedImage && parsedImage.profile) {
const profileLevel1 = parseImage1ProfileUri(parsedImage.profile);
const profileLevel2 = parseImage2ProfileUri(parsedImage.profile);
if (profileLevel1) {
return {
supportsAnyRegionAndSize: profileLevel1 >= 1
};
}
else if (profileLevel2) {
return {
supportsAnyRegionAndSize: profileLevel2 >= 1
};
}
else {
return {
supportsAnyRegionAndSize: false
};
}
}
else {
throw new Error('Invalid Image');
}
}