@remotion/gif
Version:
Embed GIFs in a Remotion video
119 lines (118 loc) • 3.64 kB
JavaScript
;
/* eslint-disable no-multi-assign */
/* eslint-disable no-redeclare */
/* eslint-disable no-var */
/**
* javascript port of java LZW decompression
* Original java author url: https://gist.github.com/devunwired/4479231
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.lzw = void 0;
const lzw = (minCodeSize, data, pixelCount) => {
const MAX_STACK_SIZE = 4096;
const nullCode = -1;
const npix = pixelCount;
let available;
let code_mask;
let code_size;
let in_code;
let old_code;
var bits;
let code;
let i;
var datum;
var first;
var top;
var bi;
var pi;
const dstPixels = new Array(pixelCount);
const prefix = new Array(MAX_STACK_SIZE);
const suffix = new Array(MAX_STACK_SIZE);
const pixelStack = new Array(MAX_STACK_SIZE + 1);
// Initialize GIF data stream decoder.
const data_size = minCodeSize;
const clear = 1 << data_size;
const end_of_information = clear + 1;
available = clear + 2;
old_code = nullCode;
code_size = data_size + 1;
code_mask = (1 << code_size) - 1;
for (code = 0; code < clear; code++) {
prefix[code] = 0;
suffix[code] = code;
}
// Decode GIF pixel stream.
var datum;
var bits;
var first;
var top;
var pi;
var bi;
datum = bits = first = top = pi = bi = 0;
for (i = 0; i < npix;) {
if (top === 0) {
if (bits < code_size) {
// get the next byte
datum += data[bi] << bits;
bits += 8;
bi++;
continue;
}
// Get the next code.
code = datum & code_mask;
datum >>= code_size;
bits -= code_size;
// Interpret the code
if (code > available || code === end_of_information) {
break;
}
if (code === clear) {
// Reset decoder.
code_size = data_size + 1;
code_mask = (1 << code_size) - 1;
available = clear + 2;
old_code = nullCode;
continue;
}
if (old_code === nullCode) {
pixelStack[top++] = suffix[code];
old_code = code;
first = code;
continue;
}
in_code = code;
if (code === available) {
pixelStack[top++] = first;
code = old_code;
}
while (code > clear) {
pixelStack[top++] = suffix[code];
code = prefix[code];
}
first = suffix[code] & 0xff;
pixelStack[top++] = first;
// add a new string to the table, but only if space is available
// if not, just continue with current table until a clear code is found
// (deferred clear code implementation as per GIF spec)
if (available < MAX_STACK_SIZE) {
prefix[available] = old_code;
suffix[available] = first;
available++;
if ((available & code_mask) === 0 && available < MAX_STACK_SIZE) {
code_size++;
code_mask += available;
}
}
old_code = in_code;
}
// Pop a pixel off the pixel stack.
top--;
dstPixels[pi++] = pixelStack[top];
i++;
}
for (i = pi; i < npix; i++) {
dstPixels[i] = 0; // clear missing pixels
}
return dstPixels;
};
exports.lzw = lzw;