How to add watermark to an animated gif image using jimp javascript?

Solution 1:

Confusingly, Jimp only deals with single frame GIFs, not the multi-frame animated GIFs that most people think of. So you need to use gifwrap.

From there you could iterate over each frame in the multi-frame GIF. Each frame is a GifFrame, which can be converted back and forth to a Jimp instance (see Leveraging Jimp in the docs). You can add your watermark to each Jimp instance that corresponds to a GifFrame. Something like this:

async function getGifFramesWithWatermarks(gifPath) {
  const readGif = await GifUtil.read(gifPath);
  const promises = readGif.frames.map(getGifFrameWithWatermark);
  const gifFramesWithWatermarks = await Promise.all(promises);

  return gifFramesWithWatermarks;
}

async function getGifFrameWithWatermark(gifFrame) {
  const jimpImage = GifUtil.copyAsJimp(Jimp, gifFrame);

  addWatermark(jimpImage); // function you will write

  return new GifFrame(jimpImage.bitmap, {
    disposalMethod: gifFrame.disposalMethod, // not documented by gifwrap but it's in the source
    delayCentisecs: gifFrame.delayCentisecs, // you'll probably want this
  });
}

const gifFramesWithWatermarks = await getGifFramesWithWatermark(GIF_PATH);
await GifUtil.write(WRITE_PATH, gifFramesWithWatermarks);

Solution 2:

UPDATE i wrote this npm library that you can use to write text on gif. its still has some bugs tho: https://www.npmjs.com/package/text-on-gif

this worked for me

const Jimp = require("jimp");
const { GifUtil,GifFrame,BitmapImage} = require('gifwrap');
var frames = [];

Jimp.loadFont(Jimp.FONT_SANS_32_WHITE).then(async function(font){
    await GifUtil.read("gif.gif").then(inputGif => {
        inputGif.frames.forEach(function(frame){
            jimpCopied = GifUtil.copyAsJimp(Jimp, frame);
            jimpCopied.print(font,0,0,"sanidhya");
            const GifCopied = new GifFrame(new BitmapImage(jimpCopied.bitmap,{
                disposalMethod: frame.disposalMethod,
                delayCentisecs: frame.delayCentisecs,
            }));
        frames.push(GifCopied);   
        });
    });
    GifUtil.quantizeDekker(frames);
    GifUtil.write("nyahhaha.gif",frames);
});

NOTE

the qunatize*() function is needed only if your Frame uses more than 256 color indexes