84 lines
2.4 KiB
Java
84 lines
2.4 KiB
Java
package ar.com.hjg.pngj;
|
|
|
|
import ar.com.hjg.pngj.chunks.PngChunkFDAT;
|
|
|
|
/**
|
|
*
|
|
* Specialization of ChunkReader, for IDAT-like chunks. These chunks are part of a set of similar chunks (contiguos
|
|
* normally, not necessariyl) which conforms a zlib stream
|
|
*/
|
|
public class DeflatedChunkReader extends ChunkReader {
|
|
|
|
protected final DeflatedChunksSet deflatedChunksSet;
|
|
protected boolean alsoBuffer = false;
|
|
|
|
protected boolean skipBytes = false; // fDAT (APNG) skips 4 bytes)
|
|
protected byte[] skippedBytes; // only for fDAT
|
|
protected int seqNumExpected = -1; // only for fDAT
|
|
|
|
public DeflatedChunkReader(int clen, String chunkid, boolean checkCrc, long offsetInPng,
|
|
DeflatedChunksSet iDatSet) {
|
|
super(clen, chunkid, offsetInPng, ChunkReaderMode.PROCESS);
|
|
this.deflatedChunksSet = iDatSet;
|
|
if (chunkid.equals(PngChunkFDAT.ID)) {
|
|
skipBytes = true;
|
|
skippedBytes = new byte[4];
|
|
}
|
|
iDatSet.appendNewChunk(this);
|
|
}
|
|
|
|
/**
|
|
* Delegates to ChunkReaderDeflatedSet.processData()
|
|
*/
|
|
@Override
|
|
protected void processData(int offsetInchunk, byte[] buf, int off, int len) {
|
|
if (skipBytes && offsetInchunk < 4) {// only for APNG (sigh)
|
|
for (int oc = offsetInchunk; oc < 4 && len > 0; oc++, off++, len--)
|
|
skippedBytes[oc] = buf[off];
|
|
}
|
|
if (len > 0) { // delegate to idatSet
|
|
deflatedChunksSet.processBytes(buf, off, len);
|
|
if (alsoBuffer) { // very rare!
|
|
System.arraycopy(buf, off, getChunkRaw().data, read, len);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* only a stupid check for fDAT (I wonder how many APGN readers do this)
|
|
*/
|
|
@Override
|
|
protected void chunkDone() {
|
|
if (skipBytes && getChunkRaw().id.equals(PngChunkFDAT.ID)) {
|
|
if (seqNumExpected >= 0) {
|
|
int seqNum = PngHelperInternal.readInt4fromBytes(skippedBytes, 0);
|
|
if (seqNum != seqNumExpected)
|
|
throw new PngjInputException("bad chunk sequence for fDAT chunk " + seqNum + " expected "
|
|
+ seqNumExpected);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isFromDeflatedSet() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* In some rare cases you might want to also buffer the data?
|
|
*/
|
|
public void setAlsoBuffer() {
|
|
if (read > 0)
|
|
throw new RuntimeException("too late");
|
|
alsoBuffer = true;
|
|
getChunkRaw().allocData();
|
|
}
|
|
|
|
/** only relevant for fDAT */
|
|
public void setSeqNumExpected(int seqNumExpected) {
|
|
this.seqNumExpected = seqNumExpected;
|
|
}
|
|
|
|
|
|
}
|