]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/jpeg/ExternalExifLibrary.java
Version 13, August 2011
[GpsPrune.git] / tim / prune / jpeg / ExternalExifLibrary.java
1 package tim.prune.jpeg;
2
3 import java.io.File;
4
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;
12
13 /**
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).
20  */
21 public class ExternalExifLibrary implements ExifLibrary
22 {
23         /**
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
27          */
28         public JpegData getJpegData(File inFile)
29         {
30                 JpegData data = new JpegData();
31                 // Read exif data from picture
32                 try
33                 {
34                         Metadata metadata = new Metadata();
35                         new ExifReader(inFile).extract(metadata);
36                         if (metadata.containsDirectory(GpsDirectory.class))
37                         {
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))
43                                 {
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});
54                                 }
55
56                                 // Altitude (if present)
57                                 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF))
58                                 {
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);
62                                 }
63
64                                 try
65                                 {
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))
69                                         {
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);
74                                                 if (dates != null) {
75                                                         data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
76                                                 }
77                                         }
78                                 }
79                                 catch (MetadataException me) {} // ignore, use other tags instead
80
81                                 // Image bearing (if present)
82                                 if (gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION_REF))
83                                 {
84                                         Rational bearing = gpsdir.getRational(GpsDirectory.TAG_GPS_IMG_DIRECTION);
85                                         if (bearing != null) {
86                                                 data.setBearing(bearing.doubleValue());
87                                         }
88                                 }
89                         }
90
91                         // Tags from Exif directory
92                         if (metadata.containsDirectory(ExifDirectory.class))
93                         {
94                                 Directory exifdir = metadata.getDirectory(ExifDirectory.class);
95
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));
99                                 }
100                                 // Also take "digitized" timestamp
101                                 if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_DIGITIZED)) {
102                                         data.setDigitizedTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_DIGITIZED));
103                                 }
104
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.
109                                 }
110
111                                 // Thumbnail
112                                 if (exifdir.containsTag(ExifDirectory.TAG_THUMBNAIL_DATA))
113                                 {
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);
119                                 }
120                         }
121
122                 }
123                 catch (Exception e) {
124                         // Exception reading metadata, just ignore it
125                         //System.err.println("Error: " + e.getClass().getName() + " - " + e.getMessage());
126                 }
127                 return data;
128         }
129
130
131         /**
132          * Check whether the exifreader class can be correctly resolved
133          * @return true if it looks ok
134          */
135         public boolean looksOK()
136         {
137                 try {
138                         String test = ExifReader.class.getName();
139                         if (test != null) return true;
140                 }
141                 catch (LinkageError le) {}
142                 return false;
143         }
144 }