【转载】图片压缩的一些心得

原文地址:http://blog.lizhigang.net/archives/228

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

整个过程持续一周。最终的结果相当让人满意,压缩率比之前提高了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的流量费用,如果我们的图片库越来越大,那将更加给力了。

原文地址:http://blog.lizhigang.net/archives/228

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值