题
什么是最有效的方式调整大图像在PHP?
目前,我正在使用的 GD 功能imagecopyresampled采取高分辨率图像,以及净调整他们的下一个尺寸对于网络的观察(大约700素宽700高素).
这工作很不错的小型(2MB)照片和整个调整操作需要不到第二个在服务器上。然而,该网站将最终服务的摄影师可以图像上传达到10MB(或图像,达到5000x4000素在大小)。
做这种调整作的大图像的倾向增加的存储使用过的一个非常大的利润(大图像可以尖峰的存储器使用的剧本过去的80MB)。是否有任何方式作出这种调整的操作更加有效?我应该采用一个备用的图像图书馆等 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);
解决方案
人们说,ImageMagick的速度要快得多。在最好的比较这两个图书馆和措施。
- 准备1000典型的图像。
- 编写的两个脚本--一个用于GD,一个 为ImageMagick.
- 运行两个他们几次。
- 比较结果(总执行 时间,CPU和I/O使用情况、结果 图像质量)。
一些东西,最好其他人一样,不可能对你最好的。
此外,在我看来,ImageMagick有更好的API接口。
其他提示
这里的一段从php.net 文档,我已经用于项目和工作的罚款:
<?
function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
// Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
// Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
// Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
// Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain.
//
// Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero.
// Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect.
// 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized.
// 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3.
// 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster.
// 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images.
// 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled.
if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; }
if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
$temp = imagecreatetruecolor ($dst_w * $quality + 1, $dst_h * $quality + 1);
imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h);
imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality);
imagedestroy ($temp);
} else imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
return true;
}
?>
http://us.php.net/manual/en/function.imagecopyresampled.php#77679
phpThumb 使用ImageMagick尽可能速度(回落到GD如果必要的),似乎相当缓以及减少负载服务器。这是很轻的尝试(调整的图像,只是呼叫phpThumb.php 有一个得到查询的,包括图形的文件和输出的尺寸),所以你还给它一个镜头来看看它是否满足了你的需求。
对于较大的图像的使用libjpeg要调整上的图像载在ImageMagick,从而显着降低了存储器的使用和改善业绩,这是不可能GD。
$im = new Imagick();
try {
$im->pingImage($file_name);
} catch (ImagickException $e) {
throw new Exception(_('Invalid or corrupted image file, please try uploading another image.'));
}
$width = $im->getImageWidth();
$height = $im->getImageHeight();
if ($width > $config['width_threshold'] || $height > $config['height_threshold'])
{
try {
/* send thumbnail parameters to Imagick so that libjpeg can resize images
* as they are loaded instead of consuming additional resources to pass back
* to PHP.
*/
$fitbyWidth = ($config['width_threshold'] / $width) > ($config['height_threshold'] / $height);
$aspectRatio = $height / $width;
if ($fitbyWidth) {
$im->setSize($config['width_threshold'], abs($width * $aspectRatio));
} else {
$im->setSize(abs($height / $aspectRatio), $config['height_threshold']);
}
$im->readImage($file_name);
/* Imagick::thumbnailImage(fit = true) has a bug that it does fit both dimensions
*/
// $im->thumbnailImage($config['width_threshold'], $config['height_threshold'], true);
// workaround:
if ($fitbyWidth) {
$im->thumbnailImage($config['width_threshold'], 0, false);
} else {
$im->thumbnailImage(0, $config['height_threshold'], false);
}
$im->setImageFileName($thumbnail_name);
$im->writeImage();
}
catch (ImagickException $e)
{
header('HTTP/1.1 500 Internal Server Error');
throw new Exception(_('An error occured reszing the image.'));
}
}
/* cleanup Imagick
*/
$im->destroy();
从你quesion,看来你还挺新GD,我将分享一些经验的雷, 也许这是有点离题,但我认为它将有助于新的人GD喜欢你:
步骤1、验证的文件。 使用下列功能检查,如果 $_FILES['image']['tmp_name']
文件是有效的文件:
function getContentsFromImage($image) {
if (@is_file($image) == true) {
return file_get_contents($image);
} else {
throw new \Exception('Invalid image');
}
}
$contents = getContentsFromImage($_FILES['image']['tmp_name']);
步骤2、获取文件的格式 试试下面的功能与finfo扩展到检查的文件格式的文件(内容)。你会说你为什么不用 $_FILES["image"]["type"]
检查文件的格式?因为它 只 检查文件的扩展不文件的内容,如果有人重新命名的文件最初被称为 世界。png 要 world.jpg, $_FILES["image"]["type"]
将返回jpeg不png,所以 $_FILES["image"]["type"]
可以返回错误的结果。
function getFormatFromContents($contents) {
$finfo = new \finfo();
$mimetype = $finfo->buffer($contents, FILEINFO_MIME_TYPE);
switch ($mimetype) {
case 'image/jpeg':
return 'jpeg';
break;
case 'image/png':
return 'png';
break;
case 'image/gif':
return 'gif';
break;
default:
throw new \Exception('Unknown or unsupported image format');
}
}
$format = getFormatFromContents($contents);
步骤。3中,获得GD资源 获得GD资源从内容,我们之前:
function getGDResourceFromContents($contents) {
$resource = @imagecreatefromstring($contents);
if ($resource == false) {
throw new \Exception('Cannot process image');
}
return $resource;
}
$resource = getGDResourceFromContents($contents);
步骤4、获得图像的尺寸 现在你可以获得图像的尺寸与以下简单的代码:
$width = imagesx($resource);
$height = imagesy($resource);
现在, 让我们看看有什么变量,我们得到了从原始图像,然后:
$contents, $format, $resource, $width, $height
OK, lets move on
步骤5、计算参数的调整大小的图像 这一步骤是关于你的问题,目的的下列功能得到调整参数GD功能 imagecopyresampled()
, 代码是有点长,但它的伟大工程,它甚至有三个选项:伸展、收缩、以及填补。
伸展:输出的图像的维是相同的新的层面。不会保持高度/宽度的比例。
收缩:输出的图像的尺寸不超过新的维你得和保留图像的高度/宽度的比例。
填充:输出的图像的尺度将是相同的,因为新的层面你给,就会 农作物和调整大小 图像,如果需要,并保持像高/宽度的比例。 这个选择你需要的是什么在你的问题。
function getResizeArgs($width, $height, $newwidth, $newheight, $option) {
if ($option === 'stretch') {
if ($width === $newwidth && $height === $newheight) {
return false;
}
$dst_w = $newwidth;
$dst_h = $newheight;
$src_w = $width;
$src_h = $height;
$src_x = 0;
$src_y = 0;
} else if ($option === 'shrink') {
if ($width <= $newwidth && $height <= $newheight) {
return false;
} else if ($width / $height >= $newwidth / $newheight) {
$dst_w = $newwidth;
$dst_h = (int) round(($newwidth * $height) / $width);
} else {
$dst_w = (int) round(($newheight * $width) / $height);
$dst_h = $newheight;
}
$src_x = 0;
$src_y = 0;
$src_w = $width;
$src_h = $height;
} else if ($option === 'fill') {
if ($width === $newwidth && $height === $newheight) {
return false;
}
if ($width / $height >= $newwidth / $newheight) {
$src_w = (int) round(($newwidth * $height) / $newheight);
$src_h = $height;
$src_x = (int) round(($width - $src_w) / 2);
$src_y = 0;
} else {
$src_w = $width;
$src_h = (int) round(($width * $newheight) / $newwidth);
$src_x = 0;
$src_y = (int) round(($height - $src_h) / 2);
}
$dst_w = $newwidth;
$dst_h = $newheight;
}
if ($src_w < 1 || $src_h < 1) {
throw new \Exception('Image width or height is too small');
}
return array(
'dst_x' => 0,
'dst_y' => 0,
'src_x' => $src_x,
'src_y' => $src_y,
'dst_w' => $dst_w,
'dst_h' => $dst_h,
'src_w' => $src_w,
'src_h' => $src_h
);
}
$args = getResizeArgs($width, $height, 150, 170, 'fill');
步骤6的调整图像 使用 $args
, $width
, $height
, $format
美元的资源,我们得到了从上到下列功能和获得新资源的调整大小的图片:
function runResize($width, $height, $format, $resource, $args) {
if ($args === false) {
return; //if $args equal to false, this means no resize occurs;
}
$newimage = imagecreatetruecolor($args['dst_w'], $args['dst_h']);
if ($format === 'png') {
imagealphablending($newimage, false);
imagesavealpha($newimage, true);
$transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
imagefill($newimage, 0, 0, $transparentindex);
} else if ($format === 'gif') {
$transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
imagefill($newimage, 0, 0, $transparentindex);
imagecolortransparent($newimage, $transparentindex);
}
imagecopyresampled($newimage, $resource, $args['dst_x'], $args['dst_y'], $args['src_x'], $args['src_y'], $args['dst_w'], $args['dst_h'], $args['src_w'], $args['src_h']);
imagedestroy($resource);
return $newimage;
}
$newresource = runResize($width, $height, $format, $resource, $args);
步骤7,获得新的内容, 使用以下的功能,以获得内容从新GD资源:
function getContentsFromGDResource($resource, $format) {
ob_start();
switch ($format) {
case 'gif':
imagegif($resource);
break;
case 'jpeg':
imagejpeg($resource, NULL, 100);
break;
case 'png':
imagepng($resource, NULL, 9);
}
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
$newcontents = getContentsFromGDResource($newresource, $format);
步骤8得到扩展, 使用以下的功能得到延长,从图像的格式(注意,像格式并不等于图像的扩展):
function getExtensionFromFormat($format) {
switch ($format) {
case 'gif':
return 'gif';
break;
case 'jpeg':
return 'jpg';
break;
case 'png':
return 'png';
}
}
$extension = getExtensionFromFormat($format);
步骤9节省的图像 如果我们有一个用户名叫麦克,你可以做到以下几点,这将节省的同一个文件夹,因为这php script:
$user_name = 'mike';
$filename = $user_name . '.' . $extension;
file_put_contents($filename, $newcontents);
步骤10破坏资源 不要忘记摧毁GD资源!
imagedestroy($newresource);
或者你可以写你的所有代码成一类,而只是使用如下:
public function __destruct() {
@imagedestroy($this->resource);
}
提示
我建议不要转换的文件格式用户传,你会遇到许多问题。
我建议你工作的东西沿着这些线:
- 执行getimagesize()上传文件,以检查的图像类型和大小
- 保存任何上传的JPEG图像比较小700x700px在到目的文件夹",是"
- 使用GD library于中等大小的图像(见本文的代码样本: 调整的图像,使用PHP和GD Library)
- 使用ImageMagick大的图像。你可以使用ImageMagick在背景如果你喜欢。
使用ImageMagick在背景,将上载的文件的临时文件夹和安排计划的工作"转换为"所有文件s jpeg和调整它们的相应。看到命令法: imagemagick-命令行处理
你可以提示用户,文件上传和计划进行处理。计划任务的工作可以是计划运行,每天在一个特定的时间间隔。源图像可以删除后处理,以确保图像不是处理两倍。
我听说大事情有关Imagick库,不幸的是,我不能安装在我工作的电脑也不在家(和相信我,我花了几个小时和小时在各种论坛).
后记,我决定要试试这个PHP class:
http://www.verot.net/php_class_upload.htm
它很酷,我可以重新调整所有类型的图像(我可以把他们JPG也同样)。
ImageMagick是多线程,所以它的出现被更快地,但是实际使用更多的资源比GD。如果你跑了几个PHP scripts在平行的所有使用GD然后他们会打ImageMagick在的速度,为简单的业务。ExactImage是不那么强大的比ImageMagick但是快了很多,虽然不可以通过PHP,你必须安装服务器上运行,它通过 exec
.
对于较大的图像的使用 phpThumb().这里是如何使用它: http://abcoder.com/php/problem-with-resizing-corrupted-images-using-php-image-functions/.它也可以作为大损坏的图像。