iiif-processor
Version:
IIIF 2.1 & 3.0 Image API modules for NodeJS
1 lines • 43.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/processor.ts","../src/geometry.ts","../src/tile-size.ts","../src/transform.ts","../src/v2/index.ts","../src/v2/info.ts","../src/v3/index.ts","../src/v3/info.ts","../src/versions.ts"],"sourcesContent":["import Debug from 'debug';\nimport mime from 'mime-types';\nimport path from 'path';\nimport sharp from 'sharp';\nimport { calculateGeometry, readGeometry } from './geometry';\nimport { Operations } from './transform';\nimport { IIIFError } from './error';\nimport Versions from './versions';\nimport type {\n MaxDimensions,\n ImageGeometry,\n ProcessorResult,\n ContentResult,\n ErrorResult,\n RedirectResult\n} from './types';\nimport type { VersionModule } from './contracts';\n\nconst debug = Debug('iiif-processor:main');\nconst debugv = Debug('verbose:iiif-processor');\n\nconst defaultpathPrefix = '/iiif/{{version}}/';\n\nfunction getIiifVersion(url: string, template: string) {\n const { origin, pathname } = new URL(url);\n const templateMatcher = template.replace(\n /\\{\\{version\\}\\}/,\n '(?<iiifVersion>\\\\d+)'\n );\n const pathMatcher = `^(?<prefix>${templateMatcher})(?<request>.+)$`;\n const re = new RegExp(pathMatcher);\n const parsed = re.exec(pathname);\n if (parsed) {\n parsed.groups.prefix = origin + parsed.groups.prefix;\n return { ...parsed.groups } as {\n prefix: string;\n iiifVersion: string;\n request: string;\n };\n } else {\n throw new IIIFError('Invalid IIIF path');\n }\n}\n\nexport type GeometryFunction = (input: {\n id: string;\n baseUrl: string;\n}) => Promise<ImageGeometry>;\nexport type StreamResolver = (input: {\n id: string;\n baseUrl: string;\n}) => Promise<NodeJS.ReadableStream>;\nexport type StreamResolverWithCallback = (\n input: { id: string; baseUrl: string },\n callback: (stream: NodeJS.ReadableStream) => Promise<unknown>\n) => Promise<unknown>;\nexport type ProcessorOptions = {\n geometryFunction?: GeometryFunction;\n max?: { width: number; height?: number; area?: number };\n includeMetadata?: boolean;\n density?: number;\n debugBorder?: boolean;\n iiifVersion?: number;\n pageThreshold?: number;\n pathPrefix?: string;\n sharpOptions?: Record<string, unknown>;\n request?: string;\n};\n\nexport class Processor {\n private errorClass = IIIFError;\n private Implementation!: VersionModule;\n private imageGeometry?: ImageGeometry;\n private sharpOptions?: Record<string, unknown>;\n\n id!: string;\n baseUrl!: string;\n version!: number;\n request!: string;\n streamResolver!: StreamResolver | StreamResolverWithCallback;\n filename?: string;\n\n // parsed params from Calculator.parsePath\n info?: string;\n region!: string;\n size!: string;\n rotation!: string;\n quality!: string;\n format!: string;\n\n // options\n geometryFunction!: GeometryFunction;\n max?: MaxDimensions;\n includeMetadata = false;\n density?: number | null;\n debugBorder = false;\n pageThreshold?: number;\n\n constructor(\n url: string,\n streamResolver: StreamResolver | StreamResolverWithCallback,\n opts: ProcessorOptions = {}\n ) {\n const { prefix, iiifVersion, request } = getIiifVersion(\n url,\n opts.pathPrefix || defaultpathPrefix\n );\n\n if (typeof streamResolver !== 'function') {\n throw new IIIFError('streamResolver option must be specified');\n }\n\n if (opts.max?.height && !opts.max?.width) {\n throw new IIIFError('maxHeight cannot be specified without maxWidth');\n }\n\n const defaults = {\n geometryFunction: null,\n density: null\n };\n\n this.setOpts({\n ...defaults,\n iiifVersion,\n ...opts,\n prefix,\n request\n }).initialize(streamResolver);\n }\n\n setOpts(opts) {\n this.geometryFunction = opts.geometryFunction;\n this.max = { ...opts.max };\n this.includeMetadata = !!opts.includeMetadata;\n this.density = opts.density;\n this.baseUrl = opts.prefix;\n this.debugBorder = !!opts.debugBorder;\n this.pageThreshold = opts.pageThreshold;\n this.sharpOptions = { ...opts.sharpOptions };\n this.version = Number(opts.iiifVersion);\n this.request = opts.request;\n return this;\n }\n\n initialize(streamResolver: StreamResolver | StreamResolverWithCallback) {\n this.Implementation = Versions[this.version] as VersionModule;\n if (!this.Implementation) {\n throw new IIIFError(\n `No implementation found for IIIF Image API v${this.version}`\n );\n }\n\n const params = this.Implementation.Calculator.parsePath(this.request);\n debug('Parsed URL: %j', params);\n Object.assign(this, params);\n this.streamResolver = streamResolver;\n\n if (this.quality && this.format) {\n this.filename = [this.quality, this.format].join('.');\n } else if (this.info) {\n this.filename = 'info.json';\n }\n return this;\n }\n\n async withStream(callback: (s: NodeJS.ReadableStream) => Promise<unknown>) {\n const { id, baseUrl } = this;\n debug('Requesting stream for %s', id);\n if (this.streamResolver.length === 2) {\n return await (this.streamResolver as StreamResolverWithCallback)(\n { id, baseUrl },\n callback\n );\n } else {\n const stream = await (this.streamResolver as StreamResolver)({\n id,\n baseUrl\n });\n return await callback(stream);\n }\n }\n\n async geometry(includeTile = false): Promise<ImageGeometry> {\n if (!this.imageGeometry) {\n debug(\n 'Attempting to use geometryFunction to retrieve dimensions for %j',\n this.id\n );\n const params = { id: this.id, baseUrl: this.baseUrl };\n let geometry: ImageGeometry = {};\n if (this.geometryFunction) {\n geometry = await this.geometryFunction(params);\n }\n if (!(geometry.tileWidth && geometry.tileHeight) && !includeTile) {\n geometry.tileWidth = null;\n geometry.tileHeight = null;\n }\n geometry = await readGeometry(this.withStream.bind(this), geometry);\n this.imageGeometry = calculateGeometry(geometry);\n }\n return this.imageGeometry;\n }\n\n async infoJson() {\n const geometry = await this.geometry(true);\n const uri = new URL(this.baseUrl);\n // Node's URL has readonly pathname in types; construct via join on new URL\n uri.pathname = path.join(uri.pathname, this.id);\n const id = uri.toString();\n const doc = this.Implementation.infoDoc({\n id,\n geometry,\n max: this.max\n });\n for (const prop in doc) {\n if (doc[prop] === null || doc[prop] === undefined) delete doc[prop];\n }\n\n const body = JSON.stringify(doc, (_key, value) =>\n value?.constructor === Set ? [...value] : value\n );\n return {\n type: 'content',\n contentType: 'application/ld+json',\n body\n } as ContentResult;\n }\n\n operations({ sizes }: ImageGeometry) {\n const sharpOpt = this.sharpOptions;\n const { max, pageThreshold } = this;\n debug('pageThreshold: %d', pageThreshold);\n return new Operations(this.version, sizes, {\n sharp: sharpOpt,\n max,\n pageThreshold\n })\n .region(this.region)\n .size(this.size)\n .rotation(this.rotation)\n .quality(this.quality)\n .format(this.format, this.density ?? undefined)\n .withMetadata(this.includeMetadata);\n }\n\n async applyBorder(transformed: sharp.Sharp) {\n const buf = await transformed.toBuffer();\n const borderPipe = sharp(buf, { limitInputPixels: false });\n const { width, height } = await borderPipe.metadata();\n const background = { r: 255, g: 0, b: 0, alpha: 1 };\n\n const topBorder = {\n create: { width, height: 1, channels: 4, background } as sharp.Create\n };\n const bottomBorder = {\n create: { width, height: 1, channels: 4, background } as sharp.Create\n };\n const leftBorder = {\n create: { width: 1, height, channels: 4, background } as sharp.Create\n };\n const rightBorder = {\n create: { width: 1, height, channels: 4, background } as sharp.Create\n };\n\n return borderPipe.composite([\n { input: topBorder, left: 0, top: 0 },\n { input: bottomBorder, left: 0, top: (height as number) - 1 },\n { input: leftBorder, left: 0, top: 0 },\n { input: rightBorder, left: (width as number) - 1, top: 0 }\n ]);\n }\n\n async iiifImage() {\n debugv('Request %s', this.request);\n const geometry = await this.geometry();\n const operations = this.operations(geometry);\n debugv('Operations: %j', operations);\n const pipeline = await operations.pipeline();\n\n const result = await this.withStream(async (stream) => {\n debug('piping stream to pipeline');\n let transformed = await stream.pipe(pipeline);\n if (this.debugBorder) {\n transformed = await this.applyBorder(transformed);\n }\n debug('converting to buffer');\n return await transformed.toBuffer();\n });\n debug('returning %d bytes', (result as Buffer).length);\n debug('baseUrl', this.baseUrl);\n\n const canonicalUrl = new URL(\n path.join(this.id, operations.canonicalPath()),\n this.baseUrl\n );\n return {\n type: 'content',\n canonicalLink: canonicalUrl.toString(),\n profileLink: this.Implementation.profileLink,\n contentType: mime.lookup(this.format) as string,\n body: result as Buffer\n } as ContentResult;\n }\n\n async execute(): Promise<ProcessorResult> {\n try {\n if (this.format === undefined && this.info === undefined) {\n debug('No format or info.json requested; redirecting to info.json');\n return {\n location: new URL(\n path.join(this.id, 'info.json'),\n this.baseUrl\n ).toString(),\n type: 'redirect'\n } as RedirectResult;\n }\n\n if (this.filename === 'info.json') {\n return await this.infoJson();\n }\n\n return await this.iiifImage();\n } catch (err) {\n if (err instanceof IIIFError) {\n debug('IIIFError caught: %j', err);\n return {\n type: 'error',\n message: err.message,\n statusCode: err.statusCode || 500\n } as ErrorResult;\n } else {\n throw err;\n }\n }\n }\n}\n\nexport default Processor;\n","import Debug from 'debug';\nimport type { ImageGeometry } from './types';\nimport sharp from 'sharp';\nimport { Readable } from 'stream';\nimport { getTileSize } from './tile-size';\n\nconst debug = Debug('iiif:geometry');\n\ntype StreamCallback = (stream: Readable) => Promise<unknown>;\n\nexport async function readGeometry(\n withStream: (callback: StreamCallback) => Promise<unknown>,\n geometry: ImageGeometry\n): Promise<ImageGeometry> {\n let metadata = {} as ImageGeometry;\n let tileSize = {} as ImageGeometry;\n const result = { ...geometry };\n\n debug('Initial geometry: %O', geometry);\n\n if (\n !geometry.width ||\n !geometry.height ||\n !(geometry.pages || geometry.sizes)\n ) {\n await withStream(async (metadataStream) => {\n metadata = await readMetadata(metadataStream);\n });\n if (!metadata.pages) metadata.pages = 1;\n debug('Read metadata: %O', metadata);\n }\n\n if (geometry.tileWidth === undefined) {\n await withStream(async (sizeStream) => {\n const size = await getTileSize(sizeStream);\n tileSize = { tileWidth: size.width, tileHeight: size.height };\n });\n debug('Read tile size: %O', tileSize);\n }\n\n const final = { ...result, ...metadata, ...tileSize };\n debug('Final geometry: %O', final);\n return final;\n}\n\nexport function calculateGeometry(geometry: ImageGeometry): ImageGeometry {\n if (geometry.sizes) {\n const result: ImageGeometry = { ...geometry };\n if (!geometry.pages) {\n result.pages = geometry.sizes.length;\n }\n if (!geometry.width || !geometry.height) {\n result.width = geometry.sizes[0].width;\n result.height = geometry.sizes[0].height;\n }\n return result;\n }\n\n if (geometry.width && geometry.height) {\n if (geometry.pages)\n if (geometry.pages === 1) {\n return {\n ...geometry,\n sizes: [{ width: geometry.width, height: geometry.height }]\n };\n }\n if (geometry.pages > 1) {\n return calculateSizesFromPages(geometry);\n }\n if (geometry.tileWidth && geometry.tileHeight) {\n return calculateSizesFromTiles(geometry);\n }\n }\n\n return geometry;\n}\n\nasync function readMetadata(stream: Readable): Promise<ImageGeometry> {\n const target = sharp({ limitInputPixels: false, page: 0 });\n\n stream.pipe(target);\n const { autoOrient, ...metadata } = await target.metadata();\n const { width, height, pages } = { ...metadata, ...autoOrient };\n return { width, height, pages };\n}\n\nfunction calculateSizesFromTiles(geometry: ImageGeometry): ImageGeometry {\n const pages =\n Math.max(\n Math.ceil(Math.log2(geometry.width! / geometry.tileWidth!)),\n Math.ceil(Math.log2(geometry.height! / geometry.tileHeight!))\n ) + 1;\n return calculateSizesFromPages({ ...geometry, pages });\n}\n\nfunction calculateSizesFromPages(geometry: ImageGeometry): ImageGeometry {\n const result: ImageGeometry = { ...geometry };\n result.sizes = [{ width: geometry.width, height: geometry.height }];\n let page = 0;\n for (page += 1; page < geometry.pages; page++) {\n const scale = 1 / 2 ** page;\n result.sizes.push({\n width: Math.floor(geometry.width * scale),\n height: Math.floor(geometry.height * scale)\n });\n }\n return result;\n}\n","import { Readable } from 'stream';\n\nexport interface TileSize {\n width: number | undefined | null;\n height: number | undefined | null;\n}\n\ntype ImageFormat = 'tiff-le' | 'tiff-be' | 'jp2' | 'unknown';\n\nconst CHUNK_SIZE = 5 * 1024; // 5KB\n\n/**\n * Wraps a Readable stream in an async interface that accumulates chunks\n * on demand. Call `ensure(n)` to buffer at least `n` bytes, then read\n * from `buf` directly.\n */\nclass StreamBuffer {\n private chunks: Buffer[] = [];\n private _length = 0;\n private done = false;\n private iterator: AsyncIterableIterator<Buffer>;\n\n constructor(stream: Readable) {\n stream.pause();\n this.iterator = stream[\n Symbol.asyncIterator\n ]() as AsyncIterableIterator<Buffer>;\n }\n\n get length() {\n return this._length;\n }\n\n get buf(): Buffer {\n return Buffer.concat(this.chunks);\n }\n\n /** Buffer at least `needed` bytes, or until stream is exhausted. */\n async ensure(needed: number): Promise<void> {\n while (this._length < needed && !this.done) {\n const { value, done } = await this.iterator.next();\n if (done) {\n this.done = true;\n } else {\n this.chunks.push(value);\n this._length += value.length;\n }\n }\n }\n\n /** Read `count` bytes starting at `offset`, fetching more chunks if needed. */\n async read(offset: number, count: number): Promise<Buffer> {\n await this.ensure(offset + count);\n return this.buf.subarray(offset, offset + count);\n }\n}\n\nconst magicNumbers = [\n { type: 'tiff-le', magic: Buffer.from([0x49, 0x49, 0x2a, 0x00]) },\n { type: 'tiff-be', magic: Buffer.from([0x4d, 0x4d, 0x00, 0x2a]) },\n { type: 'jp2', magic: Buffer.from([0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50]) },\n { type: 'jp2', magic: Buffer.from([0xff, 0x4f]) }\n];\n\nfunction detectFormat(buf: Buffer): ImageFormat {\n if (buf.length < 8) return 'unknown';\n for (const { type, magic } of magicNumbers) {\n if (buf.subarray(0, magic.length).equals(magic)) return type as ImageFormat;\n }\n return 'unknown';\n}\n\nasync function getTiffTileSize(\n sb: StreamBuffer,\n littleEndian: boolean\n): Promise<TileSize> {\n const readUInt16 = (buf: Buffer, offset: number) =>\n littleEndian ? buf.readUInt16LE(offset) : buf.readUInt16BE(offset);\n const readUInt32 = (buf: Buffer, offset: number) =>\n littleEndian ? buf.readUInt32LE(offset) : buf.readUInt32BE(offset);\n\n // Bytes 4-7 contain the IFD offset\n const header = await sb.read(0, 8);\n const ifdOffset = readUInt32(header, 4);\n\n // First 2 bytes of the IFD are the entry count\n const ifdHeader = await sb.read(ifdOffset, 2);\n const entryCount = readUInt16(ifdHeader, 0);\n\n // Each IFD entry is 12 bytes\n const ifdData = await sb.read(ifdOffset + 2, entryCount * 12);\n\n let width: number | undefined | null;\n let height: number | undefined | null;\n\n for (let i = 0; i < entryCount; i++) {\n const entryOffset = i * 12;\n const tag = readUInt16(ifdData, entryOffset);\n const value = readUInt32(ifdData, entryOffset + 8);\n\n if (tag === 322) width = value; // TileWidth\n if (tag === 323) height = value; // TileLength\n\n if (width !== undefined && height !== undefined) break;\n }\n\n return { width, height };\n}\n\nasync function getJP2TileSize(sb: StreamBuffer): Promise<TileSize> {\n const magic = await sb.read(0, 2);\n const isRawCodestream = magic[0] === 0xff && magic[1] === 0x4f;\n\n let offset = 0;\n\n if (!isRawCodestream) {\n // Walk JP2 boxes to find the jp2c (codestream) box\n let foundCodestream = false;\n while (true) {\n const boxHeader = await sb.read(offset, 8);\n if (boxHeader.length < 8) break;\n\n const boxLength = boxHeader.readUInt32BE(0);\n const boxType = boxHeader.readUInt32BE(4);\n\n if (boxType === 0x6a703263) {\n // 'jp2c'\n offset += 8; // skip box header, now pointing at codestream\n foundCodestream = true;\n break;\n }\n\n if (boxLength < 8) break; // malformed\n offset += boxLength;\n }\n\n if (!foundCodestream) return { width: null, height: null };\n }\n\n // Scan for SIZ marker (FF51), reading in chunks to avoid buffering the whole file\n while (true) {\n const chunk = await sb.read(offset, CHUNK_SIZE);\n if (chunk.length < 2) break;\n\n for (let i = 0; i < chunk.length - 1; i++) {\n if (chunk[i] === 0xff && chunk[i + 1] === 0x51) {\n // SIZ layout from marker start:\n // FF51 (2) + segment length (2) + Rsiz (2) + Xsiz (4) + Ysiz (4)\n // + XOsiz (4) + YOsiz (4) = 22 bytes before XTsiz\n const sizData = await sb.read(offset + i + 22, 8);\n if (sizData.length < 8) return { width: null, height: null };\n return {\n width: sizData.readUInt32BE(0), // XTsiz\n height: sizData.readUInt32BE(4) // YTsiz\n };\n }\n }\n\n if (chunk.length < CHUNK_SIZE) break; // end of stream\n offset += CHUNK_SIZE - 1; // overlap by 1 to avoid missing a marker at a chunk boundary\n }\n\n return { width: null, height: null };\n}\n\nexport async function getTileSize(stream: Readable): Promise<TileSize> {\n const sb = new StreamBuffer(stream);\n\n // Read just enough to detect the format\n await sb.ensure(8);\n const format = detectFormat(sb.buf);\n\n if (format === 'tiff-le' || format === 'tiff-be') {\n return getTiffTileSize(sb, format === 'tiff-le');\n }\n\n if (format === 'jp2') {\n return getJP2TileSize(sb);\n }\n\n return { width: null, height: null };\n}\n","import Sharp, { Sharp as SharpType } from 'sharp';\nimport Debug from 'debug';\nimport { Versions } from './versions';\nimport type { VersionModule, CalculatorLike, CalculatorOptions } from './contracts';\nimport type { Dimensions, BoundingBox, Format } from './types';\n\nconst debug = Debug('iiif-processor:transform');\n\nconst DEFAULT_PAGE_THRESHOLD = 1;\nconst SCALE_PRECISION = 10000000;\n\ntype PageDim = { width: number; height: number; page: number };\n\nexport class Operations {\n private keepMetadata?: boolean;\n private pages: PageDim[];\n private sharpOptions?: Record<string, unknown>;\n private calculator: CalculatorLike;\n private pageThreshold: number;\n\n constructor (version: number, dims: Dimensions[], opts: CalculatorOptions & { sharp?: Record<string, unknown>; pageThreshold?: number }) {\n const { sharp, pageThreshold, ...rest } = { ...opts };\n const Implementation: VersionModule = Versions[version];\n this.calculator = new Implementation.Calculator(dims[0], rest);\n this.pageThreshold = typeof pageThreshold === 'number' ? pageThreshold : DEFAULT_PAGE_THRESHOLD;\n\n this.pages = dims\n .map((dim, page) => ({ ...dim, page }))\n .sort((a, b) => b.width * b.height - a.width * a.height);\n this.sharpOptions = sharp;\n }\n\n region (v: string) {\n this.calculator.region(v);\n return this;\n }\n\n size (v: string) {\n this.calculator.size(v);\n return this;\n }\n\n rotation (v: string) {\n this.calculator.rotation(v);\n return this;\n }\n\n quality (v: string) {\n this.calculator.quality(v);\n return this;\n }\n\n format (v: string, density?: number) {\n this.calculator.format(v, density);\n return this;\n }\n\n info () {\n return this.calculator.info();\n }\n\n canonicalPath () {\n return this.calculator.canonicalPath();\n }\n\n withMetadata (v: boolean) {\n this.keepMetadata = v;\n return this;\n }\n\n private computePage () {\n const { fullSize } = this.info();\n const { page } = this.pages.find((_candidate, index) => {\n const next = this.pages[index + 1];\n debug('comparing candidate %j to target %j with a %d-pixel buffer', next, fullSize, this.pageThreshold);\n return !next || (next.width + this.pageThreshold < fullSize.width && next.height + this.pageThreshold < fullSize.height);\n }) as PageDim;\n\n const resolution = this.pages[page];\n const scale = page === 0 ? 1 : Math.round((resolution.width / this.pages[0].width) * SCALE_PRECISION) / SCALE_PRECISION;\n debug('Using page %d (%j) as source and scaling by %f', page, resolution, scale);\n return { page, scale };\n }\n\n pipeline (): SharpType {\n const pipeline = Sharp({\n limitInputPixels: false,\n ...{ ...this.sharpOptions }\n });\n const { page, scale } = this.computePage();\n (pipeline as any).options.input.page = page; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n const { format, quality, region, rotation: { flop, degree }, size } = this.info();\n scaleRegion(region, scale, this.pages[page]);\n\n pipeline.autoOrient().extract(region).resize(size);\n if (flop) pipeline.flop();\n pipeline.rotate(degree);\n if (quality === 'gray') pipeline.grayscale();\n if (quality === 'bitonal') pipeline.threshold();\n setFormat(pipeline, format);\n if (this.keepMetadata) pipeline.keepMetadata();\n\n debug('Pipeline: %j', { page, region, size, rotation: { flop, degree }, quality, format });\n return pipeline;\n }\n}\n\nfunction setFormat (pipeline: SharpType, format: { type: Format; density?: number }) {\n let pipelineFormat;\n const pipelineOptions: any = {}; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n switch (format.type) {\n case 'jpeg':\n pipelineFormat = 'jpg';\n break;\n case 'tif':\n pipelineFormat = 'tiff';\n if (format.density) {\n pipelineOptions.xres = format.density / 25.4;\n pipelineOptions.yres = format.density / 25.4;\n }\n break;\n default:\n pipelineFormat = format.type;\n }\n pipeline.toFormat(pipelineFormat, pipelineOptions);\n if (format.density) {\n pipeline.withMetadata({ density: format.density });\n }\n}\n\nfunction scaleRegion (region: BoundingBox, scale: number, page: { width: number; height: number }) {\n region.left = Math.floor(region.left * scale);\n region.top = Math.floor(region.top * scale);\n region.width = Math.floor(region.width * scale);\n region.height = Math.floor(region.height * scale);\n region.left = Math.max(region.left, 0);\n region.top = Math.max(region.top, 0);\n region.width = Math.min(region.width, page.width);\n region.height = Math.min(region.height, page.height);\n return region;\n}\n\nexport default { Operations };\n","export * from './info';\nexport * from '../calculator/v2';\n","import { Dimensions } from '../types';\nimport { Formats, Qualities } from '../calculator/v2';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport Debug from 'debug';\nimport type { InfoDocInput, InfoDoc } from '../contracts';\nconst profileLink = 'http://iiif.io/api/image/2/level2.json';\n\nconst IIIFProfile = {\n formats: new Set(Formats),\n qualities: new Set(Qualities),\n supports: new Set([\n 'baseUriRedirect',\n 'canonicalLinkHeader',\n 'cors',\n 'jsonldMediaType',\n 'mirroring',\n 'profileLinkHeader',\n 'regionByPct',\n 'regionByPx',\n 'regionSquare',\n 'rotationArbitrary',\n 'rotationBy90s',\n 'sizeAboveFull',\n 'sizeByConfinedWh',\n 'sizeByDistortedWh',\n 'sizeByForcedWh',\n 'sizeByH',\n 'sizeByPct',\n 'sizeByW',\n 'sizeByWh',\n 'sizeByWhListed'\n ])\n};\n\nexport function infoDoc({ id, geometry, max }: InfoDocInput): InfoDoc {\n const maxAttrs = {\n maxWidth: max?.width,\n maxHeight: max?.height,\n maxArea: max?.area\n };\n\n const { width, height, sizes } = geometry;\n const tiles = geometry.tileWidth\n ? [\n {\n width: geometry.tileWidth,\n height: geometry.tileHeight || geometry.tileWidth,\n scaleFactors: sizes.map((_v: Dimensions, i: number) => 2 ** i)\n }\n ]\n : undefined;\n return {\n '@context': 'http://iiif.io/api/image/2/context.json',\n '@id': id,\n protocol: 'http://iiif.io/api/image',\n width,\n height,\n sizes,\n tiles,\n profile: [profileLink, { ...IIIFProfile, ...maxAttrs }]\n };\n}\n\nexport { profileLink };\n","export * from './info';\nexport * from '../calculator/v3';\n","import { Dimensions } from '../types';\nimport { Formats, Qualities } from '../calculator/v3';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport Debug from 'debug';\nimport type { InfoDocInput, InfoDoc } from '../contracts';\n\nexport const profileLink = 'https://iiif.io/api/image/3/level2.json';\n\nconst defaultFormats: Set<string> = new Set(['jpg', 'png']);\nconst defaultQualities: Set<string> = new Set(['default']);\nconst IIIFExtras = {\n extraFeatures: [\n 'canonicalLinkHeader',\n 'mirroring',\n 'profileLinkHeader',\n 'rotationArbitrary',\n 'sizeByDistortedWh',\n 'sizeByForcedWh',\n 'sizeByWhListed',\n 'sizeUpscaling'\n ],\n extraFormats: new Set(Formats.filter((f) => !defaultFormats.has(f))),\n extraQualities: new Set(Qualities.filter((q) => !defaultQualities.has(q)))\n};\n\nexport function infoDoc({ id, geometry, max }: InfoDocInput): InfoDoc {\n const maxAttrs = {\n maxWidth: max?.width,\n maxHeight: max?.height,\n maxArea: max?.area\n };\n\n const { width, height, sizes } = geometry;\n const tiles = geometry.tileWidth\n ? [\n {\n width: geometry.tileWidth,\n height: geometry.tileHeight || geometry.tileWidth,\n scaleFactors: sizes.map((_v: Dimensions, i: number) => 2 ** i)\n }\n ]\n : undefined;\n return {\n '@context': 'http://iiif.io/api/image/3/context.json',\n id,\n type: 'ImageService3',\n protocol: 'http://iiif.io/api/image',\n profile: 'level2',\n width,\n height,\n sizes,\n tiles,\n ...IIIFExtras,\n ...maxAttrs\n };\n}\n","import * as v2 from './v2';\nimport * as v3 from './v3';\nimport type { VersionModule } from './contracts';\n\nexport const Versions: Record<2 | 3, VersionModule> = {\n 2: v2 as unknown as VersionModule,\n 3: v3 as unknown as VersionModule\n};\n\nexport default Versions;\n"],"mappings":"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","names":["Debug","sharp","Debug","Calculator","infoDoc","profileLink","profileLink","infoDoc","debug","Debug","sharp","debug","Debug","sharp"]}