eight04 / pyAPNG

A Python module to deal with APNG files.
MIT License
42 stars 11 forks source link

APNG_DISPOSE_OP_PREVIOUS not handled #18

Open RaenonX opened 4 years ago

RaenonX commented 4 years ago

I got an APNG from here.

I tried extracting the frames using this, but found that there is a frame being extracted in only 1x1. Here's the extraction result

image

Then I used APNG Disassembler to extract the frames, I got that "missing frame".

image

It appears that frame 6 and 8 are the same, but frame 8 cannot be extracted using this. Here's the chunk structure acquired by pngcheck v2.3.0:

image

That fdAT at 0x226 with length only 17 is the missing one. I tried finding information by inspecting the documentation of both APNG and PNG, but cannot find any information about potentially reusing the frame. All other chunks seems also not indicating this reuse.

How to handle this case?

Note

eight04 commented 4 years ago

It doesn't actually "reuse" a chunk. Frame 7 (in your picture) uses APNG_DISPOSE_OP_PREVIOUS, which means that before rendering frame 8, the image viewer should revert the buffer to frame 6. Since frame 8 is an empty image, it looks like that frame 6 is rendered again.

RaenonX commented 4 years ago

I see. So the data in fdAT are basically meaningless, is that right?

So basically everytime I encounter an DISPOSE_OP_PREVIOUS, it will go back to render the previous frame, then go to the next not-yet-rendered nonempty frame. For example, if there are 5 frames with the 3rd frame being DISPOSE_OP_PREVIOUS, my actual order will be 1 2 1 4 5, is that right?

Thanks for the response in advance & will this being implemented in the future?

eight04 commented 4 years ago

I see. So the data in fdAT are basically meaningless, is that right?

So basically everytime I encounter an DISPOSE_OP_PREVIOUS, it will go back to render the previous frame, then go to the next not-yet-rendered nonempty frame. For example, if there are 5 frames with the 3rd frame being DISPOSE_OP_PREVIOUS, my actual order will be 1 2 1 4 5, is that right?

No. The buffer will be reset to frame 2 before rendering frame 4. So it will be:

1 > 2 > 3 > (reset to the buffer before rendering 3) 4 > 5

https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk

will this being implemented in the future?

Do you mean you need an image renderer? I think it shouldn't be hard by using Pillow as the canvas. Currently I have no time to implement it but I'll merge the PR if you would like to contribute.

RaenonX commented 4 years ago

No. The buffer will be reset to frame 2 before rendering frame 4. So it will be:

1 > 2 > 3 > (reset to the buffer before rendering 3) 4 > 5

https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk

Actually I've checked this page after you responded. Not quite sure if this is correct:

Render 1 > Render 2 > Render 3 > Reset to the buffer before rendering 3 (Content depend on the OPS of 2, could be 2 itself if the OPS of 2 is APNG_DISPOSE_OP_NONE?) > 4 > 5

Will this being implemented in the future?

For the extraction not renderer actually. Will try to implement this OPS handling along with x, y offsets, if I also find some time and you're welcome for that 🤣