--- /dev/null
+package tim.prune.jpeg;
+
+import java.io.File;
+
+import com.drew.lang.Rational;
+import com.drew.metadata.Directory;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.exif.ExifDirectory;
+import com.drew.metadata.exif.ExifReader;
+import com.drew.metadata.exif.GpsDirectory;
+
+/**
+ * Class to act as a gateway into the external exif library functions.
+ * This should be the only class with dependence on the lib-metadata-extractor-java
+ * classes (which are NOT delivered with Prune).
+ * This class will not compile without this extra dependency (but is not required if
+ * the ExifGateway uses the InternalExifLibrary instead).
+ * Should not be included if the internal library will be used (from jpeg.drew package).
+ */
+public class ExternalExifLibrary implements ExifLibrary
+{
+ /**
+ * Use the _external_ exif library to get the data from the given file
+ * @param inFile file to access
+ * @return Jpeg data if available, otherwise null
+ */
+ public JpegData getJpegData(File inFile)
+ {
+ JpegData data = new JpegData();
+ // Read exif data from picture
+ try
+ {
+ Metadata metadata = new Metadata();
+ new ExifReader(inFile).extract(metadata);
+ if (metadata.containsDirectory(GpsDirectory.class))
+ {
+ Directory gpsdir = metadata.getDirectory(GpsDirectory.class);
+ if (gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE)
+ && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE)
+ && gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE_REF)
+ && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE_REF))
+ {
+ data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LATITUDE_REF));
+ Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
+ data.setLatitude(new double[] {latRats[0].doubleValue(),
+ latRats[1].doubleValue(), latRats[2].doubleValue()});
+ data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF));
+ Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
+ data.setLongitude(new double[] {lonRats[0].doubleValue(),
+ lonRats[1].doubleValue(), lonRats[2].doubleValue()});
+ }
+
+ // Altitude (if present)
+ if (gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF))
+ {
+ data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_GPS_ALTITUDE).intValue());
+ byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF);
+ data.setAltitudeRef(altRef);
+ }
+
+ // Timestamp and datestamp (if present)
+ final int TAG_GPS_DATESTAMP = 0x001d;
+ if (gpsdir.containsTag(GpsDirectory.TAG_GPS_TIME_STAMP) && gpsdir.containsTag(TAG_GPS_DATESTAMP))
+ {
+ Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_TIME_STAMP);
+ data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(),
+ times[2].intValue()});
+ Rational[] dates = gpsdir.getRationalArray(TAG_GPS_DATESTAMP);
+ data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
+ }
+ }
+
+ // Tags from Exif directory
+ if (metadata.containsDirectory(ExifDirectory.class))
+ {
+ Directory exifdir = metadata.getDirectory(ExifDirectory.class);
+
+ // Take time and date from exif tags if haven't got it already from GPS
+ if (data.getGpsDatestamp() == null && exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
+ data.setOriginalTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_ORIGINAL));
+ }
+
+ // Photo rotation code
+ if (exifdir.containsTag(ExifDirectory.TAG_ORIENTATION)) {
+ data.setOrientationCode(exifdir.getInt(ExifDirectory.TAG_ORIENTATION));
+ // NOTE: this presumably takes the _last_ orientation value found, not the first.
+ }
+
+ // Thumbnail
+ if (exifdir.containsTag(ExifDirectory.TAG_THUMBNAIL_DATA))
+ {
+ // Make a copy of the byte data rather than keeping a reference to extracted array
+ byte[] tdata = exifdir.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA);
+ byte[] thumb = new byte[tdata.length];
+ System.arraycopy(tdata, 0, thumb, 0, tdata.length);
+ data.setThumbnailImage(thumb);
+ }
+ }
+
+ }
+ catch (Exception e) {
+ // Exception reading metadata, just ignore it
+ }
+ return data;
+ }
+
+ /**
+ * Check whether the exifreader class can be correctly resolved
+ * @return true if it looks ok
+ */
+ public boolean looksOK()
+ {
+ try {
+ String test = ExifReader.class.getName();
+ if (test != null) return true;
+ }
+ catch (LinkageError le) {}
+ return false;
+ }
+}