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

发布于 2024-08-16 01:30:02 字数 1206 浏览 2 评论 0原文

我有一个允许用户上传图像的应用程序。我使用的测试用例是 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);

令我惊讶的是,调整大小过程现在需要更长的时间:具体而言,需要 15 秒。

查看我的日志,我发现每个调整大小操作都需要 2 秒,无论其大小调整为何种文件格式。我想这是因为我总是根据原始尺寸调整大小,原始尺寸非常大。

我不想将调整大小的过程转移到预定的过程中,因为这会降低网站的可用性。这意味着用户必须等待几分钟才能开始查看/处理图像。

那么,有没有什么聪明的方法可以显着加快调整大小的过程,以便我可以保持实时状态?请明确:不允许使用较小的分辨率,这是我正在构建的摄影网站。另外,我真的需要提到的六种格式。

I have an application that allows users to upload images. The test case I use is a jpeg of 1.6MB with dimensions 3872 x 2592px. The upload script in the back-end will resize the uploaded image into 6 additional formats:

  • square (small 75 x 75)
  • Small Thumb (50 x 38)
  • Thumb (100 x 76)
  • Small (240 x 161)
  • Medium (500 x 378)
  • Large (1024 x 774)

I know it's a lot but trust me, I need this. I do the resizing using Code Igniter's Image Manipulation class, which uses either GD, GD2 or ImageMagick to do the resizing. I first configured it to use GD2 and noticed that the total resize process takes 11 secs.

Since the user has to wait for this process, it is not acceptable. After a lot of reading I learned that ImageMagick is a much faster and efficient manipulation library, so I switched to that:

$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);

Much to my surprise, the resize process now takes longer: 15 secs to be specific.

Having a look at my log I see that each resize action takes 2 seconds, no matter the file format it is resizing to. I guess this is because I always resize from the original, which is very large.

I would hate to offload the resizing process to a scheduled process, because that would decrease the usability of the site. It would mean that users have to wait a few minutes before they can start seeing/working with the image.

So, are there any smart ways to dramatically speed up this resizing process so that I can keep it in real-time? Just be clear: allowing for smaller resolutions is not an option, this is a photography site I'm building. Also, I really need the six formats mentioned.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

命比纸薄 2024-08-23 01:30:02

看来您已经接受了答案,但我仍会发布我的答案。

首先,您确实不需要在质量中使用 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');

在我的慢速计算机上,这平均需要 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');

这个测试用例“仅”需要 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;
}

Seems like you've already accepted an answer but I'm gonna still post mine.

First of all, you really don't need to use 100% in quality, a 90% or 85% value will do just fine while decreasing your processing time and image size (if you don't believe me just run some tests).

I've also done some benchmarks with this image and a custom JPEG() function, first test case:

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');

This takes an average of 60 seconds on my slow slow computer.


Second test case:

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');

This one takes "only" 16 seconds (my computer is really slow ATM :P), almost 4 times faster.


Here is the JPEG() function in case you want to make your own benchmarks:

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;
}
随遇而安 2024-08-23 01:30:02

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

或者,您可以执行 ImageMagick 的命令行版本,并使用 PHP 中的异步 shell 执行

最后,虽然有点偏离主题,但您是否会允许纵向方向,或者这可能不是一个因素?

As an idea, you could resize from the uploaded size to a more sensible intermediate size and then use this as the basis for further operations.

Alternatively, you could exec out to the command line version of ImageMagick and carry out (at least the bulk of) the image transformations in the background using the process described within Asynchronous shell exec in PHP.

Finally, whilst it's a bit off topic, are you going to allow for portrait orientation, or isn't this likely to be a factor?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文