]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/drew/jpeg/ExifReader.java
Version 4, January 2008
[GpsPrune.git] / tim / prune / drew / jpeg / ExifReader.java
index 4e58199f0aab1bd4c5d1fccc6a164e1c114c9196..1637a9dbc633639d4126c2e892f58ce9f7e03498 100644 (file)
@@ -20,6 +20,11 @@ public class ExifReader
         */\r
        private boolean _isMotorolaByteOrder;\r
 \r
+       /** Thumbnail offset */\r
+       private int _thumbnailOffset = -1;\r
+       /** Thumbnail length */\r
+       private int _thumbnailLength = -1;\r
+\r
        /**\r
         * The number of bytes used per format descriptor.\r
         */\r
@@ -71,11 +76,18 @@ public class ExifReader
        public static final int TAG_GPS_TIMESTAMP = 0x0007;\r
        /** GPS date (atomic clock) GPSDateStamp 23 1d RATIONAL 3 */\r
        public static final int TAG_GPS_DATESTAMP = 0x001d;\r
+       /** Exif timestamp */\r
+       public static final int TAG_DATETIME_ORIGINAL = 0x9003;\r
+       /** Thumbnail offset */\r
+       private static final int TAG_THUMBNAIL_OFFSET = 0x0201;\r
+       /** Thumbnail length */\r
+       private static final int TAG_THUMBNAIL_LENGTH = 0x0202;\r
+\r
 \r
        /**\r
         * Creates an ExifReader for a Jpeg file.\r
         * @param inFile File object to attempt to read from\r
-        * @throws JpegProcessingException on failure\r
+        * @throws JpegException on failure\r
         */\r
        public ExifReader(File inFile) throws JpegException\r
        {\r
@@ -238,11 +250,11 @@ public class ExifReader
                        // Calculate the value as an offset for cases where the tag represents a directory\r
                        final int subdirOffset = inTiffHeaderOffset + get32Bits(tagValueOffset);\r
 \r
-                       // TODO: Also look for timestamp(s) in Exif for correlation - which directory?\r
+                       // Look in both basic Exif tags (for timestamp, thumbnail) and Gps tags (for lat, long, altitude, timestamp)\r
                        switch (tagType)\r
                        {\r
                                case TAG_EXIF_OFFSET:\r
-                                       // ignore\r
+                                       processDirectory(inMetadata, false, inDirectoryOffsets, subdirOffset, inTiffHeaderOffset);\r
                                        continue;\r
                                case TAG_INTEROP_OFFSET:\r
                                        // ignore\r
@@ -255,9 +267,14 @@ public class ExifReader
                                        continue;\r
                                default:\r
                                        // not a known directory, so must just be a normal tag\r
-                                       // ignore if we're not in gps directory\r
                                        if (inIsGPS)\r
+                                       {\r
                                                processGpsTag(inMetadata, tagType, tagValueOffset, componentCount, formatCode);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               processExifTag(inMetadata, tagType, tagValueOffset, componentCount, formatCode);\r
+                                       }\r
                                        break;\r
                        }\r
                }\r
@@ -336,16 +353,56 @@ public class ExifReader
                                inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_TIMESTAMP:\r
-                               inMetadata.setTimestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               inMetadata.setGpsTimestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_DATESTAMP:\r
-                               inMetadata.setDatestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               inMetadata.setGpsDatestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        default: // ignore all other tags\r
                }\r
        }\r
 \r
 \r
+       /**\r
+        * Process a general Exif tag\r
+        * @param inMetadata metadata holding extracted values\r
+        * @param inTagType tag type (eg latitude)\r
+        * @param inTagValueOffset start offset in data array\r
+        * @param inComponentCount component count for tag\r
+        * @param inFormatCode format code, eg byte\r
+        */\r
+       private void processExifTag(JpegData inMetadata, int inTagType, int inTagValueOffset,\r
+               int inComponentCount, int inFormatCode)\r
+       {\r
+               // Only interested in original timestamp, thumbnail offset and thumbnail length\r
+               if (inTagType == TAG_DATETIME_ORIGINAL)\r
+               {\r
+                       inMetadata.setOriginalTimestamp(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+               }\r
+               else if (inTagType == TAG_THUMBNAIL_OFFSET) {\r
+                       _thumbnailOffset = TIFF_HEADER_START_OFFSET + get16Bits(inTagValueOffset);\r
+                       extractThumbnail(inMetadata);\r
+               }\r
+               else if (inTagType == TAG_THUMBNAIL_LENGTH) {\r
+                       _thumbnailLength = get16Bits(inTagValueOffset);\r
+                       extractThumbnail(inMetadata);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Attempt to extract the thumbnail image\r
+        */\r
+       private void extractThumbnail(JpegData inMetadata)\r
+       {\r
+               if (_thumbnailOffset > 0 && _thumbnailLength > 0 && inMetadata.getThumbnailImage() == null)\r
+               {\r
+                       byte[] thumbnailBytes = new byte[_thumbnailLength];\r
+                       System.arraycopy(_data, _thumbnailOffset, thumbnailBytes, 0, _thumbnailLength);\r
+                       inMetadata.setThumbnailImage(thumbnailBytes);\r
+               }\r
+       }\r
+\r
+\r
        /**\r
         * Calculate the tag value offset\r
         * @param inByteCount\r