UNPKG

image-size

Version:
87 lines (83 loc) 2.76 kB
'use strict'; // lib/types/utils.ts var decoder = new TextDecoder(); var toUTF8String = (input, start = 0, end = input.length) => decoder.decode(input.slice(start, end)); var getView = (input, offset) => new DataView(input.buffer, input.byteOffset + offset); var readUInt32BE = (input, offset = 0) => getView(input, offset).getUint32(0, false); function readBox(input, offset) { if (input.length - offset < 4) return; const boxSize = readUInt32BE(input, offset); if (input.length - offset < boxSize) return; return { name: toUTF8String(input, 4 + offset, 8 + offset), offset, size: boxSize }; } function findBox(input, boxName, currentOffset) { while (currentOffset < input.length) { const box = readBox(input, currentOffset); if (!box) break; if (box.name === boxName) return box; currentOffset += box.size > 0 ? box.size : 8; } } // lib/types/heif.ts var brandMap = { avif: "avif", mif1: "heif", msf1: "heif", // heif-sequence heic: "heic", heix: "heic", hevc: "heic", // heic-sequence hevx: "heic" // heic-sequence }; var HEIF = { validate(input) { const boxType = toUTF8String(input, 4, 8); if (boxType !== "ftyp") return false; const ftypBox = findBox(input, "ftyp", 0); if (!ftypBox) return false; const brand = toUTF8String(input, ftypBox.offset + 8, ftypBox.offset + 12); return brand in brandMap; }, calculate(input) { const metaBox = findBox(input, "meta", 0); const iprpBox = metaBox && findBox(input, "iprp", metaBox.offset + 12); const ipcoBox = iprpBox && findBox(input, "ipco", iprpBox.offset + 8); if (!ipcoBox) { throw new TypeError("Invalid HEIF, no ipco box found"); } const type = toUTF8String(input, 8, 12); const images = []; let currentOffset = ipcoBox.offset + 8; while (currentOffset < ipcoBox.offset + ipcoBox.size) { const ispeBox = findBox(input, "ispe", currentOffset); if (!ispeBox) break; const rawWidth = readUInt32BE(input, ispeBox.offset + 12); const rawHeight = readUInt32BE(input, ispeBox.offset + 16); const clapBox = findBox(input, "clap", currentOffset); let width = rawWidth; let height = rawHeight; if (clapBox && clapBox.offset < ipcoBox.offset + ipcoBox.size) { const cropRight = readUInt32BE(input, clapBox.offset + 12); width = rawWidth - cropRight; } images.push({ height, width }); currentOffset = ispeBox.offset + ispeBox.size; } if (images.length === 0) { throw new TypeError("Invalid HEIF, no sizes found"); } return { width: images[0].width, height: images[0].height, type, ...images.length > 1 ? { images } : {} }; } }; exports.HEIF = HEIF;