Последние 4 часа я изучал алгоритм CRC. Я почти уверен, что уже освоился.
Я пытаюсь написать png-кодировщик и не хочу использовать внешние библиотеки для вычисления CRC, а также для самой кодировки png.
Моя программа смогла получить те же CRC, что и примеры на уроках. Как и в Википедии :
Используя тот же полином и сообщение, что и в примере, я смог получить один и тот же результат в обоих случаях. Я смог сделать это и для нескольких других примеров.
Однако я не могу правильно рассчитать CRC файлов png. Я проверил это, создав пустой, один пиксель большой .png файл в рисовании и используя его CRC для сравнения. Я скопировал данные (и имя чанка) из IDAT-фрагмента png (, из которого вычисляется CRC ), и вычислил его CRC, используя полином, представленный в спецификации png.
Полином, представленный в спецификации png , является следующим:
x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
Который должен переводиться в:
1 00000100 11000001 00011101 10110111
Используя этот полином, я попытался получить CRC из следующих данных:
01001001 01000100 01000001 01010100
00011000 01010111 01100011 11101000
11101100 11101100 00000100 00000000
00000011 00111010 00000001 10011100
Вот что я получаю:
01011111 11000101 01100001 01101000 (MSB First)
10111011 00010011 00101010 11001100 (LSB First)
Это то, что является фактическим CRC:
11111010 00010110 10110110 11110111
I Я не совсем уверен, как это исправить, но я думаю, что я делаю эту часть из спецификации неправильно:
В PNG 32-битный CRC является инициализируется всеми 1, а затем данные из каждого байта обрабатываются от младшего значащего бита (1) до старшего значащего бита (128). После обработки всех байтов данных CRC инвертируется (берется его дополнение). Это значение передается (сохраняется в потоке данных) MSB первым. С целью разделения на байты и упорядочения младший значащий бит 32-битного CRC определяется как коэффициент члена x31.
Я не совсем уверен, что могу понять все это.
Кроме того, вот код, который я использую для получения CRC:
public BitArray GetCRC(BitArray data)
{
// Prepare the divident; Append the proper amount of zeros to the end
BitArray divident = new BitArray(data.Length + polynom.Length - 1);
for (int i = 0; i < divident.Length; i++)
{
if (i < data.Length)
{
divident[i] = data[i];
}
else
{
divident[i] = false;
}
}
// Calculate CRC
for (int i = 0; i < divident.Length - polynom.Length + 1; i++)
{
if (divident[i] && polynom[0])
{
for (int j = 0; j < polynom.Length; j++)
{
if ((divident[i + j] && polynom[j]) || (!divident[i + j] && !polynom[j]))
{
divident[i + j] = false;
}
else
{
divident[i + j] = true;
}
}
}
}
// Strip the CRC off the divident
BitArray crc = new BitArray(polynom.Length - 1);
for (int i = data.Length, j = 0; i < divident.Length; i++, j++)
{
crc[j] = divident[i];
}
return crc;
}
Итак, как мне это исправить, чтобы соответствовать спецификации PNG?