之前的文章中有介绍过类似的东西,但是那中方法依然会把整张图片加载下来,只不过是在加载完成前获取了图片尺寸而已。

现在,我们要使用更直接的方法,直接从服务器上读取到图片的尺寸信息。之前的文章就介绍过了关于图片头的知识,现在我要向服务器发送一个HTTP请求,让服务器返回图片的尺寸信息,然后自己解析就行了。

这种方法比较适合PNG和GIF图片,因为他们的头信息中的尺寸位置是固定的。我们很容易就能解析出它的大小,JPG图片由于头部的描述信息在尺寸信息之前。

所以我们无法直接获取它尺寸信息在文件流中的位置。虽然可以加载整个头来分析,但是我不推荐使用这种做法来获取JPG文件的尺寸,除非你服务器上的JPG图片是固定格式生成的。

断点续传这种技术我想大家没用过也应该听说过吧,这就是运用了HTTP协议中的Range字段来指定让服务器返回数据流中的部分信息。现在,我们就利用这个Range字段让服务器返回图片的尺寸信息。要向服务器发送这个Range字段首先要知道,图片的尺寸信息在图片文件流中的位置,我们用16进制工具打开图片就能找到。

article image

上图是PNG和GIF文件的尺寸信息保存的位置PNG是从第16字节到第23字节,GIF是从第6字节到第9字节。先不说啥了,来看代码

article image

上面就是获取PNG图片尺寸的代码。先创建一个XHR对象,这东西是AJAX的基础我就不多说了。这里关键的是非IE中的responseType必须设置成arraybuffer,要不如返回的结果会被强制转换成字符,这可能会导致字节丢失。

致至于Range字段的参数简单的用法就是bytes=开始字节-结束字节,当然还有很多用法,这篇文字关键不是说这个所以就不介绍了。下面是接收返回的二进制数据,在浏览器上有差异,IE使用responseBody返回,但是它返回的是一个内存数组,JS的数组是经过封装的类数组所以不能直接接收。

但是可以用VBS中的数组来接收,因为VBS的数组是内存数组,这就是为什么在微软的脚本引擎上VBS的效率比JS效率高的原因。获取VBArray之后可以用它的toArray方法转换成JS使用的数组,这个是微软提供的VBS和JS之间沟通的接口。

接下来就是非IE浏览器的部分了。我们用response接收服务器返回的数据,这个类型我们在创建XHR对象的时候就已经设置了,所以可以直接使用Uint8Array把它转换成JS可用的无符号整型 数组。最后一个步骤就是解析这个数组,PNG的尺寸部分前4位是宽度,后4位是高度。我们只要逐个字节计算位权然后相加就可以得到宽度和高度了。

至于GIF的获取方法,和上面这个代码大同小异。你只需要修改Range的参数和最后一部的解析返回值就可以了,我就不再演示了。这个方法加载的最大好处就是不用去请求整个图片,我去找个超级大的图片来试试

article image

这图片够大了吧,如果直接使用Image对象载入它,用户会奔溃的。但是使用这个方法就算网速很差也不会有什么影响。而且还可以节省服务器的资源,服务器只需要处理我们请求的几个字节的数据就可以了,不用载入整张图片。基本上一瞬间就可以获取到图片的大小。

article image

好了,我想现在应该都会使用这方法了吧。对于其它图片格式当然也不是不行只不过麻烦,但是如果把它封装好就不会麻烦了。因为这个东西也不会经常用到,所以我也懒的封装这个了。