图片优化调研之实践篇

前言

之前的文章——图片优化调研之理论篇——主要以理论的东西为主。正确选择合适的图片格式——不管你用Fireworks还是Photoshop,可用预览功能多去尝试,选择size最小的且确保质量(其场景与PM商定)的图片。另一个方面,就是无损压缩。本篇文章主要针对自动无损压缩,具体再啰嗦一下如何实现。

实践

1.pngout客户端实现图片批量无损压缩

pngout官网提供一个windows平台客户端版本——http://www.ardfry.com/pngoutwin/ 简单介绍它怎么用——

1.1 设置压缩图片输出路径

1.2 选择源图文件夹

这里仅仅针对批量压缩——

1.3 看结果

这里对common模块(随意举例)进行例子解析——

 

当压缩图片的格式选择gif的时候(仅仅针对gif格式的图片进行压缩),会看到——

所有的gif图片均转换为png格式图片,再进行无损压缩,整体压缩之后的结果——

出现一个问题,本来loading.gif是多帧动画,却被压缩成了单帧png,不符合预期。因此,这里的整体替换(gif-->png)存在一定风险,要确保排除动画gif的压缩。

在这里,就不介绍将jpg转换为png的过程了(同gif),不建议这样去做,以免造成大量失真。

在来看看它的压缩率,会看到批量压缩节省的字节数——

自然就能算出整体压缩率了。

2.smushit

《高性能网站建设进阶指南》这本书的作者提供的服务http://www.smushit.com/ysmush.it/ 这里使用node-smushit模块实现批量压缩——

  1 var minifier = require('node-smushit');
  2 var log4js = require('log4js');
  3 var logger = log4js.getLogger();
  4 
  5 var util = (function() {
  6     var src_total_size = 0;     // 记录输入图片总大小
  7     var dest_total_size = 0;    // 记录输出图片总大小
  8     var total_percent;          // 记录总的压缩率
  9 
 10     var total = 0;              // 图片总个数
 11     var saving = 0;             // 需要压缩的图片总个数
 12 
 13     // 递增图片总个数
 14     var increaseTotal = function() {
 15         total = total + 1;
 16     };
 17 
 18     // 获取图片总个数
 19     var getTotal = function() {
 20         return total;
 21     };
 22 
 23     // 递增需要压缩的图片总个数
 24     var increaseSaving = function() {
 25         saving = saving + 1;
 26     };
 27 
 28     // 获取需要压缩的图片总个数
 29     var getSaving = function() {
 30         return saving;
 31     };
 32 
 33     // 递增输入图片大小
 34     var increaseSrcTotalSize = function(itemSize) {
 35         src_total_size = src_total_size + itemSize;
 36     };
 37 
 38     // 获取输入图片总大小
 39     var getSrcTotalSize = function() {
 40         return src_total_size;
 41     };
 42 
 43     // 递增输出图片总大小
 44     var increaseDestTotalSize = function(itemSize) {
 45         dest_total_size = dest_total_size + itemSize;
 46     };
 47 
 48     // 获取输出图片总大小
 49     var getDestTotalSize = function() {
 50         return dest_total_size;
 51     };
 52 
 53     // 计算压缩率
 54     var computeTotalPercent = function() {
 55         total_percent = ((src_total_size - dest_total_size) / src_total_size * 100).toFixed(2) + '%';
 56     };
 57 
 58     // 获取压缩率
 59     var getTotalPercent = function() {
 60         return total_percent;
 61     };
 62 
 63     // 压缩图片与原图片的大小差值,即节省了多少字节
 64     var getReduce = function() {
 65         return src_total_size - dest_total_size;
 66     };
 67 
 68     return {
 69         getTotal: getTotal,
 70         getSaving: getSaving,
 71         getSrcTotalSize: getSrcTotalSize,
 72         getDestTotalSize: getDestTotalSize,
 73         getTotalPercent: getTotalPercent,
 74         increaseTotal: increaseTotal,
 75         increaseSaving: increaseSaving,
 76         increaseSrcTotalSize: increaseSrcTotalSize,
 77         increaseDestTotalSize: increaseDestTotalSize,
 78         computeTotalPercent: computeTotalPercent,
 79         getReduce: getReduce
 80     };
 81 })();
 82 
 83 // 打印日志
 84 var printResult = function() {
 85     logger.info('图片总个数:' + util.getTotal());
 86     logger.info('无损压缩图片总个数:' + util.getSaving());
 87 
 88     logger.info('输入需要压缩的图片总大小:' + util.getSrcTotalSize() + ' Bytes');
 89     logger.info('输出经过压缩的图片总大小:' + util.getDestTotalSize() + ' Bytes');
 90     logger.info('-------------共节省大小:' + util.getReduce() + ' Bytes');
 91     logger.info('压缩率(相对输入图片总大小):' + util.getTotalPercent());
 92 };
 93 
 94 // 这里可以指定多个图片文件夹目录,用数组表示
 95 minifier.smushit(['./static/images/', './widget/'], {
 96 
 97     // 循环遍历文件夹及其子目录中的图片设置
 98     // true: 遍历循环
 99     // false: 非遍历循环
100     recursive: true,
101 
102     // 每张图片开始压缩
103     onItemStart: function(item) {
104         // 这里的item是每张输入图片的源地址
105     },
106 
107     // 每张图片完成压缩
108     onItemComplete: function(e, item, response) {
109         /**
110          * response的格式——
111          * {
112          *      src: '',
113          *      src_size: ,
114          *      dest: '',
115          *      dest_size: ,
116          *      percent: ,
117          *      id: ''
118          * }
119          */
120 
121         // 过滤掉svn目录中的文件
122         if (/.svn/g.test(response.src) === false) {
123             util.increaseTotal();
124 
125             /*
126              * 注意:
127              * 当检测到某些图片已经无法压缩或者已经经过压缩,此时response.src_size的值是undefined
128              * 因此在这儿加入一层过滤,针对可以压缩的图片进行统计
129              */
130             if (response.src_size && response.dest_size) {
131                 util.increaseSaving();
132                 util.increaseSrcTotalSize(response.src_size);
133                 util.increaseDestTotalSize(response.dest_size);
134             }
135         }
136 
137     },
138 
139     // 所有图片完成压缩
140     // 这里的reports变量记录所有图片的源地址、源大小、目标地址、目标大小、压缩率等信息的列表
141     onComplete: function(reports) {
142 
143         // 统计压缩率
144         util.computeTotalPercent();
145 
146         // 打印统计日志
147         printResult();
148     }
149 });

可以看到结果——

3. 其他实现方案

不管用node或者php或者shell,整体的实现思路均是循环遍历图片,然后使用合适的命令行工具实现无损压缩。在这儿就不继续说了。

 

posted @ 2014-10-27 19:35  金广国  阅读(1010)  评论(0编辑  收藏  举报