一直通过一些图片模块来取得图片的相关信息,最近在使用的过程中打开源码看了一下,学习到了不少东西。
首先,一个文件的基本信息都是存在于文件自身,即使压缩工具会去掉一些信息,但基本的文件类型,宽,高等都还会存在,所以,我们需要知道这些信息具体存在于哪个位置上。
通过相关搜索,我们得到了如下的信息:
可以看到,几乎所有的文件起始位置存放的都是 文件类型
,jpg 有三种 16 进制标记,png 只有一种,也就是说,我只需要如下判断,就可以知道文件是什么文件。
function getFileType(buffer){
if(buffer_data[0] == 0x89 && buffer_data[1] == 0x50 && buffer_data[2] == 0x4E && buffer_data[3] == 0x47 && buffer_data[4] == 0x0D && buffer_data[5] == 0x0A && buffer_data[6] == 0x1A && buffer_data[7] == 0x0A){
return 'png';
}else if(){
//...
}
}
严谨完整的判断应该是如上的代码,但通过观察整个列表,其实会发现,很多信息都是唯一的,比如 jpg 有三种,但三种的前三位都是 FF D8 FF
, 而且其他类型的文件都没有与其一样的,所以,可以不需要写那么长的判断,只需判断前三位即可。
附: 完整的 Hex signature 列表:https://en.wikipedia.org/wiki/List_of_file_signatures
那图片的宽高信息又存在于哪些位置呢?不同类型的文件,宽高信息存储的位置都不一样,如 png 的 hex 信息如下:
第 17 到 20 字节区间的位置存储着 png 的宽度信息,通过将其转换为 10 进制,就可以得到我们要的宽度值了。
如: 16 进制的 0000005A
转换为 10 进制为 90
。
知道原理后,如果只是想简单的得到图片的一些基本信息,只需要写一点代码就可以非常高性能的获取,而不需要去依赖一些稍重的图形模块。
具体代码可以查看: https://github.com/weixin/gulp-lazyimagecss/blob/master/lib/fastimagesize.js
知道原理后,也可以联想到更多,比如,.png 有可能并不是 png,有可能是其他; 如果一个图片上传模块验证不够完美,我把一个 php 文件的头改为图片头,欺骗了程序进行上传后执行,结果就有可能 呵呵 了。
文件的 hex 值可以通过一些 hex 工具查看,比如 sublime 就有 hex viewer 插件。