2016-03-17 5 views
1

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

  • 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 не сообщает о каких-либо ошибках.

Вот hex view of the file 20160317_PNG_064.png

Картину он генерирует этот small 8x8 pixel image.

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

EDIT_000 Усугубляя проблему при расчете Adler32, здесь, по просьбе @Mark Adler, используется код, который я использую для вычисления значения 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); 
} 
+0

Вы уверены, что ваш кусок 'data' представляет распакованные данные в том же образом? Изображение палитры 8x8 должно быть, если я правильно его вычислил, 8x8 = 64 байта. Каждая строка имеет перед ним фильтр-байт, который добавляет до 72 байт. Если я разделяю ваши данные вверх в строках, начинающихся с байта фильтра '0', я получаю 16 x 16 изображений (которые, плюс 16 строк фильтров, добавляет до 272 показано здесь). – usr2564301

+0

(После тестирования) Yup. Если я загружаю исходные 72 байта в текущую процедуру Adler32, я получаю значение Outgoing Adler32 ................. 0x10080061' - * точно * что dr. Адлер рассчитал. Поэтому ваша рутина кажется правильной в конце концов, вы просто применяли ее к неправильному набору данных. – usr2564301

ответ

2

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

Неподвижная изображение:

fixed

+0

Еще раз хочу поблагодарить, особенно д-р @ Марк Адлер. В моем источнике, форсирование этих значений устраняет проблемы. Теперь я должен найти, где колесо сходит с тележки. В настоящее время Adler-32 получает заголовок блока и все байты фильтра scanline. Я подозреваю, что ни один из них, ни оба они не должны быть переданы в расчет Adler-32. – SkyPirate

+0

Похоже, что байты фильтра включены в поток данных, который представлен в вычислении Adler32; байт заголовка блока и LEN и NLEN байты нет. С этими изменениями все работает хорошо для изображения 8х8 пикселей. Однако, если я сделаю изображение более крупным, все снова заскакивает на мель. Используя MS Excel для вычисления значения Adler 32, он совпадает с кодом в коде, поэтому все еще есть что-то не совсем правильное. Счастлив предоставить 16x16 пиксель гекса файла, если кто-то хотел бы оказать дополнительную помощь. – SkyPirate

+0

Что вы передаете Adler-32 - это просто несжатые данные в потоке zlib. Возможно, вы можете опубликовать свой код Adler-32. –

2

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

+1

Сообщение об ошибке, которое я получаю от ImageMagick и от pngcrush, является «неправильной проверкой данных», которая говорит о вычисляемой контрольной сумме adler32, не соответствующей последним 4 байтам потока данных zlib. Обратите внимание, что «pngcheck» не проверяет это, поэтому не сообщит об ошибке. Firefox отображает изображение при выдаче предупреждения «Предупреждение wp/PNGDecoder libpng: Усеченные сжатые данные в IDAT» –

+0

А, я тоже этого не проверял. –

+0

@ Glenn Randers-Pehrson - Чтобы я не стрелял на ветру, можете ли вы предоставить рассчитанное значение для сравнения? У меня есть несколько различных реализаций Adler32 из разных источников, и, к сожалению, некоторые из них никогда не редактируются, если обнаружены ошибки. Теперь я использую свою собственную неэффективную реализацию wiki/Adler32. Я просто сохранил результирующие байты Adler32 в неправильном порядке? – SkyPirate

 Смежные вопросы

  • Нет связанных вопросов^_^