最近鄙厂的图片系统在做优化,关于处理显示图片用什么程序处理有点争论,某个人是觉得imagick方便也挺好用的,不过一位同事指出用GD可能能更节省资源和提高效率,经过简单的测试,发现结果确实如此。

也罢,学习嘛,就是不断的折腾。于是就配合着一起改了一版GD的处理;这几天才发现这货功能倒是还能满足就是全过程式的调用,一般只提供了最基本的方法,很多imagick里用到的功能需要自己封装。

例如以下2个常用的imagick的功能

  • cropImage
  • resizeImage

在实现crop的时候GD里可以用imagecopyresampled函数,它用来把一张图片采样后复制到另外一个资源里。看到这个函数的文档时,某整个人都shuffle!了,10个必填参数,还有8个是位置、尺寸相关的数字,而且文档里的说明几乎可以说是没有,看了一下后面用户贡献的示例没有太多帮助,某就只能自己折腾了。

首先需要说明的是,某这里以crop裁剪一张图片作为出发点。这个过程可以理解成这样

将图片A上截图一部分(取名叫C?),复制到新的图片画布B上,保存!

接下来,包流水账的事情某就不做了,用某的理解来看一下参数的含义。

  • 先是dst_imagesrc_image,用脚趾头想都知道这里指的就是上面说的图片B和A了,当然是GD资源。
  • dst_xdst_y,代表了截取部分C在新画布B上的落点
  • src_xsrc_y,代表了截取部分C在原图片A上的位置
  • dst_wdst_h,代表了截取部分贴到新画布上的大小,注意这个可以比新画布大哦!
  • src_wsrc_h,代表了截取部分C的高宽,很好理解

相信大家都注意到了,这个参数的顺序很…独特?嘛,这个先不吐槽了。

先来看一个例子,原图如下,你们随意吐槽。。

saya
saya

例如,我想把这张图片正中的400x300的区域裁剪出来,大概算一下能得到这样一些数值

saya
saya

截取部分距离原图左侧有1600 / 2 - 400 / 2 => 600,同理距离上部是1200 / 2 - 300 / 2 => 450,那么就得到src_xsrc_y分别是600和450。

因为,某想裁剪好的图片就是400x300,即截取部分完全填满新画布B,那么dst_xdst_y就是(0, 0),这个也很容易理解;同理,因为是“复制”,所以我们可以任意调整截取部分在新画布B上的位置,这里的位置是以截取部分左上角(topleft,northwest)为基准的。

截取的大小反应在src_wsrc_h上,这个也非常好理解,即从src_xsrc_y出发,高度与宽度,这里是(400, 300)。

最后参数是dst_wdst_h了,这个理解起来稍微有点绕,相当于复制到画布B上后的尺寸,也就是可以任意调整截取部分的尺寸,相当于一个resize。如果只是想复制到新画布的化,保留原大小即可。在这里即为(400, 300)。

最后我们就得到了所有参数,类似

$src = imagecreatefromjpeg('saya.jpg');
$dst = imagecreatetruecolor(400, 300); // 创建画布,截取大小和新图一致

imagecopyresampled($dst, $src, 0, 0, 600, 450, 400, 300, 400, 300);

最后输出就可以看到结果了www

saya-cropped
saya-cropped

再给一个例子,如果截取的大小超过了画布B,贴上去的时候又按照截取大小的话,超出画布B的部分的话,自然就被截掉了,如果不够大小就填不满了。

// 把原图1200x900开始的400x300大小截取后,缩放成800x300贴到一张800x600的画布上去,所以画布下半部分是空的
imagecopyresampled($dst, $src, 0, 0, 1200, 900, 800, 300, 400, 300);
saya-marked2
saya-marked2

saya-cropped2
saya-cropped2

最后是今天整理的一段等价于imagick里cropImage的代码,欢迎各位巨巨触手凌辱。

{% gist 2866219 %}

以上

__END__