Skip to content

Commit

Permalink
Merge pull request cantaloupe-project#684 from janhoy/TIFF-EXIF-orien…
Browse files Browse the repository at this point in the history
…tation-classcast

Fix exception when parsing EXIF data with LONG Orientation
  • Loading branch information
DiegoPino authored Oct 9, 2024
2 parents 52062c1 + 2cc413d commit 904412b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 6 deletions.
30 changes: 24 additions & 6 deletions src/main/java/edu/illinois/library/cantaloupe/image/Metadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -120,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;
}
Expand All @@ -132,9 +130,29 @@ 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:
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)
// 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) {
orientation = Orientation.forEXIFOrientation((int) value);
}
break;
default:
LOGGER.warn("readOrientationFromEXIF(): Unsupported Orientation data type: {}",
field.getDataType());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Integer,Integer> codes = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;

Expand Down Expand Up @@ -232,6 +235,20 @@ 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
void testGetOrientationWithOnlyXMPOrientation() throws Exception {
Path fixture = TestUtil.getImage("jpg-xmp-orientation-90.jpg");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,14 @@ 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
void testHashCodeWithEqualInstances() {
final Directory subIFD1 = new Directory(TagSet.EXIF);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 904412b

Please sign in to comment.