Skip to content

Instantly share code, notes, and snippets.

@anacampesan
Last active April 24, 2023 12:02
Show Gist options
  • Save anacampesan/d451168e38d6fd0a6a9fcc32e98a5038 to your computer and use it in GitHub Desktop.
Save anacampesan/d451168e38d6fd0a6a9fcc32e98a5038 to your computer and use it in GitHub Desktop.
GIF Frame Disposal Correction Algorithm
function explodeGif(gifUrl) {
return gifler(gifUrl)._animatorPromise.then(function(gif) {
let current = createTempCanvas(gif.width, gif.height, 'current');
let currentCtx = current.getContext('2d');
let temp = createTempCanvas(gif.width, gif.height, 'temp');
let tempCtx = temp.getContext('2d');
gif._animationLength = 0;
for (let i = 0; i < gif._frames.length; i++) {
let cFrame = gif._frames[i]; // current frame
gif._animationLength += cFrame.delay;
switch (cFrame.disposal) { // how to recover AFTER drawing the frame
case 2: // dispose to background (fill frame rect with transparency)
tempCtx.putImageData(new ImageData(cFrame.pixels, gif.width, gif.height), 0, 0);
currentCtx.drawImage(temp, cFrame.x, cFrame.y, cFrame.width, cFrame.height, cFrame.x, cFrame.y, cFrame.width, cFrame.height);
gif._frames[i].data = currentCtx.getImageData(0, 0, gif.width, gif.height);
currentCtx.clearRect(cFrame.x, cFrame.y, cFrame.width, cFrame.height);
break;
case 3: // dispose to previous (restore frame rect)
tempCtx.putImageData(new ImageData(cFrame.pixels, gif.width, gif.height), 0, 0);
let prev = currentCtx.getImageData(cFrame.x, cFrame.y, cFrame.width, cFrame.height);
currentCtx.drawImage(temp, cFrame.x, cFrame.y, cFrame.width, cFrame.height, cFrame.x, cFrame.y, cFrame.width, cFrame.height);
gif._frames[i].data = currentCtx.getImageData(0, 0, gif.width, gif.height);
currentCtx.putImageData(prev, cFrame.x, cFrame.y);
break;
default: // do not dispose (none or unspecified)
tempCtx.putImageData(new ImageData(cFrame.pixels, gif.width, gif.height), 0, 0);
currentCtx.drawImage(temp, cFrame.x, cFrame.y, cFrame.width, cFrame.height, cFrame.x, cFrame.y, cFrame.width, cFrame.height);
gif._frames[i].data = currentCtx.getImageData(0, 0, gif.width, gif.height);
break;
}
}
return gif;
});
}
@anacampesan
Copy link
Author

This snipped explodes a GIF (splits into frames) and prepares it to be rendered on a canvas element, which includes fixing the frame disposal. The lib Gifler or any other of your choice is required.
http://themadcreator.github.io/gifler/assets/gifler.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment