how to save canvas data to file
Here is a literal example of how to save canvas data to a file in Nodejs. The variable img
is a string generated by canvas.toDataURL()
. I've assumed you already know how to POST that string from the browser to your Nodejs server.
HTML snippet that generates the sample image I used:
<canvas id="foo" width="20px" height="20px"></canvas>
<script>
var ctx = $('#foo')[0].getContext('2d');
for (var x = 0; x < 20; x += 10) {
for (var y = 0; y < 20; y += 10) {
if (x == y) { ctx.fillStyle = '#000000'; }
else { ctx.fillStyle = '#8888aa'; }
ctx.fillRect(x, y, 10, 10);
}
}
console.log($('#foo')[0].toDataURL());
</script>
Nodejs snippet to decode the base64 data and save the image:
const fs = require("fs").promises;
(async () => {
// string generated by canvas.toDataURL()
const img = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0"
+ "NAAAAKElEQVQ4jWNgYGD4Twzu6FhFFGYYNXDUwGFpIAk2E4dHDRw1cDgaCAASFOffhEIO"
+ "3gAAAABJRU5ErkJggg==";
// strip off the data: url prefix to get just the base64-encoded bytes
const data = img.replace(/^data:image\/\w+;base64,/, "");
const buf = Buffer.from(data, "base64");
await fs.writeFile("image.png", buf);
})();
Output:
I believe that Canvas
does not store it's data in Base64 internally. It should store data in some much more efficient binary format. So, obviously, transferring to base64 and back to binary PNG is terribly slow and memory consuming.
Quick googling to node canvas documentation gives:
To create a PNGStream simply call canvas.pngStream(), and the stream will start to emit data events, finally emitting end when finished. If an exception occurs the error event is emitted.
var fs = require('fs')
, out = fs.createWriteStream(__dirname + '/text.png')
, stream = canvas.pngStream();
stream.on('data', function(chunk){
out.write(chunk);
});
stream.on('end', function(){
console.log('saved png');
});
Currently only sync streaming is supported. If you want to do it async, you can try to use a worker or cluster (I personally never tried this).