Closed arnaudambro closed 5 years ago
There seem to be 2 conflicting questions here. One is about how to use a GIF with fs
(as that's what the code example is using) and another about calling back with the contents from a promise. I'll address them independently:
Our library outputs the GIF as data, not as an DOM element or similar. To aggregate this content, you can collect the stream into a buffer or pass it along to its target
https://nodejs.org/api/stream.html
The former has the benefit of being able to re-encode the data in a desired format (e.g. converting to a base64 image URL to reuse in a DOM element):
// Using `concat-stream` to simplify collecting content -- could be done with `gif.read()` and `gif.on('readable')`
var gif = new GifEncoder(width, height);
var gifFile = fs.createWriteStream(fileName);
gif.pipe(concatStream(function (gifBuff) {
// gifBuff is raw image data in Buffer format
// Convert our image to a data URI
// https://css-tricks.com/data-uris/
var img = new Image();
img.src = 'data:image/gif;base64' + gifBuff.toString('base64');
// Add image to page
document.body.appendChild(img);
});
gif.writeHeader();
gif.addFrame(pixels);
gif.finish();
The latter has the benefit of being not as memory intensive so it might better suit usage with zipping. In that case, we'd use the gif.pipe
from your earlier code sample
I believe that a promise expects all the contents to be collected in a single buffer. If that's not the case (e.g. it can return a stream), then simply resolve(gif)
immediately (or on process.nextTick
to avoid unexpected synchronous behavior for an async action)
Here's how to do it with calling back the buffer:
const pixelsToGIF = (pixels, fileName, width, height) =>
new Promise((resolve, reject) => {
const gif = new GifEncoder(width, height);
gif.pipe(concatStream(resolve)); // Calls back to `resolve` with the `gifBuff` buffer
gif.writeHeader();
gif.addFrame(pixels);
gif.finish();
gif.on('error', reject);
})
Great explanation, thanks !
So to make it clear (because I didn't get the first time your comment // Using 'concat-stream' to simplify collecting content
), to make it work we use the lib concat-stream and the final code is the following :
import GifEncoder from 'gif-encoder';
import concat from 'concat-stream';
const pixelsToGIF = (pixels, fileName, width, height) =>
new Promise((resolve, reject) => {
const gif = new GifEncoder(width, height);
gif.pipe(concat(resolve));
gif.writeHeader();
gif.addFrame(pixels);
gif.finish();
gif.on('error', reject);
});
thanks a lot for your help and great explanation, I spent a few hours on it yesterday, and I wouldn't have make it by myself !
May I ask you another question : when I want to export a DOM Node with some elements overflowing, the export is "corrupted", or let say really really distorted. I guess it is because the dom-to-image
lib is exporting pixel data, and there are too many pixels to fit within the width
and height
we also give as an input.
But as we use those width
and height
parameters both with dom-to-image
and gif-encoder
libs, I don't know where the distorsion happens, and where (and how) it should be corrected : I guess we would have to filter the pixel data removing all the overflowing pixels just before it goes to gif-encoder
, do you agree ?
Yea, I'd say that sanitizing the output of dom-to-image seems right. Otherwise this and all other image generating libraries would be doing a lot more work =P
For what it's worth, it might be easier if you use a library like save-pixels thought that introduces more overhead of libraries to bundle
On Mon, Oct 22, 2018, 4:19 AM Arnaud Ambroselli notifications@github.com wrote:
May I ask you another question : when I want to export a DOM Node with some elements overflowing, the export is "corrupted", or let say really really distorted. I guess it is because the dom-to-image lib is exporting pixel data, and there are too many pixels to fit within the width and height we also give as an input. But as we use those width and height parameters both with dom-to-image and gif-encoder libs, I don't know where the distorsion happens, and where (and how) it should be corrected : I guess we would have to filter the pixel data removing all the overflowing pixels just before it goes to gif-encoder, do you agree ?
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/twolfson/gif-encoder/issues/16#issuecomment-431801996, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3FWMEHuRinNHH1aQtI6n1679jcOqiZks5unamqgaJpZM4XtF4N .
Hi there,
I want to thank you for your lib, but I can't yet because I couldn't make it work :)
I am trying to create a gif on client-side, starting with the DOM. I use for that the lib dom-to-image which, thanks to it's method
toPixelData
, return some pixels. Then I want these pixels to give me a gif. I thought about using a Promise for that because the last step is to put this gif in a ZIP file created by JSZip.Anyway, so here is my Promise, and it's not returning what I want, could you help please ?