1 package tim.prune.jpeg;
5 import com.drew.imaging.ImageMetadataReader;
6 import com.drew.lang.Rational;
7 import com.drew.metadata.Directory;
8 import com.drew.metadata.Metadata;
9 import com.drew.metadata.exif.ExifSubIFDDirectory;
10 import com.drew.metadata.exif.ExifIFD0Directory;
11 import com.drew.metadata.exif.ExifReader;
12 import com.drew.metadata.exif.ExifThumbnailDirectory;
13 import com.drew.metadata.exif.GpsDirectory;
16 * Class to act as a gateway into the external exif library functions.
17 * This should be the only class with dependence on the lib-metadata-extractor-java
18 * classes (which are NOT delivered with GpsPrune).
19 * This class will not compile without this extra dependency (but is not required if
20 * the ExifGateway uses the InternalExifLibrary instead).
21 * Should not be included if the internal library will be used (from jpeg.drew package).
23 public class ExternalExifLibrary implements ExifLibrary
26 * Use the _external_ exif library to get the data from the given file
27 * @param inFile file to access
28 * @return Jpeg data if available, otherwise null
30 public JpegData getJpegData(File inFile)
32 JpegData data = new JpegData();
33 // Read exif data from picture
36 Metadata metadata = ImageMetadataReader.readMetadata(inFile);
37 if (metadata.containsDirectory(GpsDirectory.class))
39 Directory gpsdir = metadata.getDirectory(GpsDirectory.class);
40 if (gpsdir.containsTag(GpsDirectory.TAG_LATITUDE)
41 && gpsdir.containsTag(GpsDirectory.TAG_LONGITUDE)
42 && gpsdir.containsTag(GpsDirectory.TAG_LATITUDE_REF)
43 && gpsdir.containsTag(GpsDirectory.TAG_LONGITUDE_REF))
45 data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_LATITUDE_REF));
46 Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_LATITUDE);
47 double seconds = ExifGateway.convertToPositiveValue(latRats[2].getNumerator(), latRats[2].getDenominator());
48 data.setLatitude(new double[] {latRats[0].doubleValue(),
49 latRats[1].doubleValue(), seconds});
50 data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_LONGITUDE_REF));
51 Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_LONGITUDE);
52 seconds = ExifGateway.convertToPositiveValue(lonRats[2].getNumerator(), lonRats[2].getDenominator());
53 data.setLongitude(new double[] {lonRats[0].doubleValue(),
54 lonRats[1].doubleValue(), seconds});
57 // Altitude (if present)
58 if (gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE_REF))
60 data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_ALTITUDE).intValue());
61 byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_ALTITUDE_REF);
62 data.setAltitudeRef(altRef);
65 // Timestamp and datestamp (if present)
66 final int TAG_DATESTAMP = 0x001d;
67 if (gpsdir.containsTag(GpsDirectory.TAG_TIME_STAMP) && gpsdir.containsTag(TAG_DATESTAMP))
69 Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_TIME_STAMP);
70 data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(),
71 times[2].intValue()});
72 Rational[] dates = gpsdir.getRationalArray(TAG_DATESTAMP);
74 data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
78 // Image bearing (if present)
79 if (gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION_REF))
81 Rational bearing = gpsdir.getRational(GpsDirectory.TAG_IMG_DIRECTION);
82 if (bearing != null) {
83 data.setBearing(bearing.doubleValue());
88 // Tags from Exif directory
89 if (metadata.containsDirectory(ExifSubIFDDirectory.class))
91 Directory exifdir = metadata.getDirectory(ExifSubIFDDirectory.class);
93 // Take time and date from exif tags
94 if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)) {
95 data.setOriginalTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL));
97 // Also take "digitized" timestamp
98 if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED)) {
99 data.setDigitizedTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED));
102 if (metadata.containsDirectory(ExifIFD0Directory.class))
104 Directory exifdir = metadata.getDirectory(ExifIFD0Directory.class);
106 // Photo rotation code
107 if (exifdir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
108 data.setOrientationCode(exifdir.getInt(ExifIFD0Directory.TAG_ORIENTATION));
109 // NOTE: this presumably takes the _last_ orientation value found, not the first.
113 if (metadata.containsDirectory(ExifThumbnailDirectory.class))
115 ExifThumbnailDirectory exifdir = metadata.getDirectory(ExifThumbnailDirectory.class);
117 // TODO: Check this thumbnail stuff
118 if (exifdir.hasThumbnailData())
120 // Make a copy of the byte data
121 byte[] tdata = exifdir.getThumbnailData();
122 byte[] thumb = new byte[tdata.length];
123 System.arraycopy(tdata, 0, thumb, 0, tdata.length);
124 data.setThumbnailImage(thumb);
129 catch (Exception e) {
130 // Exception reading metadata, just ignore it
131 //System.err.println("Error: " + e.getClass().getName() + " - " + e.getMessage());
138 * Check whether the exifreader class can be correctly resolved
139 * @return true if it looks ok
141 public boolean looksOK()
144 String test = ExifReader.class.getName();
145 if (test != null) return true;
147 catch (LinkageError le) {}