I am attempting to allow the user to save images that have been rendered to the canvas. There may be several images and I want the user to be able to download all the images at once as a single tar file. I am trying to write the code to generate this tar file. I have most of this working, but when the tar file is downloaded to my computer at the end I discover that some of the binary data that composes the png files has been corrupted. Here is the relevant code:
var canvBuffer = $('<canvas>').attr('width', canvasWidth).attr('height', canvasHeight);
var ctxBuffer = canvBuffer[0].getContext('2d');
imgData.data.set(renderedFrames[0]);
ctxBuffer.putImageData(imgData,0,0);
var strURI = canvBuffer[0].toDataURL();
var byteString = atob(decodeURIComponent(strURI.substring(strURI.indexOf(',')+1)));
toTar([byteString]);
function toTar(files /* array of blobs to convert */){
var tar = '';
for (var i = 0, f = false, chkSumString, totalChkSum, out; i < files.length; i++) {
f = files[i];
chkSumString = '';
var content = f;
var name = 'p1.png'.padRight('\0', 100);
var mode = '0000664'.padRight('\0', 8);
var uid = (1000).toString(8).padLeft('0', 7).padRight('\0',8);
var gid = (1000).toString(8).padLeft('0', 7).padRight('\0',8);
var size = (f.length).toString(8).padLeft('0', 11).padRight('\0',12);
var mtime = '12123623701'.padRight('\0', 12); // modification time
var chksum = ' '; // enter all spaces to calculate chksum
var typeflag = '0';
var linkname = ''.padRight('\0',100);
var ustar = 'ustar \0';
var uname = 'chris'.padRight('\0', 32);
var gname = 'chris'.padRight('\0', 32);
// Construct header with spaces filling in for chksum value
chkSumString = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512);
// Calculate chksum for header
totalChkSum = 0;
for (var i = 0, ch; i < chkSumString.length; i++){
ch = chkSumString.charCodeAt(i);
totalChkSum += ch;
}
// reconstruct header plus content with chksum inserted
chksum = (totalChkSum).toString(8).padLeft('0', 6) + '\0 ';
out = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512);
out += content.padRight('\0', (512 + Math.floor(content.length/512) * 512)); // pad out to a multiple of 512
out += ''.padRight('\0', 1024); // two 512 blocks to terminate the file
tar += out;
}
var b = new Blob([tar], {'type': 'application/tar'});
window.location.href = window.URL.createObjectURL(b);
}
I am putting a previously rendered frame onto a non-rendered canvas and using the canvases toDataURL() method to an encoded png version of the frame with Base64 encoding. Next I use atob to convert this to a byte string so it can be appended to the contents of the tar file I am generating.
When I view the file in a hex editor my tar header is correct, but the contents of the png are not quite right. The ASCII contents looks normal but binary data is scrambled.
Any help offered would be greatly appreciated. Thanks.
PS
I have attached links to related posts that I have looked at. They have been helpful, but I have not yet seen anything there that fully resolves my issues. Thanks.
Convert Data URI to File then append to FormData, and Data URI to Object URL with createObjectURL in chrome/ff