在PHP中调整大图像大小的最有效方法是什么?
我目前正在使用GD函数imagecopyresampled来拍摄高分辨率图像,并将它们干净地调整到适合网页查看的大小(大约700像素宽,700像素高) .
这适用于小(2 MB以下)的照片,整个调整大小操作在服务器上只需不到一秒钟 . 但是,该网站最终将为可能上传最大10 MB图像的摄影师提供服务(或者图像尺寸最大为5000x4000像素) .
使用大图像执行此类调整大小操作往往会大幅增加内存使用量(较大的图像会使脚本的内存使用量超过80 MB) . 有没有办法让这个调整大小操作更有效率?我应该使用备用图像库,例如ImageMagick吗?
现在,调整大小代码看起来像这样
function makeThumbnail($sourcefile, $endfile, $thumbwidth, $thumbheight, $quality) {
// Takes the sourcefile (path/to/image.jpg) and makes a thumbnail from it
// and places it at endfile (path/to/thumb.jpg).
// Load image and get image size.
$img = imagecreatefromjpeg($sourcefile);
$width = imagesx( $img );
$height = imagesy( $img );
if ($width > $height) {
$newwidth = $thumbwidth;
$divisor = $width / $thumbwidth;
$newheight = floor( $height / $divisor);
} else {
$newheight = $thumbheight;
$divisor = $height / $thumbheight;
$newwidth = floor( $width / $divisor );
}
// Create a new temporary image.
$tmpimg = imagecreatetruecolor( $newwidth, $newheight );
// Copy and resize old image into new image.
imagecopyresampled( $tmpimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height );
// Save thumbnail into a file.
imagejpeg( $tmpimg, $endfile, $quality);
// release the memory
imagedestroy($tmpimg);
imagedestroy($img);
9 回答
ImageMagick是多线程的,因此看起来更快,但实际上使用的资源比GD多得多 . 如果您使用GD并行运行多个PHP脚本,那么它们必须在服务器上安装它并通过
exec
运行它 .对于较大的图像,请使用phpThumb() . 以下是如何使用它:http://abcoder.com/php/problem-with-resizing-corrupted-images-using-php-image-functions/ . 它也适用于大型损坏的图像 .
人们说ImageMagick要快得多 . 最好只比较两个库并测量它 .
准备1000张典型图像 .
编写两个脚本 - 一个用于GD,一个用于ImageMagick .
运行它们几次 .
比较结果(总执行时间,CPU和I / O使用情况,结果图像质量) .
其他人最好的东西,对你来说不是最好的 .
另外,在我看来,ImageMagick有更好的API接口 .
这是我在项目中使用的php.net文档的一个片段,工作正常:
http://us.php.net/manual/en/function.imagecopyresampled.php#77679
phpThumb尽可能使用ImageMagick速度(必要时回退到GD)并且似乎缓存非常好以减少服务器上的负载 . 尝试它是非常轻量级的(调整图像大小,只需用包含图形文件名和输出尺寸的GET查询调用phpThumb.php),这样你就可以试一试它是否符合你的需求 .
对于较大的图像,使用libjpeg调整ImageMagick中的图像负载大小,从而显着减少内存使用并提高性能,GD不可能实现 .
从你的问题来看,你似乎对GD有点新意,我会分享一些我的经历,也许这有点偏离主题,但我认为对你这样的新人来说会有所帮助:
Step 1, validate file. 使用以下函数检查
$_FILES['image']['tmp_name']
文件是否为有效文件:Step 2, get file format 尝试使用finfo扩展名的以下函数来检查文件的文件格式(内容) . 你会说为什么不用
$_FILES["image"]["type"]
检查文件格式?因为它检查文件扩展名不是文件内容,如果有人将原来名为world.png的文件重命名为world.jpg,$_FILES["image"]["type"]
将返回jpeg而不是png,因此$_FILES["image"]["type"]
可能返回错误的结果 .Step.3, Get GD resource 从之前的内容中获取GD资源:
Step 4, get image dimension 现在,您可以使用以下简单代码获取图像尺寸:
Now, 让我们看看我们从原始图像中获得了什么变量:
Step 5, calculate resized image arguments 这一步与您的问题有关,以下函数的目的是为GD函数
imagecopyresampled()
获取调整大小参数,代码有点长,但它工作得很好,它甚至有三个选项:拉伸,收缩和填充 .stretch :输出图像's dimension is the same as the new dimension you set. Won' t保持高/宽比 .
shrink :输出图像's dimension won' t超出您给出的新尺寸,并保持图像高度/宽度比 .
fill :输出图像的尺寸与您给出的新尺寸相同,如果需要,它将为 crop & resize 图像,并保持图像高度/宽度比 . This option is what you need in your question.
Step 6, resize image 使用我们从上面获得的
$args
,$width
,$height
,$format
和$资源到以下函数中并获取已调整大小的图像的新资源:Step 7, get new contents ,使用以下函数从新的GD资源获取内容:
Step 8 get extension ,使用以下函数从图像格式获取扩展名(注意,图像格式不等于图像扩展名):
Step 9 save image 如果我们有一个名为mike的用户,您可以执行以下操作,它将保存到与此php脚本相同的文件夹中:
Step 10 destroy resource 别忘了销毁GD资源!
或者您可以将所有代码写入类中,只需使用以下代码:
TIPS
I recommend not to convert file format that user upload, you will meet many problems.
我建议你按照以下方式开展工作:
在上传的文件上执行getimagesize()以检查图像类型和尺寸
将任何小于700x700px的上传JPEG图像保存到目标文件夹"as-is"
将GD库用于中等大小的图像(有关代码示例,请参阅此文章:Resize Images Using PHP and GD Library)
使用ImageMagick拍摄大图像 . 如果您愿意,可以在后台使用ImageMagick .
要在后台使用ImageMagick,请将上传的文件移动到临时文件夹,并安排一个CRON作业"convert"s将所有文件转换为jpeg并相应地调整它们的大小 . 请参阅命令语法:imagemagick-command line processing
您可以提示用户上载和计划处理文件 . 可以安排CRON作业每天以特定间隔运行 . 处理后可以删除源图像,以确保图像不被处理两次 .
我听说过Imagick图书馆的大事,不幸的是我无法在我的工作电脑上安装它,也不能在家里安装(相信我,我在各种论坛上花费了数小时和数小时) .
后来,我决定尝试这个PHP类:
http://www.verot.net/php_class_upload.htm
这很酷,我可以调整各种图像(我也可以将它们转换为JPG) .