UNPKG

iiif-processor

Version:

IIIF 2.1 & 3.0 Image API modules for NodeJS

1 lines 22 kB
{"version":3,"sources":["../src/error.ts","../src/calculator/base.ts","../src/calculator/v2.ts","../src/calculator/v3.ts"],"sourcesContent":["export class IIIFError extends Error {\n statusCode?: number;\n\n constructor (message: string, opts: { statusCode?: number } = {}) {\n super(message);\n this.statusCode = opts.statusCode;\n }\n}\n\nexport default IIIFError;\n","import Debug from 'debug';\nimport { IIIFError } from '../error';\nimport type { BoundingBox, Dimensions, MaxDimensions } from '../types';\nimport type { Calculated, CalculatorOptions } from '../contracts';\n\nconst debug = Debug('iiif-processor:calculator');\n\nexport type ValidatorKey = 'quality' | 'format' | 'region' | 'size' | 'rotation' | 'density';\nexport type ValidatorMap = Record<ValidatorKey, string[]>;\n\nconst IR = '\\\\d+';\nconst FR = '\\\\d+(?:\\\\.\\\\d+)?';\nconst PCTR = /^pct:(?<val>[\\d.,]+)/;\n\nexport const Formats = ['gif', 'jpg', 'tif', 'png', 'webp'];\nexport const Qualities = ['color', 'gray', 'bitonal', 'default'];\n\n\nconst extraFormats = ['jpeg', 'tiff'];\n\nconst Validators: ValidatorMap = {\n quality: Qualities,\n format: [...Formats, ...extraFormats],\n region: ['full', 'square', `pct:${FR},${FR},${FR},${FR}`, `${IR},${IR},${IR},${IR}`],\n size: ['full', 'max', `pct:${FR}`, `${IR},`, `,${IR}`, `\\\\!?${IR},${IR}`],\n rotation: [`\\\\!?${FR}`],\n density: []\n};\n\ntype SizeDesc = { width?: number | null; height?: number | null; fit?: 'fill' | 'inside' };\ntype CanonicalInfo = { region: 'full' | BoundingBox; size: 'full' | 'max' | string; rotation: string; quality: string; format: string };\ntype ParsedInfo = { region: BoundingBox; size: SizeDesc; rotation: { flop: boolean; degree: number }; quality: string; format: { type: string; density?: number }; upscale: boolean };\n\nfunction validateDensity (v: unknown) {\n debug('validating density %s', v);\n if (v === null) return true;\n if (v === undefined) return true;\n if (typeof v !== 'number' || v < 0) {\n throw new IIIFError(`Invalid density value: ${v}`);\n }\n return true;\n}\n\nexport class Base {\n protected dims: Dimensions;\n protected opts: { max?: MaxDimensions };\n protected _canonicalInfo: CanonicalInfo;\n protected _parsedInfo: ParsedInfo;\n protected _sourceDims: Dimensions;\n\n static _matchers(): typeof Validators {\n return Validators;\n }\n\n static _validator(type: ValidatorKey) {\n const result = this._matchers()[type].join('|');\n return `(?<${type}>${result})`;\n }\n\n static parsePath(path: string) {\n path = decodeURIComponent(path);\n debug('parsing IIIF path: %s', path);\n const idOnlyRe = new RegExp('^/?(?<id>.+)/?$');\n const infoJsonRe = new RegExp('^/?(?<id>.+)/(?<info>info.json)$');\n const transformRe = new RegExp(\n '^/?(?<id>.+)/(?<region>.+)/(?<size>.+)/(?<rotation>.+)/(?<quality>.+)\\\\.(?<format>.+)$'\n );\n\n let result = infoJsonRe.exec(path)?.groups;\n debug('info.json match result: %j', result);\n if (result) return result;\n\n result = transformRe.exec(path)?.groups;\n debug('transform match result: %j', result);\n if (result) {\n for (const component of [\n 'region',\n 'size',\n 'rotation',\n 'quality',\n 'format'\n ] as ValidatorKey[]) {\n const validator = new RegExp(this._validator(component));\n if (!validator.test(result[component] as string)) {\n throw new IIIFError(`Invalid ${component} in IIIF path: ${path}`, {\n statusCode: 400\n });\n }\n }\n return result;\n }\n\n result = idOnlyRe.exec(path)?.groups;\n debug('ID only match result: %j', result);\n if (result) return result;\n\n throw new IIIFError(`Not a valid IIIF path: ${path}`, {\n statusCode: 400\n });\n }\n\n constructor(dims: Dimensions, opts: CalculatorOptions = {}) {\n this.dims = { ...dims };\n this.opts = { ...opts };\n this._sourceDims = { ...dims };\n this._canonicalInfo = {\n region: 'full',\n size: 'full',\n rotation: '0',\n quality: 'default',\n format: 'jpg'\n };\n this._parsedInfo = {\n region: { left: 0, top: 0, ...dims },\n size: { width: dims.width, height: dims.height, fit: 'fill' },\n rotation: { flop: false, degree: 0 },\n quality: 'default',\n format: { type: 'jpg' },\n upscale: true\n };\n }\n\n protected _validate(type: keyof typeof Validators | 'density', v: unknown) {\n if (type === 'density') return validateDensity(v);\n const re = new RegExp(`^${Base._validator(type)}$`);\n debug('validating %s %s against %s', type, v, re);\n if (!re.test(String(v))) {\n throw new IIIFError(`Invalid ${type}: ${v}`, { statusCode: 400 });\n }\n return true;\n }\n\n region(v: string) {\n this._validate('region', v);\n const pct = PCTR.exec(v);\n let isFull = false;\n if (v === 'full') {\n this._parsedInfo.region = { left: 0, top: 0, ...this.dims };\n isFull = true;\n } else if (v === 'square') {\n this._parsedInfo.region = regionSquare(this.dims);\n } else if (pct) {\n this._parsedInfo.region = regionPct(pct.groups?.val as string, this.dims);\n } else {\n this._parsedInfo.region = regionXYWH(v);\n }\n this._canonicalInfo.region = isFull ? 'full' : this._parsedInfo.region;\n this._constrainRegion();\n return this;\n }\n\n size(v: string) {\n this._validate('size', v);\n const pct = PCTR.exec(v);\n let isMax = false;\n if (['full', 'max'].includes(v)) {\n this._setSize(this._parsedInfo.region);\n isMax = true;\n } else if (pct) {\n this._setSize(\n sizePct(pct.groups?.val as string, this._parsedInfo.region)\n );\n } else {\n this._setSize(sizeWH(v));\n }\n this._canonicalInfo.size = isMax ? v : this._canonicalSize();\n return this;\n }\n\n rotation(v: string) {\n this._validate('rotation', v);\n this._canonicalInfo.rotation = v;\n this._parsedInfo.rotation = {\n flop: v[0] === '!',\n degree: Number(v.replace(/^!/, ''))\n };\n return this;\n }\n\n quality(v: string) {\n this._validate('quality', v);\n this._canonicalInfo.quality = v;\n this._parsedInfo.quality = v;\n return this;\n }\n\n format(v: string, density?: number) {\n this._validate('format', v);\n this._validate('density', density);\n this._canonicalInfo.format = v;\n this._parsedInfo.format = { type: v, density };\n return this;\n }\n\n info(): Calculated {\n return {\n ...this._parsedInfo,\n fullSize: fullSize(this._sourceDims, this._parsedInfo)\n } as Calculated;\n }\n\n canonicalPath() {\n const { region, size, rotation, quality, format } = this._canonicalInfo;\n return `${region}/${size}/${rotation}/${quality}.${format}`;\n }\n\n protected _setSize(v: BoundingBox | SizeDesc) {\n const max: MaxDimensions = { ...(this.opts?.max || {}) };\n max.height = max.height || max.width;\n this._parsedInfo.size =\n 'left' in v\n ? { width: v.width, height: v.height, fit: 'fill' }\n : { ...v };\n this._constrainSize(max);\n return this;\n }\n\n protected _constrainSize(constraints: MaxDimensions) {\n const full = fullSize(this._sourceDims, this._parsedInfo);\n const constraint = minNum(\n constraints.width / full.width,\n constraints.height / full.height,\n constraints.area / (full.width * full.height)\n );\n if (constraint < 1) {\n if (this._parsedInfo.size.width) {\n this._parsedInfo.size.width = Math.floor(\n this._parsedInfo.size.width * constraint\n );\n }\n if (this._parsedInfo.size.height) {\n this._parsedInfo.size.height = Math.floor(\n this._parsedInfo.size.height * constraint\n );\n }\n }\n }\n\n protected _canonicalSize() {\n const { width, height } = this._parsedInfo.size;\n const result = `${width},${height}`;\n return this._parsedInfo.size.fit === 'inside' ? `!${result}` : result;\n }\n\n protected _constrainRegion() {\n let { left, top, width, height } = this._parsedInfo.region;\n left = Math.max(left, 0);\n top = Math.max(top, 0);\n if (left > this.dims.width || top > this.dims.height) {\n throw new IIIFError('Region is out of bounds', { statusCode: 400 });\n }\n width = Math.min(width, this.dims.width - left);\n height = Math.min(height, this.dims.height - top);\n this._parsedInfo.region = { left, top, width, height };\n }\n}\n\nfunction minNum(...args: unknown[]) {\n const nums = args.filter((arg) => typeof arg === 'number' && !isNaN(arg));\n return Math.min(...(nums as number[]));\n}\n\nfunction fillMissingDimension(size: SizeDesc, aspect: number) {\n if (!size.width && size.height != null)\n size.width = Math.floor(size.height * aspect);\n if (!size.height && size.width != null)\n size.height = Math.floor(size.width / aspect);\n}\n\nfunction fullSize(dims: Dimensions, { region, size }: ParsedInfo) {\n const regionAspect = region.width / region.height;\n fillMissingDimension(size, regionAspect);\n const scaleFactor = (size.width as number) / region.width;\n const result = {\n width: Math.floor(dims.width * scaleFactor),\n height: Math.floor(dims.height * scaleFactor)\n };\n debug(\n 'Region %j at size %j yields full size %j, a scale factor of %f',\n region,\n size,\n result,\n scaleFactor\n );\n return result;\n}\n\nfunction regionSquare(dims: Dimensions): BoundingBox {\n let result: BoundingBox = {\n left: 0,\n top: 0,\n width: dims.width,\n height: dims.height\n };\n if (dims.width !== dims.height) {\n const side = Math.min(dims.width, dims.height);\n result = { ...result, width: side, height: side };\n const offset = Math.abs(Math.floor((dims.width - dims.height) / 2));\n if (dims.width > dims.height) {\n result.left = offset;\n result.top = 0;\n } else {\n result.left = 0;\n result.top = offset;\n }\n }\n return result;\n}\n\nfunction regionPct(v: string, dims: Dimensions): BoundingBox {\n let x: number, y: number, w: number, h: number;\n [x, y, w, h] = v.split(/\\s*,\\s*/).map((pct) => Number(pct) / 100.0) as [\n number,\n number,\n number,\n number\n ];\n [x, w] = [x, w].map((val) => Math.floor(dims.width * val)) as [\n number,\n number\n ];\n [y, h] = [y, h].map((val) => Math.floor(dims.height * val)) as [\n number,\n number\n ];\n return regionXYWH([x, y, w, h]);\n}\n\nfunction regionXYWH(v: string | number[]): BoundingBox {\n const parts: number[] =\n typeof v === 'string' ? v.split(/\\s*,\\s*/).map((val) => Number(val)) : v;\n const result: BoundingBox = {\n left: parts[0],\n top: parts[1],\n width: parts[2],\n height: parts[3]\n };\n if (result.width === 0 || result.height === 0) {\n throw new IIIFError('Region width and height must both be > 0', {\n statusCode: 400\n });\n }\n return result;\n}\n\nfunction sizePct(v: string, dims: Dimensions) {\n const pct = Number(v);\n if (isNaN(pct) || pct <= 0) {\n throw new IIIFError(`Invalid resize %: ${v}`, { statusCode: 400 });\n }\n const width = Math.floor(dims.width * (pct / 100.0));\n return sizeWH(`${width},`);\n}\n\nfunction sizeWH(v: string) {\n const result: SizeDesc = { fit: 'fill' };\n if (v[0] === '!') {\n result.fit = 'inside';\n v = v.slice(1);\n }\n const parts: (number | null)[] = v\n .split(/\\s*,\\s*/)\n .map((val) => (val === '' ? null : Number(val)));\n [result.width, result.height] = parts as [number | null, number | null];\n if (result.width === 0 || result.height === 0) {\n throw new IIIFError('Resize width and height must both be > 0', {\n statusCode: 400\n });\n }\n return result;\n}\n\nexport default { Base, Qualities, Formats };\n","import { Base } from './base';\n\nexport class Calculator extends Base {}\n\nexport * from './base';\n\nexport default { Calculator };\n","import { CalculatorOptions } from '../contracts';\nimport { Base, ValidatorMap } from './base';\nimport { IIIFError } from '../error';\n\nexport class Calculator extends Base {\n static _matchers(): ValidatorMap {\n const result: ValidatorMap = { ...super._matchers() };\n result.size = [...result.size].reduce(\n (sizes: string[], pattern: string) => {\n if (pattern !== 'full') sizes.push(`\\\\^?${pattern}`);\n return sizes;\n },\n [] as string[]\n );\n return result;\n }\n\n constructor(\n dims: { width: number; height: number },\n opts: CalculatorOptions = {}\n ) {\n super(dims, opts);\n this._canonicalInfo.size = 'max';\n this._parsedInfo.upscale = false;\n }\n\n size(v: string) {\n if (v[0] === '^') {\n this._parsedInfo.upscale = true;\n v = v.slice(1, v.length);\n }\n super.size(v);\n const { region, size, upscale } = this._parsedInfo;\n if (!upscale) {\n if (size.width > region.width || size.height > region.height) {\n throw new IIIFError('Requested size requires upscaling', {\n statusCode: 400\n });\n }\n }\n return this;\n }\n}\n\nexport * from './base';\n\nexport default { Calculator };\n"],"mappings":"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","names":["Calculator"]}