P33pingtom
P33pingtom

Reputation: 63

Create a animated Gif from an array of url images in NodeJs

I have an array of urls of image which could be of different type (png, jpg) and I would like with it to build a gif, all in nodeJS.

Since I'm very new to this language I'm struggling a bit with it, any leads, ideas ?

I looked at gifencoder with this exemple :

var GIFEncoder = require('gifencoder');
var encoder = new GIFEncoder(854, 480);
var pngFileStream = require('png-file-stream');
var fs = require('fs');
pngFileStream('test/**/frame?.png')
 .pipe(encoder.createWriteStream({ repeat: -1, delay: 500, quality: 10 }))
 .pipe(fs.createWriteStream('myanimated.gif'));

What I get, it looks for png files maching the expression. Since I have an array of urls of different types of images, should I use fs.createReadStream ?

Thanks

Upvotes: 3

Views: 1777

Answers (1)

TacoEater
TacoEater

Reputation: 2268

const GIFEncoder = require("gif-encoder-2");
const { createCanvas, Image } = require("canvas");
const { createWriteStream, readdir } = require("fs");
const { promisify } = require("util");
const path = require("path");
const fs = require("fs");

var outputDir = path.join(__dirname, "/output")


const createGif = async (fileName, frameURLs) => {
  return new Promise(async resolve1 => {
    try {
      // find the width and height of the image
      const [width, height] = await new Promise(resolve2 => {
        const image = new Image();
        image.onload = () => resolve2([image.width, image.height]);
        image.src = frameURLs[0];
      });

      // base GIF filepath on which algorithm is being used
      const dstPath = path.join(__dirname, "/output", `${fileName}.gif`);
      // create a write stream for GIF data
      const writeStream = createWriteStream(dstPath);
      // when stream closes GIF is created so resolve promise
      writeStream.on("close", () => {
        resolve1(dstPath);
      });

      // encode with the neuquant algorithm
      const encoder = new GIFEncoder(width, height, "neuquant");
      // pipe encoder's read stream to our write stream
      encoder.createReadStream().pipe(writeStream);
      encoder.start();
      encoder.setDelay(200);

      const canvas = createCanvas(width, height);
      const ctx = canvas.getContext("2d");

      // draw an image for each file and add frame to encoder
      const promisses = frames.map(frame => {
        return new Promise(resolve3 => {
          const image = new Image();
          image.onload = () => {
            ctx.drawImage(image, 0, 0);
            encoder.addFrame(ctx);
            resolve3();
          };
          image.src = frame; // set the frame url
        });
      });
      // run all the frame promisses
      await Promise.all(promisses);
      // close the writing stream
      writeStream.close();
    } catch (error) {
      console.error("error");
      console.error(error);
      throw error;
    }
  });
};

Upvotes: 1

Related Questions