c - 带有 IDAT 的调色板基础 PNG,其 BTYPE=00 用于无压缩,现在带有 Adler32 代码

标签 c image png zlib adler32

我正在编写一些代码,这些代码可以在没有 libpng 的情况下构建基于简单调色板的 PNG 文件。输出文件,在这个阶段只有 IHDR、PLTE、IDAT(x3) 和 IEND block 。唯一可能有点不同的是 IDAT block 中的像素索引值未被压缩,即各种 zlib/ block 头字节如下。

  • CMF = 0x78。
  • FLG = 0x9C(此处还有一些其他值,但始终清除第 5 位)。
  • block 头字节 = 0x01(BFINAL = 1,BTYPE = 00)。

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

  • MS Paint 很高兴。
  • GIMP 很高兴。
  • LibreOffice Draw 很开心。
  • Ristretto >> 读取 PNG 图像文件时出现 fatal error :压缩数据不足。
  • ImageMagick >> 识别:没有足够的图像数据“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 .

因此,对于接下来要尝试什么,我有点走投无路了。感谢任何和所有帮助。

编辑_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);
}

最佳答案

计算 Adler-32 值的任何方法都是不正确的。数据的正确 Adler-32 值是 0x10080061,它应该作为 10 08 00 61 存储在流中。如果我在链接文件中修复它,并为该 block 创建一个新的 CRC,那么一切都很好。

固定图像是:

fixed

关于c - 带有 IDAT 的调色板基础 PNG,其 BTYPE=00 用于无压缩,现在带有 Adler32 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36070759/

相关文章:

iOS:更改栏按钮项目中的 png

ios - C 与 Swift 的互操作性

c - ‘sockaddr_in 6’ 未声明的错误,即使包含了头文件

html - 将 div 边框与图像背景结合起来

png - 将 PNG 图像中的透明度替换为白色背景

javascript - 使用vite将原始图像数据导入到脚本中

c++ - 如何将 Graphics.h 包含在 Codelite 中?

在 R (Windows) 中从 C 创建一个 dll 动态库

html - 网站的自动 Retina 图像

image - 平均损坏图像以消除 MATLAB 中的噪声的问题