2016-03-17 66 views
1

我工作的一些代码,建立简单的调色板基于PNG文件没有libpng。输出文件在这个阶段只有IHDR,PLTE,IDAT(x3)和IEND块。唯一可能有点不同的是,IDAT块中的像素索引值未被压缩,即各种zlib /块头字节如下所示。调色板基础PNG与IDAT BTYPE = 00无压缩,现在与Adler32代码

  • CMF = 0x78。
  • FLG = 0x9C(在这里也有一些其他的值,但总是清除第5位)。
  • 块头字节= 0x01(BFINAL = 1,BTYPE = 00)。

从我所看到的代码正确构建文件,但是一些图像查看器完全拒绝显示图像(如果有的话)。

  • MS Paint很高兴。
  • GIMP很高兴。
  • LibreOffice Draw很高兴。
  • Ristretto >>阅读PNG图像文件致命错误:压缩数据不足。
  • ImageMagick >> identify:没有足够的图片数据'20160317_PNG_064.png'@ error/png.c/MagickPNGErrorHandler/1645。
  • 侏儒之眼>>图片数据不够。

我已经通过几个不同的工具,文件再次混合的结果。

  • optipng >>没有足够的图像数据。
  • pngchunks不会报告任何错误。
  • pngcheck不报告任何错误。

这里是hex view of the file 20160317_PNG_064.png

它生成的图片是这个small 8x8 pixel image

因此,我接下来要尝试的是什么,我处在一个死路一条。任何和所有的援助表示赞赏。

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); 
} 
+0

你确定你的'data'的块代表在同一​​幅图像的未压缩的数据?如果我计算正确,8x8 = 64字节长,8x8调色板图像应该是。每行在它之前都有一个过滤器字节,这样只会增加到72个字节。如果我将数据分成以'0'过滤器字节开始的行,则会得到一个16 x 16的图像(其中加上16行过滤器,总计达到此处显示的272)。 – usr2564301

+0

(经过测试)是。如果我将最初的72个字节输入到当前的Adler32例程中,我会得到'Outgoing Adler32 value ................. 0x10080061' - * *正是* dr。阿德勒计算。所以你的例程似乎是正确的,你只是将它应用于一组错误的数据。 – usr2564301

回答

2

无论计算Adler-32的值是不正确的。数据的正确的Adler-32值是0x10080061,应该将其存储在流中作为10 08 00 61。如果我在链接的文件中解决了这个问题,并为该块创建一个新的CRC,那么一切都很好。

的固定形象是:

fixed

+0

再一次我要特别感谢@Mark Adler博士。在我的资料来源中,强制这些值可以解决问题。我现在只能找到车轮从比利车上下来的地方。目前,Adler-32获得块头和所有扫描线过滤器字节。我怀疑这两者中的一个或两个都不会被传递给Adler-32计算。 – SkyPirate

+0

看起来,过滤器字节包含在呈现给Adler32计算的数据流中;块头字节和LEN和NLEN字节不是。所有这些更改对8x8像素图像都有效。然而,如果我让图像变得更大,事情会再次搁浅。使用MS Excel计算Adler 32值,它与代码中的匹配,所以仍然有些不太正确。如果有人想提供进一步的帮助,很乐意提供一个16x16像素的十六进制文件。 – SkyPirate

+0

你传递给Adler-32的只是zlib流中的未压缩数据。也许你可以发布你的Adler-32代码。 –

2

作为PNG规范的共同作者,我相信这个文件是完全兼容的。 PNG规范推迟RFC 1951的“deflate”定义,并且RFC明确允许BTYPE = 0部分。您可能希望联系那些有问题的程序的作者,并报告错误,并附上您的文件作为示例输入。

+1

我从ImageMagick和pngcrush获得的错误消息是“不正确的数据检查”,它正在讨论计算的adler32校验和不匹配zlib数据流的最后4个字节。请注意,“pngcheck”不检查这个,所以不会报告错误。 Firefox在发出警告“W/PNGDecoder libpng警告:IDAT中的截断压缩数据” –

+0

时显示图像啊,我也没有检查。 –

+0

@ Glenn Randers-Pehrson - 为了不让我在微风中拍摄,你能提供的计算值是用于比较吗?我有许多来自不同来源的不同Adler32实现,不幸的是,如果发现错误,一些从不会被重新编辑。我现在正在使用我自己的低效实现wiki/Adler32。我是否以错误的顺序存储了生成的Adler32字节? – SkyPirate