Description
PHP Version
7.4
CodeIgniter4 Version
4.2
CodeIgniter4 Installation Method
Composer (as dependency to an existing project)
Which operating systems have you tested for this bug?
macOS
Which server did you use?
apache
Database
MySQL 8
What happened?
Due to running commands multiple time through multiple exec calls and through unnecessarily setting the quality to 100 the implementation is greatly slowed down
Steps to Reproduce
The following code with a 712kb image is routinely taking over 14.5 seconds to execute.
$image = \Config\Services::image();
$image->withFile($path)
->reorient()
->resize(2400, 16, true)
->save(null, 90);
Expected Output
The same image processed through ImageMagick using CodeIgniter 3 takes less than 2 seconds.
There are 2 primary differences. CodeIgniter 3 executes everything in one exec command instead of 2 in CodeIgnter 4, which brings up the second difference of when CodeIgniter 4 executes a command without a quality it sets it to 100.
Simply updating line 209 of the ImageMagickHandler
from:
$cmd .= $action === '-version' ? ' ' . $action : ' -quality ' . $quality . ' ' . $action;
to:
$cmd .= $action === '-version' || $quality == 100 ? ' ' . $action : ' -quality ' . $quality . ' ' . $action;
Increases performance to just over 6 seconds.
However, doing this and batching the requests together so one is made instead of 2 from:
path/to/imagemagick/convert -quality 100 -resize 2400x1600 'image.png' 'image.png'
path/to/imagemagick/convert -quality 90 'image.png' 'image.png'
to:
path/to/imagemagick/convert -quality 90 -resize 2400x1600 'image.png' 'image.png'
increases performance back to CodeIgniter 3 levels of around 2 seconds.
Anything else?
I've implemented a custom ImageMagickHandler
that does this successfully for my specific use cases, however I'm not sure if there are other cases where waiting until save is called to execute a list of commands that have been compiled would be unwanted, in which case the implementation of image handlers as a whole might have to be reconsidered.
i.e at the moment calling $image->resize(2400, 16, true);
actually does something, where as in the case of my custom handler it just queues the command to be run when $image->save()
is called.