This is a continuation of Last time.
In addition to the required chunks (IHDR / IDAT / IEND)
Chunk | Contents |
---|---|
acTL | Inform that it is APNG |
fcTL | Inform the frame |
fdAT | Image data of frame |
The above three. See Animated PNG graphics for more information.
Unlike IDAT, fdAT has a sequence number in the first 4 bytes. Please note that this is different from the frame number.
It looks like the one below.
chunk | Frame number | Sequence number |
---|---|---|
acTL(none) | (none) | |
fcTL | 0 | 0 |
IDAT | 0 | (none) |
IDAT | 0 | (none) |
IDAT | 0 | (none) |
fcTL | 1 | 1 |
fdAT | 1 | 2 |
fdAT | 1 | 3 |
fdAT | 1 | 4 |
fcTL | 2 | 5 |
fdAT | 2 | 6 |
fdAT | 2 | 7 |
fdAT | 2 | 8 |
Excluding the actual PNG file, IDAT and fdAT are split into multiple parts, but this is just one file split into chunks. It will be to reduce memory consumption by outputting to the buffer size when handling Defrator.
Pick it up from Pixiv using Ank-Pixiv-Tool. If you take the metadata together, you will get two .zip and .json. Actually, the frame data is contained in the .json file. Without this data, the timeline will be unknown.
Contents of json file
{
"info": {
"illust": {
//abridgement
"path": [
{
"src": "https://i.pximg.net/img-zip-ugoira/img/xx .... xx.zip",
"frames": [
{
"f": "000000.jpg ",
"d": 50
//abridgement
"referrer": "https://www.pixiv.net/member_illust.php?xxxxx"
}
]
}
}
All you have to do is earn f and d under info-> path [0]-> frames []. f is the file name and d is the delay (in 1ms increments).
However, Java does not have a standard JSON library, so I will bring it from the outside.
The difference from the last time is that it supports alpha channel and separates APNG output and IDAT chunk. (I tried to divide the size into 64KB-12byte.)
This is a difference in how to use Deflater. Last time, if the compressed data could not be larger than the original, the buffer size was decided to be the same as the input size, but it is switched to the fixed buffer.
Deflater encoder = new Deflater();
encoder.setInput(buffer);
encoder.finish();
int compresslength;
do {
byte[] outbuffer = new byte[buffersize];
PNGChunk data = new PNGChunk(ChunkTYPE.IDAT);
compresslength = encoder.deflate(outbuffer);
data.setBuffer(outbuffer);
data.setLength(compresslength);
if (compresslength != 0) {
list.add(data);
}
} while (compresslength != 0);
This time, I have decided on a file to move it for the time being.
https://github.com/tsudon/Ugoira2GIF