import java.io.File;\r
import java.util.HashMap;\r
\r
+import tim.prune.jpeg.ExifGateway;\r
import tim.prune.jpeg.JpegData;\r
\r
/**\r
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
+ /** "Original" Exif timestamp */\r
public static final int TAG_DATETIME_ORIGINAL = 0x9003;\r
+ /** "Creation" or "Digitized" timestamp */\r
+ public static final int TAG_DATETIME_DIGITIZED = 0x9004;\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
/** Orientation of image */\r
private static final int TAG_ORIENTATION = 0x0112;\r
+ /** Bearing direction of image */\r
+ private static final int TAG_BEARING = 0x0011;\r
\r
\r
/**\r
*/\r
public ExifReader(File inFile) throws JpegException\r
{\r
- JpegSegmentData segments = JpegSegmentReader.readSegments(inFile);\r
- _data = segments.getSegment(JpegSegmentReader.SEGMENT_APP1);\r
+ _data = JpegSegmentReader.readExifSegment(inFile);\r
}\r
\r
/**\r
private void processGpsTag(JpegData inMetadata, int inTagType, int inTagValueOffset,\r
int inComponentCount, int inFormatCode)\r
{\r
- // Only interested in tags latref, lat, longref, lon, altref, alt and gps timestamp\r
- switch (inTagType)\r
+ try\r
{\r
- case TAG_GPS_LATITUDE_REF:\r
- inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
- break;\r
- case TAG_GPS_LATITUDE:\r
- Rational[] latitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setLatitude(new double[] {latitudes[0].doubleValue(), latitudes[1].doubleValue(), latitudes[2].doubleValue()});\r
- break;\r
- case TAG_GPS_LONGITUDE_REF:\r
- inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
- break;\r
- case TAG_GPS_LONGITUDE:\r
- Rational[] longitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setLongitude(new double[] {longitudes[0].doubleValue(), longitudes[1].doubleValue(), longitudes[2].doubleValue()});\r
- break;\r
- case TAG_GPS_ALTITUDE_REF:\r
- inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
- break;\r
- case TAG_GPS_ALTITUDE:\r
- inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount).intValue());\r
- break;\r
- case TAG_GPS_TIMESTAMP:\r
- Rational[] times = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), times[2].intValue()});\r
- break;\r
- case TAG_GPS_DATESTAMP:\r
- Rational[] dates = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});\r
- break;\r
- default: // ignore all other tags\r
+ // Only interested in tags latref, lat, longref, lon, altref, alt and gps timestamp\r
+ switch (inTagType)\r
+ {\r
+ case TAG_GPS_LATITUDE_REF:\r
+ inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ break;\r
+ case TAG_GPS_LATITUDE:\r
+ Rational[] latitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setLatitude(new double[] {latitudes[0].doubleValue(), latitudes[1].doubleValue(),\r
+ ExifGateway.convertToPositiveValue(latitudes[2].getNumerator(), latitudes[2].getDenominator())});\r
+ break;\r
+ case TAG_GPS_LONGITUDE_REF:\r
+ inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ break;\r
+ case TAG_GPS_LONGITUDE:\r
+ Rational[] longitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setLongitude(new double[] {longitudes[0].doubleValue(), longitudes[1].doubleValue(),\r
+ ExifGateway.convertToPositiveValue(longitudes[2].getNumerator(), longitudes[2].getDenominator())});\r
+ break;\r
+ case TAG_GPS_ALTITUDE_REF:\r
+ inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
+ break;\r
+ case TAG_GPS_ALTITUDE:\r
+ inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount).intValue());\r
+ break;\r
+ case TAG_GPS_TIMESTAMP:\r
+ Rational[] times = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), times[2].intValue()});\r
+ break;\r
+ case TAG_GPS_DATESTAMP:\r
+ Rational[] dates = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ if (dates != null) {\r
+ inMetadata.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});\r
+ }\r
+ else\r
+ {\r
+ // Not in rational array format, but maybe as String?\r
+ String date = readString(inTagValueOffset, inFormatCode, inComponentCount);\r
+ if (date != null && date.length() == 10) {\r
+ inMetadata.setGpsDatestamp(new int[] {Integer.parseInt(date.substring(0, 4)),\r
+ Integer.parseInt(date.substring(5, 7)), Integer.parseInt(date.substring(8))});\r
+ }\r
+ }\r
+ break;\r
+ case TAG_BEARING:\r
+ Rational val = readRational(inTagValueOffset, inFormatCode, inComponentCount);\r
+ if (val != null) {\r
+ inMetadata.setBearing(val.doubleValue());\r
+ }\r
+ break;\r
+ default: // ignore all other tags\r
+ }\r
}\r
+ catch (Exception e) {} // ignore and continue\r
}\r
\r
\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
+ if (inTagType == TAG_DATETIME_ORIGINAL) {\r
inMetadata.setOriginalTimestamp(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
}\r
+ else if (inTagType == TAG_DATETIME_DIGITIZED) {\r
+ inMetadata.setDigitizedTimestamp(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ }\r
else if (inTagType == TAG_THUMBNAIL_OFFSET) {\r
_thumbnailOffset = TIFF_HEADER_START_OFFSET + get16Bits(inTagValueOffset);\r
extractThumbnail(inMetadata);\r