Date: Mon, 30 Aug 2004 08:39:25 -0700 From: Chris Nokleberg each frame has an index of some sort, the decoder should even be able to fixup images that have been mangled by apng-unaware editors. If it encounters an out-of-sequence frame, it can just buffer it as long as necessary. Keeping each frame within a single chunk makes this a bit easier to do, but even multiple chunks per frame is possible if each ADAT or whatever contains both the frame index and an ADAT-within-frame index. Chris Date: Mon, 30 Aug 2004 08:54:43 -0700 (PDT) From: Thomas Boutell You had me until you got to the part about the index numbers in frames. Please, no! Implementation simplicity, especially for the decoders, is the whole point. This would introduce an element of unfortunate comedy that implementers would just... flee from. We just can't mung the simplicity thing up. Not to mention the space overhead. It would be much better, if we're going to go with ancillary chunks, to go with the nested approach (no one has really convinced me that there is anything truly evil about this on any level, other than the aesthetic) or, if we just can't live with that, live with the reality that applications which try to edit PNGs and preserve ancillary chunks will need to be updated pronto to respect a new requirement that ancillary chunk order not be changed. It wouldn't surprise me if the idea of nesting structured things in a single ancillary chunk had been mentioned during the original discussion of ancillary chunks and whether their order had to be preserved. It's a perfectly valid notion and it meets all of our compatibility goals perfectly. But just in case we can't agree to that approach, does anybody know of any real-world PNG editing applications that (1) preserve ancillary chunks they don't directly understand and (2) don't preserve their order in practice? Date: Mon, 30 Aug 2004 11:59:16 -0700 From: Stuart Parmenter I think I would much prefer seeing seperate nocopy chunks per frame instead of having a single chunk with all the frames in it. Having a single chunk with all the frames in it won't work at all if you are trying to do server push since you may not know the actual chunk size ahead of time. The single frames would still have the size limitation, but it wouldn't be as big of one... I hate putting this limit in, despite agreeing that people probably shouldn't make multi-GB animations. I can only assume that the reason for multiple consecutive IDATs was to avoid the chunk size problem... Date: Mon, 30 Aug 2004 12:15:36 -0700 (PDT) From: Thomas Boutell You're right, Stuart, this is a major limitation. I think it's probably a dealbreaker. This is the very reason why multiple IDATs to complete a single PNG image are allowed. If only we hadn't imposed the "don't have to preserve the ordering of ancillary chunks" rule. OK, so what would be so terrible about multiple ancillary nocopy chunks after IDAT? Tools like pngcrush and so forth would lose them until they are upgraded to know how to handle them... but they will be upgraded; we have pretty good contact with the parties involved. The vast majority of editing tools don't attempt to preserve ancillary chunks at all, ever, and would just resave that first frame in any case. The nocopy behavior would prevent them from being preserved *in the wrong order* by applications that do try to respect ancillary chunks, which is definitely worse than dropping them. And browsers would still do the right thing. Date: Mon, 30 Aug 2004 13:47:15 -0700 (PDT) From: Thomas Boutell We could, however, if we really feel it is absolutely necessary, put in a one-byte sequence number with each frame, the idea being to verify that this reordering has not happened and reject the APNG if it has -- NOT to ask the player to try to cope or fix the image or wait to display frames in order. Personally I would rather just document the potential for this rare problem and the best practices to avoid it. Date: Mon, 30 Aug 2004 14:27:01 -0700 From: Vladimir Vukicevic I agree; adding in frame numbers and whatnot to be handled by apps that would already know not to reoder the adAt chunks seems like a not very useful exercise. :) Date: Mon, 30 Aug 2004 14:59:39 -0700 From: Vladimir Vukicevic Should this be a showstopper, we can add some sort of LINK chunk with a 32-bit value that must appear at the end of every adAt chunk that's followed by another with another LINK chunk appearing at the beginning of the following chunk, to make detection of out of order chunks possible without introducing chunk numbering. I don't understand why this would be necessary, however. Date: Mon, 30 Aug 2004 14:59:48 -0700 (PDT) From: Thomas Boutell like to go the "all in one chunk" route too, but it completely rules out support for outputting an APNG animation while you are still generating it and do not know the final size. Date: Mon, 30 Aug 2004 15:07:17 -0700 (PDT) From: Thomas Boutell The potential need stems from the fact that, according to the PNG spec, fully compliant existing applications could read a PNG with ancillary chunks it in it, then decide to write the PNG out again with those chunks in any order, even if the ancillary chunks are marked "unsafe to copy" -- provided that the application does not alter the image data or other critical chunks in any way. An example would be an application that adds text annotations to existing PNGs but does not otherwise modify them. I do not think that this is likely to happen with any frequency and for the reasons I have previously explained I think it is something we can live with, however the "cheapest" way to detect the resulting damage -- if we decide it's worth the trouble -- is to include a one-byte sequence number field at the start of each aDAt. If those are not consecutive (wrapping around from 255 to 0 of course) then we know the animated PNG has been munged by an old, non-APNG-aware annotation application and we reject it. We *don't* try to reconstruct the order -- we just flag the situation, don't try to show the animation and, ideally, tell the user what happened. From: Glenn Randers-Pehrson Date: Mon, 30 Aug 2004 18:44:42 -0400 The ordering problem is trouble. You can deal with it by putting sequence numbers in the chunks and checking if they are in the correct order. Let's assume that out-of-order chunks would be a rare condition, so it would be sufficient to bail out with an error message, and leave it to pngcrush or some other QA program to put them back in the right order according to the sequence numbers. Requiring the browser to buffer them and display them in the right order is a killer. You'd run out of memory reordering a thousand frames that got reversed (probably deliberatly as a DOS scheme). Date: Mon, 30 Aug 2004 17:43:29 -0700 (PDT) From: Thomas Boutell But I am perfectly willing to accept a one-byte ordinal field in the aDAt chunks as a check for this problem, I accept it is possible. > You stated your reality that "there are very few such non-image-altering, > ancillary-chunk-manipulating applications", I was attempting to point out > that, in my reality, they seem to be quite signifiant applications. Okay, I accept the need for the one-byte ordinal field to detect such problems. Date: Mon, 30 Aug 2004 19:17:30 -0700 (PDT) From: Thomas Boutell If we have an ordinal field to test for actual order munging and a single new type of ancillary PNG chunk, which we repeat, then I see a few likely scenarios when a PNG-compliant editor modifies the datastream: 1. All the aPNg chunks are preserved in the right order, hooray. 2. All the aPNg chunks get dumped. Straightforward fallback behavior here. 3. The aPNg chunks get preserved, but in reverse order (as in your stack example). In this case we spot the problem right off the bat 255/256ths of the time, or by the second animation frame 100% of the time. So the fallback behavior is again the same. We can use two byte ordinals to increase the odds of first-frame problem detection... but it's not worth it, IMHO. We can consider not starting progressive display of animation frames until we receive the beginning of the second aPNg. This greatly improves the likelihood of elegant user-perceived fallback to the basic PNG. 4. The aPNg chunks get preserved, but in a random order. Typically we spot this right off using the techniques above. In fairly rare cases, we don't (perhaps the application is tossing the ancillary chunks into a hash data structure of some sort, but through sheer chance the first two or three come out in order). But we always spot it eventually and can detect this and tell the user what the problem is when they open the PNG again in an APNG-aware editing tool. 5. Only one of the aPNg chunks is preserved. I don't think this is likely and I know it's not good editor behavior. It's only a problem if the only one preserved is the first one. If we think this is likely, we can add an end marker distinct from IEND that always comes in an aPNg unto itself which is not the first one and includes the total number of frames in the sequence. That way, if the AEND is missing *or* we only get an AEND and the framecount isn't zero, we know to flag the animation as munged. From: John Bowler Date: Mon, 30 Aug 2004 20:02:27 -0700 BTW I believe a 4 byte sequence is highly desireable. It means that a special purpose program can fix up out of order chunks unambiguously and that long ranges of dropped data can be handled too. If you want to save space squash multiple frames into each chunk - that saves 12 bytes a frame even without the sequence number. Date: Mon, 30 Aug 2004 20:19:08 -0700 (PDT) From: Thomas Boutell Oooooooo. Yeah. I like this [multiple frames per chunk] a lot. Date: Tue, 31 Aug 2004 05:37:49 +0000 From: "Adam M. Costello" One remaining concern is that if you want to insert a few frames near the beginning, you need to reread the entire remainder of the animation so you can update the sequence numbers and the CRCs. Maybe we can live with that. From: John Bowler Date: Tue, 31 Aug 2004 09:12:34 -0700 I'm saying "Decoders shall verify the sequence numbers and, if chunks are present out of order shall ignore the animation data completely. A decoder is permitted to commence display if the first two chunks (0 and 1) are present, chunks shall be displayed in order, if a chunk is missing display shall cease at that point. If the first chunk (0) contains frame data the decoder must assume it contains all the data and shall not decode or display any further chunks." Date: Wed, 1 Sep 2004 17:04:11 -0400 From: Cosmin Truta Having a chunk in a chunk adds up unnecessary complexity. Why are chunk headers needed, if aDAT serves as a chunk header already? Why should the CRC32 be calculated twice, once for the internal chunks, then again for aDAT? I think there is a better approach: - Define an aHDR chunk, whose definition is a concatenation of the fCTL+IHDR fields (16+13 bytes) - Redefine the aDAT chunk to work as IDAT: first the zlib header, then the compressed bytes, then the Adler32 checksum. This stream could be split across multiple aDAT chunks. This would yield IHDR aCTL IDAT aHDR aDAT aDAT aHDR aDAT aDAT aDAT IEND If you worry about reordering, then you could simply concatenate the fields in my versions of aHDR+aDAT; in other words, you could define aDAT as follows: - first 16 bytes as in fCTL - next 13 bytes as in IHDR - next bytes make up the zlib stream, possibly split across multiple aDAT's. Which would yield IHDR aCTL IDAT aHDR aDAT aDAT aDAT IEND Date: Wed, 1 Sep 2004 14:24:38 -0700 (PDT) From: Thomas Boutell Spec-compliant PNG editing tools can and will scramble the order of all of these aHDR and aDAT tags utterly and completely. I've had to repeat this enough times that I'm not sure people are really getting it. OK, maybe most tools won't really do that, but we can't prove they won't and it only takes one example to prove they will. This is the only reason I favor a "superchunk" (heh) containing subchunks, and whenever possible,