Reputation: 41
Looking at the APNG spec, it seems that APNGs are PNGs which describe the frames after the first in their "extra" chunks". So it seems like it'd be feasible to create APNGs in Javascript easily by just compositing PNG headers and appending dataURIs to them. However it's not going well.
function compileAPNG (frames, width, height, fps) {
var fromCharCode = String.fromCharCode;
var CRC = fromCharCode(0, 0, 0, 0);
var pngData = fromCharCode(137, 80, 78, 71, 13, 10, 26, 10);
pngData += fromCharCode(0, 0, 0, 13) + "IHDR" + convertIntToBytes(width) + convertIntToBytes(height) + fromCharCode(0, 0, 0, 0, 0) + CRC
pngData += fromCharCode(0, 0, 0, 8) + "acTL" + convertIntToBytes(frames.length) + fromCharCode(0, 0, 0, 0) + CRC;
pngData += fromCharCode(0, 0, 0, 25) + "fcTL" + fromCharCode(0, 0, 0, 0) + convertIntToBytes(width) + convertIntToBytes(height);
pngData += fromCharCode(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + convertShortToBytes(fps) + fromCharCode(1, 0) + CRC;
pngData += convertIntToBytes(frames[0].toDataURL().length) + "IDAT" + frames[0].toDataURL() + CRC;
for (index = 1; index < frames.length; index++) {
pngData += fromCharCode(0, 0, 0, 25) + "fcTL" + fromCharCode(0, 0, 0, 0) + convertIntToBytes(width) + convertIntToBytes(height);
pngData += fromCharCode(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + convertShortToBytes(fps) + fromCharCode(1, 0) + CRC;
pngData += convertIntToBytes(frames[index].toDataURL().length) + "fdAT" + convertIntToBytes(index) + frames[index].toDataURL() + CRC;
}
pngData += fromCharCode(0, 0, 0, 0) + "IEND" + CRC;
window.open("data:image/png;base64," + btoa(pngData));
}
The CRC calcs are computationally expensive, so I tried to fudge them by setting them all to 0. Is this why Firefox doesn't accept the dataURI as an image?
Upvotes: 2
Views: 230
Reputation: 12465
Your file is being rejected by Firefox for at least these reasons:
Firefox will reject chunks that have an incorrect CRC.
The IHDR bit-depth must not be zero.
The sequence numbers on the fcTL chunks and fdAT chunks, except for the first fcTL chunk, must not be zero (must be 0001, 0002, etc.)
Upvotes: 3