zoukankan      html  css  js  c++  java
  • 图片压缩的一些心得

    FROM: Jackie li's Blog

    这次乐高的题目是如何提高图片的压缩率。帮助公司省流量的费用。

    整个过程持续一周。最终的结果相当让人满意,压缩率比之前提高了67.5%,为公司每个月省下至少2W多RMB的流量费用=。=

    而且这次的研究也让我对图片的压缩有了一定的心得。

    马上分享一下:

    1. 选择一个合适的图片处理扩展包。
      • 常见的扩展如GD,imagick,Gmagick。
      • 老古董的GD丢掉吧,效率很低,而且压缩的图片体积很大=。=   imagick是个不错的选择,在PHP的图片处理扩展中表现的很显眼。不管是对jpg或png的静态图片,还是对gif的动态图片,压缩和缩小放大尺寸都非常给力。
      • Gmagic没怎么试过,而GraphicsMagick据说也是相当的给力,但网上很多评论基本上都是对效率的一些评测。感觉压缩上面不太给力,详细的描述可参看老王的博客http://hi.baidu.com/thinkinginlamp/blog/item/4b61e9241f08820f4c088d95.html
    2. 程序的优化,看下三个小组的解决方案和最终最好的解决方案。

    大家对加水印这块无异议,仅在压缩上面做了文章,我只贴这里的代码。

    优化前:

    /**
    * 缩小图片尺寸.
    *
    * @param $image 待处理的二进制图片
    * @param $width 处理后图片尺寸的宽度(px)
    * @param $height 处理后图片尺寸的高度(px)
    * @param $crop 是否裁剪图片
    *
    * @return 处理好的二进制图片
    */
    function resize($image, $width, $height, $crop) {
    $imagick = new Imagick();
    $imagick->readImageBlob($image);
    $w = $imagick->getImageWidth();
    $h = $imagick->getImageHeight();
    if ($w > $width || $h > $height) {
    if ($crop) {
    $imagick->cropThumbnailImage($width, $height);
    } else {
    $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true);
    }
    }
    $processed_image = $imagick->getImageBlob();
    return $processed_image;
    }

    第一小组:

    function resize($image, $width, $height, $crop) {
    
    $im = new Imagick();
    
    $im->readImageBlob($image);
    
    $input_width = $width;
    
    $input_height = $height;
    
    $src_width = $im->getImageWidth();
    
    $src_height = $im->getImageHeight();
    
    $width_rate = $src_width/$width;
    
    $height_rate = $src_height/$height;
    
    if($width_rate>1||$height_rate>1){
    
    if($crop){
    
    if($width_rate>$height_rate){
    
    $width = $src_width/$height_rate;
    
    }else{
    
    $height = $src_height/$width_rate;
    
    }
    
    }else{
    
    if($width_rate>$height_rate){
    
    $height = $src_height/$width_rate;
    
    }else{
    
    $width = $src_width/$height_rate;
    
    }
    
    }
    
    $im->resizeImage($width, $height, Imagick::FILTER_CATROM, 1, false);
    
    if($crop){
    
    if($width>$input_width){
    
    $im->cropImage ( $input_width , $height , ($width-$input_width)/2 , 0 );
    
    }elseif($height>$input_height){
    
    $im->cropImage ( $width , $input_height , 0 , ($height-$input_height)/2 );
    
    }
    
    }
    
    }
    
    $im->setImageCompression(Imagick::COMPRESSION_JPEG);
    
    $im->setImageCompressionQuality(75);
    
    $im->stripImage();
    
    $im->setImageFormat(‘JPEG’);
    
    $blob = $im->getImageBlob();
    
    $im->clear();
    
    $im->destroy();
    
    return $blob;
    
    }

    第二小组:

    function resize($image,$width,$height,$crop) {
    
    $imagick = new Imagick();
    
    $imagick->readImageBlob($image);
    
    $imagick->setImageCompression($compression_type);
    
    $imagick->setImageCompressionQuality(80);
    
    if($crop) {
    
    $imagick->cropThumbnailImage($width, $height);
    
    }else{
    
    $imagick->resizeImage($width, $height, Imagick::FILTER_CATROM, 1, true);
    
    }
    
    $imagick->stripImage();
    
    $processed_image = $imagick->getImageBlob();
    
    return $processed_image;
    
    }

    第三小组:

    function resize($image, $width, $height, $crop) {
    
    $imagick = new Imagick();
    
    $imagick->readImageBlob($image);
    
    if ($crop) {
    
    $imagick->cropThumbnailImage($width, $height);
    
    } else {
    
    $imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1, true);
    
    }
    
    $imagick->setImageFormat(‘JPEG’);
    
    $imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
    
    $a = $imagick->getImageCompressionQuality() * 0.75;
    
    if ($a == 0) $a = 75;
    
    $imagick->setImageCompressionQuality($a);
    
    $geo = $imagick->getImageGeometry();
    
    $imagick->ThumbnailImage($geo['width'], $geo['height']);
    
    $imagick->stripImage();
    
    $blob = $imagick->getImageBlob();
    
    $imagick->clear();
    
    $imagick->destroy();
    
    return $blob;
    
    }

    最终解决方案:

    function resize($image, $width, $height, $crop) {
    
    $imagick = new Imagick();
    
    $imagick->readImageBlob($image);
    
    $w = $imagick->getImageWidth();
    
    $h = $imagick->getImageHeight();
    
    if ($w > $width || $h > $height) {
    
    if ($crop) {
    
    $imagick->cropThumbnailImage($width, $height);
    
    } else {
    
    $imagick->resizeImage($width, $height, Imagick::FILTER_CATROM, 1, true);
    
    }
    
    }
    
    $imagick->setImageFormat(‘JPEG’);
    
    $imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
    
    $a = $imagick->getImageCompressionQuality() * 0.75;
    
    if ($a == 0) {
    
    $a = 75;
    
    }
    
    $imagick->setImageCompressionQuality($a);
    
    $imagick->stripImage();
    
    $blob = $imagick->getImageBlob();
    
    $imagick->clear();
    
    $imagick->destroy();
    
    return $blob;
    
    }

    看下成绩:

    对300张生产环境下抽取的原始图片进行测试,结果如下:

    • 示例代码
      29,220,912 (28,536KB)
    • 1组
      11,282,151 (11,018KB) 比示例代码节省: 61.39%
    • 2组
      16,281,139 (15,900KB) 比示例代码节省: 44.28%
    • 3组
      10,531,926 (10,285KB) 比示例代码节省: 63.96%

    性能方面都符合要求。除了第3组比示例代码慢5%左右,其他两组都比示例代码更快(1组约快15%,2组约快6%)
    2组提交太慢太快,有一处遗漏,其实可以简单提高压缩比到58%左右

    之后,综合3组的代码,弄了个best版本,测试结果为,

    • best
      9,626,986 (9,401KB) 比示例代码节省: 67.05%

    总结 :

    1、压缩率尽可能的小,这个要和业务部门商量,找到一个平衡点。(请注意best方法设置品质方法使用获取到当前图片的压缩率然后再取75%,如果当前图片压缩率为60%,如果使用$imagick->setImageCompressionQuality(80)方法将使图片压缩率提高至80%,这会使图片变大!!!)

    2、一定要移除图片的exif信息!!!!  这部分内容详情请查看 http://baike.baidu.com/view/22006.htm

    3、压缩尺寸使用Imagick::FILTER_CATROM方法对速度有一定的提升,图片本身的品质没有大的变化。

    4、$imagick->setImageFormat(‘JPEG’)也很给力。

    5、简单算了一下,这几行代码每个月给我们公司省至少2W RMB的流量费用,如果我们的图片库越来越大,那将更加给力了。

  • 相关阅读:
    【SSH网上商城项目实战11】查询和删除商品功能的实现
    【SSH网上商城项目实战10】商品类基本模块的搭建
    【SSH网上商城项目实战09】添加和更新商品类别功能的实现
    【SSH网上商城项目实战08】查询和删除商品类别功能的实现
    【SSH网上商城项目实战07】Struts2和Json的整合
    【SSH网上商城项目实战06】基于DataGrid的数据显示
    thinkphp模版主题使用方法
    sql语句中#{}和${}的区别
    SQL语句中有关单引号、双引号和加号的问题
    LEFT JOIN 关键字语法
  • 原文地址:https://www.cnblogs.com/goldenstones/p/4717651.html
Copyright © 2011-2022 走看看