Skip to content

Instantly share code, notes, and snippets.

@friendlyanon
Last active March 24, 2018 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friendlyanon/c63fe71a01001ce744b94cb65a8fca1e to your computer and use it in GitHub Desktop.
Save friendlyanon/c63fe71a01001ce744b94cb65a8fca1e to your computer and use it in GitHub Desktop.
Worker addition for gif-engine-js
const getDisposals = frameObj => frameObj.graphicExtension && frameObj.graphicExtension.disposalMethod || 0;
const getDelays = frameObj => frameObj.graphicExtension && frameObj.graphicExtension.delay - 1 || 0;
const copyColorsTransparent = async (source, target, fWidth, fHeight, oLeft, oTop, cWidth, flag) => {
for (let row = 0, pointer = -1; fHeight > row; ++row)
for (let column = 0; fWidth > column; ++column) {
let offset = (column + oLeft + (row + oTop) * cWidth) * 4;
if (flag && source[pointer + 4] === 0) {
pointer += 4;
continue;
}
target[ offset] = source[++pointer];
target[++offset] = source[++pointer];
target[++offset] = source[++pointer]; ++pointer;
target[++offset] = flag ? source[pointer] : 255;
}
};
const copyColors = async (source, target, fWidth, fHeight, oLeft, oTop, cWidth) => {
for (let row = 0, pointer = -1; fHeight > row; ++row)
for (let column = 0; fWidth > column; ++column) {
let offset = (column + oLeft + (row + oTop) * cWidth) * 4;
target[++pointer] = source[ offset];
target[++pointer] = source[++offset];
target[++pointer] = source[++offset];
target[++pointer] = source[++offset];
}
};
const messageHandler = async e => {
const o = await GIF(
await (
await fetch(e.data, { headers: { pragma: "no-cache", "cache-control": "no-cache" }})
).arrayBuffer()
);
const frameCount = o.frames.length;
const compiledFrames = new Array(frameCount);
const delays = o.frames.map(getDelays);
const canvasWidth = o.descriptor.width;
const canvasHeight = o.descriptor.height;
const disposals = o.frames.map(getDisposals);
const canvas = new Uint8ClampedArray(canvasWidth * canvasHeight * 4);
let index = 0;
do {
const frame = o.frames[index];
const transparentColorFlag = frame.graphicExtension && frame.graphicExtension.transparentColorFlag;
const [
{
data: frameImageData,
width: frameWidth,
height: frameHeight
},
offsetLeft,
offsetTop
] = await o.toImageData(index);
switch(disposals[index]) {
case 2:
for (let row = 0; frameHeight > row; ++row)
for (let column = 0; frameWidth > column; ++column) {
let offset = (column + offsetLeft + (row + offsetTop) * canvasWidth) * 4;
canvas[ offset] = 0;
canvas[++offset] = 0;
canvas[++offset] = 0;
canvas[++offset] = transparentColorFlag ? 0 : 255;
} break;
case 3:
if (index > 0) {
const [
{
data: frameImageData,
width: frameWidth,
height: frameHeight
},
offsetLeft,
offsetTop
] = compiledFrames[index - 1];
await copyColors(frameImageData, canvas, frameWidth, frameHeight, offsetLeft, offsetTop, canvasWidth);
} break;
}
await copyColorsTransparent(frameImageData, canvas, frameWidth, frameHeight, offsetLeft, offsetTop, canvasWidth, transparentColorFlag);
await copyColors(canvas, frameImageData, frameWidth, frameHeight, offsetLeft, offsetTop, canvasWidth);
compiledFrames[index] = [new ImageData(frameImageData, frameWidth, frameHeight), offsetLeft, offsetTop];
} while(++index < frameCount);
postMessage([compiledFrames, delays, canvasWidth, canvasHeight]);
};
(global => {
global.onmessage = messageHandler;
global.onerror = e => {
postMessage(["log", e]);
};
})((() => this)());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment