Put generated PNG image into JSZip

Polygon picture Polygon · Jun 1, 2016 · Viewed 7.5k times · Source

I am using JSZip to make a program that generates the image data from a canvas element and puts the image into a zip file.

Right now, it is turning the canvas image into an DataURL. Then, I get rid of the part of the resulting string that says data:image/png;base64,. Now, there is nothing left but the base64 data. I then use atob to change it to ascii.

It seems like putting the remaining string into an image file should work, but the generated ascii text is not correct. Many parts of it are correct, but something is not right.

Here is my code:

//screen is the name of the canvas.
var imgData = screen.toDataURL();
imgData = imgData.substr(22);
imgData = atob(imgData);
console.log(imgData);

Here is an image of the resulting png file (in notepad): incorrect text http://upurs.us/image/71280.png

And here is what is should look like: correct text http://upurs.us/image/71281.png

As you can see, there are slight differences, and I have no idea why. I know absolutely nothing about the PNG file type or ASCII, so I don't know where to go from here.

If you want to see all my work, here's the project: http://s000.tinyupload.com/download.php?file_id=09682586927694868772&t=0968258692769486877226111

EDIT: My end goal is to have a program that exports every single frame of a canvas animation so that I can use them to make a video. If anyone knows a program that does that, please post it!

Answer

David Duponchel picture David Duponchel · Jun 1, 2016

When you use zip.file("hello.png", imgData) where imgData is a string, you tell JSZip to save an (unicode) string. Since it's not a textual content, you get a corrupted content. To fix that, you can do:

zip.file("hello.png", imgData, {binary: true})

As dandavis suggested, using a blob will be more efficient here. You can convert a canvas to a blob with canvas.toBlob:

screen.toBlob(function (blob) {
  zip.file("hello.png", blob);
});

The only caveat is that toBlob is asynchronous: you should disable the download button during that time (or else, if a user is quick enough or the browser slow enough, zip.file won't be executed and you will give an empty zip to your user).

document.getElementById("download_button").disabled = true;
screen.toBlob(function (blob) {
  zip.file("hello.png", blob);
  document.getElementById("download_button").disabled = false;
});