1 package tim.prune.jpeg;
5 import com.drew.lang.Rational;
6 import com.drew.metadata.Directory;
7 import com.drew.metadata.Metadata;
8 import com.drew.metadata.MetadataException;
9 import com.drew.metadata.exif.ExifDirectory;
10 import com.drew.metadata.exif.ExifReader;
11 import com.drew.metadata.exif.GpsDirectory;
14 * Class to act as a gateway into the external exif library functions.
15 * This should be the only class with dependence on the lib-metadata-extractor-java
16 * classes (which are NOT delivered with GpsPrune).
17 * This class will not compile without this extra dependency (but is not required if
18 * the ExifGateway uses the InternalExifLibrary instead).
19 * Should not be included if the internal library will be used (from jpeg.drew package).
21 public class ExternalExifLibrary implements ExifLibrary
24 * Use the _external_ exif library to get the data from the given file
25 * @param inFile file to access
26 * @return Jpeg data if available, otherwise null
28 public JpegData getJpegData(File inFile)
30 JpegData data = new JpegData();
31 // Read exif data from picture
34 Metadata metadata = new Metadata();
35 new ExifReader(inFile).extract(metadata);
36 if (metadata.containsDirectory(GpsDirectory.class))
38 Directory gpsdir = metadata.getDirectory(GpsDirectory.class);
39 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE)
40 && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE)
41 && gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE_REF)
42 && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE_REF))
44 data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LATITUDE_REF));
45 Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
46 double seconds = ExifGateway.convertToPositiveValue(latRats[2].getNumerator(), latRats[2].getDenominator());
47 data.setLatitude(new double[] {latRats[0].doubleValue(),
48 latRats[1].doubleValue(), seconds});
49 data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF));
50 Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
51 seconds = ExifGateway.convertToPositiveValue(lonRats[2].getNumerator(), lonRats[2].getDenominator());
52 data.setLongitude(new double[] {lonRats[0].doubleValue(),
53 lonRats[1].doubleValue(), seconds});
56 // Altitude (if present)
57 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF))
59 data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_GPS_ALTITUDE).intValue());
60 byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF);
61 data.setAltitudeRef(altRef);
66 // Timestamp and datestamp (if present)
67 final int TAG_GPS_DATESTAMP = 0x001d;
68 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_TIME_STAMP) && gpsdir.containsTag(TAG_GPS_DATESTAMP))
70 Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_TIME_STAMP);
71 data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(),
72 times[2].intValue()});
73 Rational[] dates = gpsdir.getRationalArray(TAG_GPS_DATESTAMP);
75 data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
79 catch (MetadataException me) {} // ignore, use other tags instead
81 // Image bearing (if present)
82 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION_REF))
84 Rational bearing = gpsdir.getRational(GpsDirectory.TAG_GPS_IMG_DIRECTION);
85 if (bearing != null) {
86 data.setBearing(bearing.doubleValue());
91 // Tags from Exif directory
92 if (metadata.containsDirectory(ExifDirectory.class))
94 Directory exifdir = metadata.getDirectory(ExifDirectory.class);
96 // Take time and date from exif tags
97 if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
98 data.setOriginalTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_ORIGINAL));
100 // Also take "digitized" timestamp
101 if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_DIGITIZED)) {
102 data.setDigitizedTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_DIGITIZED));
105 // Photo rotation code
106 if (exifdir.containsTag(ExifDirectory.TAG_ORIENTATION)) {
107 data.setOrientationCode(exifdir.getInt(ExifDirectory.TAG_ORIENTATION));
108 // NOTE: this presumably takes the _last_ orientation value found, not the first.
112 if (exifdir.containsTag(ExifDirectory.TAG_THUMBNAIL_DATA))
114 // Make a copy of the byte data rather than keeping a reference to extracted array
115 byte[] tdata = exifdir.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA);
116 byte[] thumb = new byte[tdata.length];
117 System.arraycopy(tdata, 0, thumb, 0, tdata.length);
118 data.setThumbnailImage(thumb);
123 catch (Exception e) {
124 // Exception reading metadata, just ignore it
125 //System.err.println("Error: " + e.getClass().getName() + " - " + e.getMessage());
132 * Check whether the exifreader class can be correctly resolved
133 * @return true if it looks ok
135 public boolean looksOK()
138 String test = ExifReader.class.getName();
139 if (test != null) return true;
141 catch (LinkageError le) {}