为什么图片传输不开启gzip压缩呢?

前文

这个问题为什么会被关注了,说来话长。之前的文章通过Performance测网络下行网速和php输出指定大小图片实践过程中。

  1. 一开始是用的script标签加载指定长度内容,后面发现默认的传输类型是 application/javascript,1M的数据被GZIP压缩成5k。
  2. 换成img标签,尺寸正确,但是不能按指定大小输出图片
  3. 为了输出指定大小图片,换成php输出图片,因为忘记声明Content-Type头,默认以text\html被nginx再次压缩

对此我就产生了疑问,为啥图片不开启gzip呢。翻了以下nginx的默认压缩类型,确实也是没有图片类型。

 gzip_types       text/plain application/x-javascript text/css application/xml;

后续又在格式里面添加了图片格式,一波测试后才会出现一句奇怪的备注,实践上就是忘了删类型。

//修改输出类型或者将nginx gzip_types 中对应类型去掉,经过压缩后无法初始指定大小的图片
header("Content-type: image/x-png");

GZip

一句话:gzip 的核心是 Deflate,而它使用了 LZ77 算法与 Huffman 编码来压缩文件,重复度越高的文件可压缩的空间就越大。

主要应用场景

对于文本文件,GZip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3。主要用于 HTTP 文件传输中,比如 JS、CSS 等,但一般不会压缩图片。

文字测试

  • 测试代码
    php -S 127.0.0.1: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 sizer=0r=1
gzip=01.2kB1.2kB
gzip=1210B712kB
  • 小结
    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);
	
    //测试图 如果本地测试要把图下载下来
    #$im     = imagecreatefrompng('https://bjun.tech/public/demo/image_interlace/c.png');

    header("Content-type: image/png");
    imagepng($im,null,$_GET['quality']);
    imagedestroy($im);
    $content = ob_get_contents();
    $len =ob_get_length();
    ob_end_flush();

}


  • 结果
    表格内transferred size,quality为png图片输出是的压缩等级,0为不压缩,1为压缩等级为1,6为压缩速度和大小较为均衡的等级,gzip=0 为关闭gzip压缩。

    • 自己创建的单色图:
    transferred sizequality=0quality=1quality=6quality=9
    gzip=0126 kB785 B357 B357 B
    gzip=1565 B312 B294 B294 B
    • 测试图:
    transferred sizequality=0quality=1quality=6quality=9
    gzip=06.2 MB208 kB178 kB174 kB
    gzip=1184 kB202 kB173 kB169 kB
  • 小结

  1. 对于为压缩过的原图,gzip有明显的压缩效果
  2. 对于原图,gzip压缩效果略差于图片自身的压缩算法
  3. 对于单色图片,二次压缩有一定效果。
  4. 对于示例图片,可以看出gzip对原图的压缩,可以接近到quality=6的水平
  5. 对于示例图片,进行二次压缩,仅小了1Kb,意义不大

特别注意:测试图片为灰白图片,并不是彩色。单色图片也较为特殊,几乎无应用场景。仅作实验数据参考

答案

回到最初的问题为啥不用gzip去压缩图片呢,那是因为主流的图片格式都是经过压缩处理的,几次在进行二次压缩,效果可以说等于没有,而且压缩无论是服务器压缩还是客户端解压,其成本对于效果来说,可以说是白费劲了。而对于未压缩的原图和单色图片,在互联网上的传播可以说是少之又少。

为啥原图gzip压缩效果会和自身压缩大小相似

[摘]png的压缩和过滤 - Deflate 压缩算法学习过程中,也才回忆起之前提到的奇怪场景。而其中对于png压缩算法的介绍就让我明白了这是为啥。Gzip和png在压缩的算法上都是使用了deflate算法,所以说本质上是一样的,区别就是,gzip在压缩图片,则是把整个图片文件当成一个整体进行压缩,而在png中在处理压缩算法时会针对图片的内容针对性处理。所以这也解释了在quality=6时,为啥图片压缩算法就比原图gzip压缩效果更好了。

备注:php中的gzip压缩默认等级是6

补充

  1. php中的gzip压缩默认等级是6
  2. chrome dev tools 中查看transferred size
    在请求的Size上悬浮,就会显示这个请求的细节,在打开【使用大量(大的)请求行】时,Size会变成2个,上面为传输大小 (transfereed size),下面的则是资源大小(resources size)。传输大小就是加压后的,资源大小就是解压后的。
    chrome dev tools 中查看transferred size

参考

从 Nginx 默认不压缩 HTTP/1.0 说起
gzip 的原理是什么,如何配置

原文链接

为什么图片传输不开启gzip压缩呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值