UNPKG

@unlazy/core

Version:

Universal lazy loading library for placeholder images leveraging native browser APIs

129 lines (127 loc) 2.16 kB
/** * Encodes an RGBA image to a PNG data URI. RGB should not be premultiplied by A. * * @remarks * This is optimized for speed and simplicity and does not optimize for size * at all. This does not do any compression (all values are stored uncompressed). * * @see https://github.com/evanw/thumbhash * @author Evan Wallace * @license MIT */ function rgbaToDataUri(w, h, rgba) { const row = w * 4 + 1; const idat = 6 + h * (5 + row); const bytes = [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, w >> 8, w & 255, 0, 0, h >> 8, h & 255, 8, 6, 0, 0, 0, 0, 0, 0, 0, idat >>> 24, idat >> 16 & 255, idat >> 8 & 255, idat & 255, 73, 68, 65, 84, 120, 1 ]; const table = [ 0, 498536548, 997073096, 651767980, 1994146192, 1802195444, 1303535960, 1342533948, -306674912, -267414716, -690576408, -882789492, -1687895376, -2032938284, -1609899400, -1111625188 ]; let a = 1; let b = 0; for (let y = 0, i = 0, end = row - 1; y < h; y++, end += row - 1) { bytes.push(y + 1 < h ? 0 : 1, row & 255, row >> 8, ~row & 255, row >> 8 ^ 255, 0); for (b = (b + a) % 65521; i < end; i++) { const u = rgba[i] & 255; bytes.push(u); a = (a + u) % 65521; b = (b + a) % 65521; } } bytes.push( b >> 8, b & 255, a >> 8, a & 255, 0, 0, 0, 0, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ); for (let [start, end] of [[12, 29], [37, 41 + idat]]) { let c = -1; for (let i = start; i < end; i++) { c ^= bytes[i]; c = c >>> 4 ^ table[c & 15]; c = c >>> 4 ^ table[c & 15]; } c = ~c; bytes[end++] = c >>> 24; bytes[end++] = c >> 16 & 255; bytes[end++] = c >> 8 & 255; bytes[end++] = c & 255; } const base64 = globalThis.btoa(String.fromCharCode(...bytes)); return `data:image/png;base64,${base64}`; } export { rgbaToDataUri as r };