diff --git a/Source/com/drew/imaging/png/PngMetadataReader.java b/Source/com/drew/imaging/png/PngMetadataReader.java
index c276e9bfa..1a0447451 100644
--- a/Source/com/drew/imaging/png/PngMetadataReader.java
+++ b/Source/com/drew/imaging/png/PngMetadataReader.java
@@ -330,7 +330,7 @@ private static void processChunk(@NotNull Metadata metadata, @NotNull PngChunk c
metadata.addDirectory(directory);
} else if (chunkType.equals(PngChunkType.eXIf)) {
try {
- ExifTiffHandler handler = new ExifTiffHandler(metadata, null);
+ ExifTiffHandler handler = new ExifTiffHandler(metadata, null, 0);
new TiffReader().processTiff(new ByteArrayReader(bytes), handler, 0);
} catch (TiffProcessingException ex) {
PngDirectory directory = new PngDirectory(PngChunkType.eXIf);
diff --git a/Source/com/drew/imaging/tiff/TiffMetadataReader.java b/Source/com/drew/imaging/tiff/TiffMetadataReader.java
index 7137a0384..5db7883d4 100644
--- a/Source/com/drew/imaging/tiff/TiffMetadataReader.java
+++ b/Source/com/drew/imaging/tiff/TiffMetadataReader.java
@@ -67,7 +67,7 @@ public static Metadata readMetadata(@NotNull InputStream inputStream) throws IOE
public static Metadata readMetadata(@NotNull RandomAccessReader reader) throws IOException, TiffProcessingException
{
Metadata metadata = new Metadata();
- ExifTiffHandler handler = new ExifTiffHandler(metadata, null);
+ ExifTiffHandler handler = new ExifTiffHandler(metadata, null, 0);
new TiffReader().processTiff(reader, handler, 0);
return metadata;
}
diff --git a/Source/com/drew/metadata/exif/ExifReader.java b/Source/com/drew/metadata/exif/ExifReader.java
index ff2e9a954..d343597f1 100644
--- a/Source/com/drew/metadata/exif/ExifReader.java
+++ b/Source/com/drew/metadata/exif/ExifReader.java
@@ -87,7 +87,7 @@ public void extract(@NotNull final RandomAccessReader reader, @NotNull final Met
/** Reads TIFF formatted Exif data at a specified offset within a {@link RandomAccessReader}. */
public void extract(@NotNull final RandomAccessReader reader, @NotNull final Metadata metadata, int readerOffset, @Nullable Directory parentDirectory)
{
- ExifTiffHandler exifTiffHandler = new ExifTiffHandler(metadata, parentDirectory);
+ ExifTiffHandler exifTiffHandler = new ExifTiffHandler(metadata, parentDirectory, readerOffset);
try {
// Read the TIFF-formatted Exif data
diff --git a/Source/com/drew/metadata/exif/ExifThumbnailDescriptor.java b/Source/com/drew/metadata/exif/ExifThumbnailDescriptor.java
index 430491772..15525e87f 100644
--- a/Source/com/drew/metadata/exif/ExifThumbnailDescriptor.java
+++ b/Source/com/drew/metadata/exif/ExifThumbnailDescriptor.java
@@ -63,7 +63,8 @@ public String getThumbnailLengthDescription()
@Nullable
public String getThumbnailOffsetDescription()
{
- String value = _directory.getString(TAG_THUMBNAIL_OFFSET);
- return value == null ? null : value + " bytes";
+ Integer offset = _directory.getAdjustedThumbnailOffset();
+
+ return offset == null ? null : offset.intValue() + " bytes";
}
}
diff --git a/Source/com/drew/metadata/exif/ExifThumbnailDirectory.java b/Source/com/drew/metadata/exif/ExifThumbnailDirectory.java
index 85b106f7e..572a0505f 100644
--- a/Source/com/drew/metadata/exif/ExifThumbnailDirectory.java
+++ b/Source/com/drew/metadata/exif/ExifThumbnailDirectory.java
@@ -34,7 +34,11 @@
public class ExifThumbnailDirectory extends ExifDirectoryBase
{
/**
- * The offset to thumbnail image bytes.
+ * The offset to thumbnail image bytes, relative to the start of the IFD.
+ *
+ * To obtain the offset relative to the start of the TIFF data stream, use
+ * getAdjustedThumbnailOffset
, which includes the value of
+ * getExifStartOffset
.
*/
public static final int TAG_THUMBNAIL_OFFSET = 0x0201;
/**
@@ -59,8 +63,11 @@ public class ExifThumbnailDirectory extends ExifDirectoryBase
_tagNameMap.put(TAG_THUMBNAIL_LENGTH, "Thumbnail Length");
}
- public ExifThumbnailDirectory()
+ private final int _exifStartOffset;
+
+ public ExifThumbnailDirectory(int exifStartOffset)
{
+ _exifStartOffset = exifStartOffset;
this.setDescriptor(new ExifThumbnailDescriptor(this));
}
@@ -77,4 +84,35 @@ protected HashMap getTagNameMap()
{
return _tagNameMap;
}
+
+ /**
+ * Gets the offset at which the Exif data stream commenced within any containing stream.
+ */
+ public int getExifStartOffset()
+ {
+ return _exifStartOffset;
+ }
+
+ /**
+ * Returns the offset to thumbnail data within the outermost data stream.
+ *
+ * The value for TagThumbnailOffset
is relative to the Exif data stream.
+ * Generally, consumers of thumbnail data need this value relative to the outermost stream,
+ * so that the thumbnail data may be extracted from that stream.
+ *
+ * This property adds the value of ExifStartOffset
to this tag's value in order
+ * to produce that value.
+ *
+ * Returns null
when the tag is not defined in this directory.
+ */
+ public Integer getAdjustedThumbnailOffset()
+ {
+ Integer offset = this.getInteger(TAG_THUMBNAIL_OFFSET);
+
+ if (offset == null) {
+ return null;
+ }
+
+ return offset.intValue() + _exifStartOffset;
+ }
}
diff --git a/Source/com/drew/metadata/exif/ExifTiffHandler.java b/Source/com/drew/metadata/exif/ExifTiffHandler.java
index 2acf88294..39857b440 100644
--- a/Source/com/drew/metadata/exif/ExifTiffHandler.java
+++ b/Source/com/drew/metadata/exif/ExifTiffHandler.java
@@ -57,9 +57,12 @@
*/
public class ExifTiffHandler extends DirectoryTiffHandler
{
- public ExifTiffHandler(@NotNull Metadata metadata, @Nullable Directory parentDirectory)
+ private final int _exifStartOffset;
+
+ public ExifTiffHandler(@NotNull Metadata metadata, @Nullable Directory parentDirectory, int exifStartOffset)
{
super(metadata, parentDirectory);
+ _exifStartOffset = exifStartOffset;
}
public void setTiffMarker(int marker) throws TiffProcessingException
@@ -149,7 +152,7 @@ public boolean hasFollowerIfd()
if (_currentDirectory.containsTag(ExifDirectoryBase.TAG_PAGE_NUMBER))
pushDirectory(ExifImageDirectory.class);
else
- pushDirectory(ExifThumbnailDirectory.class);
+ pushDirectory(new ExifThumbnailDirectory(_exifStartOffset));
return true;
}
diff --git a/Source/com/drew/metadata/photoshop/PhotoshopTiffHandler.java b/Source/com/drew/metadata/photoshop/PhotoshopTiffHandler.java
index b5de35ea8..a90e52827 100644
--- a/Source/com/drew/metadata/photoshop/PhotoshopTiffHandler.java
+++ b/Source/com/drew/metadata/photoshop/PhotoshopTiffHandler.java
@@ -33,7 +33,7 @@ public class PhotoshopTiffHandler extends ExifTiffHandler
public PhotoshopTiffHandler(Metadata metadata, Directory parentDirectory)
{
- super(metadata, parentDirectory);
+ super(metadata, parentDirectory, 0);
}
public boolean customProcessTag(final int tagOffset,
diff --git a/Source/com/drew/metadata/tiff/DirectoryTiffHandler.java b/Source/com/drew/metadata/tiff/DirectoryTiffHandler.java
index a327bd808..21ed52917 100644
--- a/Source/com/drew/metadata/tiff/DirectoryTiffHandler.java
+++ b/Source/com/drew/metadata/tiff/DirectoryTiffHandler.java
@@ -67,21 +67,26 @@ protected void pushDirectory(@NotNull Class extends Directory> directoryClass)
throw new RuntimeException(e);
}
+ pushDirectory(newDirectory);
+ }
+
+ protected void pushDirectory(@NotNull Directory directory)
+ {
// If this is the first directory, don't add to the stack
if (_currentDirectory == null) {
// Apply any pending root parent to this new directory
if (_rootParentDirectory != null) {
- newDirectory.setParent(_rootParentDirectory);
+ directory.setParent(_rootParentDirectory);
_rootParentDirectory = null;
}
}
else {
// The current directory is pushed onto the stack, and set as the new directory's parent
_directoryStack.push(_currentDirectory);
- newDirectory.setParent(_currentDirectory);
+ directory.setParent(_currentDirectory);
}
- _currentDirectory = newDirectory;
+ _currentDirectory = directory;
_metadata.addDirectory(_currentDirectory);
}
diff --git a/Tests/com/drew/metadata/MetadataTest.java b/Tests/com/drew/metadata/MetadataTest.java
index 7a10e52a2..05b5239cb 100644
--- a/Tests/com/drew/metadata/MetadataTest.java
+++ b/Tests/com/drew/metadata/MetadataTest.java
@@ -96,7 +96,7 @@ public void testOrderOfDifferentTypes()
{
Metadata metadata = new Metadata();
Directory directory1 = new ExifSubIFDDirectory();
- Directory directory2 = new ExifThumbnailDirectory();
+ Directory directory2 = new ExifThumbnailDirectory(0);
Directory directory3 = new ExifIFD0Directory();
metadata.addDirectory(directory1);
diff --git a/Tests/com/drew/metadata/exif/ExifDirectoryTest.java b/Tests/com/drew/metadata/exif/ExifDirectoryTest.java
index d818dcbac..d96822b23 100644
--- a/Tests/com/drew/metadata/exif/ExifDirectoryTest.java
+++ b/Tests/com/drew/metadata/exif/ExifDirectoryTest.java
@@ -46,7 +46,7 @@ public void testGetDirectoryName() throws Exception
{
Directory subIFDDirectory = new ExifSubIFDDirectory();
Directory ifd0Directory = new ExifIFD0Directory();
- Directory thumbDirectory = new ExifThumbnailDirectory();
+ Directory thumbDirectory = new ExifThumbnailDirectory(0);
Directory gpsDirectory = new GpsDirectory();
assertFalse(subIFDDirectory.hasErrors());
diff --git a/Tests/com/drew/metadata/exif/ExifThumbnailDescriptorTest.java b/Tests/com/drew/metadata/exif/ExifThumbnailDescriptorTest.java
index a223eab42..1c3bc304f 100644
--- a/Tests/com/drew/metadata/exif/ExifThumbnailDescriptorTest.java
+++ b/Tests/com/drew/metadata/exif/ExifThumbnailDescriptorTest.java
@@ -36,7 +36,7 @@ public class ExifThumbnailDescriptorTest
@Test
public void testGetYCbCrSubsamplingDescription() throws Exception
{
- ExifThumbnailDirectory directory = new ExifThumbnailDirectory();
+ ExifThumbnailDirectory directory = new ExifThumbnailDirectory(0);
directory.setIntArray(TAG_YCBCR_SUBSAMPLING, new int[]{2, 1});
ExifThumbnailDescriptor descriptor = new ExifThumbnailDescriptor(directory);