Normalise non-EXIF orientation metadata when auto-orienting - #4586
Open
thedavidweng wants to merge 1 commit into
Open
Normalise non-EXIF orientation metadata when auto-orienting#4586thedavidweng wants to merge 1 commit into
thedavidweng wants to merge 1 commit into
Conversation
thedavidweng
force-pushed
the
fix-auto-orient-xmp-4585
branch
2 times, most recently
from
August 9, 2026 22:52
9b31e30 to
6e0cf0b
Compare
autoOrient() and SetExifOrientation/RemoveExifOrientation previously only updated the EXIF IFD0 Orientation tag, leaving the same value duplicated in PNG text-chunk comments (e.g. macOS sips output) and XMP packets (<tiff:Orientation>) untouched. Consumers that read XMP first would rotate the already-corrected pixels a second time. Also normalise these non-EXIF sources of orientation to match, so that no stale orientation metadata survives an auto-orient/bake-in operation. lovell#4585
thedavidweng
force-pushed
the
fix-auto-orient-xmp-4585
branch
from
August 10, 2026 00:53
6e0cf0b to
48ff637
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
autoOrient()(and the relatedSetExifOrientation/RemoveExifOrientationhelpers) only normalised the EXIF IFD0Orientationtag. The same value is frequently duplicated in two other places — PNG text-chunk comments (e.g. files produced by macOSsips) and XMP packets (<tiff:Orientation>) — and these were left untouched.After an auto-orient/bake-in operation the pixels are already rotated, but the stale PNG-comment / XMP orientation survives into the output. Consumers that honour XMP first (or read PNG text chunks) rotate the already-corrected pixels a second time, producing an incorrectly-displayed image.
Resolves #4585.
Solution
Add
UpdateOrientationMetadata(), called from bothSetExifOrientationandRemoveExifOrientation, which — alongside the existing EXIF IFD0 handling — also:EXIF:Orientationorxmp:tiff:Orientation(libvips exposes these aspng-comment-<index>-<keyword>fields), and<tiff:Orientation>…</tiff:Orientation>element within an embedded XMP packet, tolerating attribute-bearing and self-closing forms and leaving values inside XML comments untouched.Both writes take ownership of the buffer through glib-owned memory and a libvips free callback, so the metadata outlives the operation.
Explicit user-supplied metadata (e.g.
.withXmp(...)) is intentionally left untouched, since it represents deliberate user input rather than inherited orientation.Verification
sharp@0.34.5: an input PNG carrying EXIF Orientation6plus an XMP<tiff:Orientation>6</tiff:Orientation>produced output whose EXIF Orientation was normalised to1but whose XMP orientation remained6.1, and the XMP packet survives intact (exiftoolparses it without warnings).Tests
Two unit tests in
test/unit/rotate.js, each failing without the corresponding C++ change:Auto-orient normalises orientation duplicated in non-EXIF metadata— PNG text-chunk path (inputPngWithExifXmpOrientation.png).Auto-orient normalises XMP packet orientation and preserves packet integrity— real XMP packet path (inputPngWithXmpOrientation.png); also guards the buffer-lifetime fix.npm run test-unitpasses (the only failure locally —Lossless JPEGintest/unit/metadata.js— is pre-existing and unrelated; it reproduces on pristinemainwith my libvips build).npm run lint-cppandbiome lintare clean.(Happy to add a changelog entry if you'd like — left it out since recent external-contributor PRs leave that to you at merge time.)