liip / LiipImagineBundle

Symfony Bundle to assist in image manipulation using the imagine library
http://liip.ch
MIT License
1.66k stars 378 forks source link

Images are automatically rotated #1580

Closed MichaelBrauner closed 6 months ago

MichaelBrauner commented 6 months ago

I have the following config:

        my_filter:
            quality: 85
            jpeg_quality: 85
            filters:
                auto_rotate: ~

And if this is then applied to an image that was taken upright with an iPhone, for example, then the image is always rotated.

Preconditions

PHP: 8.2.18 GD: bundled (2.1.0 compatible) Liip: 2.12.2

Steps to reproduce

Here is such a picture. It should be rotated, regardless of whether autorate is switched on or not. image

dbu commented 6 months ago

setting auto-rotate: ~ enables the filter with the default options. if the image is encoded rotated and with the information in the metadata, i expect it to be rotate when the filter is enabled.

if the filter is not enabled, no rotation should happen because you did not activate the filter.

if the image is already rotated when you put it on the server, no rotation should need to take place.

from the issue description, i am not quite sure to understand what you expect to happen and what happens

MichaelBrauner commented 6 months ago

Yes, exactly. That's what you would expect.

auto_rotate: ~ does not matter. With or without - it is rotated.

The raw image on the server is not rotated. But all filtered images in the cache folder are rotated.

To put it briefly: The image should not be rotated, but it is rotated. With or without auto_rotate. And the image stored on the server is not rotated as long as no image manipulation has yet taken place.

dbu commented 6 months ago

i don't think i can help here. dumping the exif data of the image as attached here shows that the orientation is "right-top". i am no exif expert, but some googling found me this: https://github.com/mattiasw/ExifReader/issues/99 - i did not fully read through it, but there seems to be some confusion about mobile phones portrait mode.

maybe something is wrong in the imagine library or in only gd or imagick?

MichaelBrauner commented 6 months ago

I solved it by moving to imagick driver:

liip_imagine:
    driver: 'imagick'

So it looks as if this is a problem with gd. Thank you for your time.

dbu commented 6 months ago

thanks for reporting back, might be helpful to others facing this issue.

maybe somewhere gd has an open issue about that (or maybe its been fixed in some version and your system uses an older version)

cmb69 commented 4 months ago

libgd does not read exif information at all. You would need to read that yourself, and cater to the Orientation tag (see https://jpegclub.org/exif_orientation.html) by doing the appropriate operations yourself; possibly using the classic gdImageRotateInterpolated(), gdImageFlipHorizontal() and gdImageFlipVertical() (if coding in C). For PHP you can use something like:

    /**
     * @param GdImage $image
     * @return GdImage|null
     */
    private function normalize($image, int $orientation)
    {
        switch ($orientation) {
            default:
                return $image;
            case 2:
                if (!imageflip($image, IMG_FLIP_HORIZONTAL)) {
                    return null;
                }
                return $image;
            case 3:
                return imagerotate($image, 180, 0) ?: null;
            case 4:
                if (!imageflip($image, IMG_FLIP_VERTICAL)) {
                    return null;
                }
                return $image;
            case 5:
                if (!imageflip($image, IMG_FLIP_VERTICAL)) {
                    return null;
                }
                return imagerotate($image, 270, 0) ?: null;
            case 6:
                return imagerotate($image, 270, 0) ?: null;
            case 7:
                if (!imageflip($image, IMG_FLIP_VERTICAL)) {
                    return null;
                }
                return imagerotate($image, 90, 0) ?: null;
            case 8:
                return imagerotate($image, 90, 0) ?: null;
        }
    }

See https://github.com/php/doc-en/issues/2745#issuecomment-2241627577 on how to get the Orientation.