Repository navigation
Add support for image orientation - #148
Conversation
… from Exif data then fallback to normal orientation.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 48 minutes. View limit details
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to The change adds image orientation support through the picture APIs and the Exif parsers. No actionable merge-blocking risk was found in the supplied context. Pre-merge checks |
|
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # tests/image/test_jpeg.py
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces #110 (head fork
TheZ3ro:image-rotationis not pushable by this repo's maintainers, so the reviewed changes land here instead).Fixes python-openxml#540
Modern image formats (PNG, JPEG, Tiff, etc) embed the orientation in Exif metadata.
When rotating or displaying an image, software like Word, PowerPoint, macOS Preview, Android Google Photo, etc do not rotate the actual pixel data but instead change the orientation metadata integer (https://exifstrip.com/guides/orientation-tag-explained)
This is governed in OpenXML with the
a:xfrm(transform) tag. This tag can contain therot,flipV, andflipHattributes. By mapping the 1-8 orientation values to the respective rot and flip attributes it's possible to display images that were rotated by merely changing the Exif metadata with the correct orientation.This PR adds support for image orientation.
By default it gets orientation from Exif metadata. If orientation metadata is not available it falls back to "Normal" orientation (like now, defined by raw pixel data).
It is also possible to force a given orientation programmatically by:
Review fixes (commit
8ac3261)Addresses the CodeRabbit review on #110:
src/docx/image/jpeg.py: bothExif/Jfifconstructors now select the EXIF-specific APP1 marker (_JfifMarkers.exif_app1) so a preceding non-EXIF APP1 segment (e.g. XMP) can no longer override EXIF orientation; regression test builds a JFIF stream with non-EXIF APP1 before EXIF APP1 and asserts the later marker's orientation survives.src/docx/parts/story.py: resolveAUTOorientation before scaling and cross-mapwidth/heightwhenorientation.swaps_axes, so aspect-ratio scaling runs in native image axes whilewp:extentis swapped exactly once.src/docx/shape.py:InlineShape.width/heightsetters apply the same crossed-axis mapping whena:xfrm/@rotis 90°/270°, keeping explicit dimensions correct afterwp:extentaxis swapping.All 1656 tests pass;
ruff check/formatunchanged from baseline.Made with Cursor
Summary by CodeRabbit