PHP裁剪图片
原文地址:http://www.blogkid.net/archives/699.html
现在新兴的社区都比较流行小张的图片作为头像,douban几乎把32*32(UPDATE:是48*48)做成了尺寸的标准。V2EX用的也是小头像,比起原来PW/DZ那种用户指定头像、指定大小的方式,都用一样的尺寸看起来整洁了许多。
但是,假如现在有这样一张图片,我们怎么把它处理到合适的尺寸呢?我找了三段程序,实现的思路大体是一致的。
第一个我找了ECShop的code。一个购物系统当然少不了图片上传的部分。里面是这样写的:
……
/* 先将背景置为白色 */
$clr = imagecolorallocate($img_thumb, 255, 255, 255);
imagefilledrectangle($img_thumb, 0, 0, $thumb_width, $thumb_height, $clr);……
$scale_thumb = $thumb_width / $thumb_height;
$scale_org = $org_info[0] / $org_info[1];if ($scale_org > 1)
{
/* 原始图片比较宽,这时以宽度为准 */
$lessen_width = $thumb_width;
$lessen_height = $thumb_width / $scale_org;
}
else
{
/* 原始图片比较高,则以高度为准 */
$lessen_width = $thumb_height * $scale_org;
$lessen_height = $thumb_height;
}$dst_x = ($thumb_width – $lessen_width) / 2;
$dst_y = ($thumb_height – $lessen_height) / 2;if ($gd == 2)/*GD版本*/
{
imagecopyresampled ($img_thumb, $img_org, $dst_x, $dst_y, 0, 0, $lessen_width, $lessen_height, $org_info[0], $org_info[1]);
}
else
{
imagecopyresized ($img_thumb, $img_org, $dst_x, $dst_y, 0, 0, $lessen_width, $lessen_height, $org_info[0], $org_info[1]);
}
这种方法的确适合处理商品图片,但不适合用来做头像。因为这样处理图片只是进行缩放,并不进行裁减。按比例缩放肯定会使宽度(或高度)上留出空白,将以背景色代替,显然不是我们需要的。
第二个是在网上Google到的。节选关键部分来看,想要完整的source可以看一下:http://php.mydict.com/ziliao/5/2006_05/CaiJianTuPianDaoGuDingChiCunDeLei3525_1.html
//改变后的图象的比例
$resize_ratio = ($this->resize_width)/($this->resize_height);
//实际图象的比例
$ratio = ($this->width)/($this->height);if($ratio>=$resize_ratio)
//高度优先
{
$newimg = imagecreatetruecolor($this->resize_width,$this->resize_height);
imagecopyresampled($newimg, $this->im, 0, 0, 0, 0, $this->resize_width,$this->resize_height, (($this->height)*$resize_ratio), $this->height);
ImageJpeg ($newimg,$this->dstimg);
}
if($ratio< $resize_ratio)
//宽度优先
{
$newimg = imagecreatetruecolor($this->resize_width,$this->resize_height);
imagecopyresampled($newimg, $this->im, 0, 0, 0, 0, $this->resize_width, $this->resize_height, $this->width, (($this->width)/$resize_ratio));
ImageJpeg ($newimg,$this->dstimg);
}
处理得不错,但是注意到截取的部分不是中间,而是从一角开始。这样做往往得不到或截取不完整图片的主体。
第三个是Livid的Babel中的程序,在/htdocs/core/ImageCore.php中。Livid把图像操作写成一个类,其中就有一个改变大小的函数。有兴趣可以下载Babel的程序来看。
switch ($cutmode) {
case CM_LEFT_OR_TOP: $srcX = 0; $srcY = 0; break;
case CM_MIDDLE: $srcX = round(($srcW – $testW) / 2);
$srcY = round(($srcH – $testH) / 2); break;
case CM_RIGHT_OR_BOTTOM: $srcX = $srcW – $testW;
$srcY = $srcH – $testH;
}/*通过switch语句,可以确定裁剪的模式,对付头像自然用CM_MIDDLE*/
Livid的程序中注释比较少,因为GD版本不一样,所以使用了不少变量作为函数名。通过半个上午的研究,终于把这些搞懂了。最后还有一个问题就是效率。PHP这样处理的效率和用C++/Delphi相比,效率怎么样?会慢到什么程度?
UPDATE: 做的过程中一定会用到一个函数”imagecopyresampled”,低版本的GD里面用”imagecopyresized”。在PHP用户手册上可以查到他们的使用:
int imagecopyresized ( resource dst_im, resource src_im, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
imagecopyresized() 将一幅图像中的一块正方形区域拷贝到另一个图像中。dst_im 和 src_im 分别是目标图像和源图像的标识符。如果源和目标的宽度和高度不同,则会进行相应的图像收缩和拉伸。坐标指的是左上角。本函数可用来在同一幅图内部拷贝(如果 dst_im 和 src_im 相同的话)区域,但如果区域交迭的话则结果不可预知。


1 Response to “PHP裁剪图片”
[...] 我曾经写过两篇关于和web开发中处理图片有关的文章,一篇是在PHP中如何裁剪图片,对比了ECShop/Babel这两套系统的做法,侧重于对图片本身的操作;另一篇是在rails项目中如何上传图片,侧重于上传并保存的策略,即使上传的是pdf文档,也一样适用。 [...]