Skip to content

Commit

Permalink
Fix attribute reader for WebP images with Exif App1 Sections
Browse files Browse the repository at this point in the history
The current attribute reader for WebP images fails to read the attributes if the Exif metadata contains an Exif App1 Section. The reason is that the byte-order is specified after the Exif App1 Section marker in the Exif payload. This patch will check if the Exif App1 section is present and correct the payload accordingly. This will allow it to read the Exif metadata (such as image orientation) correctly.

Test: Added a new image to cover this use case with a test. Run the instrument test using: ./gradlew :exifinterface:exifinterface:connectedAndroidTest

Fixes: b/281638358
Change-Id: Idbb14e9fbcb038616ce650da03ed1d7eb9f997a5
  • Loading branch information
falcon4ever authored and Tommy-Geenexus committed May 20, 2024
1 parent f208a0b commit e33d69a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public class ExifInterfaceExtendedTest {
private static final String PNG_WITH_EXIF_BYTE_ORDER_II = "png_with_exif_byte_order_ii.png";
private static final String PNG_WITHOUT_EXIF = "png_without_exif.png";
private static final String WEBP_WITH_EXIF = "webp_with_exif.webp";
private static final String INVALID_WEBP_WITH_JPEG_APP1_MARKER =
"invalid_webp_with_jpeg_app1_marker.webp";
private static final String WEBP_WITHOUT_EXIF_WITH_ANIM_DATA =
"webp_with_anim_without_exif.webp";
private static final String WEBP_WITHOUT_EXIF = "webp_without_exif.webp";
Expand All @@ -127,6 +129,7 @@ public class ExifInterfaceExtendedTest {
raw.png_with_exif_byte_order_ii,
raw.png_without_exif,
raw.webp_with_exif,
raw.invalid_webp_with_jpeg_app1_marker,
raw.webp_with_anim_without_exif,
raw.webp_without_exif,
raw.webp_lossless_without_exif,
Expand All @@ -148,6 +151,7 @@ public class ExifInterfaceExtendedTest {
PNG_WITH_EXIF_BYTE_ORDER_II,
PNG_WITHOUT_EXIF,
WEBP_WITH_EXIF,
INVALID_WEBP_WITH_JPEG_APP1_MARKER,
WEBP_WITHOUT_EXIF_WITH_ANIM_DATA,
WEBP_WITHOUT_EXIF,
WEBP_WITHOUT_EXIF_WITH_LOSSLESS_ENCODING,
Expand Down Expand Up @@ -557,6 +561,15 @@ public void testWebpWithExifAndXmp() throws Throwable {
writeToFilesWithoutMetadata(WEBP_WITH_ICC_WITH_EXIF_WITH_XMP, WEBP_TEST, true, true);
}

@Test
@LargeTest
public void testWebpWithExifApp1() throws Throwable {
readFromFilesWithExif(INVALID_WEBP_WITH_JPEG_APP1_MARKER,
array.invalid_webp_with_jpeg_app1_marker);
writeToFilesWithExif(INVALID_WEBP_WITH_JPEG_APP1_MARKER,
array.invalid_webp_with_jpeg_app1_marker);
}

@Test
@LargeTest
public void testWebpWithoutExif() throws Throwable {
Expand Down
Binary file not shown.
47 changes: 47 additions & 0 deletions app/src/androidTest/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,53 @@
<item />
<item />
</array>
<array name="invalid_webp_with_jpeg_app1_marker">
<!--Whether thumbnail exists-->
<item>false</item>
<item>0</item>
<item>0</item>
<item>0</item>
<item>0</item>
<item>false</item>
<!--Whether GPS LatLong information exists-->
<item>false</item>
<item>0</item>
<item>0</item>
<item>0.0</item>
<item>0.0</item>
<item>0.0</item>
<!--Whether Make information exists-->
<item>false</item>
<item>0</item>
<item>0</item>
<item />
<item />
<item>0.0</item>
<item />
<item>0.0</item>
<item>0.0</item>
<item />
<item />
<item />
<item />
<item />
<item />
<item />
<item />
<item />
<item />
<item>0</item>
<item>0</item>
<item />
<item>8</item>
<item>0</item>
<item>false</item>
<item>0</item>
<item>0</item>
<item />
<item>true</item>
<item />
</array>
<array name="heif_with_exif">
<!--Whether thumbnail exists-->
<item>false</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6122,10 +6122,18 @@ private void getWebpAttributes(final ByteOrderedDataInputStream source) throws I
chunkTypes.add(new String(type));
} else if (Arrays.equals(WEBP_CHUNK_TYPE_EXIF, type) && exifFlagSet) {
// TODO: Need to handle potential OutOfMemoryError
final byte[] data = new byte[chunkSizePadded];
byte[] data = new byte[chunkSizePadded];
if (source.read(data) != chunkSizePadded) {
throw new IOException("Failed to read WebP EXIF chunk");
}
// Skip a JPEG APP1 marker that some image libraries incorrectly include in the
// Exif data in WebP images (e.g.
// https://github.com/ImageMagick/ImageMagick/issues/3140)
if (ExifInterfaceExtendedUtils.startsWith(data, IDENTIFIER_EXIF_APP1)) {
final int adjustedChunkSize = chunkSizePadded - IDENTIFIER_EXIF_APP1.length;
data = Arrays.copyOfRange(data, IDENTIFIER_EXIF_APP1.length,
adjustedChunkSize);
}
// Save offset to EXIF data for handling thumbnail and attribute offsets.
mOffsetToExifData = bytesRead;
readExifSegment(data, IFD_TYPE_PRIMARY);
Expand Down

0 comments on commit e33d69a

Please sign in to comment.