jolicode / jolicode/MediaBundle

EXIF orientation is never applied: portrait photos are rendered sideways

Open
#169 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
PHP
Stars
118
Forks
13
Avg merge
22h 54m
Merged PRs (30d)
3

Description

## Summary

Photos that carry an EXIF `Orientation` tag other than `1` (e.g. a portrait photo shot on a phone, stored as landscape pixels + a rotation flag) are never physically rotated anywhere in the pipeline. Every generated variation — and the raw "original" — ends up displayed sideways/squished wherever the consumer doesn't itself respect EXIF orientation (Imagick resizes, canvas-based previews such as Dropzone.js thumbnails, etc.).

## Where I looked

- `PreProcessor\ExifRemovalPreProcessor` only strips the `ifd1` group (embedded thumbnail metadata) via `exiftool -ifd1:all=`; it leaves the `Orientation` tag (in `ifd0`) intact.
- `Processor\Imagine::process()` calls `$this->imagine->load($binary->getContent())` and then runs the transformer chain (e.g. `Resize`), but never applies any rotation. `imagine/imagine`'s `Imagick` adapter does **not** auto-rotate on load either.
- `imagine/imagine` actually ships a filter for exactly this (`Imagine\Filter\Basic\Autorotate`, reading `ifd0.Orientation`), but nothing in `JoliMediaBundle` wires it in — there's no built-in pre-processor, processor step, or config option that calls it.
- Searching the bundle source for `orient`/`rotate` (case-insensitive) returns zero matches outside `Autorotate.php` in `imagine/imagine` itself.

Because the `Resize` transformer (`Transformer\Resize`) computes target dimensions from the *un-rotated* pixel dimensions, a portrait 3024×4032 source (stored as landscape 4032×3024 pixels + `Orientation: 6`) gets resized as if it were landscape, producing a visibly wrong/squished result in every variation — not just a rotation issue in consumers that ignore EXIF.

## Reproduction

1. Configure a library with the `imagine` processor (`driver: imagick`) and any `resize` variation.
2. Upload a JPEG shot in portrait orientation on a phone (has `Orientation: 6` or similar, landscape pixel dimensions).
3. Request any variation, or view the stored "original" directly.
4. The image (and any generated cache file) is sideways / has the wrong effective aspect ratio for the resize.

## Environment

- `jolicode/media-bundle` v0.9.1 (latest on Packagist as of this report)
- `processors.imagine.driver: imagick`
- ext-imagick 3.8.1 / ImageMagick 7.1.1

## Suggested fix

Rotate the pixel data once, before any transformer runs, and normalize the orientation flag so nothing double-rotates it later — e.g. a pre-processor for JPEG/TIFF (and HEIF, after `HeifPreProcessor` converts it) that calls `Imagick::autoOrientImage()` (or `autoOrient()` on older ext-imagick releases, the method was renamed) when `getImageOrientation()` isn't already `ORIENTATION_TOPLEFT`/`ORIENTATION_UNDEFINED`.

We worked around it locally with exactly that, registered ahead of `ExifRemovalPreProcessor` in `pre_processors`, and it resolves the issue. Happy to turn that into a PR against this repo if that's useful — let me know.

Contributor guide

Open the contributing guide

Research direction

Start by reading Processor\Imagine::process(), Transformer\Resize, and PreProcessor\ExifRemovalPreProcessor, then trace the configured pre_processors ordering. Check the available Imagine Autorotate filter and the stated Imagick orientation behavior before deciding where the step belongs. Done means oriented pixels are normalized before resizing, the orientation flag cannot cause double rotation, and generated variations retain the correct aspect ratio.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.