Files
greek-manifests/src/service/ManifestBuilder.js

176 lines
4.7 KiB
JavaScript

'use strict';
import Manifest from '../iiif/Manifest.js';
import Sequence from '../iiif/Sequence.js';
import Canvas from '../iiif/Canvas.js';
import Image from '../iiif/Image.js';
import ManifestMetadata from '../iiif/Metadata.js';
import { parse, getCanvasLabel, getCanvasName } from './FilenameParser.js';
import { getImageList } from './ImageRepository.js';
import { TECH_NAMES } from '../constants.js';
/**
* Builds a manifest object based on canvases
* and available metadata
* @module ManifestBuilder
*/
const IIIF_API_VERSION = process.env.IIIF_API_VERSION;
const BASE_URL = process.env.BASE_URL;
const IMAGE_SERVER_URL = process.env.IMAGE_SERVER_URL;
/**
* Builds a Manifest object
* @param {String} manifestId
* @returns {Object}
*/
export async function buildManifest(manifestId) {
let manifest = new Manifest(IIIF_API_VERSION, BASE_URL);
manifest.generateID(manifestId);
manifest.generateLabel();
const images = await getImageList(manifestId);
manifest = await populateCanvases(manifest, images, manifestId);
manifest.setMetadata(
createMetadata(
manifest,
images[0], // A single image filename is sufficient to extract metadata
)
);
return manifest.toObject();
}
/**
* Builds a Canvas object from route parameters
* @param {String} manifestId
* @param {String} name The canvas name
*/
export async function buildCanvas(manifestId, name) {
const manifest = new Manifest(IIIF_API_VERSION, BASE_URL);
manifest.generateID(manifestId);
let filename = await getImageName(name, manifestId);
return createCanvas(manifest, filename);
}
/**
* Create a canvas from an image filename
* @param {Manifest} manifest
* @param {string} filename The image filename
* @returns {Canvas}
*/
async function createCanvas (manifest, filename) {
let canvas = new Canvas(IIIF_API_VERSION, BASE_URL);
const canvasName = getCanvasName(filename, manifest.technique);
canvas.generateID(manifest.resourceId, canvasName.toLowerCase());
canvas.label = getCanvasLabel(canvasName);
let image = new Image(canvas.id);
image.generateID(IMAGE_SERVER_URL, filename, manifest.technique);
const imgSize = await getImageSize(image.id);
image.setSize(imgSize.height, imgSize.width);
canvas.setThumbnail(
imgSize.thumb.height,
imgSize.thumb.width,
image.id
);
canvas.addImage(image);
return canvas;
}
/**
* @param {string} imageId The image's id as a URL to the image server
* @returns {{width: number, height: number, thumb: {width: number, height: number}}}
*/
async function getImageSize(imageId) {
let infoURL = imageId.replace(/full.*$/,'info.json');
const res = await fetch(infoURL);
let size = {};
if (res.ok) {
const infoJson = await res.json();
const maxSize = infoJson.sizes[infoJson.sizes.length - 1];
size.height = maxSize.height;
size.width = maxSize.width;
size.thumb = {
width: infoJson.sizes[1].width,
height: infoJson.sizes[1].height,
}
}
return size;
}
/**
* @param {Manifest} manifest The manifest object
* @param {string[]} images List of image filenames from folder
* @returns {Manifest}
*/
async function populateCanvases (manifest, images) {
const sequence = new Sequence(BASE_URL);
// There's only one sequence
sequence.generateID(manifest.resourceId, 0);
for (let img of images) {
// Skip failing images (TODO log error to file)
try {
let canvas = await createCanvas(manifest, img);
sequence.addCanvas(canvas);
} catch (error) {
console.error(error);
console.log(`\nAffected image: ${img}`);
continue;
}
}
// Sort them according to their ID number... (cornice, colonna, ecc...)
sequence.canvases.sort((a, b) => {
const firstId = a['@id'].slice(a['@id'].lastIndexOf('/') + 1).replace(/[a-z]+/ig,'');
const secondId = b['@id'].slice(b['@id'].lastIndexOf('/') + 1).replace(/[a-z]+/ig,'');
return Number(firstId) - Number(secondId);
});
manifest.addSequence(sequence);
return manifest;
}
/**
* Get image name for given canvas
* @todo Use regex in filter!!
* @param {String} name The canvas name
* @param {String} manifestId The manifest (resource) id
* @returns {string}
*/
async function getImageName(name, manifestId) {
const images = await getImageList(manifestId);
// Adjust canvas name for HSI with PCA...
if (/pc(1|3)/.test(name)) {
name = name.replace(
/pc((1|3))/,
function (match, group1) {
return `_HSI_PC${group1}`;
}
);
}
return images.filter(i => i.includes(name))[0];
}
/**
* @param {Manifest} manifest The Manifest object
* @param {string} imgFilename
* @returns {ManifestMetadata}
*/
function createMetadata(manifest, imgFilename) {
let metadata = parse(imgFilename, manifest.technique);
metadata.technique = TECH_NAMES[manifest.technique];
return new ManifestMetadata(metadata);
}