快速解析Png格式图片获得其宽高
前言
在Unity中我们常常需要将图片加载为Texture2D才能知道其宽和高。但是这样意味着要写这样的代码获取图片Byte[]数据。
Texture2D tex = new Texture2D(16,16);
string pngPath = "D:\\1\\Long.png";
Byte[] aa = System.IO.File.ReadAllBytes(pngPath);
tex.LoadImage(aa);
这样无疑开销较大且没有必要。
Png图的的格式
头部固定字节
十六进制 | 89 50 4E 47 0D 0A 1A 0A |
数据块组成
名称 | 字节数 | 说明 |
Length(长度) | 4字节 | 指定数据块中数据域的长度,其长度不超过(231-1)字节 |
Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码有ASCII字母(A-Z和a-z)组成 |
Chunk Data(数据块数据) | 可变长度 | 存储按照Chunk Type Code指定的数据 |
CRC(循环冗余检测) | 4字节 | 存储用来检测是否有错误的循环冗余码 |
数据块类型
数据块符号 | 数据块名称 | 多数据块 | 可选否 | 位置限制 |
IHDR | 文件头数据块 | 否 | 否 | 第一块 |
cHRM | 基色和白色点数据块 | 否 | 是 | 在PLTE和IDAT之前 |
gAMA | 图像γ数据块 | 否 | 是 | 在PLTE和IDAT之前 |
sBIT | 样本有效位数据块 | 否 | 是 | 在PLTE和IDAT之前 |
PLTE | 调色板数据块 | 否 | 是 | 在IDAT之前 |
bKGD | 背景颜色数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
hIST | 图像直方图数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
tRNS | 图像透明数据块 | 否 | 是 | 在PLTE之后IDAT之前 |
oFFs | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
pHYs | 物理像素尺寸数据块 | 否 | 是 | 在IDAT之前 |
sCAL | (专用公共数据块) | 否 | 是 | 在IDAT之前 |
IDAT | 图像数据块 | 是 | 否 | 与其他IDAT连续 |
tIME | 图像最后修改时间数据块 | 否 | 是 | 无限制 |
tEXt | 文本信息数据块 | 是 | 是 | 无限制 |
zTXt | 压缩文本数据块 | 是 | 是 | 无限制 |
fRAc | (专用公共数据块) | 是 | 是 | 无限制 |
gIFg | (专用公共数据块) | 是 | 是 | 无限制 |
gIFt | (专用公共数据块) | 是 | 是 | 无限制 |
gIFx | (专用公共数据块) | 是 | 是 | 无限制 |
IEND | 图像结束数据 | 否 | 否 | 最后一个数据块 |
IHDR
C#代码计算图片宽高
以图片1024x1024为例
可根据上面的格式介绍知道
00 00 04 00是宽
00 00 04 00是高
通过代码计算
FileStream imageStream = System.IO.File.OpenRead(pngPath);
byte[] imageHeader = new byte[24];
testS.Read(imageHeader, 0,24);
int width = 0;
int height = 0;
for (int i = 16; i < 24; i++)
{
if (i > 19)
{
width += imageHeader[i] * (int)Mathf.Pow(16, (19 - i) *2);
}
else
{
height += imageHeader[j] *(int)Mathf.Pow(16, (23 - i) * 2);
}
}
可得图片宽高为 1024 x1024
参照链接