PNG IDAT 规范

rob*_*nex 3 png encode image image-processing

我正在阅读 W3 PNG 规范(从头开始创建一个 PNG 库),我终于找到了如何创建绿色 1x1 图像。

现在我正在尝试创建一个更大的混合红色、绿色和蓝色像素的图像。假设一个 4x4 图像。可悲的是,我将所有像素混合在一起,其中一些是黑色或粉红色。

细节:

  • 签名:好的
  • IHDR:好的
    • 宽度:4
    • 高度:4
    • 位深:8
    • 颜色:2
    • 过滤器:0
    • 压缩:0
    • 隔行:0
  • IDATA:4 块*
  • IEND:好的

*IDATA 块:

  • 4字节长度:Zlib deflate后DATA的字节数
  • 4*1 字节类型:IDAT
  • X 字节数据:4*4bytes 无符号整数,Zlib 压缩,一个接一个,网络字节序
    • 255 蓝色**
    • 65280 绿色**
    • 16711680 为红色**
  • 4 字节 crc:好的

**按位结果:

alpha<<24 | red<<16 | green<<8 | blue
Run Code Online (Sandbox Code Playgroud)

alpha、蓝色、绿色和红色取值从 0 到 255

这有什么问题?

Gle*_*son 5

PNG 像素按 RGBA 顺序排列,而不是 ARGB,因此您需要编写

alpha | red<<24 | green << 16 | blue <<8
Run Code Online (Sandbox Code Playgroud)

但是您正在编写颜色类型 2,因此您的像素每个应该是 3 个字节而不是 4 个;你不能像你所做的那样用 4 字节整数对它们进行编码。因此,要么将颜色类型更改为 6,要么切换为将每个样本写入一个单独的字节。

您还需要在每行的开头有一个过滤器字节。零将为您工作。因此,在您的示例 4x4 RGB 图像中,您需要每行写入 13 个字节

0 R G B R G B R G B R G B
0 R G B R G B R G B R G B
0 R G B R G B R G B R G B
0 R G B R G B R G B R G B
Run Code Online (Sandbox Code Playgroud)

然后将所有行字节连接成一个字节流并对其进行 zlib 压缩。它可以全部放入一个 IDAT 块中。如果您需要编写较小的 IDAT 块,则必须先对图像进行 zlib 压缩,然后将 zlib 输出拆分为您放入连续 IDAT 块中的部分。