图片压缩的一些心得
FROM: Jackie li's Blog
这次乐高的题目是如何提高图片的压缩率。帮助公司省流量的费用。
整个过程持续一周。最终的结果相当让人满意,压缩率比之前提高了67.5%,为公司每个月省下至少2W多RMB的流量费用=。=
而且这次的研究也让我对图片的压缩有了一定的心得。
马上分享一下:
- 选择一个合适的图片处理扩展包。
- 常见的扩展如GD,imagick,Gmagick。
- 老古董的GD丢掉吧,效率很低,而且压缩的图片体积很大=。= imagick是个不错的选择,在PHP的图片处理扩展中表现的很显眼。不管是对jpg或png的静态图片,还是对gif的动态图片,压缩和缩小放大尺寸都非常给力。
- Gmagic没怎么试过,而GraphicsMagick据说也是相当的给力,但网上很多评论基本上都是对效率的一些评测。感觉压缩上面不太给力,详细的描述可参看老王的博客http://hi.baidu.com/thinkinginlamp/blog/item/4b61e9241f08820f4c088d95.html
- 程序的优化,看下三个小组的解决方案和最终最好的解决方案。
大家对加水印这块无异议,仅在压缩上面做了文章,我只贴这里的代码。
优化前:
/** * 缩小图片尺寸. * * @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%