我在程序中需要验证png各段的CRC,后来从网上搜得该段代码,可不知为什么,我输入数据得出的结果总与实际结果不符,现贴出该段代码,请高手指点!十分感谢!!!以下是C++Builder代码,与Delphi类似!!!//---------------------------------------------------------------------------
// 构造 32 位 CRC 表
void TForm1::BuildTable32( unsigned long aPoly )
{
unsigned long i, j;
unsigned long nData;
unsigned long nAccum; String str; //Memo1->Clear(); for ( i = 0; i < 256; i++ )
{
nData = ( unsigned long )( i << 24 );
nAccum = 0;
for ( j = 0; j < 8; j++ )
{
if ( ( nData ^ nAccum ) & 0x80000000 )
nAccum = ( nAccum << 1 ) ^ aPoly;
else
nAccum <<= 1;
nData <<= 1;
}
Table_CRC[i] = nAccum; str = IntToStr(i)+", "+(nAccum);
//Memo1->Lines->Add(str);
}
}//---------------------------------------------------------------------------
// 计算 32 位 CRC-32 值
unsigned long TForm1::CRC_32( unsigned char * aData, unsigned long aSize )
{
unsigned long i;
unsigned long nAccum = 0; for ( i = 0; i < aSize; i++ )
nAccum = ( nAccum << 8 ) ^ Table_CRC[( nAccum >> 24 ) ^ (*aData++)]; return nAccum;
}//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
unsigned long crc;
String str; byte testcrc[8]={
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44,
}; //这是png文件IEND部分固定的数据
//这是该段固定的CRC = (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82
//而我用该方法计算出的CRC=91, A5, D1, 8C请问我错在哪里?应该怎么改?
/*
//列出另一IDAT数据块
byte testcrc[47]={
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x27,
(byte)0x49, (byte)0x44, (byte)0x41, (byte)0x54,
(byte)0x78, (byte)0x9c, (byte)0x63, (byte)0x38,
(byte)0xbd, (byte)0xb2, (byte)0x3d, (byte)0x95,
(byte)0x61, (byte)0xd7, (byte)0x8c, (byte)0xb2,
(byte)0x10, (byte)0x06, (byte)0x20, (byte)0xc3,
(byte)0x99, (byte)0x01, (byte)0xc8, (byte)0x30,
(byte)0x62, (byte)0x00, (byte)0x32, (byte)0x14,
(byte)0x19, (byte)0x80, (byte)0x0c, (byte)0x01,
(byte)0x06, (byte)0x10, (byte)0x83, (byte)0x01,
(byte)0xc4, (byte)0x00, (byte)0x00, (byte)0x24,
(byte)0xa7, (byte)0x0b, (byte)0xa4
};
//最后的CRC应该是DA 12 06 A5
//该方法计算得89 AC 1D 7C
*/
unsigned long cnCRC_32 = 0x04C10DB7; BuildTable32(cnCRC_32); crc = CRC_32( testcrc, 8); str = "crc="+IntToHex((int)crc,4);
str += ", a1="+ IntToHex((int)(crc>>24), 2);
str += ", a2="+ IntToHex((int)((crc>>16)&0xFF), 2);
str += ", a3="+ IntToHex((int)((crc>>8)&0xFF), 2);
str += ", a4="+ IntToHex((int)((crc)&0xFF), 2);
Label1->Caption = str;
}
//---------------------------------------------------------------------------
// 构造 32 位 CRC 表
void TForm1::BuildTable32( unsigned long aPoly )
{
unsigned long i, j;
unsigned long nData;
unsigned long nAccum; String str; //Memo1->Clear(); for ( i = 0; i < 256; i++ )
{
nData = ( unsigned long )( i << 24 );
nAccum = 0;
for ( j = 0; j < 8; j++ )
{
if ( ( nData ^ nAccum ) & 0x80000000 )
nAccum = ( nAccum << 1 ) ^ aPoly;
else
nAccum <<= 1;
nData <<= 1;
}
Table_CRC[i] = nAccum; str = IntToStr(i)+", "+(nAccum);
//Memo1->Lines->Add(str);
}
}//---------------------------------------------------------------------------
// 计算 32 位 CRC-32 值
unsigned long TForm1::CRC_32( unsigned char * aData, unsigned long aSize )
{
unsigned long i;
unsigned long nAccum = 0; for ( i = 0; i < aSize; i++ )
nAccum = ( nAccum << 8 ) ^ Table_CRC[( nAccum >> 24 ) ^ (*aData++)]; return nAccum;
}//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
unsigned long crc;
String str; byte testcrc[8]={
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44,
}; //这是png文件IEND部分固定的数据
//这是该段固定的CRC = (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82
//而我用该方法计算出的CRC=91, A5, D1, 8C请问我错在哪里?应该怎么改?
/*
//列出另一IDAT数据块
byte testcrc[47]={
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x27,
(byte)0x49, (byte)0x44, (byte)0x41, (byte)0x54,
(byte)0x78, (byte)0x9c, (byte)0x63, (byte)0x38,
(byte)0xbd, (byte)0xb2, (byte)0x3d, (byte)0x95,
(byte)0x61, (byte)0xd7, (byte)0x8c, (byte)0xb2,
(byte)0x10, (byte)0x06, (byte)0x20, (byte)0xc3,
(byte)0x99, (byte)0x01, (byte)0xc8, (byte)0x30,
(byte)0x62, (byte)0x00, (byte)0x32, (byte)0x14,
(byte)0x19, (byte)0x80, (byte)0x0c, (byte)0x01,
(byte)0x06, (byte)0x10, (byte)0x83, (byte)0x01,
(byte)0xc4, (byte)0x00, (byte)0x00, (byte)0x24,
(byte)0xa7, (byte)0x0b, (byte)0xa4
};
//最后的CRC应该是DA 12 06 A5
//该方法计算得89 AC 1D 7C
*/
unsigned long cnCRC_32 = 0x04C10DB7; BuildTable32(cnCRC_32); crc = CRC_32( testcrc, 8); str = "crc="+IntToHex((int)crc,4);
str += ", a1="+ IntToHex((int)(crc>>24), 2);
str += ", a2="+ IntToHex((int)((crc>>16)&0xFF), 2);
str += ", a3="+ IntToHex((int)((crc>>8)&0xFF), 2);
str += ", a4="+ IntToHex((int)((crc)&0xFF), 2);
Label1->Caption = str;
}
//---------------------------------------------------------------------------
// http://www.w3.org/TR/PNG/#D-CRCAppendix
class CPngCyclicRedundancyCode
{
private:
static unsigned long crc_table[256]; /* Make the table for a fast CRC. */
static int make_crc_table(void)
{
unsigned long c; for (int n = 0; n < 256; n++)
{
c = (unsigned long) n;
for (int k = 0; k < 8; k++)
{
if (c & 1)
c = 0xedb88320L ^ (c >> 1);
else
c = c >> 1;
}
crc_table[n] = c;
} return 0;
} /* 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). */
static unsigned long update_crc(unsigned long crc, unsigned char *buf, int len)
{
static int ntemp = make_crc_table(); unsigned long c = crc;
for (int n = 0; n < len; n++)
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); return c;
}public:
/* Return the CRC of the bytes buf[0..len-1]. */
static unsigned long crc(unsigned char *buf, int len)
{
return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
}
};.cpp 文件
unsigned long CPngCyclicRedundancyCode::crc_table[256];测试代码:
注意png chunk 的长度字段不列入计算:
unsigned char iend[8] = { 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44 };
unsigned long lcrc = CPngCyclicRedundancyCode::crc(iend + 4, 4);
cout << "crc = " << hex << lcrc << endl;
return 0;参考:
http://blog.csdn.net/egxsguo/archive/2006/10/23/1346315.aspx
http://www.w3.org/TR/PNG/#D-CRCAppendix