PNG文件格式

1 PNG文件格式

参考 PNG File Structure
PNG文件是由一个signature和一系列chunk组成的

PNG: [ signature(8) | chunkx n ]

1.1 PNG File Signature

signature是由固定的8字节组成的

signature: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]
             137     P     N     G    \r    \n    26    \n

1.2 PNG File Chunk Layout

所有的chunk包含Length, Chunk Type, Chunk Data, CRC四个字段, 按照以下结构排列

            ┌─────────────────────────────────────┐
            |                                     ↓
chunk: [ Length(4) | Chunk Type(4) | Chunk Data(length) | CRC(4) ]
                          ↑               ↑                |
                          └───────────────┴────────────────┘

1.2.1 Length

Length字段是一个四字节大小的无符号整数, 用来表示Chunk Data的长度(以字节为单位)

1.2.2 Chunk Type

Chunk Type是一个四字节大小字段, 可以看作是字符数组, 内容为'a'-'z''A'-'Z'的集合
每个字段的大小写均代表不同的含义

关键数据标记与辅助数据标记(第一个字节)

大写: 表示是关键数据块, 对解码器来讲, 必须要解析的块, 出问题的话, 必须向用户报告
小写: 表示是辅助数据块, 对解码器来讲, 可以忽略

公共数据标记与私有数据标记(第二个字节)

大写: 表示是公共数据块, PNG规范中定义了一些列公共区块, 参考Additional chunk types
小写: 表示是私有数据块, 解码器不会访问这些区块

保留数据标记(第三个字节)

大写: 保留标记, 目前版本的PNG都是大写
小写: 留作协议扩展

安全复制标记与非安全赋值标记(第四个字节)

大写: 复制不安全, 解码器不关心, 编辑器可能会对这个块修改
小写: 复制安全, 解码器不关心, 编辑器不论怎么修改都会将这个块复制到新图像中

1.2.3 Chunk Data

数据段, 由Chunk Type决定数据格式, 可以为零

1.2.4 CRC

参考 CRC32学习

2 常见的Chunk类型

完整版参考Additional chunk types

IHDR结构

第一个Chunk

域名字节数(Byte)说明
Width4图像宽度,以像素为单位
Height4图像高度,以像素为单位
Bit Depth1图像深度:
索引彩色图像: 1,2,4或8
灰度图像: 1,2,4,8或16
真彩色图像: 8或16
Color Type1颜色类型:
0: 灰度图像, 1,2,4,8或16
2:真彩色图像,8或16
3索引彩色图像,1,2,4或8
4: 带α通道数据的灰度图像,8或16
6: 带α通道数据的真彩色图像,8或16
Compression method1压缩方法(LZ77派生算法)
Filter Method1滤波器方法
Interlace method1隔行扫描方法:
0: 非隔行扫描
1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法)
IDAT结构

IDAT数据块存储的格式取决于PNG的格式以及是否压缩。

PNG文件格式分为PNG-24和PNG-8,其最大的区别是PNG-24是用24位来保存一个像素值,是真彩色,而PNG-8是用8位索引值来在调色盘 中索引一个颜色,因为一个索引值的最大上限为2的8次方既128,故调色盘中颜色数最多为128种,

一旦使用了压缩我们必须使用zlib解压才能看见它的具体颜色。

IEND结构

最后一个Chunk
值得注意的是,IEND区块虽然也按照数据块的结构,但Chunk Data是没有的,所以是固定的12个字节: 0x00000000, 0x49454e44, 0xae426082

IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82

3 测试读取PNG图片

打印出每个ChunkLength, Chunk Type, CRC. 由于Chunk Data大小不固定因此不打印

/**
 * file png.c
 * 方便贴代码, 在一个文件里面实现, 这不是一个好习惯, 嗯
 *
 */


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct
{

} PNG_CHUNK_TYPE;

typedef struct
{

} PNG_CHUNK;

typedef struct
{

} PNG;

int png_chunk_type_check(const PNG_CHUNK_TYPE *self);
int png_chunk_check(const PNG_CHUNK *self);
int png_check(const PNG_CHUNK *self);

int png_chunk_type_display(const PNG_CHUNK_TYPE *self);
int png_chunk_display(const PNG_CHUNK *self);
int png_display(const PNG_CHUNK *self);

PNG_CHUNK *png_get_first_chunk(const PNG *self);
PNG_CHUNK *png_get_next_chunk(const PNG_CHUNK *self);

int main(int argc, char const *argv[])
{
    FILE *fp = NULL;
    uint8_t buffer[10 * 1024] = {}; // 10MB大小缓存
    PNG *png = NULL;

    fp = fopen("test.png", "r");
    fread(buffer, sizeof(uint8_t), sizeof(buffer), fp);
    fclose(fp);

    png = (PNG *)buffer;
    png_check(png);
    png_display(png);

    return 0;
}
// TODO
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值