out-of-your-element/d2m/converters/lottie.js

49 lines
1.4 KiB
JavaScript
Raw Normal View History

2023-09-10 09:35:51 +00:00
// @ts-check
2024-03-04 04:02:38 +00:00
const assert = require("assert")
2024-01-18 03:54:09 +00:00
const stream = require("stream")
2024-07-20 13:30:07 +00:00
const {PNG} = require("@cloudrac3r/pngjs")
2023-09-10 09:35:51 +00:00
const SIZE = 160 // Discord's display size on 1x displays is 160
/**
* @typedef RlottieWasm
* @prop {(string) => boolean} load load lottie data from string of json
* @prop {() => number} frames get number of frames
* @prop {(frameCount: number, width: number, height: number) => Uint8Array} render render lottie data to bitmap
*/
const Rlottie = (async () => {
const Rlottie = require("./rlottie-wasm.js")
await new Promise(resolve => Rlottie.onRuntimeInitialized = resolve)
return Rlottie
})()
/**
2024-01-18 03:54:09 +00:00
* @param {string} text
* @returns {Promise<import("stream").Readable>}
2023-09-10 09:35:51 +00:00
*/
2024-01-18 03:54:09 +00:00
async function convert(text) {
2023-09-10 09:35:51 +00:00
const r = await Rlottie
/** @type RlottieWasm */
const rh = new r.RlottieWasm()
const status = rh.load(text)
2024-03-04 04:02:38 +00:00
assert(status, `Rlottie unable to load ${text.length} byte data file.`)
2023-09-10 09:35:51 +00:00
const rendered = rh.render(0, SIZE, SIZE)
let png = new PNG({
width: SIZE,
height: SIZE,
bitDepth: 8, // 8 red + 8 green + 8 blue + 8 alpha
colorType: 6, // RGBA
inputColorType: 6, // RGBA
inputHasAlpha: true,
})
png.data = Buffer.from(rendered)
2024-03-04 04:02:38 +00:00
// png.pack() is a bad stream and will throw away any data it sends if it's not connected to a destination straight away.
// We use Duplex.from to convert it into a good stream.
return stream.Duplex.from(png.pack())
2023-09-10 09:35:51 +00:00
}
module.exports.convert = convert
2024-01-18 03:54:09 +00:00
module.exports.SIZE = SIZE