Giter VIP home page Giter VIP logo

image's Introduction

Contao Open Source CMS

About

Contao is a powerful open source CMS that allows you to create professional websites and scalable web applications. Visit the project website for more information.

Purpose

The purpose of this package is to develop the Contao bundles in a monorepo. Use it when you want to create a pull request or report an issue.

The monorepo is automatically split into separate packages:

Please do not use contao/contao in production! Use the split packages instead.

Platinum partners

Thanks to our platinum partners for helping us fund the development of Contao.

Development

To create a pull request and to test your changes within a running Contao application, it is the easiest to use the Contao Managed Edition. Start by installing it in your current directory:

composer create-project --no-install contao/managed-edition <directory> <branch>

Replace <directory> with the directory where you want to install the Managed Edition (use . for the current directory). Replace <branch> with 5.x-dev if you want to add a new feature, or with <lts-version>.x-dev (currently 4.13.x-dev) if you want to fix a bug.

Then adjust the require section in your composer.json file, so Composer loads the monorepo instead of the individual bundles:

"require": {
    "php": "^8.1",
    "contao/contao": "5.x-dev"
},

Again, use 5.x-dev if you want to add a new feature or <lts-version>.x-dev if you want to fix a bug.

Next, install the dependencies:

composer update

Composer automatically clones the Git repository into the vendor/contao/contao folder. You can complete the setup by running vendor/bin/contao-setup on the command line.

Any changes you make in vendor/contao/contao will be tracked via Git, so you can submit your pull request directly from your application.

Running scripts

First install the code quality tools:

composer bin all install

Then run the code quality scripts via Composer:

composer all

You can also run the scripts separately:

composer rector
composer ecs
composer service-linter
composer monorepo-tools
composer unit-tests
composer functional-tests
composer phpstan
composer depcheck

Use the -- argument to pass additional flags to the underlying commands:

composer unit-tests -- --filter CoreBundle
composer ecs -- --clear-cache

Functional tests

To set up the functional tests, create a database named contao_test:

mysql -e "CREATE DATABASE contao_test"

If your database uses credentials, copy the file core-bundle/phpunit.xml.dist to core-bundle/phpunit.xml and adjust the following line:

<php>
    <env name="DATABASE_URL" value="mysql://root@localhost:3306/contao_test" />
</php>

Then run the functional tests via Composer:

composer functional-tests

Yarn 4

To build the assets and to run the end-to-end tests (see below), you need to enable Corepack, a package manager that allows you to manage different Yarn package versions across multiple projects:

corepack enable

If Corepack is not bundled with your Node.js installation, you might have to install it as a separate package, e.g. using npm install -g corepack or brew install corepack.

End-to-end tests

The Contao end-to-end tests are availabe as an NPM package. You can install and run them via Yarn:

yarn add contao-e2e-tests --dev
yarn contao-e2e-tests

License

Contao is licensed under the terms of the LGPLv3.

Getting support

Visit the support page to learn about the available support options.

image's People

Contributors

aschempp avatar ausi avatar leofeyer avatar m-vo avatar toflar avatar xchs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

image's Issues

Add a prefix argument to Image::getUrl()

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'

Add more resize modes

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?

Length of either side cannot be 0 or negative, current size is 2x0

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

return new ResizeCoordinates(
new Box(
(int) round($size[0] * $scale),
(int) round($size[1] * $scale)
),
new Point(
(int) round($cropStart[0] * $scale),
(int) round($cropStart[1] * $scale)
),
new Box(
(int) round($cropSize[0] * $scale),
(int) round($cropSize[1] * $scale)
)
);

Remove constructors from interfaces

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?

Image attributes partial override

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.

Gmagick does not like tempnam without file extension

The resizer uses a temporary file for atomic write operations:

image/src/Resizer.php

Lines 123 to 127 in 9cd4150

// Atomic write operation
$tmpPath = $this->filesystem->tempnam($dir, 'img');
$this->filesystem->chmod($tmpPath, 0666, umask());
$imagineImage->save($tmpPath, $imagineOptions);
$this->filesystem->rename($tmpPath, $path, true);

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.

IPTC/EXIF metadata get lost when resizing images in Contao

We're having a legal issue right now, that boils down to:

  • when using stock images (istock, adobe stock, fotolia etc.) the source file contains copyright information
  • when resizing the image in Contao, the copyright information gets lost
  • removing copyright information from images is problematic, not to say: illegal

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 :)

The same source appears multiple times for too small images

// 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.

Read EXIF metadata and show images with orientation

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.

behavior of responsive images when original image is smaller than target size

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>

bildschirmfoto 2019-01-18 um 12 27 38

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.

bildschirmfoto 2019-01-18 um 12 27 10

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

Prevent resizing of images when resize mode is proportional and width and height of the image equal

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:

/**
* Returns true if the resize would have no effect.
*/
public function isEmpty(): bool
{
return 0 === $this->width && 0 === $this->height && 0 === $this->zoomLevel;
}

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;
    }

Different imagine options should result in a different image path

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

Relative path parts don’t get removed

$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

unexpected behaviour with svg-images and image-sizes

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.

Improve zlib stream test

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;
         }

Use symfony/filesystem instead of webmozart/path-util

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)  

Max zoom density setting

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

Percentage values for the important part

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:

  1. If an image has no important part it just defaults to {x: 0%, y: 0%, width: 100%, height: 100%} and we don’t have to read the dimensions from the image as in Image::getImportantPart()
  2. An important part object can be validated very easily without needing to know anything about the image.
  3. Features like contao/core#8360 (comment) would be easier to implement.

Is it too late to change that in image 0.4 / core-bundle 4.4?
cc @contao/developers

Already used by contao 4

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.

X descriptor doesn’t get corrected for too small images

// 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.

Symlinked cache directory resolves to invalid paths

Deferred images store the source path of the image relative to the cache directory in

$targetPath = Path::makeRelative($targetPath, $this->cacheDir);

When resizing the path gets appended to the cache dir path in

new Image($this->cacheDir.'/'.$config['path'], $imagine, $this->filesystem),

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.

Race condition

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

Scaling factors should get rounded

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.

Bug with resize configuration

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?

Problem with responsive images

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.