PHP - 压缩图像以满足文件大小限制

时间:2014-07-21 18:21:50

标签: php image compression gd php-gd

我必须上传符合最大宽度尺寸和最大文件大小的图像文件。

我有代码检查宽度大小并调整图像大小以满足最大图像宽度。

但是,当我保存文件时,我可以设置质量

imagejpeg( $imgObject , 'resized/50.jpg' , 50 ); //save image and set quality

我想要做的是避免设置标准质量,因为提交的图像质量差异很大,开始时可能很低。

图像质量应尽可能高,不要超过最大文件大小限制。

我唯一的解决方案是以不同的质量保存图像的多个版本,检查每个文件大小并选择最佳文件。这可行,但速度很慢,而且过程密集。

有关如何做得更好的任何建议?

由于

3 个答案:

答案 0 :(得分:2)

这是实现这一目标的一种方法。除非确信文件大小小于指定的最大值,否则它不会保存文件。

$original_file = 'original.jpg';
$resized_file = 'resized.jpg';
$max_file_size = '30000'; // maximum file size, in bytes

$original_image = imagecreatefromjpeg($original_file);

$image_quality = 100;

do {
    $temp_stream = fopen('php://temp', 'w+');
    $saved = imagejpeg($original_image, $temp_stream, $image_quality--);
    rewind($temp_stream);
    $fstat = fstat($temp_stream);
    fclose($temp_stream);

    $file_size = $fstat['size'];
}
while (($file_size > $max_file_size) && ($image_quality >= 0));

if (-1 == $image_quality) {
    echo "Unable to get the file that small. Best I could do was $file_size bytes at image quality 0.\n";
}
else {
    echo "Successfully resized $original_file to $file_size bytes using image quality $image_quality. Resized file saved as $resized_file.\n";
    imagejpeg($new_image, $resized_file, $image_quality + 1);
}

在成功找到理想的压缩率之前,不需要写入任何文件。

此循环以$ image_quality为100开始,然后递减尝试在临时内存缓冲区中尝试每个新值。如果下降到尝试0并且文件仍然太大,则会返回错误消息。否则,如果达到一个可行的值,它将报告该错误并使用该图像质量设置保存新文件。

如果您喜欢冒险,可以实施二进制搜索算法来更快地找到理想的压缩率,但是这种快速修复方法可以提供相同的结果,尽管可能慢一些。

答案 1 :(得分:0)

没有。这是最佳的选择。

答案 2 :(得分:-1)

不幸的是,估算最终文件大小并不是因为您无法访问JPEG编码器的内部状态所能做的事情。

您可以做的一件事是压缩较小版本的图像并从那里进行推断。将宽度和高度减小四意味着计算机必须仅处理十六分之一的像素。这里的技巧是如何准备代表性的测试图像。使用imagecopyresampled()或imagecopyresized()缩小图像不会起作用。它过多地改变了压缩特性。相反,您要做的是从原始图像中复制每四个8x8磁贴:

$width1 = imagesx($img1);
$height1 = imagesy($img1);
$width2 = floor($width1 / 32) * 8;
$height2 = floor($height1 / 32) * 8;
$img2 = imagecreatetruecolor($width2, $height2);
for($x1 = 0, $x2 = 0; $x2 + 8 < $width2; $x1 += 32, $x2 += 8) {
    for($y1 = 0, $y2 = 0; $y2 + 8 < $height2; $y1 += 32, $y2 += 8) {
        imagecopy($img2, $img1, $x2, $y2, $x1, $y1, 8, 8);
    }
}

以各种质量级别压缩较小的图像并获得受尊重的文件大小。将它们乘以16可以得出对原始图像所得到的相当好的估计。