Skip to content

Instantly share code, notes, and snippets.

@LingDong-
Created September 15, 2023 00:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LingDong-/e0a312fd826d28ac68c51a33fbfd40a9 to your computer and use it in GitHub Desktop.
Save LingDong-/e0a312fd826d28ac68c51a33fbfd40a9 to your computer and use it in GitHub Desktop.
minimal animated GIF encoder in 50 lines
// encode_anim_gif.js
// minimal code to make animated GIFs from arrays of pixels
// - no compression
// - supports 127 colors (127 shades of gray by default)
function encode_anim_gif(frames,w,h,delay=5){
let bytes = [];
bytes.push(0x47,0x49,0x46,0x38,0x39,0x61);
bytes.push(w&0xff);
bytes.push((w>>8)&0xff);
bytes.push(h&0xff);
bytes.push((h>>8)&0xff);
bytes.push(0xf6);
bytes.push(0,0);
for (let i = 0; i < 127; i++){
bytes.push(i*2,i*2,i*2); //change this for alternative color table
}
bytes.push(0xff,0xff,0xff);
bytes.push(0x21,0xff,0x0b);
bytes.push(0x4E,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2E,0x30);
bytes.push(0x03,0x01,0xff,0xff,0x00);
for (let k = 0; k < frames.length; k++){
let data = frames[k];
bytes.push(0x21,0xf9,0x04,0b00000100);
bytes.push(delay&0xff); // change this for different delay each frame
bytes.push((delay>>8)&0xff);
bytes.push(0xff,0x00);
bytes.push(0x2c,0,0,0,0);
bytes.push(w&0xff);
bytes.push((w>>8)&0xff);
bytes.push(h&0xff);
bytes.push((h>>8)&0xff);
bytes.push(0,7);
let n = ~~(w*h/126);
let inc = n*126;
let exc = w*h-inc;
for (let i = 0; i < n; i++){
bytes.push(0x7f,0x80);
for (let j = 0; j < 126; j++){
bytes.push(~~(data[i*126+j]/2));
}
}
if (exc){
bytes.push(exc+1);
bytes.push(0x80);
for (let i = 0; i < exc; i++){
bytes.push(~~(data[inc+i]/2));
}
}
bytes.push(0x01,0x81,0x00);
}
bytes.push(0x3B);
return bytes;
}
// ------ end library -------
// ----- begin example ------
let frames = [];
let W = 255;
let H = 255;
for (let k = 0; k < 100; k++){
let data = [];
for (let i = 0; i < H; i++){
for (let j = 0; j < W; j++){
data.push((j+k*5)%255);
}
}
frames.push(data);
}
const fs = require('fs');
fs.writeFileSync("test.gif",Buffer.from(encode_anim_gif(frames,W,H,10)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment