#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <tchar.h>
//ref_start[http://www.w3.org/TR/PNG/]
/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];
/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;
/* Make the table for a fast CRC. */
void make_crc_table(void)
{
unsigned long c;
int n, k;
for (n = 0; n < 256; n++) {
c = (unsigned long) n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = 0xedb88320L ^ (c >> 1);
else
c = c >> 1;
}
crc_table[n] = c;
}
crc_table_computed = 1;
}
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
should be initialized to all 1's, and the transmitted value
is the 1's complement of the final running CRC (see the
crc() routine below). */
unsigned long update_crc(unsigned long crc, unsigned char *buf,
int len)
{
unsigned long c = crc;
int n;
if (!crc_table_computed)
make_crc_table();
for (n = 0; n < len; n++) {
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
}
return c;
}
/* Return the CRC of the bytes buf[0..len-1]. */
unsigned long crc(unsigned char *buf, int len)
{
return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
}
//ref_end[http://www.w3.org/TR/PNG/]
struct DATASTREAM {
unsigned char ucSignature[8];
unsigned char ucChunkDataLength[4];
unsigned long ulChunkTypeAndChunkDataLength;
unsigned char ucChunkTypeAndChunkData[4 + 32768];
unsigned char ucCrcInFile[4]; // CRC of ChunkType and ChunkData[In PNG Files]
unsigned long ulCrcInFile; // CRC of ChunkType and ChunkData[In PNG Files]
} datastream;
int main(int argc, char* argv[]) {
unsigned long ulCrcByCalc; // CRC of ChunkType and ChunkData[By Calculate]
size_t freadsize = 0; // The number of full items actually read
bool bCrcCheckResult = true;
if(2 == argc) { // Check arg OK
#ifdef _DEBUG
printf("arg:%s %s[%d]\n", argv[0], argv[1], __LINE__);
#endif
} else { // Check arg NG
printf("usage:%s path/file.png\n", argv[0], __LINE__);
return false;
}
// Open for read (will fail if file does not exist)
FILE *filestream = NULL;
if( NULL != (filestream = fopen( argv[1], "rb" )) ) {
#ifdef _DEBUG
printf( "fopen OK[%d]\n", __LINE__);
#endif
} else {
printf( "fopen NG[%d]\n", __LINE__);
return false;
}
//Signature_start
freadsize = fread(
datastream.ucSignature,
sizeof( char ),
sizeof( datastream.ucSignature ),
filestream);
if(freadsize == sizeof( datastream.ucSignature )) {
#ifdef _DEBUG
printf( "fread OK:%s[%d]\n", "Signature", __LINE__);
#endif
if (datastream.ucSignature[0] == 0x89 &&
datastream.ucSignature[1] == 0x50 &&
datastream.ucSignature[2] == 0x4E &&
datastream.ucSignature[3] == 0x47 &&
datastream.ucSignature[4] == 0x0D &&
datastream.ucSignature[5] == 0x0A &&
datastream.ucSignature[6] == 0x1A &&
datastream.ucSignature[7] == 0x0A)
{
#ifdef _DEBUG
printf( "check OK:%s[%d]\n", "Signature", __LINE__);
#endif
} else {
printf( "check NG:%s[%d]\n", "Signature", __LINE__);
return false;
}
} else {
printf( "fread NG:%s[%d]\n", "Signature", __LINE__);
return false;
}
//Signature_end
do {
//ChunkDataLength_start
freadsize = fread(
datastream.ucChunkDataLength,
sizeof( char ),
sizeof( datastream.ucChunkDataLength ),
filestream);
if(freadsize == sizeof( datastream.ucChunkDataLength )) {
#ifdef _DEBUG
printf( "fread OK:%s[%d]\n", "ChunkDataLength", __LINE__);
#endif
datastream.ulChunkTypeAndChunkDataLength = 4 + (
(datastream.ucChunkDataLength[0] << 24) |
(datastream.ucChunkDataLength[1] << 16) |
(datastream.ucChunkDataLength[2] << 8) |
(datastream.ucChunkDataLength[3] )
);
//ChunkTypeAndChunkData_start
freadsize = fread(
datastream.ucChunkTypeAndChunkData,
sizeof( char ),
datastream.ulChunkTypeAndChunkDataLength,
filestream);
if(freadsize == datastream.ulChunkTypeAndChunkDataLength) {
#ifdef _DEBUG
printf( "fread OK:%s[%d]\n", "ChunkTypeAndChunkData", __LINE__);
#endif
for(int ii = 0; ii < 4; ii++) {
printf("%c", datastream.ucChunkTypeAndChunkData[ii]);
}
//CrcInFile_start
freadsize = fread(
datastream.ucCrcInFile,
sizeof( char ),
sizeof( datastream.ucCrcInFile ),
filestream);
if(freadsize == sizeof( datastream.ucCrcInFile )) {
#ifdef _DEBUG
printf( "fread OK:%s[%d]\n", "CrcInFile", __LINE__);
#endif
datastream.ulCrcInFile = (
(datastream.ucCrcInFile[0] << 24) |
(datastream.ucCrcInFile[1] << 16) |
(datastream.ucCrcInFile[2] << 8) |
(datastream.ucCrcInFile[3] )
);
ulCrcByCalc = crc(
datastream.ucChunkTypeAndChunkData,
datastream.ulChunkTypeAndChunkDataLength);
if( ulCrcByCalc == datastream.ulCrcInFile ){
printf(" check OK!\n");
} else {
bCrcCheckResult = false;
printf(" check NG!\n");
printf("->CrcInFile:%08X\n", datastream.ulCrcInFile);
printf("->CrcByCalc:%08X\n", ulCrcByCalc);
}
} else {
printf( "fread NG:%s[%d]\n", "CrcInFile", __LINE__);
return false;
}
//CrcInFile_end
} else {
printf( "fread NG:%s[%d]\n", "ChunkTypeAndChunkData", __LINE__);
return false;
}
//ChunkTypeAndChunkData_end
} else {
printf( "fread NG:%s[%d]\n", "ChunkDataLength", __LINE__);
return false;
}
//ChunkDataLength_end
} while (!(
datastream.ucChunkTypeAndChunkData[0] == 0x49 && // I
datastream.ucChunkTypeAndChunkData[1] == 0x45 && // E
datastream.ucChunkTypeAndChunkData[2] == 0x4E && // N
datastream.ucChunkTypeAndChunkData[3] == 0x44)); // D
// Close stream if it is not NULL
if( filestream ) {
if ( !fclose( filestream ) ) {
#ifdef _DEBUG
printf( "close OK[%d]\n", __LINE__);
#endif
} else {
printf( "close NG(close failed)[%d]\n", __LINE__);
return false;
}
} else {
printf( "close NG(file pointer is null)[%d]\n", __LINE__);
return false;
}
if( bCrcCheckResult ) {
printf( "Everything OK!\n", __LINE__);
} else {
printf( "Something NG!\n", __LINE__);
}
return 0;
}