matrix-react-sdk
Version:
SDK for matrix.org using React
100 lines (96 loc) • 14.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.blobIsAnimated = blobIsAnimated;
exports.mayBeAnimated = mayBeAnimated;
var _arrays = require("./arrays");
/*
* Copyright 2024 New Vector Ltd.
* Copyright 2022 The Matrix.org Foundation C.I.C.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
* Please see LICENSE files in the repository root for full details.
*/
function mayBeAnimated(mimeType) {
// AVIF animation support at the time of writing is only available in Chrome hence not having `blobIsAnimated` check
return ["image/gif", "image/webp", "image/png", "image/apng", "image/avif"].includes(mimeType);
}
function arrayBufferRead(arr, start, len) {
return new Uint8Array(arr.slice(start, start + len));
}
function arrayBufferReadInt(arr, start) {
const dv = new DataView(arr, start, 4);
return dv.getUint32(0);
}
function arrayBufferReadStr(arr, start, len) {
return String.fromCharCode.apply(null, Array.from(arrayBufferRead(arr, start, len)));
}
async function blobIsAnimated(mimeType, blob) {
switch (mimeType) {
case "image/webp":
{
// Only extended file format WEBP images support animation, so grab the expected data range and verify header.
// Based on https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
const arr = await blob.slice(0, 17).arrayBuffer();
if (arrayBufferReadStr(arr, 0, 4) === "RIFF" && arrayBufferReadStr(arr, 8, 4) === "WEBP" && arrayBufferReadStr(arr, 12, 4) === "VP8X") {
const [flags] = arrayBufferRead(arr, 16, 1);
// Flags: R R I L E X _A_ R (reversed)
const animationFlagMask = 1 << 1;
return (flags & animationFlagMask) != 0;
}
break;
}
case "image/gif":
{
// Based on https://gist.github.com/zakirt/faa4a58cec5a7505b10e3686a226f285
// More info at http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
const dv = new DataView(await blob.arrayBuffer(), 10);
const globalColorTable = dv.getUint8(0);
let globalColorTableSize = 0;
// check first bit, if 0, then we don't have a Global Color Table
if (globalColorTable & 0x80) {
// grab the last 3 bits, to calculate the global color table size -> RGB * 2^(N+1)
// N is the value in the last 3 bits.
globalColorTableSize = 3 * Math.pow(2, (globalColorTable & 0x7) + 1);
}
// move on to the Graphics Control Extension
const offset = 3 + globalColorTableSize;
const extensionIntroducer = dv.getUint8(offset);
const graphicsControlLabel = dv.getUint8(offset + 1);
let delayTime = 0;
// Graphics Control Extension section is where GIF animation data is stored
// First 2 bytes must be 0x21 and 0xF9
if (extensionIntroducer & 0x21 && graphicsControlLabel & 0xf9) {
// skip to the 2 bytes with the delay time
delayTime = dv.getUint16(offset + 4);
}
return !!delayTime;
}
case "image/png":
case "image/apng":
{
// Based on https://stackoverflow.com/a/68618296
const arr = await blob.arrayBuffer();
if ((0, _arrays.arrayHasDiff)([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], Array.from(arrayBufferRead(arr, 0, 8)))) {
return false;
}
for (let i = 8; i < blob.size;) {
const length = arrayBufferReadInt(arr, i);
i += 4;
const type = arrayBufferReadStr(arr, i, 4);
i += 4;
switch (type) {
case "acTL":
return true;
case "IDAT":
return false;
}
i += length + 4;
}
break;
}
}
return false;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYXJyYXlzIiwicmVxdWlyZSIsIm1heUJlQW5pbWF0ZWQiLCJtaW1lVHlwZSIsImluY2x1ZGVzIiwiYXJyYXlCdWZmZXJSZWFkIiwiYXJyIiwic3RhcnQiLCJsZW4iLCJVaW50OEFycmF5Iiwic2xpY2UiLCJhcnJheUJ1ZmZlclJlYWRJbnQiLCJkdiIsIkRhdGFWaWV3IiwiZ2V0VWludDMyIiwiYXJyYXlCdWZmZXJSZWFkU3RyIiwiU3RyaW5nIiwiZnJvbUNoYXJDb2RlIiwiYXBwbHkiLCJBcnJheSIsImZyb20iLCJibG9iSXNBbmltYXRlZCIsImJsb2IiLCJhcnJheUJ1ZmZlciIsImZsYWdzIiwiYW5pbWF0aW9uRmxhZ01hc2siLCJnbG9iYWxDb2xvclRhYmxlIiwiZ2V0VWludDgiLCJnbG9iYWxDb2xvclRhYmxlU2l6ZSIsIk1hdGgiLCJwb3ciLCJvZmZzZXQiLCJleHRlbnNpb25JbnRyb2R1Y2VyIiwiZ3JhcGhpY3NDb250cm9sTGFiZWwiLCJkZWxheVRpbWUiLCJnZXRVaW50MTYiLCJhcnJheUhhc0RpZmYiLCJpIiwic2l6ZSIsImxlbmd0aCIsInR5cGUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvSW1hZ2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuICogQ29weXJpZ2h0IDIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbiAqXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcbiAqIFBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4gKi9cblxuaW1wb3J0IHsgYXJyYXlIYXNEaWZmIH0gZnJvbSBcIi4vYXJyYXlzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXlCZUFuaW1hdGVkKG1pbWVUeXBlPzogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgLy8gQVZJRiBhbmltYXRpb24gc3VwcG9ydCBhdCB0aGUgdGltZSBvZiB3cml0aW5nIGlzIG9ubHkgYXZhaWxhYmxlIGluIENocm9tZSBoZW5jZSBub3QgaGF2aW5nIGBibG9iSXNBbmltYXRlZGAgY2hlY2tcbiAgICByZXR1cm4gW1wiaW1hZ2UvZ2lmXCIsIFwiaW1hZ2Uvd2VicFwiLCBcImltYWdlL3BuZ1wiLCBcImltYWdlL2FwbmdcIiwgXCJpbWFnZS9hdmlmXCJdLmluY2x1ZGVzKG1pbWVUeXBlISk7XG59XG5cbmZ1bmN0aW9uIGFycmF5QnVmZmVyUmVhZChhcnI6IEFycmF5QnVmZmVyLCBzdGFydDogbnVtYmVyLCBsZW46IG51bWJlcik6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShhcnIuc2xpY2Uoc3RhcnQsIHN0YXJ0ICsgbGVuKSk7XG59XG5cbmZ1bmN0aW9uIGFycmF5QnVmZmVyUmVhZEludChhcnI6IEFycmF5QnVmZmVyLCBzdGFydDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBkdiA9IG5ldyBEYXRhVmlldyhhcnIsIHN0YXJ0LCA0KTtcbiAgICByZXR1cm4gZHYuZ2V0VWludDMyKDApO1xufVxuXG5mdW5jdGlvbiBhcnJheUJ1ZmZlclJlYWRTdHIoYXJyOiBBcnJheUJ1ZmZlciwgc3RhcnQ6IG51bWJlciwgbGVuOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIEFycmF5LmZyb20oYXJyYXlCdWZmZXJSZWFkKGFyciwgc3RhcnQsIGxlbikpKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJsb2JJc0FuaW1hdGVkKG1pbWVUeXBlOiBzdHJpbmcgfCB1bmRlZmluZWQsIGJsb2I6IEJsb2IpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBzd2l0Y2ggKG1pbWVUeXBlKSB7XG4gICAgICAgIGNhc2UgXCJpbWFnZS93ZWJwXCI6IHtcbiAgICAgICAgICAgIC8vIE9ubHkgZXh0ZW5kZWQgZmlsZSBmb3JtYXQgV0VCUCBpbWFnZXMgc3VwcG9ydCBhbmltYXRpb24sIHNvIGdyYWIgdGhlIGV4cGVjdGVkIGRhdGEgcmFuZ2UgYW5kIHZlcmlmeSBoZWFkZXIuXG4gICAgICAgICAgICAvLyBCYXNlZCBvbiBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9zcGVlZC93ZWJwL2RvY3MvcmlmZl9jb250YWluZXIjZXh0ZW5kZWRfZmlsZV9mb3JtYXRcbiAgICAgICAgICAgIGNvbnN0IGFyciA9IGF3YWl0IGJsb2Iuc2xpY2UoMCwgMTcpLmFycmF5QnVmZmVyKCk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgYXJyYXlCdWZmZXJSZWFkU3RyKGFyciwgMCwgNCkgPT09IFwiUklGRlwiICYmXG4gICAgICAgICAgICAgICAgYXJyYXlCdWZmZXJSZWFkU3RyKGFyciwgOCwgNCkgPT09IFwiV0VCUFwiICYmXG4gICAgICAgICAgICAgICAgYXJyYXlCdWZmZXJSZWFkU3RyKGFyciwgMTIsIDQpID09PSBcIlZQOFhcIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgW2ZsYWdzXSA9IGFycmF5QnVmZmVyUmVhZChhcnIsIDE2LCAxKTtcbiAgICAgICAgICAgICAgICAvLyBGbGFnczogUiBSIEkgTCBFIFggX0FfIFIgKHJldmVyc2VkKVxuICAgICAgICAgICAgICAgIGNvbnN0IGFuaW1hdGlvbkZsYWdNYXNrID0gMSA8PCAxO1xuICAgICAgICAgICAgICAgIHJldHVybiAoZmxhZ3MgJiBhbmltYXRpb25GbGFnTWFzaykgIT0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBcImltYWdlL2dpZlwiOiB7XG4gICAgICAgICAgICAvLyBCYXNlZCBvbiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS96YWtpcnQvZmFhNGE1OGNlYzVhNzUwNWIxMGUzNjg2YTIyNmYyODVcbiAgICAgICAgICAgIC8vIE1vcmUgaW5mbyBhdCBodHRwOi8vd3d3Lm1hdHRoZXdmbGlja2luZ2VyLmNvbS9sYWIvd2hhdHNpbmFnaWYvYml0c19hbmRfYnl0ZXMuYXNwXG4gICAgICAgICAgICBjb25zdCBkdiA9IG5ldyBEYXRhVmlldyhhd2FpdCBibG9iLmFycmF5QnVmZmVyKCksIDEwKTtcblxuICAgICAgICAgICAgY29uc3QgZ2xvYmFsQ29sb3JUYWJsZSA9IGR2LmdldFVpbnQ4KDApO1xuICAgICAgICAgICAgbGV0IGdsb2JhbENvbG9yVGFibGVTaXplID0gMDtcbiAgICAgICAgICAgIC8vIGNoZWNrIGZpcnN0IGJpdCwgaWYgMCwgdGhlbiB3ZSBkb24ndCBoYXZlIGEgR2xvYmFsIENvbG9yIFRhYmxlXG4gICAgICAgICAgICBpZiAoZ2xvYmFsQ29sb3JUYWJsZSAmIDB4ODApIHtcbiAgICAgICAgICAgICAgICAvLyBncmFiIHRoZSBsYXN0IDMgYml0cywgdG8gY2FsY3VsYXRlIHRoZSBnbG9iYWwgY29sb3IgdGFibGUgc2l6ZSAtPiBSR0IgKiAyXihOKzEpXG4gICAgICAgICAgICAgICAgLy8gTiBpcyB0aGUgdmFsdWUgaW4gdGhlIGxhc3QgMyBiaXRzLlxuICAgICAgICAgICAgICAgIGdsb2JhbENvbG9yVGFibGVTaXplID0gMyAqIE1hdGgucG93KDIsIChnbG9iYWxDb2xvclRhYmxlICYgMHg3KSArIDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBtb3ZlIG9uIHRvIHRoZSBHcmFwaGljcyBDb250cm9sIEV4dGVuc2lvblxuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gMyArIGdsb2JhbENvbG9yVGFibGVTaXplO1xuXG4gICAgICAgICAgICBjb25zdCBleHRlbnNpb25JbnRyb2R1Y2VyID0gZHYuZ2V0VWludDgob2Zmc2V0KTtcbiAgICAgICAgICAgIGNvbnN0IGdyYXBoaWNzQ29udHJvbExhYmVsID0gZHYuZ2V0VWludDgob2Zmc2V0ICsgMSk7XG4gICAgICAgICAgICBsZXQgZGVsYXlUaW1lID0gMDtcblxuICAgICAgICAgICAgLy8gR3JhcGhpY3MgQ29udHJvbCBFeHRlbnNpb24gc2VjdGlvbiBpcyB3aGVyZSBHSUYgYW5pbWF0aW9uIGRhdGEgaXMgc3RvcmVkXG4gICAgICAgICAgICAvLyBGaXJzdCAyIGJ5dGVzIG11c3QgYmUgMHgyMSBhbmQgMHhGOVxuICAgICAgICAgICAgaWYgKGV4dGVuc2lvbkludHJvZHVjZXIgJiAweDIxICYmIGdyYXBoaWNzQ29udHJvbExhYmVsICYgMHhmOSkge1xuICAgICAgICAgICAgICAgIC8vIHNraXAgdG8gdGhlIDIgYnl0ZXMgd2l0aCB0aGUgZGVsYXkgdGltZVxuICAgICAgICAgICAgICAgIGRlbGF5VGltZSA9IGR2LmdldFVpbnQxNihvZmZzZXQgKyA0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuICEhZGVsYXlUaW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSBcImltYWdlL3BuZ1wiOlxuICAgICAgICBjYXNlIFwiaW1hZ2UvYXBuZ1wiOiB7XG4gICAgICAgICAgICAvLyBCYXNlZCBvbiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNjg2MTgyOTZcbiAgICAgICAgICAgIGNvbnN0IGFyciA9IGF3YWl0IGJsb2IuYXJyYXlCdWZmZXIoKTtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBhcnJheUhhc0RpZmYoWzB4ODksIDB4NTAsIDB4NGUsIDB4NDcsIDB4MGQsIDB4MGEsIDB4MWEsIDB4MGFdLCBBcnJheS5mcm9tKGFycmF5QnVmZmVyUmVhZChhcnIsIDAsIDgpKSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDg7IGkgPCBibG9iLnNpemU7ICkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5QnVmZmVyUmVhZEludChhcnIsIGkpO1xuICAgICAgICAgICAgICAgIGkgKz0gNDtcbiAgICAgICAgICAgICAgICBjb25zdCB0eXBlID0gYXJyYXlCdWZmZXJSZWFkU3RyKGFyciwgaSwgNCk7XG4gICAgICAgICAgICAgICAgaSArPSA0O1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJhY1RMXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIklEQVRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaSArPSBsZW5ndGggKyA0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFRQSxJQUFBQSxPQUFBLEdBQUFDLE9BQUE7QUFSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFJTyxTQUFTQyxhQUFhQSxDQUFDQyxRQUFpQixFQUFXO0VBQ3REO0VBQ0EsT0FBTyxDQUFDLFdBQVcsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQ0MsUUFBUSxDQUFDRCxRQUFTLENBQUM7QUFDbkc7QUFFQSxTQUFTRSxlQUFlQSxDQUFDQyxHQUFnQixFQUFFQyxLQUFhLEVBQUVDLEdBQVcsRUFBYztFQUMvRSxPQUFPLElBQUlDLFVBQVUsQ0FBQ0gsR0FBRyxDQUFDSSxLQUFLLENBQUNILEtBQUssRUFBRUEsS0FBSyxHQUFHQyxHQUFHLENBQUMsQ0FBQztBQUN4RDtBQUVBLFNBQVNHLGtCQUFrQkEsQ0FBQ0wsR0FBZ0IsRUFBRUMsS0FBYSxFQUFVO0VBQ2pFLE1BQU1LLEVBQUUsR0FBRyxJQUFJQyxRQUFRLENBQUNQLEdBQUcsRUFBRUMsS0FBSyxF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