Skip to content

Bug: ImageMagickHandler throws exception without imagick extension #6297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
blurpy opened this issue Jul 26, 2022 · 12 comments · Fixed by #6312
Closed

Bug: ImageMagickHandler throws exception without imagick extension #6297

blurpy opened this issue Jul 26, 2022 · 12 comments · Fixed by #6312

Comments

@blurpy
Copy link

blurpy commented Jul 26, 2022

PHP Version

7.4

CodeIgniter4 Version

4.2.1

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

cli-server (PHP built-in webserver)

Database

MariaDB v5.5

What happened?

I'm migrating an app from CodeIgniter 3 to 4, and when trying to use the new image library it throws an exception:

CodeIgniter\Images\Exceptions\ImageException

The framework needs the following extension(s) installed and loaded: IMAGICK.

I have never installed the imagick extension with ci3, and according to the documentation it should not be required in ci4 either:

The ImageMagick handler does NOT require the imagick extension to be loaded on the server. As long as your script can access the library and can run exec() on the server, it should work.

Steps to Reproduce

Having just the command line imagemagick tools installed without the imagick extension.

.env:

images.defaultHandler = 'imagick'
images.libraryPath = '/usr/bin/convert'
class Images extends BaseController {

    private BaseHandler $image;

    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) {
        // Do Not Edit This Line
        parent::initController($request, $response, $logger);

        $this->image = Services::image(); // Exception thrown here
    }
...

Expected Output

Would expect the library to load without the imagick extension installed.

Anything else?

Looking at the description in the code, it seems to agree with the documentation in that the extension is not required:

* To make this library as compatible as possible with the broadest
* number of installations, we do not use the Imagick extension,
* but simply use the command line version.

However, the actual code looks for the extension and if it's not there it throws an exception in the constructor:

public function __construct($config = null)
{
parent::__construct($config);
// We should never see this, so can't test it
// @codeCoverageIgnoreStart
if (! (extension_loaded('imagick') || class_exists(Imagick::class))) {
throw ImageException::forMissingExtension('IMAGICK');
}

If I comment out throw ImageException::forMissingExtension('IMAGICK'); then the library allows me to resize an image, so the documentation seems to be correct in that the extension is not required.

I have not finished migration yet, so there could be some cases that do not work though.

@blurpy blurpy added the bug Verified issues on the current code behavior or pull requests that will fix them label Jul 26, 2022
@MGatner
Copy link
Member

MGatner commented Jul 27, 2022

It seems that the extension is actually required, as noted in that header comment:

hmm - the width & height accessors at the end use the imagick extension

Even though the User Guide explicitly states it is not necessary: https://codeigniter4.github.io/CodeIgniter4/libraries/images.html#initializing-the-class

I'm not familiar with the "width & height accessors" but that seems to be the area of need.

@kenjis
Copy link
Member

kenjis commented Jul 27, 2022

It seems these accessors are used only for testing. These methods should be @internal?

public function _getWidth()
{
return imagesx(imagecreatefromstring(file_get_contents($this->resource)));
}

* Return image width.
*
* accessor for testing; not part of interface
*
* @return int
*/
public function getWidth()
{
return ($this->resource !== null) ? $this->_getWidth() : $this->width;
}

@MGatner
Copy link
Member

MGatner commented Jul 28, 2022

Definitely. I assume the _ was in part supposed to indicate this.

If we make these @internal and remove the exception the this class should work without the extension?

@kenjis
Copy link
Member

kenjis commented Jul 28, 2022

If we make these @internal and remove the exception the this class should work without the extension?

I think so.

@MGatner
Copy link
Member

MGatner commented Jul 29, 2022

Can't be worse than it already is 🤷‍♂️

@kenjis
Copy link
Member

kenjis commented Jul 29, 2022

Sorry, I missed this:

protected function supportedFormatCheck()
{
switch ($this->image()->imageType) {
case IMAGETYPE_WEBP:
if (! in_array('WEBP', Imagick::queryFormats(), true)) {
throw ImageException::forInvalidImageCreate(lang('images.webpNotSupported'));
}
break;
}
}

@kenjis
Copy link
Member

kenjis commented Jul 29, 2022

It looks like we were planning to change it to use the imagick extension.

* FIXME - This needs conversion & unit testing, to use the imagick extension

@kenjis kenjis removed the bug Verified issues on the current code behavior or pull requests that will fix them label Jul 29, 2022
@kenjis
Copy link
Member

kenjis commented Jul 29, 2022

@blurpy Why don't you install the imagick extension?

@blurpy
Copy link
Author

blurpy commented Jul 29, 2022

I guess I could. I checked the production server, and both of these return true:

var_dump(extension_loaded('imagick'));
var_dump(class_exists(Imagick::class));

If the plan is to actually use the imagick extension then I can update my development environment.

@MGatner
Copy link
Member

MGatner commented Jul 30, 2022

If the current implementation relies on the extension and we have an exception enforcing that then the straightforward thing is to change the UG to match. I'm not familiar enough with Imagick and the differences between the installation and extension to make suggestions in implementation changes.

@kenjis
Copy link
Member

kenjis commented Jul 30, 2022

@blurpy I've created the issue: #6317

There is a problem with the current ImageMagickHandler and it seems to need to be fixed.

@blurpy
Copy link
Author

blurpy commented Jul 31, 2022

@kenjis Thanks, that issue with multiple calls to convert is a bit worrisome as I need scaling to be fast enough for users not to notice. And that works really well in ci3.

I also have a feature request I added a few days ago in the forums: https://forum.codeigniter.com/showthread.php?tid=82610
No one has approved it so it's not visible yet. But I need to be able to strip the exif when scaling images. Would be nice for that to be included while work is being done on the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants