#368 related clean-up

This commit is contained in:
Harald Kuhr 2018-01-17 19:24:31 +01:00
parent 2b29c14593
commit c294c5869c
4 changed files with 49 additions and 59 deletions

View File

@ -40,7 +40,7 @@ import static com.twelvemonkeys.lang.Validate.noNullElements;
* @version $Id: AbstractDirectory.java,v 1.0 Nov 11, 2009 5:31:04 PM haraldk Exp$ * @version $Id: AbstractDirectory.java,v 1.0 Nov 11, 2009 5:31:04 PM haraldk Exp$
*/ */
public abstract class AbstractDirectory implements Directory { public abstract class AbstractDirectory implements Directory {
private final List<Entry> entries = new ArrayList<Entry>(); private final List<Entry> entries = new ArrayList<>();
private final List<Entry> unmodifiable = Collections.unmodifiableList(entries); private final List<Entry> unmodifiable = Collections.unmodifiableList(entries);
protected AbstractDirectory(final Collection<? extends Entry> entries) { protected AbstractDirectory(final Collection<? extends Entry> entries) {

View File

@ -28,7 +28,6 @@
package com.twelvemonkeys.imageio.metadata.tiff; package com.twelvemonkeys.imageio.metadata.tiff;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
import com.twelvemonkeys.imageio.metadata.Directory; import com.twelvemonkeys.imageio.metadata.Directory;
import com.twelvemonkeys.imageio.metadata.Entry; import com.twelvemonkeys.imageio.metadata.Entry;
import com.twelvemonkeys.imageio.metadata.MetadataReader; import com.twelvemonkeys.imageio.metadata.MetadataReader;
@ -105,24 +104,41 @@ public final class TIFFReader extends MetadataReader {
throw new IIOException(String.format("Wrong TIFF magic in input data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC)); throw new IIOException(String.format("Wrong TIFF magic in input data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC));
} }
long directoryOffset = readOffset(input); return readLinkedIFDs(input);
}
return readDirectory(input, directoryOffset, true); private TIFFDirectory readLinkedIFDs(final ImageInputStream input) throws IOException {
long nextOffset = readOffset(input);
List<IFD> ifds = new ArrayList<>();
// Read linked IFDs
while (nextOffset != 0) {
try {
ifds.add(readIFD(input, nextOffset));
nextOffset = readOffset(input);
}
catch (EOFException eof) {
// catch EOF here as missing EOF marker
nextOffset = 0;
}
}
return new TIFFDirectory(ifds);
} }
private long readOffset(final ImageInputStream input) throws IOException { private long readOffset(final ImageInputStream input) throws IOException {
return longOffsets ? input.readLong() : input.readUnsignedInt(); return longOffsets ? input.readLong() : input.readUnsignedInt();
} }
// TODO: Consider re-writing so that the linked IFD parsing is done externally to the method private IFD readIFD(final ImageInputStream pInput, final long pOffset) throws IOException {
protected Directory readDirectory(final ImageInputStream pInput, final long pOffset, final boolean readLinked) throws IOException {
List<IFD> ifds = new ArrayList<>();
List<Entry> entries = new ArrayList<>();
pInput.seek(pOffset); pInput.seek(pOffset);
long entryCount = readEntryCount(pInput); long entryCount = readEntryCount(pInput);
List<TIFFEntry> entries = new ArrayList<>();
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
try { try {
TIFFEntry entry = readEntry(pInput); TIFFEntry entry = readEntry(pInput);
@ -136,60 +152,27 @@ public final class TIFFReader extends MetadataReader {
} }
} }
if (readLinked) {
long nextOffset;
try {
nextOffset = readOffset(pInput);
}
catch (EOFException e) {
// catch EOF here as missing EOF marker
nextOffset = 0;
}
// Read linked IFDs
if (nextOffset != 0) {
CompoundDirectory next = (CompoundDirectory) readDirectory(pInput, nextOffset, true);
for (int i = 0; i < next.directoryCount(); i++) {
Directory directory = next.getDirectory(i);
// Linked directories might be empty if nextOffset is after EOF (skip these)
if (directory.size() > 0) {
ifds.add((IFD) directory);
}
}
}
}
// TODO: Consider leaving to client code what sub-IFDs to parse (but always parse TAG_SUB_IFD). // TODO: Consider leaving to client code what sub-IFDs to parse (but always parse TAG_SUB_IFD).
readSubdirectories(pInput, entries, readSubIFDs(pInput, entries,
Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD, TIFF.TAG_SUB_IFD) Arrays.asList(TIFF.TAG_EXIF_IFD, TIFF.TAG_GPS_IFD, TIFF.TAG_INTEROP_IFD, TIFF.TAG_SUB_IFD)
); );
ifds.add(0, new IFD(entries)); return new IFD(entries);
return new TIFFDirectory(ifds);
} }
private long readEntryCount(final ImageInputStream pInput) throws IOException { private long readEntryCount(final ImageInputStream pInput) throws IOException {
try { return longOffsets ? pInput.readLong() : pInput.readUnsignedShort();
return longOffsets ? pInput.readLong() : pInput.readUnsignedShort();
}
catch (EOFException e) {
// Treat EOF here as empty Sub-IFD
return 0;
}
} }
// TODO: Might be better to leave this for client code, as it's tempting go really overboard and support any possible embedded format.. private void readSubIFDs(ImageInputStream input, List<TIFFEntry> entries, List<Integer> subIFDIds) throws IOException {
private void readSubdirectories(ImageInputStream input, List<Entry> entries, List<Integer> subIFDIds) throws IOException {
if (subIFDIds == null || subIFDIds.isEmpty()) { if (subIFDIds == null || subIFDIds.isEmpty()) {
return; return;
} }
long initialPosition = input.getStreamPosition();
for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) { for (int i = 0, entriesSize = entries.size(); i < entriesSize; i++) {
TIFFEntry entry = (TIFFEntry) entries.get(i); TIFFEntry entry = entries.get(i);
int tagId = (Integer) entry.getIdentifier(); int tagId = (Integer) entry.getIdentifier();
if (subIFDIds.contains(tagId)) { if (subIFDIds.contains(tagId)) {
@ -199,10 +182,14 @@ public final class TIFFReader extends MetadataReader {
List<IFD> subIFDs = new ArrayList<>(pointerOffsets.length); List<IFD> subIFDs = new ArrayList<>(pointerOffsets.length);
for (long pointerOffset : pointerOffsets) { for (long pointerOffset : pointerOffsets) {
CompoundDirectory subDirectory = (CompoundDirectory) readDirectory(input, pointerOffset, false); try {
subIFDs.add(readIFD(input, pointerOffset));
for (int j = 0; j < subDirectory.directoryCount(); j++) { }
subIFDs.add((IFD) subDirectory.getDirectory(j)); catch (EOFException ignore) {
// TODO: Issue warning
if (DEBUG) {
ignore.printStackTrace();
}
} }
} }
@ -210,7 +197,7 @@ public final class TIFFReader extends MetadataReader {
// Replace the entry with parsed data // Replace the entry with parsed data
entries.set(i, new TIFFEntry(tagId, entry.getType(), subIFDs.get(0))); entries.set(i, new TIFFEntry(tagId, entry.getType(), subIFDs.get(0)));
} }
else { else if (!subIFDs.isEmpty()) {
// Replace the entry with parsed data // Replace the entry with parsed data
entries.set(i, new TIFFEntry(tagId, entry.getType(), subIFDs.toArray(new IFD[subIFDs.size()]))); entries.set(i, new TIFFEntry(tagId, entry.getType(), subIFDs.toArray(new IFD[subIFDs.size()])));
} }
@ -225,6 +212,9 @@ public final class TIFFReader extends MetadataReader {
} }
} }
} }
// Restore initial position
input.seek(initialPosition);
} }
private long[] getPointerOffsets(final Entry entry) throws IIOException { private long[] getPointerOffsets(final Entry entry) throws IIOException {
@ -537,7 +527,7 @@ public final class TIFFReader extends MetadataReader {
Directory directory; Directory directory;
if (args.length > 1) { if (args.length > 1) {
directory = reader.readDirectory(stream, pos, false); directory = reader.readIFD(stream, pos);
} }
else { else {
directory = reader.read(stream); directory = reader.read(stream);

View File

@ -240,9 +240,9 @@ public class EXIFReaderTest extends MetadataReaderAbstractTest {
// The interop IFD isn't there (offset points to outside the TIFF structure)... // The interop IFD isn't there (offset points to outside the TIFF structure)...
// Have double-checked using ExifTool, which says "Warning : Bad InteropOffset SubDirectory start" // Have double-checked using ExifTool, which says "Warning : Bad InteropOffset SubDirectory start"
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue(); Object interop = exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
assertNotNull(interop); assertNotNull(interop);
assertEquals(0, interop.size()); assertEquals(240L, interop);
} }
@Test @Test

View File

@ -254,9 +254,9 @@ public class TIFFReaderTest extends MetadataReaderAbstractTest {
// The interop IFD isn't there (offset points to outside the TIFF structure)... // The interop IFD isn't there (offset points to outside the TIFF structure)...
// Have double-checked using ExifTool, which says "Warning : Bad InteropOffset SubDirectory start" // Have double-checked using ExifTool, which says "Warning : Bad InteropOffset SubDirectory start"
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue(); Object interop = exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
assertNotNull(interop); assertNotNull(interop);
assertEquals(0, interop.size()); assertEquals(240L, interop);
} }
@Test @Test