Keep every target of a 'thmb', 'auxl', 'cdsc' or 'prem' reference - #3331
Keep every target of a 'thmb', 'auxl', 'cdsc' or 'prem' reference#3331Nexory wants to merge 2 commits into
Conversation
|
Thank you for your interest in libavif. I am not so sure that rejecting files is a better behavior. How about fixing the issue instead? |
|
Fair point, and I think you are right. I checked how the four relations are consumed. Across the tree they appear only So the fields can become id arrays, the loop pushes instead of overwriting, and Happy to rework the PR that way, with the two tests asserting that the metadata |
As you wish! |
92fe7f6 to
3b4342e
Compare
|
Reworked as suggested. The four single-valued fields became one per item array of (type, toID) Both tests now assert survival instead of rejection. The Exif metadata is One thing I did not change: in the MinimizedImageBox path, the line that used stores a one bit flag in a field the consumer compares against the alpha item |
A SingleItemTypeReferenceBox links to an array of to_item_IDs, and several boxes of one type may share a from_item_ID. libavif stored these four relations in a single valued field per item, and the parsing loop overwrote it per entry, so the target parsed last silently won and the others were dropped, with no error and an exit code of zero. Store the references in a per item array instead, and turn the read sites into membership checks. 'dimg' is unchanged: it refers in the opposite direction and already refuses what it cannot represent.
3b4342e to
09d91b0
Compare
|
I measured the MinimizedImageBox line I mentioned, and folded the fix into this Under the array this PR introduces, toID is an item ID. The old line stored the The behaviour on main, measured with avifenc on one input image: encoded with The parameterized test in avifminitest.cc already compares a MinimizedImageBox Happy to split it back out if you would rather review the two separately. |
The MinimizedImageBox path stored the one bit alpha_is_premultiplied value in premByID, which the decoder compares against the alpha item ID. That ID is 2 in this path, so the comparison never matched and a premultiplied image decoded as straight alpha, with no error and an exit code of zero. The parameterized test in avifminitest.cc already compares a MinimizedImageBox against a regular MetaBox for the same image, and AreImagesEqual() compares alphaPremultiplied. No parameter set marks the alpha as premultiplied though, so the flag was never exercised. Add a test that does.
09d91b0 to
a5f609f
Compare
A SingleItemTypeReferenceBox links one item to an array of to_item_IDs
(ISO/IEC 14496-12, section 8.11.12.1). libavif stored the 'thmb', 'auxl',
'cdsc' and 'prem' relations in a single-valued field, and the parsing loop
overwrote it per entry, so the target parsed last silently won.
Measured on files differing from a working one only in the order of two
to_item_ID values, the Exif item describing items [1, 2]:
The decoded pixels are identical in all three, only the Exif payload is gone. For
'auxl' the effect is heavier: with the alpha item declared auxiliary for
[1, 3], the alpha plane is dropped and the image decodes as opaque, again with
exit code 0 and no diagnostic. Two boxes of one type sharing a from_item_ID
behave the same.
This keeps every target instead. The references live in a per item array, the
parsing loop pushes rather than overwrites, and the read sites became
membership checks. 'dimg' is unchanged: it refers in the opposite direction and
already refuses what it cannot represent.
Without the change both tests fail with the Exif data and the alpha plane
missing, while the decode itself still returns AVIF_RESULT_OK.
A second commit fixes the MinimizedImageBox path, which stored the one bit
alpha_is_premultiplied value in the same field. Under the array introduced here
that is a reference to item 1, the primary item itself, so a premultiplied image
decoded as straight alpha. The parameterized test in avifminitest.cc already
compares a MinimizedImageBox against a regular MetaBox and compares
alphaPremultiplied, but no parameter set marks the alpha as premultiplied, so
the flag was never exercised. The added test does.
Two limits remain. I found no encoder that writes such files (libheif passes a
single ID at every call site), so both test files are hand-crafted. I built with
dav1d and aom from the system, rav1e, svt and libgav1 off, not the five codecs
the CI builds from source.