]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/jpeg/ExternalExifLibrary.java
Version 18.6, December 2016
[GpsPrune.git] / tim / prune / jpeg / ExternalExifLibrary.java
1 package tim.prune.jpeg;
2
3 import java.io.File;
4
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;
14
15 /**
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).
22  */
23 public class ExternalExifLibrary implements ExifLibrary
24 {
25         /**
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
29          */
30         public JpegData getJpegData(File inFile)
31         {
32                 JpegData data = new JpegData();
33                 // Read exif data from picture
34                 try
35                 {
36                         Metadata metadata = ImageMetadataReader.readMetadata(inFile);
37                         if (metadata.containsDirectory(GpsDirectory.class))
38                         {
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))
44                                 {
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});
55                                 }
56
57                                 // Altitude (if present)
58                                 if (gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE_REF))
59                                 {
60                                         data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_ALTITUDE).intValue());
61                                         byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_ALTITUDE_REF);
62                                         data.setAltitudeRef(altRef);
63                                 }
64
65                                 // Timestamp and datestamp (if present)
66                                 final int TAG_DATESTAMP = 0x001d;
67                                 if (gpsdir.containsTag(GpsDirectory.TAG_TIME_STAMP) && gpsdir.containsTag(TAG_DATESTAMP))
68                                 {
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);
73                                         if (dates != null) {
74                                                 data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
75                                         }
76                                 }
77
78                                 // Image bearing (if present)
79                                 if (gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION_REF))
80                                 {
81                                         Rational bearing = gpsdir.getRational(GpsDirectory.TAG_IMG_DIRECTION);
82                                         if (bearing != null) {
83                                                 data.setBearing(bearing.doubleValue());
84                                         }
85                                 }
86                         }
87
88                         // Tags from Exif directory
89                         if (metadata.containsDirectory(ExifSubIFDDirectory.class))
90                         {
91                                 Directory exifdir = metadata.getDirectory(ExifSubIFDDirectory.class);
92
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));
96                                 }
97                                 // Also take "digitized" timestamp
98                                 if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED)) {
99                                         data.setDigitizedTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED));
100                                 }
101                         }
102                         if (metadata.containsDirectory(ExifIFD0Directory.class))
103                         {
104                                 Directory exifdir = metadata.getDirectory(ExifIFD0Directory.class);
105
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.
110                                 }
111                         }
112
113                         if (metadata.containsDirectory(ExifThumbnailDirectory.class))
114                         {
115                                 ExifThumbnailDirectory exifdir = metadata.getDirectory(ExifThumbnailDirectory.class);
116
117                                 // TODO: Check this thumbnail stuff
118                                 if (exifdir.hasThumbnailData())
119                                 {
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);
125                                 }
126                         }
127
128                 }
129                 catch (Exception e) {
130                         // Exception reading metadata, just ignore it
131                         //System.err.println("Error: " + e.getClass().getName() + " - " + e.getMessage());
132                 }
133                 return data;
134         }
135
136
137         /**
138          * Check whether the exifreader class can be correctly resolved
139          * @return true if it looks ok
140          */
141         public boolean looksOK()
142         {
143                 try {
144                         String test = ExifReader.class.getName();
145                         if (test != null) return true;
146                 }
147                 catch (LinkageError le) {}
148                 return false;
149         }
150 }