Closed jamesmacwhite closed 2 years ago
Thanks for reporting!
This is caused by the same underlying issue that caused #157 (and for reference it's due to https://externals.io/message/116543). PHP's utility method for extracting information about images doesn't work, the image will probably have to be loaded with the image driver (GD or Imagick), for the size to be determined. There's a straight forward fix, but I'll do some additional testing because I suspect it'll impact performance somewhat. Maybe better to use the information stored on the asset, if the source image is an asset, and then use the loading route only for external images.
Thanks for your prompt reply!
The easy workaround at the moment is don't use AVIF as the source image, although Craft CMS allows it and as far as I can tell you can't easily remove/restrict extensions, only add additional ones or custom kinds which you'd then need to update any asset field, I did consider just blocking AVIF uploads for assets for now, but I don't think that is easily doable through the Craft CMS config from what I can tell.
Although if there's a workable and performant fix in Imager-X that would be even better!
I will fix it one way or another for Imager, just need to test a little bit on what the best approach is.
The only native thing that would help in this regard is the extraFileKinds
general config setting, ie:
'extraFileKinds' => [
'websafeimage' => [
'label' => 'Web Safe Image',
'extensions' => ['gif', 'jpg', 'jpeg', 'png'],
],
],
Which will only allow these extensions to be added to a field. But as you say, you'd have to go through and edit all your fields, and the client would still be able to upload avifs to assets, so not perfect.
We created a plugin for adding restrictions to asset uploads that we use internally at my agency, so it's definately possible to make. But it'd rather belong in core.
Thank you for acknowledging and committing to a fix. I will just inform users for now to avoid anything AVIF to be honest, I agree anything around restricting file types should be in core, I could also likely do a similar thing like you've done with adding some custom handling in a module.
Main thing has been to understand and report the issue, as we've seen it a few times now in Sentry, so good to flag it and start the process on working on a fix.
Various steps to amend this issue was added to 4.1.3 and 3.6.3. If the size of a transformed image can't be calculated (the image is of a format that getimagesize
can't read, and the transform itself is not enough to calculate the size), the following three steps will be tried on the source image:
1) Use getimagesize
on the source image.
2) If that fails, use the width and height of the source asset, if an asset was passed.
3) If that fails, the source image is loaded with Imagine and the image driver tries to get the size (which will succeed if the driver has support for the format). The result is cached in the data cache to ease the pain of the performance hit.
At this stage, the probablility that we don't have a size to work with, is really slim.
Amazing work! Thank you for your efforts!
FYI. I tested Imager-X 3.6.3.1 with an AVIF image and it still errors with the DivisionByZero error, here' the full stack trace if it helps where our website is failing at each part of the plugin.
DivisionByZeroError: Division by zero in /srv/app/nttmcoll-staging/htdocs/vendor/spacecatninja/imager-x/src/models/ImgixTransformedImageModel.php:94
Stack trace:
#0 /srv/app/nttmcoll-staging/htdocs/vendor/spacecatninja/imager-x/src/transformers/ImgixTransformer.php(116): spacecatninja\imagerx\models\ImgixTransformedImageModel->__construct('https://notting...', Object(craft\elements\Asset), Array, Object(spacecatninja\imagerx\models\ImgixSettings))
#1 /srv/app/nttmcoll-staging/htdocs/vendor/spacecatninja/imager-x/src/transformers/ImgixTransformer.php(67): spacecatninja\imagerx\transformers\ImgixTransformer->getTransformedImage(Object(craft\elements\Asset), Array)
#2 /srv/app/nttmcoll-staging/htdocs/vendor/spacecatninja/imager-x/src/services/ImagerService.php(472): spacecatninja\imagerx\transformers\ImgixTransformer->transform(Object(craft\elements\Asset), Array)
#3 /srv/app/nttmcoll-staging/htdocs/vendor/spacecatninja/imager-x/src/variables/ImagerVariable.php(38): spacecatninja\imagerx\services\ImagerService->transformImage(Object(craft\elements\Asset), Array, NULL, NULL)
#4 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Extension/CoreExtension.php(1566): spacecatninja\imagerx\variables\ImagerVariable->transformImage(Object(craft\elements\Asset), Array)
#5 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/helpers/Template.php(106): twig_get_attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(spacecatninja\imagerx\variables\ImagerVariable), 'transformImage', Array, 'method', false, false)
#6 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/ba/bac01bbefd36ba85303cda5c1a3f701f3c0b7f84ab71369c965c280352badece.php(76): craft\helpers\Template::attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(spacecatninja\imagerx\variables\ImagerVariable), 'transformImage', Array, 'method')
#7 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Extension/CoreExtension.php(1169): __TwigTemplate_bde5669c3c26113909821dbf0dcc52426cf0286171c6c0d3b3e51c07b086b722->macro_imageTransformAny(Object(craft\elements\Asset), Array, 'Charlie and Deb...', NULL)
#8 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/ba/bac01bbefd36ba85303cda5c1a3f701f3c0b7f84ab71369c965c280352badece.php(123): twig_call_macro(Object(__TwigTemplate_bde5669c3c26113909821dbf0dcc52426cf0286171c6c0d3b3e51c07b086b722), 'macro_imageTran...', Array, 21, Array, Object(Twig\Source))
#9 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Extension/CoreExtension.php(1169): __TwigTemplate_bde5669c3c26113909821dbf0dcc52426cf0286171c6c0d3b3e51c07b086b722->macro_sized(Object(craft\elements\Asset), 300, 800, 'Charlie and Deb...', NULL, 'fit')
#10 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/32/3206c3a82fc10acaeb973885fab9a232f25d3940b1ec2ba146f432b3b9edd096.php(103): twig_call_macro(Object(__TwigTemplate_bde5669c3c26113909821dbf0dcc52426cf0286171c6c0d3b3e51c07b086b722), 'macro_sized', Array, 23, Array, Object(Twig\Source))
#11 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(405): __TwigTemplate_566c3a3650c20ae673ea7b4042c36ba999a9afffb5147f481c962f69b4dc112e->doDisplay(Array, Array)
#12 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array)
#13 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/ba/ba19465ceeaef756eb130ccf3dd795fe78404b97e37887aa5241fcfd9c94b134.php(120): Twig\Template->display(Array)
#14 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(405): __TwigTemplate_7bfaf7fa67651f1b3b6f373bd653ac3cdc9f4f33544e2e921129f9bd176da145->doDisplay(Array, Array)
#15 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array)
#16 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/b6/b69cb55b6a4e888965d30edf101a6cb47b0a32005364cc0723fabfa7bbe39ab0.php(140): Twig\Template->display(Array)
#17 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(182): __TwigTemplate_34a5dcd031fe6ba6e83c824da30ed81fdcde7d2c93d716c213fb0b880d319c9e->block_body(Array, Array)
#18 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/b6/b69cb55b6a4e888965d30edf101a6cb47b0a32005364cc0723fabfa7bbe39ab0.php(108): Twig\Template->displayBlock('body', Array, Array)
#19 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(182): __TwigTemplate_34a5dcd031fe6ba6e83c824da30ed81fdcde7d2c93d716c213fb0b880d319c9e->block_content(Array, Array)
#20 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/a1/a1dcd9d8126e591269366c011ebd0eed57245df6a785d14f2da92bdf8548fcab.php(569): Twig\Template->displayBlock('content', Array, Array)
#21 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(182): __TwigTemplate_940441b0a9a9a4a86ff8ee9a9705b8ffa5ce3c28f7e9d7a7c7844946b156ab5b->block_fullPage(Array, Array)
#22 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/a1/a1dcd9d8126e591269366c011ebd0eed57245df6a785d14f2da92bdf8548fcab.php(416): Twig\Template->displayBlock('fullPage', Array, Array)
#23 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(405): __TwigTemplate_940441b0a9a9a4a86ff8ee9a9705b8ffa5ce3c28f7e9d7a7c7844946b156ab5b->doDisplay(Array, Array)
#24 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array)
#25 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/b6/b69cb55b6a4e888965d30edf101a6cb47b0a32005364cc0723fabfa7bbe39ab0.php(49): Twig\Template->display(Array, Array)
#26 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(405): __TwigTemplate_34a5dcd031fe6ba6e83c824da30ed81fdcde7d2c93d716c213fb0b880d319c9e->doDisplay(Array, Array)
#27 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array)
#28 /srv/app/nttmcoll-staging/htdocs/storage/runtime/compiled_templates/0c/0cd84fcfbfd9105c49fd3b71a667132eea7fd7489e72c27411a9b51b9cc75878.php(152): Twig\Template->display(Array, Array)
#29 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(405): __TwigTemplate_405d614b56dfd502476ed37b7a11d99c24114741ec88d22c9ff7650f6a8b302f->doDisplay(Array, Array)
#30 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(378): Twig\Template->displayWithErrorHandling(Array, Array)
#31 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Template.php(390): Twig\Template->display(Array)
#32 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/TemplateWrapper.php(45): Twig\Template->render(Array, Array)
#33 /srv/app/nttmcoll-staging/htdocs/vendor/twig/twig/src/Environment.php(318): Twig\TemplateWrapper->render(Array)
#34 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/web/View.php(408): Twig\Environment->render('_dispatcher', Array)
#35 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/web/View.php(461): craft\web\View->renderTemplate('_dispatcher', Array)
#36 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/web/Controller.php(205): craft\web\View->renderPageTemplate('_dispatcher', Array, 'site')
#37 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/controllers/TemplatesController.php(102): craft\web\Controller->renderTemplate('_dispatcher', Array)
#38 [internal function]: craft\controllers\TemplatesController->actionRender('_dispatcher', Array)
#39 /srv/app/nttmcoll-staging/htdocs/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#40 /srv/app/nttmcoll-staging/htdocs/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#41 /srv/app/nttmcoll-staging/htdocs/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('render', Array)
#42 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/web/Application.php(293): yii\base\Module->runAction('templates/rende...', Array)
#43 /srv/app/nttmcoll-staging/htdocs/vendor/yiisoft/yii2/web/Application.php(103): craft\web\Application->runAction('templates/rende...', Array)
#44 /srv/app/nttmcoll-staging/htdocs/vendor/craftcms/cms/src/web/Application.php(278): yii\web\Application->handleRequest(Object(craft\web\Request))
#45 /srv/app/nttmcoll-staging/htdocs/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#46 /srv/app/nttmcoll-staging/htdocs/web/index.php(12): yii\base\Application->run()
#47 {main}
Dang. Need some more information:
1) I see that you're passing in an asset right? If you go to the asset detail view in Craft, or activate dimensions in the element index, does it show the dimensions of the image there? 2) Can you post your imgix config (make sure to strip out any sensitive credentials). 3) What type of source is the Imgix source? 4) What's the transform you're doing on the asset when this fails?
Sure.
<?php
/**
* Imager by André Elvan
*
* @author André Elvan <http://vaersaagod.no>
* @package Imager
* @copyright Copyright (c) 2016, André Elvan
* @license http://opensource.org/licenses/mit-license.php MIT License
* @link https://github.com/aelvan/Imager-Craft
*/
/**
* Configuration file for Imager
*
* Override this by placing a file named 'imager-x.php' inside your config folder and override variables as needed.
* Multi-environment settings work in this file the same way as in general.php or db.php
*/
use craft\helpers\App;
return [
'*' => [
'transformer' => App::env('IMGIX_ENABLED') ? 'imgix' : 'craft',
'imagerSystemPath' => 'resized/',
'imagerUrl' => rtrim(App::env('UPLOAD_ASSET_BASE_URL'), '/') . '/resized/' . strtolower(CRAFT_ENVIRONMENT) . '/',
'interlace' => true,
'allowUpscale' => true,
'removeMetadata' => true,
'filenamePattern' => 'postfix',
'hashRemoteUrl' => false,
'instanceReuseEnabled' => false,
'useForCpThumbs' => App::parseBooleanEnv('$IMGIX_ENABLED') ?? false,
'imgixApiKey' => App::env('IMGIX_API_KEY'),
'imgixConfig' => [
'default' => [
'domain' => App::env('IMGIX_HOSTNAME'),
'useHttps' => true,
'signKey' => App::env('IMGIX_SIGN_TOKEN'),
'sourceIsWebProxy' => false,
'useCloudSourcePath' => true,
'getExternalImageDimensions' => true,
'defaultParams' => [
'auto' => 'compress,format',
'q'=> 80
],
],
],
'curlOptions' => [
CURLOPT_PROXY => App::env('HTTP_PROXY') ?: null,
]
],
'dev' => [
// Dev can fallback to local images if required
'imagerSystemPath' => $_SERVER['DOCUMENT_ROOT'] . '/resized/',
'imagerUrl' => '/resized/'
]
];
{% macro imageTransformAny(asset, transform, alt, htmlAttrs) %}
<!-- Original asset source: {{ asset.getUrl() }} -->
<img src="{{ craft.imager.transformImage(asset, transform).url }}" alt="{{ alt }}" {{ htmlAttrs }}>
{% endmacro %}
- No dimensions are shown on the AVIF image in the asset view.
Huh.. Do you see the image in the control panel? What image driver are you using (GD or Imagick)? And if you check the PHP info section for your driver, does it have AVIF support?
I see the image in the assets list with no dimensions when adding that column on the element index view.
Our hosting environment provides the following PHP setup: https://phpinfo-81.frb.io/
We are on 8.0, but the 8.0 link is currently throwing a 403, however I don't think it would be too different in terms of image drivers for analysis purposes, the versions will differ of course.
Based on this info it would appear imagick module does not support AVIF as it is not listed in the ImageMagick supported formats, so that's likely the problem here. I might need to contact our web hosting provider about this. It looks like PHP 8.1 may be the version it is supported in, although our provider currently isn't using a ImageMagick library version that does by the looks of it but apparently GD does in 8.1, based on:
Technically this isn't an issue if we just don't use AVIF but the fact Craft CMS doesn't let you just block certain file types easily as mentioned before, it does potentially create for a scenario where AVIF images can be used without restrictions as assets, which aren't then going to work on the front end currently with the issue with obtaining width and height values on these formats, despite your best efforts in defending against it.
Ok, I kinda got blinded by the fact that one sometimes wouldn't get the size from an avif file, even if the image driver had support for it. :) In this case where there's no support for avif, Imager will not be able to get the necessary information from it.
So I think the only resolution here would be to limit the file formats for fields, or create a custom plugin/module to keep avif files from being uploaded at all, and maybe add a conditional in twig (inside that macro for instance) to check the extension to make sure that you don't pass any avif files to Imager.
@aelvan
Thanks! You mentioned you implemented a custom module to prevent AVIF files being uploaded, any chance you can share the way you've done it, as I think we might have to block AVIF files as you say to prevent this.
Sure, it's here: https://github.com/vaersaagod/assetmate
It has a few shortcomings due to limitations in Craft itself, but overall it works well.
Thank you! I'll have a look at the way it's done and see if we can implement it.
I'm submitting a...
Steps to reproduce
Description
Imager-X appears to not be able to calculate the width/height of a AVIF image format when uploaded. AVIF image support was added in Craft CMS in 3.7.26 and Imgix does appear to support the image format as a transform, but the Imager-X plugin itself seems to throw a DivisionByZeroError when an AVIF image format is used on the front end. The error indicates it cannot get the width/height numeric values for the calculation on line 93 here: https://github.com/spacecatninja/craft-imager-x/blob/v3/src/models/ImgixTransformedImageModel.php#L93
The situation that led to this was a user happened to right click, save as on a image on the front end that was an AVIF, uploaded this into Craft then attempted to use it on the front end in the AVIF format. Imager-X then threw this error, using a more common format like JPG works fine as expected.
There's a couple of options I guess,
Displayed errors, stack trace, relevant logs
Full stack trace can be viewed here
https://sentry.io/share/issue/f9a6a23b8daa4df0b02cc1e58bb7c266
Additional info