PNG базы палитры с IDAT, которая имеет BTYPE=00 без сжатия, теперь с кодом Adler32

Я работаю над кодом, который создает простые PNG-файлы на основе палитры без libpng. Выходной файл на этом этапе содержит только блоки IHDR, PLTE, IDAT(x3) и IEND. Единственное, что, возможно, немного отличается тем, что значения индекса пикселя в блоке IDAT не сжимаются, то есть различные байты заголовка zlib / block заключаются в следующем.

  • CMF = 0x78.
  • FLG = 0x9C (здесь также есть несколько других значений, но всегда с очищенным битом 5).
  • Байт заголовка блока = 0x01 (BFINAL = 1, BTYPE = 00).

Из того, что я вижу, код правильно строит файл, однако некоторые программы просмотра изображений отказываются отображать изображение полностью, если вообще.

  • MS Paint счастлив.
  • GIMP счастлив.
  • LibreOffice Draw счастлив.
  • Ristretto >> Неустранимая ошибка чтения файла изображения PNG: недостаточно сжатых данных.
  • ImageMagick >> определить: недостаточно данных изображения `20160317_PNG_064.png '@ error / png.c / MagickPNGErrorHandler / 1645.
  • Eye of Gnome >> Недостаточно данных изображения.

Я поставил файл через несколько разных инструментов, опять же со смешанными результатами.

  • optipng >> недостаточно данных изображения.
  • pngchunks не сообщает об ошибках.
  • pngcheck не сообщает об ошибках.

Вот шестнадцатеричный вид файла 20160317_PNG_064.png

Изображение, которое он генерирует, - это маленькое изображение размером 8x8 пикселей.

Так что я зашел в тупик относительно того, что попробовать дальше. Любая помощь приветствуется.

EDIT_000 Здесь, по запросу @Mark Adler, сузили проблему до расчета Adler32, и это код, который я использую для вычисления значения Adler32 с тестовыми данными в основной функции. Кстати, это не модно, и я пишу очень многословно.

#include <stdio.h>

#define     DEBUG

static const unsigned long GC_ADLER32_BASE = 0xFFF1;   // Largest prime smaller than 65536 is 65521.

unsigned long Adler32_Update
        (
        unsigned long Adler32,
        unsigned char *Buffer,
        unsigned int BufferLength
        )
{
    unsigned long   ulW0;
    unsigned long   ulW1;
    unsigned int    uiW0;
#ifdef DEBUG
    printf("\n");
    printf("        Incoming Adler32 value.................0x%.8X\n", Adler32);
#endif
    ulW0 = Adler32 & 0xFFFF;
    ulW1 = (Adler32 >> 0x0010) & 0xFFFF;
#ifdef DEBUG
    printf("        Inital sum values are..................0x%.8X, 0x%.8X\n", ulW0, ulW1);
#endif
    for (uiW0 = 0x0000; uiW0 < BufferLength; uiW0 = uiW0 + 0x0001)
        {
        ulW0 = (ulW0 + Buffer[uiW0]) % GC_ADLER32_BASE;
        ulW1 = (ulW1 + ulW0) % GC_ADLER32_BASE;
        }
#ifdef DEBUG
    printf("        Final sum values are...................0x%.8X, 0x%.8X\n", ulW0, ulW1);
#endif
    Adler32 = (ulW1 << 0x0010) | ulW0;
#ifdef DEBUG
    printf("        Outgoing Adler32 value.................0x%.8X\n", Adler32);
#endif
    return (Adler32);
}


unsigned long Adler32_Get
        (
        unsigned char *Buffer,
        unsigned int BufferLength
        )
{
    unsigned long   Adler32;

    Adler32 = 0x00000001L;
    Adler32 = Adler32_Update(Adler32, Buffer, BufferLength);
    return (Adler32);
}


int main
    (
    unsigned int    argc,
    unsigned char   *arg[]
    )
{
    unsigned long   Adler32;
    unsigned char data[272] = 
        {
    0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
    0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 
    0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 
    0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 
    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 
    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 
    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 
    0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02
        };
    Adler32 = Adler32_Get(data, sizeof(data));
    printf("\n");
    printf("The Adler32 value is ..........................0x%.8X\n", Adler32);
    return(0x00);
}

2 ответа

Решение

Что бы ни вычислялось значение Адлера-32, это неверно. Правильное значение Adler-32 для данных 0x10080061, который должен храниться в потоке как 10 08 00 61, Если я исправлю это в связанном файле и сделаю новый CRC для этого чанка, то все будет хорошо.

Фиксированное изображение:

фиксированный

Как соавтор спецификации PNG, я считаю, что этот файл полностью соответствует. Спецификация PNG откладывает определение "deflate" на RFC 1951, и этот RFC явно разрешает разделы BTYPE=0. Возможно, вы захотите связаться с авторами тех программ, которые имеют проблемы с ним и сообщить об ошибке, прикрепив ваш файл в качестве примера ввода.

Другие вопросы по тегам