contao / image Goto Github PK
View Code? Open in Web Editor NEWContao Image Library
Contao Image Library
I think there should be support for image orientation.
Currently pictures taken in portrait format are displayed with the wrong orientation.
I'm not sure where it should be integrated. Either the images should be rotated to the right orientation during the upload process, or the orientation should be taken into account with each resize.
The imagine library support reading Exif metadata (https://imagine.readthedocs.io/en/latest/usage/metadata.html#exif-metadata-reader). They warn that it adds some overhead to the image handling, but I don't think it's too much in relation to the time needed for the resize process itself.
BTW, Nextcloud is supporting image orientation and it's incredible fast on my virtual server, so maybe the overhead is negligible.
Composer told me
Package webmozart/path-util is abandoned, you should avoid using it. Use symfony/filesystem instead.
so I checked
composer why webmozart/path-util
contao/image 1.1.1 requires webmozart/path-util (^2.0)
Affected version(s)
4.6.13 (I think in all 4.x)
Description
Too small images will be upscaled in frontend which causes an extreme loss of quality
How to reproduce
I have an image with a width of 71px. I make an image size setting with a media query (min-width: 1200px)
and the following settings: width: 200px, Resize mode: Proportional, Pixel densities/scale factors: 1x, 1.5x, 2x (all other settings are empty). If I include the image with the image size, the image will be scaled to the target width of 200px, because there's a scale of 0.355x:
<picture>
<source srcset="files/xxx.jpg 0.355x" media="(min-width: 1200px)">
<img src="files/xxx.jpg" srcset="files/xxx.jpg 0.355x" alt="xxx" itemprop="image">
</picture>
This behavior is not correct, because the image should not be additional upscaled. The upscaling for the retina screen is at least 2x by default and additionally 1/0,355 = 2,817. So the final upscaling of the image will be 2*1/0,355 = 5,633802817.
If I don't use the media query setting and add my settings to the default setting of the image size, the behavior is correct: there's no output of scaling and the image is not bigger than the original size.
So the behavior should be identical and there should be no scaling factor output if the original image is smaller than the target image size.
/cc @ausi
The paths for resized versions of private images should not be guessable for security reasons.
$resizer = new Resizer('/path/to/subdir/../cache/dir');
$image = $resizer->resize(...);
$image->getUrl('/path/to');
This returns subdir/../cache/dir/image.jpg
instead of cache/dir/image.jpg
Could probably get fixed by #11
Working on contao/core-bundle#651 I realized that it would have made much more sense to use percentages instead of integer-pixel-values for the ImportantPart
. I see some benefits with it:
{x: 0%, y: 0%, width: 100%, height: 100%}
and we don’t have to read the dimensions from the image as in Image::getImportantPart()
Is it too late to change that in image 0.4 / core-bundle 4.4?
cc @contao/developers
We're having a legal issue right now, that boils down to:
I did a good deal of investigation there, but still have not figured out what specifically Imagine is doing differently. Because Imagemagick and Graphicsmagick have native support for the IPTC and EXIF metadata and retain the data with no extra settings. Console tools behave the same as both PHP extensions. GD does not know how to handle metadata, but it's limited in many other ways too - that's where IM or GM come into play.
But channeling the process through Imagine is doing something to explicitly remove metadata :(
I found a couple of tickets there, but they've been closed for many years due to inactivity.
How could this be solved?
The image handling in Contao is a real USP, fixing the legal issue would be a mandatory step for me to keep it that way :)
See contao/core#8592
A solution could be to use number_format()
instead of number-to-string conversion.
We should check if the json_encode
was successful in
Related: contao/contao#827 (comment)
Related: contao/contao#6256 (comment)
Or maybe VFS support directly by abstracting the filesystem in a way that contao/core-bundle
could add an adapter that maps the filesystem calls to the VFS?
Currently if you have an image with a very small important part and an image size with a zoom level of 100%
you will get very small images that will be shown blurry to the user as they will get upscaled by the browser.
It might make sense to add a setting for a minimum density that ensures that the zoom will stop as soon as the minimum density is reached. Possible names: zoomMinDensity
, maxZoomDensity
,…
/cc @Toflar
See https://community.contao.org/de/showthread.php?81203
If a small image gets resized with a very wide aspect ratio the calculated height might end up being zero. This is invalid as there are no images with 0
height or width.
I think we should force a minimum width/height of 1
in
image/src/ResizeCalculator.php
Lines 225 to 238 in fcfda96
In this example, the second resize returns the same image as the first one:
$options1 = (new ResizeOptions())
->setImagineOptions(['jpeg_quality' => 100])
;
$options2 = (new ResizeOptions())
->setImagineOptions(['jpeg_quality' => 50])
;
$resizedImage1 = $resizer->resize(..., ..., $options1);
$resizedImage2 = $resizer->resize(..., ..., $options2);
A new version of imagine/imagine got released.
Check the compatibility and update composer.json to:
"imagine/imagine": "^0.6|^0.7",
A resize configuration with a width of 1920
and the densities set to 1.3333x
should result in an image width of 2560
instead of 2559
.
The ResizeConfiguration has a method where it checks whether an resize is unnecessary. Theres a missing check whether the height and width on the image are already equal when the resize mode is "proportional".
One good reason to change this behavior is: The image URLs don't change during an upgrade from an older version, this could be bad in perspective of seo (google images rankings).
This function:
image/src/ResizeConfiguration.php
Lines 41 to 47 in 1846080
Would need to check it like this:
/**
* Returns true if the resize would have no effect.
*/
public function isEmpty(): bool
{
$size_and_mode_proportional = ($this->width === $this->height) && ($this->mode === self::MODE_PROPORTIONAL);
return (0 === $this->width
&& 0 === $this->height
&& 0 === $this->zoomLevel)
|| $size_and_mode_proportional;
}
Should we add more resize modes like a version of box
that adds a background color to the image to get exactly the configured size?
A general background color setting might be useful for other cases too like converting images with transparency to JPEG.
/cc @bennyborn
Related: contao/contao#3347
Are there other resize modes that might be useful?
I think constructors should not be part of an interface in most cases. I should remove the constructors of all interfaces in this library.
@contao/developers do you agree?
Deferred images store the source path of the image relative to the cache directory in
Line 147 in 2dc4390
When resizing the path gets appended to the cache dir path in
Line 185 in 2dc4390
Resulting in something like /contao/assets/images/../../files/image.jpg
. Now if /contao/assets/images
is a symlink to /foo/bar/baz
the path gets converted to /foo/files/image.jpg
which is wrong. We should resolve the ..
parts before creating the Image
object.
When resizing a lot of images one might run into race conditions. See stack trace:
ErrorException: fopen(/var/www/vhosts/foobar/httpdocs/releases/106/assets/images/deferred/5/e09d6c21-833fdbd0.jpg.json): failed to open stream: No such file or directory
#13 vendor/contao/image/src/DeferredImageStorageFilesystem.php(87): handleError
#12 src/AppBundle/Sentry/ErrorHandler.php(27): handleError
#11 src/AppBundle/Sentry/ErrorHandler.php(0): fopen
#10 vendor/contao/image/src/DeferredImageStorageFilesystem.php(87): getLocked
#9 vendor/contao/image/src/DeferredResizer.php(87): resizeDeferredImage
#8 vendor/contao/core-bundle/src/Command/ResizeImagesCommand.php(162): resizeImage
#7 vendor/contao/core-bundle/src/Command/ResizeImagesCommand.php(139): execute
#6 vendor/symfony/console/Command/Command.php(255): run
#5 vendor/symfony/console/Application.php(939): doRunCommand
#4 vendor/symfony/framework-bundle/Console/Application.php(87): doRunCommand
#3 vendor/symfony/console/Application.php(273): doRun
#2 vendor/symfony/framework-bundle/Console/Application.php(73): doRun
#1 vendor/symfony/console/Application.php(149): run
#0 vendor/contao/manager-bundle/bin/contao-console(42): null
I think thumbnails do not need any EXIF data and should never be in any other color space than RGB. This would make the thumbnails a lot smaller :-)
Issue by @asaage
April 10th, 2018, 15:56 GMT
i noticed that when i use image-sizes in combination with svg-images
additional svg's in the srcset
are created under assets/images/
<img src="assets/images/4/foo-b4a0c460.svg"
srcset="assets/images/4/foo-b4a0c460.svg 1x, assets/images/3/foo-eeec80d9.svg 2x"
width="250" height="250" alt="foo" itemprop="image">
The svg's i am using do not contain width/height
attributes - only the viewbox
attribute and i did not set any important-part
for them in the filemanager.
I would expect contao to just set the width and height on the <img>
and not create additional svg's with contained width/height attributes.
Of course i could just use a different image-size without pixel-density descriptors but i have mixed filetypes in a gallery so that's not really an option.
The current test is not enough and may lead to
PHP message: PHP Warning: XMLReader::open():
Unable to open source data in /vendor/contao/image/src/Image.php on line 201
The following diff solves the issue.
if (null === $zlibSupport) {
- $zlibSupport = \in_array('compress.zlib', stream_get_wrappers(), true);
+ $zlibSupport = \in_array('compress.zlib', stream_get_wrappers(), true)
+ && ($reader = new XMLReader)
+ && @$reader->open('compress.zlib://data:text/xml,<x/>') === true
+ && @$reader->read() === true
+ && @$reader->close() === true;
}
// 1500x1500 large image
$image = new Image('/path/to/image.jpg', $imagine);
$config = (new PictureConfiguration())
->setSize((new PictureConfigurationItem())
->setResizeConfig((new ResizeConfiguration())
->setWidth(1000)
)
->setDensities('1x, 2x')
)
;
$pictureGenerator->generate($image, $config, new ResizeOptions())->getImg('/path/to')['srcset'];
// cache/dir/4/image-de332f09.jpg 1x, image.jpg 2x
The descriptor for the image.jpg should be 1.5x
in this case, because the image didn’t get upscaled and is only 1500 pixels wide instead of the intended 2000.
Issue by @mlwebworker
October 26th, 2017, 19:12 GMT
Es geht um die neue Variante bei Pixeldichte/Skalierungsfaktor - die Breitenbeschreibung (z.B. 300w), die ich sehr begrüße.
Bei einem Test ist mir allerdings zufällig aufgefallen, dass ein für mich nicht nachvollziehbares srcset entsteht, falls die angegebene Breite größer ist als die Breite des Originalbildes.
Beschrieben im Forum https://community.contao.org/de/showthread.php?68549-Responsive-geht-gar-nicht&p=454886&viewfull=1#post454886.
Da wir grundsätzlich nicht ausschließen können, dass Redakteure das auf zu kleine Originalbilder anwenden, sollte dieser Fall m.E. genauso abgefangen werden wie das passiert, wenn ich für ein Bild 600w angebe aber das Originalbild diese Breite gar nicht hergibt.
Handling paths requires some complicated checks, webmozart/path-util looks like a small but good library.
Sorry, if I abuse this for a question.
Is this library already used by contao 4?
I try to rewrite my imageondemand extension for contao 4 and currently searching how to implement it the best way. So I found this library but no informations. If this will be used in contao 4 in the future I want to rely on.
We should use Imagine\Image\ImageInterface::interlace()
to store the JPEG files as progressive images.
This should most likely be configurable.
When my image is too small to be resized, I thought contao/image
is not supposed to touch it.
This is the case when I use this code:
$resizeConfig = new ResizeConfiguration();
$resizeConfig->setWidth($width)->setHeight($height)->setMode(ResizeConfiguration::MODE_PROPORTIONAL);
$image = $this->imageFactory->create($absolutePath, $resizeConfig);
However, if I do not set any mode (so the default one CROP
is used), like so:
$resizeConfig = new ResizeConfiguration();
$resizeConfig->setWidth($width)->setHeight($height);
$image = $this->imageFactory->create($absolutePath, $resizeConfig);
I get a cropped version anyway. Is that intended? Even if my $width
and $height
are both smaller than what I set on the ResizeConfiguration
?
To be used like:
$image = new Image('/path/to/root/foo/bar.jpg', ...);
$image->getUrl('/path/to/root', 'https://cdn.example.com/images/');
// 'https://cdn.example.com/images/foo/bar.jpg'
Is it possible to override only one of the needed attributes (set in the "Dateiverwaltung", var = default_image_meta) in the image ("Metadaten überschreiben")?
I suggest to show default_image_meta every time "Metadaten überschreiben" is needed.
The resizer uses a temporary file for atomic write operations:
Lines 123 to 127 in 9cd4150
This temporary file, however, does not have a file extension, which leads to an No encode delegate for this image format (webp)
error in Gmagick on Ubuntu 16.04. The error did not occur in my dev environment on macOS.
Appending the file extension to the temporary file fixed the issue:
// Atomic write operation
$tmpPath = $this->filesystem->tempnam($dir, 'img');
$this->filesystem->chmod($tmpPath, 0666, umask());
// Append the file extension to the temporary file
rename($tmpPath, $tmpPath.'.'.$imagineOptions['format']);
$tmpPath .= '.'.$imagineOptions['format'];
$imagineImage->save($tmpPath, $imagineOptions);
$this->filesystem->rename($tmpPath, $path, true);
Not sure if there is a better way to accomplish this though.
Hi, the created files at assets/images are 600 not 640. Can you verify this point. Thx.
PictureConfigurationItem::setDensities()
should allow w
descriptors like '100w, 200w'
in addition to x
descriptors and should be handled correctly by PictureGenerator::generate()
.
// 100x100 large image
$image = new Image('/path/to/image.jpg', $imagine);
$config = (new PictureConfiguration())
->setSize((new PictureConfigurationItem())
->setResizeConfig((new ResizeConfiguration())
->setWidth(50)
)
->setDensities('1x, 2x, 3x, 4x')
)
;
$pictureGenerator->generate($image, $config, new ResizeOptions())->getImg('/path/to')['srcset'];
// cache/dir/4/image-de332f09.jpg 1x, image.jpg 2x, image.jpg 2x, image.jpg 2x
Duplicate sources should get removed from $srcset
in PictureGenerator.php:99.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.