_signature.add (sig);
_bigEndian = false;
// end of parsing prologue.
if (! checkSignBytes(dstream,SIGNATURE)) {
repInfo.setMessage(new ErrorMessage ("Bad PNG Header", 0));
repInfo.setWellFormed (RepInfo.FALSE);
return 0;
}
repInfo.setFormat("PNG");
// If we got this far, take note that the signature is OK.
repInfo.setSigMatch(_name);
repInfo.setModule(this);
// First chunk MUST be IHDR
int declChunkLen = (int)(readUnsignedInt(dstream, PNG_ENDIANITY, this)
&0x7FFFFFFF);
chcks.reset();
int chunkSig = (int)(readUnsignedInt(dstream, PNG_ENDIANITY, this)&0x7FFFFFFF);
chcks.update(int2byteArray(chunkSig));
if (chunkSig != IHDR_HEAD_SIG ) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("IHDR header not found where expected." ));
return 0;
}
else {
checkIHDR(dstream,repInfo,declChunkLen);
if (somethingWrongP(repInfo))
return 0;
// not sure it's useful...
expectingIHDR = RepInfo.FALSE;
}
// The IHDR is where it should be and it's fine, now let's
// handle the other chunks.
while (expectingIEND == RepInfo.TRUE) {
declChunkLen = (int)(readUnsignedInt(dstream, PNG_ENDIANITY, this)
&0x7FFFFFFF);
// Each chunk has its checsum;
chcks.reset();
chunkSig = (int)(readUnsignedInt(dstream, PNG_ENDIANITY, this)&0x7FFFFFFF);
chcks.update(int2byteArray(chunkSig));
switch (chunkSig) {
case IHDR_HEAD_SIG:
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Duplicated IHDR chunk." ));
break;
case PLTE_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Unexpected or duplicated PLTE chunk." ));
break;
}
checkPLTE(dstream,repInfo,declChunkLen);
expectingPLTE = RepInfo.FALSE;
break;
case IDAT_HEAD_SIG:
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Expected PLTE chunk not found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"IDAT");
expectingIDAT = RepInfo.FALSE;
break;
case IEND_HEAD_SIG:
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Expected PLTE chunk not found." ));
break;
}
if (expectingIDAT == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("No IDAT chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"IEND");
expectingIEND = RepInfo.FALSE;
break;
case cHRM_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("cHRM chunk found after PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("cHRM chunk found after IDAT ones." ));
break;
}
if (expecting_cHRM == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra cHRM chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"cHRM");
expecting_cHRM = RepInfo.FALSE;
break;
case gAMA_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("gAMA chunk found after PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("gAMA chunk found after IDAT ones." ));
break;
}
if (expecting_gAMA == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra gAMA chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"gAMA");
expecting_gAMA = RepInfo.FALSE;
break;
case iCCP_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("iCCP chunk found after PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("iCCP chunk found after IDAT ones." ));
break;
}
if (expecting_iCCP == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra iCCP chunk found." ));
break;
}
if (expecting_sRGB == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("iCCP chunk with sRGB chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"iCCP");
expecting_iCCP = RepInfo.FALSE;
expecting_sRGB = RepInfo.FALSE;
break;
case sBIT_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("sBIT chunk found after PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("sBIT chunk found after IDAT ones." ));
break;
}
if (expecting_sBIT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra sBIT chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"sBIT");
expecting_sBIT = RepInfo.FALSE;
break;
case sRGB_HEAD_SIG:
if (expectingPLTE == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("sRGB chunk found after PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("sRGB chunk found after IDAT ones." ));
break;
}
if (expecting_sRGB == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra sRGB chunk found." ));
break;
}
if (expecting_iCCP == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("iCPP chunk after sRGB chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"sRGB");
expecting_sRGB = RepInfo.FALSE;
expecting_iCCP = RepInfo.FALSE;
break;
case tEXt_HEAD_SIG:
checkChunk(dstream, repInfo, declChunkLen,"tEXT");
break;
case zTXt_HEAD_SIG:
checkChunk(dstream, repInfo, declChunkLen,"zEXT");
break;
case iTXt_HEAD_SIG:
checkChunk(dstream, repInfo, declChunkLen,"iEXT");
break;
case bKGD_HEAD_SIG:
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("gAMA chunk found before PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("gAMA chunk found after IDAT ones." ));
break;
}
if (expecting_gAMA == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra gAMA chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"bKGRD");
expecting_gAMA = RepInfo.FALSE;
break;
case hIST_HEAD_SIG:
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("hIST chunk found before PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("hIST chunk found after IDAT ones." ));
break;
}
if (expecting_hIST == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra hIST chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"hIST");
expecting_hIST = RepInfo.FALSE;
break;
case tRNS_HEAD_SIG:
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("tRNS chunk found before PLTE one." ));
break;
}
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("tRNS chunk found after IDAT ones." ));
break;
}
if (expecting_tRNS == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra tRNS chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"tRNS");
expecting_tRNS = RepInfo.FALSE;
break;
case pHYs_HEAD_SIG:
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("pHYs chunk found after IDAT ones." ));
break;
}
if (expecting_pHYs == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra pHYs chunk found." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"pHYs");
expecting_pHYs = RepInfo.FALSE;
break;
case sPLT_HEAD_SIG:
if (expectingIDAT == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("sPLT chunk found after IDAT ones." ));
break;
}
checkChunk(dstream, repInfo, declChunkLen,"sPLT");
break;
case tIME_HEAD_SIG:
if (expecting_tIME == RepInfo.FALSE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Extra tIME chunk found." ));
break;
}
checktIME(dstream, repInfo, declChunkLen);
expecting_tIME = RepInfo.FALSE;
break;
default:
// Some strong choices. Reject undefined non ancillary chunks
if (( chunkSig & ( PROP_ANCILLARY ) ) == 0) {
repInfo.setValid(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("Unknown non ancillary chunk found. Datastream not interpretable!" ));
break;
}
sigName.delete(0, sigName.length());
sigName.append((char)((chunkSig & 0x7F000000) >>> 24) );
sigName.append((char)((chunkSig & 0x007F0000) >>> 16) );
sigName.append((char)((chunkSig & 0x00007F00) >>> 8) );
sigName.append((char)((chunkSig & 0x0000007F)) );
// a private chunk, check the CRC
checkChunk(dstream, repInfo, declChunkLen, sigName.toString());
break;
}
if (somethingWrongP(repInfo))
return 0;
}
// epilogue
if (expectingPLTE == RepInfo.TRUE) {
repInfo.setWellFormed(RepInfo.FALSE);
repInfo.setMessage(new ErrorMessage("PLTE chunk not found (but was expected)." ));
}
return 0;