1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
package tim.prune.jpeg;
import java.io.File;
import com.drew.imaging.ImageMetadataReader;
import com.drew.lang.Rational;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifReader;
import com.drew.metadata.exif.ExifThumbnailDirectory;
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 GpsPrune).
* 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 = ImageMetadataReader.readMetadata(inFile);
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);
double seconds = ExifGateway.convertToPositiveValue(latRats[2].getNumerator(), latRats[2].getDenominator());
data.setLatitude(new double[] {latRats[0].doubleValue(),
latRats[1].doubleValue(), seconds});
data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF));
Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
seconds = ExifGateway.convertToPositiveValue(lonRats[2].getNumerator(), lonRats[2].getDenominator());
data.setLongitude(new double[] {lonRats[0].doubleValue(),
lonRats[1].doubleValue(), seconds});
}
// 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);
if (dates != null) {
data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
}
}
// Image bearing (if present)
if (gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION_REF))
{
Rational bearing = gpsdir.getRational(GpsDirectory.TAG_GPS_IMG_DIRECTION);
if (bearing != null) {
data.setBearing(bearing.doubleValue());
}
}
}
// Tags from Exif directory
if (metadata.containsDirectory(ExifSubIFDDirectory.class))
{
Directory exifdir = metadata.getDirectory(ExifSubIFDDirectory.class);
// Take time and date from exif tags
if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)) {
data.setOriginalTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL));
}
// Also take "digitized" timestamp
if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED)) {
data.setDigitizedTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED));
}
}
if (metadata.containsDirectory(ExifIFD0Directory.class))
{
Directory exifdir = metadata.getDirectory(ExifIFD0Directory.class);
// Photo rotation code
if (exifdir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
data.setOrientationCode(exifdir.getInt(ExifIFD0Directory.TAG_ORIENTATION));
// NOTE: this presumably takes the _last_ orientation value found, not the first.
}
}
if (metadata.containsDirectory(ExifThumbnailDirectory.class))
{
ExifThumbnailDirectory exifdir = metadata.getDirectory(ExifThumbnailDirectory.class);
// TODO: Check this thumbnail stuff
if (exifdir.hasThumbnailData())
{
// Make a copy of the byte data
byte[] tdata = exifdir.getThumbnailData();
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
//System.err.println("Error: " + e.getClass().getName() + " - " + e.getMessage());
}
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;
}
}
|