2

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?

  • 1
    This question is unclear, _please_ elaborate or create a fiddle. Or are you just curious how Firefox works? – WhiteHat Aug 02 '15 at 23:35

1 Answers1

3

Your file is being rejected by Firefox for at least these reasons:

  1. Firefox will reject chunks that have an incorrect CRC.

  2. The IHDR bit-depth must not be zero.

  3. 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.)

Glenn Randers-Pehrson
  • 11,940
  • 3
  • 37
  • 61
  • 1
    So I must use the CRC, in all its unsuitability for client-side Javascript, or give up the project. C'est la vei. Thank you for your answer. – Anthony Caudill Aug 03 '15 at 03:37