目录
前文
这个问题为什么会被关注了,说来话长。之前的文章通过Performance测网络下行网速和php输出指定大小图片实践过程中。
- 一开始是用的<script>加载指定长度内容,后面发现默认的传输类型是 application/javascript,1M的数据被GZIP压缩成5k。
- 换成img标签,尺寸正确,但是不能按指定大小输出图片
- 为了输出指定大小图片,换成php输出图片,因为忘记声明Content-Type头,默认以text\html被nginx再次压缩
对此我就产生了疑问,为啥图片不开启gzip呢。翻了以下nginx的默认压缩类型,确实也是没有图片类型。
gzip_types text/plain application/x-javascript text/css application/xml;
后续又在格式里面添加了图片格式,一波测试后才会出现一句奇怪的备注,实践上就是忘了删类型。
header("Content-type: image/x-png");
GZip
一句话:gzip 的核心是 Deflate,而它使用了 LZ77 算法与 Huffman 编码来压缩文件,重复度越高的文件可压缩的空间就越大。
主要应用场景
对于文本文件,GZip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3。主要用于 HTTP 文件传输中,比如 JS、CSS 等,但一般不会压缩图片。
文字测试
- 测试代码
php -S 127.0.0.222:80 运行,没有经过nginx
if(empty($_GET['txt'])){
echo '<script src="http://127.0.0.222/test.php?r=1&gzip=1&txt=1"></script>';
echo '<script src="http://127.0.0.222/test.php?r=1&gzip=0&txt=1"></script>';
echo '<script src="http://127.0.0.222/test.php?r=0&gzip=1&txt=1"></script>';
echo '<script src="http://127.0.0.222/test.php?r=0&gzip=0&txt=1"></script>';
}else{
if(empty($_GET['gzip'])){
ob_start();
}else{
ob_start('ob_gzhandler');
}
for ($i = 0;$i<1024;$i++){
if(empty($_GET['r'])){
echo 0;
}else{
echo rand(0,9);
}
}
ob_end_flush();
}
- 结果
transferred size 为传输大小。gzip=0 为关闭压缩,r=0为关闭随机
transferred size |
r=0 |
r=1 |
gzip=0 |
1.2kB |
1.2kB |
gzip=1 |
210B |
712kB |
- 小结
gzip对重复文本压缩效率极高,对于随机文本有大概70%压缩效果
图片测试
if(empty($_GET['image'])){
echo '<img src="http://127.0.0.222/test.php?image=1&gzip=1&quality=0">';
echo '<img src="http://127.0.0.222/test.php?image=1&gzip=0&quality=1">';
echo '<img src="http://127.0.0.222/test.php?image=1&gzip=1&quality=1">';
echo '<img src="http://127.0.0.222/test.php?image=1&gzip=0&quality=0">';
}else{
if(empty($_GET['gzip'])){
ob_start();
}else{
ob_start('ob_gzhandler');
}
$im = imagecreate(1000,1000);
$orange = imagecolorallocate($im, 220, 210, 60);
header("Content-type: image/png");
imagepng($im,null,$_GET['quality']);
imagedestroy($im);
$content = ob_get_contents();
$len =ob_get_length();
ob_end_flush();
}
- 对于为压缩过的原图,gzip有明显的压缩效果
- 对于原图,gzip压缩效果略差于图片自身的压缩算法
- 对于单色图片,二次压缩有一定效果。
- 对于示例图片,可以看出gzip对原图的压缩,可以接近到quality=6的水平
- 对于示例图片,进行二次压缩,仅小了1Kb,意义不大
特别注意:测试图片为灰白图片,并不是彩色。单色图片也较为特殊,几乎无应用场景。仅作实验数据参考
答案
回到最初的问题为啥不用gzip去压缩图片呢,那是因为主流的图片格式都是经过压缩处理的,即使再进行二次压缩,效果可以说等于没有,而且压缩无论是服务器压缩还是客户端解压,其成本对于效果来说,可以说是白费劲了。而对于未压缩的原图和单色图片,在互联网上的传播可以说是少之又少。
为啥原图gzip压缩效果会和自身压缩大小相似
在[摘]png的压缩和过滤 - Deflate 压缩算法学习过程中,也才回忆起之前提到的奇怪场景。而其中对于png压缩算法的介绍就让我明白了这是为啥。Gzip和png在压缩的算法上都是使用了deflate算法,所以说本质上是一样的,区别就是,gzip在压缩图片,则是把整个图片文件当成一个整体进行压缩,而在png中在处理压缩算法时会针对图片的内容针对性处理。所以这也解释了在quality=6时,为啥图片压缩算法就比原图gzip压缩效果更好了。
补充
- php中的gzip压缩默认等级是6
- chrome dev tools 中查看transferred size
在请求的Size上悬浮,就会显示这个请求的细节,在打开【使用大量(大的)请求行】时,Size会变成2个,上面为传输大小 (transfereed size),下面的则是资源大小(resources size)。传输大小就是加压后的,资源大小就是解压后的。
- 补充了个测试页面
gzip测试页面
参考
从 Nginx 默认不压缩 HTTP/1.0 说起
gzip 的原理是什么,如何配置