Keep all values of repeatable IPTC datasets on insert - #9484
Open
jadhavgaurav wants to merge 1 commit into
Open
Conversation
metacopy() copied IPTC in preserve mode with `targetImage->iptcData()[iptc.key()] = iptc.value()`. IptcData::operator[] returns the first entry matching the key, so for a repeatable dataset such as Iptc.Application2.Keywords every source value was written onto the target's first matching entry and all but the last one were lost. Drop the target's entries for the datasets the source provides, then append all source entries in their original order. Non-repeatable datasets keep the same behaviour: the source value replaces the target value. The reference output of conversions_test and stdin_test changes accordingly: both round-trip files whose keywords were previously dropped. Fixes Exiv2#3334
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.
Fixes #3334.
Problem
Exporting IPTC to an
.exvsidecar and inserting it again loses all but one value of a repeatable IPTC dataset:The
.exvitself is fine; the values are lost on insert.Cause
metacopy()copies IPTC in preserve mode (the mode used by the insert action) with:targetImage->iptcData()[iptc.key()] = iptc.value();IptcData::operator[]looks up the first entry with that key. Datasets likeIptc.Application2.Keywords,Iptc.Application2.BylineandIptc.Application2.SuppCategoryare repeatable, so every source value is written onto the same first target entry and only the last one survives. Exif and XMP are unaffected: their keys are unique.Fix
Remove the target's entries for the datasets the source provides, then append all source entries in their original order. Non-repeatable datasets behave exactly as before: the source value replaces the target value, and target-only datasets are still preserved.
Tests
New system test
tests/bugfixes/github/test_issue_3334.pyreproduces the report: it adds three keywords, exports with-ea, re-inserts with-iaand checks that all three come back in order. It fails before the change and passes after.Two existing reference outputs change, both because keywords that used to be dropped are now kept:
conversions.out: step 9 ("And back to IPTC") now returns all three keywords (Sex,Drugs,Rock'n'roll) instead of only the last one.stdin-test.out: pipingexiv2 -ea-fromReagan.jpgintoexiv2 -ia-now carries all 10 keywords and all 3SuppCategoryvalues, so the APP13 segment grows from 784 to 952 bytes and the following segment offsets shift.Ran locally on macOS (arm64, Ninja, Release):
unit_tests: 370/370 passtests/runner.py bugfixes: 325 pass, 10 skippedtests/runner.py regression_tests: 329 passtests/runner.py bash_tests: 66/67 pass;io_testfails both with and without this change because this build has webready/network support disabledtests/runner.py tiff_test: 1 passclang-formatwas not available on this machine, so the new code was matched to the surrounding style by hand rather than verified with the tool.