如何在CodeIgniter PHP应用程序中加快图像大小调整?

Fer*_*Fer 7 php codeigniter imagemagick gd2

我有一个允许用户上传图像的应用程序.我使用的测试用例是一个1.6MB的jpeg,尺寸为3872 x 2592px.后端的上传脚本会将上传的图像调整为另外6种格式:

  • 方形(小75 x 75)
  • 小拇指(50 x 38)
  • 拇指(100 x 76)
  • 小(240 x 161)
  • 中等(500 x 378)
  • 大(1024 x 774)

我知道这很多但是相信我,我需要这个.我使用Code Igniter的Image Manipulation类进行调整大小,该类使用GD,GD2或ImageMagick进行调整大小.我首先将它配置为使用GD2,并注意到总调整大小过程需要11秒.

由于用户必须等待此过程,因此不可接受.经过大量阅读后,我了解到ImageMagick是一个更快更有效的操作库,所以我切换到了:

$sourceimage = $data['filedata']['file_path'] . $data['imagedata']['user_id'] . "/" . $imageid . $data['filedata']['file_ext'];
$resize_settings['image_library'] = 'imagemagick';
$resize_settings['library_path'] = '/usr/bin';
$resize_settings['source_image'] = $sourceimage;
$resize_settings['maintain_ratio'] = false;
$resize_settings['quality'] = "100%";
$this->load->library('image_lib', $resize_settings);
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,调整大小过程现在需要更长的时间:特定的15秒.

看一下我的日志,我看到每个调整大小动作需要2秒,无论它调整大小的文件格式.我想这是因为我总是从原来的大小调整,这是非常大的.

我不想将调整大小过程卸载到预定的进程,因为这会降低站点的可用性.这意味着用户必须等待几分钟才能开始查看/使用图像.

那么,有什么聪明的方法可以大大加快这个调整大小过程,以便我可以实时保存它吗?请注意:允许较小的分辨率不是一种选择,这是我正在建立的摄影网站.另外,我真的需要提到的六种格式.

Ali*_*xel 9

好像你已经接受了答案,但我还是会发布我的.

首先,你真的不需要100%的质量,90%85%的价值会很好,同时减少处理时间和图像尺寸(如果你不相信我只是进行一些测试).

我还用这个图像和一个自定义JPEG()函数做了一些基准测试,第一个测试用例:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg');
JPEG('./original.jpg', null, '500*378', './output/medium.jpg');
JPEG('./original.jpg', null, '240*161', './output/small.jpg');
JPEG('./original.jpg', null, '100*76', './output/thumb.jpg');
JPEG('./original.jpg', null, '50*38', './output/small_thumb.jpg');
JPEG('./original.jpg', null, '75*75', './output/square.jpg');
Run Code Online (Sandbox Code Playgroud)

我的慢速计算机平均需要60秒.


第二个测试案例:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg');
JPEG('./output/large.jpg', null, '500*378', './output/medium.jpg');
JPEG('./output/medium.jpg', null, '240*161', './output/small.jpg');
JPEG('./output/medium.jpg', null, '100*76', './output/thumb.jpg');
JPEG('./output/medium.jpg', null, '50*38', './output/small_thumb.jpg');
JPEG('./output/medium.jpg', null, '75*75', './output/square.jpg');
Run Code Online (Sandbox Code Playgroud)

这个"仅"16秒(我的电脑真的很慢ATM :P),快了近4倍.


以下是JPEG()您想要制作自己的基准测试的功能:

function JPEG($source, $crop = null, $scale = null, $destination = null)
{
    $source = ImageCreateFromJPEG($source);

    if (is_resource($source) === true)
    {
        $size = array(ImageSX($source), ImageSY($source));

        if (isset($crop) === true)
        {
            $crop = array_filter(explode('/', $crop), 'is_numeric');

            if (count($crop) == 2)
            {
                $crop = array($size[0] / $size[1], $crop[0] / $crop[1]);

                if ($crop[0] > $crop[1])
                {
                    $size[0] = $size[1] * $crop[1];
                }

                else if ($crop[0] < $crop[1])
                {
                    $size[1] = $size[0] / $crop[1];
                }

                $crop = array(ImageSX($source) - $size[0], ImageSY($source) - $size[1]);
            }

            else
            {
                $crop = array(0, 0);
            }
        }

        else
        {
            $crop = array(0, 0);
        }

        if (isset($scale) === true)
        {
            $scale = array_filter(explode('*', $scale), 'is_numeric');

            if (count($scale) >= 1)
            {
                if (empty($scale[0]) === true)
                {
                    $scale[0] = $scale[1] * $size[0] / $size[1];
                }

                else if (empty($scale[1]) === true)
                {
                    $scale[1] = $scale[0] * $size[1] / $size[0];
                }
            }

            else
            {
                $scale = array($size[0], $size[1]);
            }
        }

        else
        {
            $scale = array($size[0], $size[1]);
        }

        $result = ImageCreateTrueColor($scale[0], $scale[1]);

        if (is_resource($result) === true)
        {
            if (ImageCopyResampled($result, $source, 0, 0, $crop[0] / 2, $crop[1] / 2, $scale[0], $scale[1], $size[0], $size[1]) === true)
            {
                return ImageJPEG($result, $destination, 90);
            }
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • @Ferdy:是的,它在速度方面不应该太重要,但你仍然应该使用较低的质量,90%将图像的大小减少一半并保持所有的质量. (4认同)
  • @Alix,非常感谢你.我只是将质量改为90%,并注意到文件大小下降了2到3倍.因素取决于图像的大小,它越大,因子越大.我确实看不到质量差异.这很漂亮,因为我有一个预定的服务,将这些图像传输到Amazon S3,所以你只是为我节省了很多钱! (3认同)

Joh*_*ker 7

作为一个想法,您可以将上传的大小调整为更合理的中间大小,然后将其用作进一步操作的基础.

或者,您可以执行ImageMagick的命令行版本,并使用PHP中的异步shell exec中描述的过程在后台执行(至少大部分)图像转换.

最后,虽然它有点偏离主题,你是否允许纵向定位,或者这可能不是一个因素?

  • 非常感谢.我现在使用涓流效果调整大小,这意味着我从大到大调整到中等,接下来我使用中等图像(而不是大图像)来调整大小等等.现在需要不到3秒的时间来进行嘎吱嘎吱.我确实撕掉了一种格式(正方形)并切换回GD2,而不是imagemagick.据我所知,使用这种涓滴调整大小没有明显的质量问题.再次感谢! (3认同)