您的位置:首页 > 其它

PNG文件头格式解析

2017-08-07 18:49 330 查看
近来为了获取图片大小,有点伤脑筋,引擎库不能再读取文件路径后马上得到图片大小

所以无奈决定,直接通过读取png文件头来获取文件大小

00000000h: 89 50 4E 47 0D 0A 1A 0A00 00 00 0D49
48 44 52 ; 塒NG........IHDR

00000010h: 00 00 00 CE 00 00 00 CE 08 02 00 00 00 F9 7D AA ; ...?..?....鶀?

00000020h: 93 00 00 00 09 70 48 59 73 00 00 0A 75 00 00 0A ; ?...pHYs...u...

00000030h: 75 01 4A 25 DD FD 00 00 0C 91 49 44 41 54 78 9C ; u.J%蔟...慖DATx?

00000040h: ED 9D D9 96 DC 2A 0C 45 A9 AC FC FF 2F D7 7D 70 ; 頋贃?.E┈?/讅p

00000050h: C7 97 66 10 9A 98 CF 7E C8 EA 54 95 6D 86 83 24 ; 菞f.殬蟸汝T昺唭$

00000060h: 04 B6 3F DF EF 37 00 D0 9F 3F B3 0B 00 6E 01 52 ; .?唢7.袩??.n.R

00000070h: 03 83 F8 3B BB 00 AB F2 F9 98 0E 47 58 92 01 A9 ; .凐;?鶚.GX?? 

89 50 4E 47 0D 0A 1A 0A 是PNG头部署名域,表示这是一个PNG图片
00 00 00 0D 描述IHDR头部的大小
49 48 44 52 是Chunk
Type Code, 这里Chunk Type Code=IHDR
00 00 00 CE 00 00 00 CE 08 02 00 00 00 描述了Chunk
Data,它是可变长度数据,00 00 00 0D 定义了长度为13个Bytes,所以,这里,你看到是13个字节)
F9 7D AA 93 是对IHDR的CRC校验

紧接着下面的就是pHys数据块,原理也是一样

------------------------------------------------------------------------------------------------------

但是这里还是木有文件头的信息,接下来,可以参考如下:



也就是可以从IHDR中,来获取头文件信息,这里的IHDR,其实在开始就可以看到了

00 00 00 CE 00 00 00 CE 08 02 00 00 00 描述了Chunk
Data

也就是前面的这块数据,前四个字节是宽度,后四个字节是高度,也就是此图大小为:206 * 206

由于,暂时不需要其他数据,也就不再往下研究,直接贴上,lua获取png文件头的代码

[cpp]
view plain
copy

print?

function hexstring2number(hexstring, len)  
    if not len or len > 8 then return end  
  
    local hexbyte = {}  
    for i = 1, len do  
        hexbyte[i] = string.byte(hexstring, i)  
    end  
  
    local num = tonumber(string.format("0x%x%x%x%x", hexbyte[1], hexbyte[2], hexbyte[3], hexbyte[4]), 16)  
    return num  
end  
  
function get_png_size(path)  
    local png_file = io.open(path, "rb")  
    local data = png_file:read("*all")  
  
    -- 保证png至少有37个字节,因为包含文件头等起码就超过这个数字了  
    if #data < 37 then return end  
  
    -- 文件头的相关信息请百度  
    local png_header_info = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52}  
    for i = 1, #png_header_info do  
        if (string.byte(data, i) ~= png_header_info[i]) then  
            return  
        end  
    end  
  
    -- 这四个字节表示png的宽度  
    data = string.sub(data, #png_header_info + 1)  
    local width = hexstring2number(data, 4)  
  
    -- 这四个字节表示png的高度  
    data = string.sub(data, 5)  
    local height = hexstring2number(data, 4)  
  
    return width, height  
end  
  
get_png_size("2.png")  

function hexstring2number(hexstring, len)
if not len or len > 8 then return end

local hexbyte = {}
for i = 1, len do
hexbyte[i] = string.byte(hexstring, i)
end

local num = tonumber(string.format("0x%x%x%x%x", hexbyte[1], hexbyte[2], hexbyte[3], hexbyte[4]), 16)
return num
end

function get_png_size(path)
local png_file = io.open(path, "rb")
local data = png_file:read("*all")

-- 保证png至少有37个字节,因为包含文件头等起码就超过这个数字了
if #data < 37 then return end

-- 文件头的相关信息请百度
local png_header_info = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52}
for i = 1, #png_header_info do
if (string.byte(data, i) ~= png_header_info[i]) then
return
end
end

-- 这四个字节表示png的宽度
data = string.sub(data, #png_header_info + 1)
local width = hexstring2number(data, 4)

-- 这四个字节表示png的高度
data = string.sub(data, 5)
local height = hexstring2number(data, 4)

return width, height
end

get_png_size("2.png")
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: