Fork me on GitHub

图片文件二进制编码合并与解析

 

  前边都是废话,直接从第四段开始看

  对于一些html的动画页面,canvas动画页面,会需要大量的图片文件。一张一张的从服务器获取图片,会影响页面的显示。

  怎样提高动画的效果,可以写一个load页面,然后通过js把图片先从服务器加载下来,避免在动画的时候,保证动画的流畅性。但是问题来了,在有大量图片的页面里,需要大量的请求数,在前端优化里就有提到要减少请求数,雪碧图很好,但是每次都要找设计给你拼好,当然,自己花点时间也是可以掌握这个东西,去做。但是有没有一种程序的方式,把图片整合,然后运用呢,重点来了,往下看。

  图片基本上都是一些二进制数据的拼接,对我要整合的就是这些二进制数据。前提知识点,nodejs(不需要很多)中的文件操作就是 fs 了,文件的读、写。接下来就是js中的 API ArrayBuffer,还有他的两个视图TypedArray和DataView。还有blob,都用的比较浅,我本人也是初接触这些。

  压缩阶段: 通过nodejs来进行压缩,很好的一点通过nodejs的 fs 读取到的文件是一个buffer数据。在前端用过js可以完美解析

  由于nodejs读取文件的一个便利性,所以压缩主要是,读取文件然后设置文件的存储规则,我的文件基本是每个图片包括四部分: 图片名称的大小(指字节数)+图片名称+图片文件的大小+图片的二进制文件,前边三部分通过Uint32来存储,存储方式是一个默认的小端字节序。

  上代码:

var fs = require('fs');

//所要读取文件的所在的位置 文件夹 
var pat = './img/';
//生成文件的保存位置与文件名,文件后缀可以任意
var create = './cgppt/cg.sw';

var buffer = new Buffer(0);
var files = fs.readdirSync(pat);
var count = files.length;
files.forEach(function(filename) {
    count--;
    //读取文件数据
    var text = fs.readFileSync(pat + filename);
    //将文件的名称以及数据等信息压缩在一起
    var headerBuffer = header(filename, text);
    if(!!headerBuffer) {
        //将不同文件的二进制数据合并在一起,并写入文件
        buffer = Buffer.concat([buffer, headerBuffer]);
        if(count == 0) {
            fs.writeFile(create, buffer, (err) => {
                if (err) throw err;
                console.log('It\'s saved!');
            });
        }
    }
});

function header(filename, data) {   //整合单个文件数据
    var text = fs.readFileSync(pat + filename);
    var fileLen = numToBuffer(filename.length + 4);
    if(filename.search(/\.png$|\.jpg$/ig) != -1) {
        var file = strToBuffer('img/' + filename);
        var dataLen = numToBuffer(text.length);
        var data = new Buffer(text);
        var header = Buffer.concat([fileLen, file, dataLen, data]);
        return header;
    }
    return false;
}

function strToBuffer(data) {  //文件名称等信息规则
    var buffer = new Buffer(0);
    var str = data.toString();
    for(let i = str.length - 1; i >= 0; i--) {
        var num = str.charCodeAt(i);
        var strBuffer = numToBuffer(num);
        buffer = Buffer.concat([strBuffer, buffer]);
    }
    return buffer;
}

function numToBuffer(num) {  //以小端字节序方式将文件大小信息编入
    var buffer = new Buffer(4),
        ppp = [];
    ppp[0] = num % 256;
    ppp[1] = num % (256*256) / 256;
    ppp[2] = num / (256*256) % (256);
    ppp[3] = num / (256*256*256);
    for (var i = 0; i < buffer.length; i++) {
      buffer[i] = ppp[i];
    }
    return buffer;
}
View Code

 

  前端解析: 这里就是通过js来解析这个二进制文件,将通过blob和URL生成的一个链接赋值给img的src,也可以用于canvas动画

  

  关键代码

while(len < data.byteLength) {
        //获取文件名的长度
    var f = data.getUint32(len, !0);
    len += 4;
    var l = '';
        //读取文件名
    for(var c = 0; c< f; c++) {
        var h = data.getUint32(len, !1);
        len += 4;
        l += String.fromCharCode(h);
    }
    //读取文件的长度
    var p = data.getUint32(len, !0);
        len += 4;
    //读取文件
        var d = new Uint8Array(buffer, len, p);
    //obj为文件名->文件的一个对象
        obj[l] = d;
        len += p,
    //文件名数组
        o.push(l),
    //文件数组
        a.push(d)
}
                         
View Code

 

本文的大部分要点都来自于 阮一峰老师的JavaScript标准参考教程,还有MDN的web技术文档。

本人前端小白,如有问题还请指正

欢迎转载、交流

 

 

参考链接: 阮一峰 二进制数据阮一峰 nodejs fs模块阮一峰 二进制数组

JavaScript 标准参考教程(alpha)MDN

 

posted @ 2016-12-05 15:35  Chris-dc  阅读(1554)  评论(2编辑  收藏  举报