【问题标题】:PNG IDAT specificationPNG IDAT 规范
【发布时间】:2014-05-05 12:16:19
【问题描述】:

我正在研究 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:OK

**按位结果:

alpha<<24 | red<<16 | green<<8 | blue

Alpha、蓝色、绿色和红色的取值范围为 0 到 255

这是怎么回事?

【问题讨论】:

  • 这个问题被交叉发布到 DSP,所以我在那里复制了我的答案。

标签: image image-processing png encode


【解决方案1】:

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

alpha | red<<24 | green << 16 | blue <<8

但是您正在编写颜色类型 2,因此您的像素每个应该是 3 个字节 而不是四个;您不能真正将它们编码为 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

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

【讨论】:

  • 很好的解释。我马上试试。关于行...我猜它们将根据图像宽度呈现,对吗?所以我只需要一个接一个地写这些 13bytes 组
  • 是的,只需将您的行字节连接成一个长流并将其发送到 zlib。