Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
87 lines
2.7 KiB
Plaintext
87 lines
2.7 KiB
Plaintext
'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;
|