From 219142139c02f47f76656fcec3387ef1bbb8e815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 8 Aug 2024 21:04:15 +0200 Subject: [PATCH 1/5] TIFF EXIF orientation fix Based on #549 Fixes #548 --- .../illinois/library/cantaloupe/image/Metadata.java | 13 +++++++++++-- .../library/cantaloupe/image/exif/Directory.java | 8 ++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java index 8a2d26819..00d482554 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import edu.illinois.library.cantaloupe.image.exif.Directory; +import edu.illinois.library.cantaloupe.image.exif.Field; import edu.illinois.library.cantaloupe.image.exif.Tag; import edu.illinois.library.cantaloupe.image.iptc.DataSet; import edu.illinois.library.cantaloupe.image.xmp.MapReader; @@ -132,9 +133,17 @@ public Orientation getOrientation() { } private void readOrientationFromEXIF() { + Field field = exif.getField(Tag.ORIENTATION); Object value = exif.getValue(Tag.ORIENTATION); - if (value != null) { - orientation = Orientation.forEXIFOrientation((int) value); + if (field != null && value != null) { + switch (field.getDataType()) { + case LONG: + orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); + break; + case SHORT: + orientation = Orientation.forEXIFOrientation((int) value); + break; + } } } diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/exif/Directory.java b/src/main/java/edu/illinois/library/cantaloupe/image/exif/Directory.java index c421ae259..193397d44 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/exif/Directory.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/exif/Directory.java @@ -170,6 +170,14 @@ public Object getValue(Tag tag) { .orElse(null); } + public Field getField(Tag tag) { + return fields.keySet() + .stream() + .filter(f -> f.getTag().equals(tag)) + .findFirst() + .orElse(null); + } + @Override public int hashCode() { final Map codes = new HashMap<>(); From 565de9e8bdb8262c20666ff9bc5622881f82b1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Thu, 8 Aug 2024 21:10:23 +0200 Subject: [PATCH 2/5] Add signed variants and log warning on unknown dataType --- .../illinois/library/cantaloupe/image/Metadata.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java index 00d482554..b93a3bcee 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java @@ -121,10 +121,7 @@ public Orientation getOrientation() { if (orientation == null) { orientation = Orientation.ROTATE_0; } - } catch (IllegalArgumentException e) { - LOGGER.info("readOrientation(): {}", e.getMessage()); - orientation = Orientation.ROTATE_0; - } catch (RiotException e) { + } catch (IllegalArgumentException | RiotException e) { LOGGER.info("readOrientation(): {}", e.getMessage()); orientation = Orientation.ROTATE_0; } @@ -138,11 +135,16 @@ private void readOrientationFromEXIF() { if (field != null && value != null) { switch (field.getDataType()) { case LONG: + case SLONG: orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); break; case SHORT: + case SSHORT: orientation = Orientation.forEXIFOrientation((int) value); break; + default: + LOGGER.warn("readOrientationFromEXIF(): Unsupported Orientation data type: {}", + field.getDataType()); } } } From c6e9d676561f1683828dd142b9b6530426a6ffe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Fri, 9 Aug 2024 11:31:01 +0200 Subject: [PATCH 3/5] Add tests --- .../library/cantaloupe/image/Metadata.java | 11 +++++++--- .../cantaloupe/image/MetadataTest.java | 19 +++++++++++++++++- .../cantaloupe/image/exif/DirectoryTest.java | 10 ++++++++- .../images/jpg-exif-long-orientation.jpg | Bin 0 -> 36000 bytes 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100755 src/test/resources/images/jpg-exif-long-orientation.jpg diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java index b93a3bcee..b78b15a7b 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java @@ -136,11 +136,16 @@ private void readOrientationFromEXIF() { switch (field.getDataType()) { case LONG: case SLONG: - orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); - break; case SHORT: case SSHORT: - orientation = Orientation.forEXIFOrientation((int) value); + // According to spec the orientation must be an unsigned short (16 bit) + // However, we have seen exif data in the wild with LONG and SLONG types + // Thus to be lenient we accept either and convert to int (github issue #548) + if (value instanceof Long) { + orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); + } else if (value instanceof Integer) { + orientation = Orientation.forEXIFOrientation((int) value); + } break; default: LOGGER.warn("readOrientationFromEXIF(): Unsupported Orientation data type: {}", diff --git a/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java b/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java index de3d914f6..e3b46bd3e 100644 --- a/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java +++ b/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java @@ -17,12 +17,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.nio.file.FileVisitOption; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; @@ -232,7 +235,21 @@ void testGetOrientationWithOnlyIllegalEXIFOrientation() throws Exception { } } - @Test + @Test + void testGetOrientationWithOnlyLONGEXIFOrientation() throws Exception { + // This image has exif Orientation stored as SLONG, causing a failure (github issue #548) + Path fixture = TestUtil.getImage("jpg-exif-long-orientation.jpg"); + ImageReader reader = new ImageReaderFactory() + .newImageReader(Format.get("jpg"), fixture); + try { + Metadata metadata = reader.getMetadata(0); + assertEquals(Orientation.ROTATE_0, metadata.getOrientation()); + } finally { + reader.dispose(); + } + } + + @Test void testGetOrientationWithOnlyXMPOrientation() throws Exception { Path fixture = TestUtil.getImage("jpg-xmp-orientation-90.jpg"); ImageReader reader = new ImageReaderFactory() diff --git a/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java b/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java index 9624a6c8a..6a740e2d6 100644 --- a/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java +++ b/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java @@ -366,7 +366,15 @@ void testGetValueWithoutMatchingValue() { assertNull(ifd.getValue(Tag.MAKE)); } - @Test + @Test + void testGetField() { + final Directory ifd = new Directory(TagSet.BASELINE_TIFF); + ifd.put(Tag.MAKE, DataType.ASCII, "Cats"); + Field field = ifd.getField(Tag.MAKE); + assertEquals(DataType.ASCII, field.getDataType()); + } + + @Test void testHashCodeWithEqualInstances() { final Directory subIFD1 = new Directory(TagSet.EXIF); subIFD1.put(Tag.EXPOSURE_TIME, DataType.RATIONAL, new Rational(1, 160)); diff --git a/src/test/resources/images/jpg-exif-long-orientation.jpg b/src/test/resources/images/jpg-exif-long-orientation.jpg new file mode 100755 index 0000000000000000000000000000000000000000..8ad6fb145a6d95d821fd1f2cc1ca081db77e6a5e GIT binary patch literal 36000 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 X5mYb-zhC4 Date: Thu, 22 Aug 2024 15:32:32 +0200 Subject: [PATCH 4/5] Fix indents --- .../library/cantaloupe/image/Metadata.java | 32 +++++++++---------- .../cantaloupe/image/MetadataTest.java | 30 ++++++++--------- .../cantaloupe/image/exif/DirectoryTest.java | 18 +++++------ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java index b78b15a7b..02c9bd5c0 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java @@ -134,22 +134,22 @@ private void readOrientationFromEXIF() { Object value = exif.getValue(Tag.ORIENTATION); if (field != null && value != null) { switch (field.getDataType()) { - case LONG: - case SLONG: - case SHORT: - case SSHORT: - // According to spec the orientation must be an unsigned short (16 bit) - // However, we have seen exif data in the wild with LONG and SLONG types - // Thus to be lenient we accept either and convert to int (github issue #548) - if (value instanceof Long) { - orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); - } else if (value instanceof Integer) { - orientation = Orientation.forEXIFOrientation((int) value); - } - break; - default: - LOGGER.warn("readOrientationFromEXIF(): Unsupported Orientation data type: {}", - field.getDataType()); + case LONG: + case SLONG: + case SHORT: + case SSHORT: + // According to spec the orientation must be an unsigned short (16 bit) + // However, we have seen exif data in the wild with LONG and SLONG types + // Thus to be lenient we accept either and convert to int (github issue #548) + if (value instanceof Long) { + orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); + } else if (value instanceof Integer) { + orientation = Orientation.forEXIFOrientation((int) value); + } + break; + default: + LOGGER.warn("readOrientationFromEXIF(): Unsupported Orientation data type: {}", + field.getDataType()); } } } diff --git a/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java b/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java index e3b46bd3e..325a5d5f4 100644 --- a/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java +++ b/src/test/java/edu/illinois/library/cantaloupe/image/MetadataTest.java @@ -235,21 +235,21 @@ void testGetOrientationWithOnlyIllegalEXIFOrientation() throws Exception { } } - @Test - void testGetOrientationWithOnlyLONGEXIFOrientation() throws Exception { - // This image has exif Orientation stored as SLONG, causing a failure (github issue #548) - Path fixture = TestUtil.getImage("jpg-exif-long-orientation.jpg"); - ImageReader reader = new ImageReaderFactory() - .newImageReader(Format.get("jpg"), fixture); - try { - Metadata metadata = reader.getMetadata(0); - assertEquals(Orientation.ROTATE_0, metadata.getOrientation()); - } finally { - reader.dispose(); - } - } - - @Test + @Test + void testGetOrientationWithOnlyLONGEXIFOrientation() throws Exception { + // This image has exif Orientation stored as SLONG, causing a failure (github issue #548) + Path fixture = TestUtil.getImage("jpg-exif-long-orientation.jpg"); + ImageReader reader = new ImageReaderFactory() + .newImageReader(Format.get("jpg"), fixture); + try { + Metadata metadata = reader.getMetadata(0); + assertEquals(Orientation.ROTATE_0, metadata.getOrientation()); + } finally { + reader.dispose(); + } + } + + @Test void testGetOrientationWithOnlyXMPOrientation() throws Exception { Path fixture = TestUtil.getImage("jpg-xmp-orientation-90.jpg"); ImageReader reader = new ImageReaderFactory() diff --git a/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java b/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java index 6a740e2d6..be13f18ff 100644 --- a/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java +++ b/src/test/java/edu/illinois/library/cantaloupe/image/exif/DirectoryTest.java @@ -366,15 +366,15 @@ void testGetValueWithoutMatchingValue() { assertNull(ifd.getValue(Tag.MAKE)); } - @Test - void testGetField() { - final Directory ifd = new Directory(TagSet.BASELINE_TIFF); - ifd.put(Tag.MAKE, DataType.ASCII, "Cats"); - Field field = ifd.getField(Tag.MAKE); - assertEquals(DataType.ASCII, field.getDataType()); - } - - @Test + @Test + void testGetField() { + final Directory ifd = new Directory(TagSet.BASELINE_TIFF); + ifd.put(Tag.MAKE, DataType.ASCII, "Cats"); + Field field = ifd.getField(Tag.MAKE); + assertEquals(DataType.ASCII, field.getDataType()); + } + + @Test void testHashCodeWithEqualInstances() { final Directory subIFD1 = new Directory(TagSet.EXIF); subIFD1.put(Tag.EXPOSURE_TIME, DataType.RATIONAL, new Rational(1, 160)); From 2cc413d782923d7f2c77bc7059f69b30b6086a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B8ydahl?= Date: Wed, 2 Oct 2024 17:45:48 +0200 Subject: [PATCH 5/5] Add extra comments about data types --- .../java/edu/illinois/library/cantaloupe/image/Metadata.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java index 02c9bd5c0..4c5809bce 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java +++ b/src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java @@ -141,6 +141,8 @@ private void readOrientationFromEXIF() { // According to spec the orientation must be an unsigned short (16 bit) // However, we have seen exif data in the wild with LONG and SLONG types // Thus to be lenient we accept either and convert to int (github issue #548) + // It could also happen that 'value' is in fact a Java Integer even if the + // exif data type is LONG or SLONG, so we need to check for that as well. if (value instanceof Long) { orientation = Orientation.forEXIFOrientation(Math.toIntExact((long) value)); } else if (value instanceof Integer) {