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
62 lines
2.1 KiB
Plaintext
62 lines
2.1 KiB
Plaintext
// lib/types/utils.ts
|
|
var decoder = new TextDecoder();
|
|
var toUTF8String = (input, start = 0, end = input.length) => decoder.decode(input.slice(start, end));
|
|
var toHexString = (input, start = 0, end = input.length) => input.slice(start, end).reduce((memo, i) => memo + `0${i.toString(16)}`.slice(-2), "");
|
|
var getView = (input, offset) => new DataView(input.buffer, input.byteOffset + offset);
|
|
var readInt16LE = (input, offset = 0) => getView(input, offset).getInt16(0, true);
|
|
var readUInt24LE = (input, offset = 0) => {
|
|
const view = getView(input, offset);
|
|
return view.getUint16(0, true) + (view.getUint8(2) << 16);
|
|
};
|
|
|
|
// lib/types/webp.ts
|
|
function calculateExtended(input) {
|
|
return {
|
|
height: 1 + readUInt24LE(input, 7),
|
|
width: 1 + readUInt24LE(input, 4)
|
|
};
|
|
}
|
|
function calculateLossless(input) {
|
|
return {
|
|
height: 1 + ((input[4] & 15) << 10 | input[3] << 2 | (input[2] & 192) >> 6),
|
|
width: 1 + ((input[2] & 63) << 8 | input[1])
|
|
};
|
|
}
|
|
function calculateLossy(input) {
|
|
return {
|
|
height: readInt16LE(input, 8) & 16383,
|
|
width: readInt16LE(input, 6) & 16383
|
|
};
|
|
}
|
|
var WEBP = {
|
|
validate(input) {
|
|
const riffHeader = "RIFF" === toUTF8String(input, 0, 4);
|
|
const webpHeader = "WEBP" === toUTF8String(input, 8, 12);
|
|
const vp8Header = "VP8" === toUTF8String(input, 12, 15);
|
|
return riffHeader && webpHeader && vp8Header;
|
|
},
|
|
calculate(_input) {
|
|
const chunkHeader = toUTF8String(_input, 12, 16);
|
|
const input = _input.slice(20, 30);
|
|
if (chunkHeader === "VP8X") {
|
|
const extendedHeader = input[0];
|
|
const validStart = (extendedHeader & 192) === 0;
|
|
const validEnd = (extendedHeader & 1) === 0;
|
|
if (validStart && validEnd) {
|
|
return calculateExtended(input);
|
|
}
|
|
throw new TypeError("Invalid WebP");
|
|
}
|
|
if (chunkHeader === "VP8 " && input[0] !== 47) {
|
|
return calculateLossy(input);
|
|
}
|
|
const signature = toHexString(input, 3, 6);
|
|
if (chunkHeader === "VP8L" && signature !== "9d012a") {
|
|
return calculateLossless(input);
|
|
}
|
|
throw new TypeError("Invalid WebP");
|
|
}
|
|
};
|
|
|
|
export { WEBP };
|