Fields Summary |
---|
public static final String | TAG_ORIENTATIONType is int. |
public static final String | TAG_DATETIMEType is String. |
public static final String | TAG_MAKEType is String. |
public static final String | TAG_MODELType is String. |
public static final String | TAG_FLASHType is int. |
public static final String | TAG_IMAGE_WIDTHType is int. |
public static final String | TAG_IMAGE_LENGTHType is int. |
public static final String | TAG_GPS_LATITUDEString. Format is "num1/denom1,num2/denom2,num3/denom3". |
public static final String | TAG_GPS_LONGITUDEString. Format is "num1/denom1,num2/denom2,num3/denom3". |
public static final String | TAG_GPS_LATITUDE_REFType is String. |
public static final String | TAG_GPS_LONGITUDE_REFType is String. |
public static final String | TAG_EXPOSURE_TIMEType is String. |
public static final String | TAG_APERTUREType is String. |
public static final String | TAG_ISOType is String. |
public static final String | TAG_GPS_ALTITUDEThe altitude (in meters) based on the reference in TAG_GPS_ALTITUDE_REF.
Type is rational. |
public static final String | TAG_GPS_ALTITUDE_REF0 if the altitude is above sea level. 1 if the altitude is below sea
level. Type is int. |
public static final String | TAG_GPS_TIMESTAMPType is String. |
public static final String | TAG_GPS_DATESTAMPType is String. |
public static final String | TAG_WHITE_BALANCEType is int. |
public static final String | TAG_FOCAL_LENGTHType is rational. |
public static final String | TAG_GPS_PROCESSING_METHODType is String. Name of GPS processing method used for location finding. |
public static final int | ORIENTATION_UNDEFINED |
public static final int | ORIENTATION_NORMAL |
public static final int | ORIENTATION_FLIP_HORIZONTAL |
public static final int | ORIENTATION_ROTATE_180 |
public static final int | ORIENTATION_FLIP_VERTICAL |
public static final int | ORIENTATION_TRANSPOSE |
public static final int | ORIENTATION_ROTATE_90 |
public static final int | ORIENTATION_TRANSVERSE |
public static final int | ORIENTATION_ROTATE_270 |
public static final int | WHITEBALANCE_AUTO |
public static final int | WHITEBALANCE_MANUAL |
private static SimpleDateFormat | sFormatter |
private String | mFilename |
private HashMap | mAttributes |
private boolean | mHasThumbnail |
private static final Object | sLock |
Methods Summary |
---|
private native boolean | appendThumbnailNative(java.lang.String fileName, java.lang.String thumbnailFileName)
|
private native void | commitChangesNative(java.lang.String fileName)
|
private static float | convertRationalLatLonToFloat(java.lang.String rationalString, java.lang.String ref)
try {
String [] parts = rationalString.split(",");
String [] pair;
pair = parts[0].split("/");
double degrees = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[1].split("/");
double minutes = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[2].split("/");
double seconds = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
if ((ref.equals("S") || ref.equals("W"))) {
return (float) -result;
}
return (float) result;
} catch (NumberFormatException e) {
// Some of the nubmers are not valid
throw new IllegalArgumentException();
} catch (ArrayIndexOutOfBoundsException e) {
// Some of the rational does not follow the correct format
throw new IllegalArgumentException();
}
|
public double | getAltitude(double defaultValue)Return the altitude in meters. If the exif tag does not exist, return
defaultValue.
double altitude = getAttributeDouble(TAG_GPS_ALTITUDE, -1);
int ref = getAttributeInt(TAG_GPS_ALTITUDE_REF, -1);
if (altitude >= 0 && ref >= 0) {
return (double) (altitude * ((ref == 1) ? -1 : 1));
} else {
return defaultValue;
}
|
public java.lang.String | getAttribute(java.lang.String tag)Returns the value of the specified tag or {@code null} if there
is no such tag in the JPEG file.
return mAttributes.get(tag);
|
public double | getAttributeDouble(java.lang.String tag, double defaultValue)Returns the double value of the specified rational tag. If there is no
such tag in the JPEG file or the value cannot be parsed as double, return
defaultValue.
String value = mAttributes.get(tag);
if (value == null) return defaultValue;
try {
int index = value.indexOf("/");
if (index == -1) return defaultValue;
double denom = Double.parseDouble(value.substring(index + 1));
if (denom == 0) return defaultValue;
double num = Double.parseDouble(value.substring(0, index));
return num / denom;
} catch (NumberFormatException ex) {
return defaultValue;
}
|
public int | getAttributeInt(java.lang.String tag, int defaultValue)Returns the integer value of the specified tag. If there is no such tag
in the JPEG file or the value cannot be parsed as integer, return
defaultValue.
String value = mAttributes.get(tag);
if (value == null) return defaultValue;
try {
return Integer.valueOf(value);
} catch (NumberFormatException ex) {
return defaultValue;
}
|
private native java.lang.String | getAttributesNative(java.lang.String fileName)
|
public long | getDateTime()Returns number of milliseconds since Jan. 1, 1970, midnight.
Returns -1 if the date time information if not available.
String dateTimeString = mAttributes.get(TAG_DATETIME);
if (dateTimeString == null) return -1;
ParsePosition pos = new ParsePosition(0);
try {
Date datetime = sFormatter.parse(dateTimeString, pos);
if (datetime == null) return -1;
return datetime.getTime();
} catch (IllegalArgumentException ex) {
return -1;
}
|
public long | getGpsDateTime()Returns number of milliseconds since Jan. 1, 1970, midnight UTC.
Returns -1 if the date time information if not available.
String date = mAttributes.get(TAG_GPS_DATESTAMP);
String time = mAttributes.get(TAG_GPS_TIMESTAMP);
if (date == null || time == null) return -1;
String dateTimeString = date + ' " + time;
if (dateTimeString == null) return -1;
ParsePosition pos = new ParsePosition(0);
try {
Date datetime = sFormatter.parse(dateTimeString, pos);
if (datetime == null) return -1;
return datetime.getTime();
} catch (IllegalArgumentException ex) {
return -1;
}
|
public boolean | getLatLong(float[] output)Stores the latitude and longitude value in a float array. The first element is
the latitude, and the second element is the longitude. Returns false if the
Exif tags are not available.
String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
try {
output[0] = convertRationalLatLonToFloat(latValue, latRef);
output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
return true;
} catch (IllegalArgumentException e) {
// if values are not parseable
}
}
return false;
|
public byte[] | getThumbnail()Returns the thumbnail inside the JPEG file, or {@code null} if there is no thumbnail.
The returned data is in JPEG format and can be decoded using
{@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)}
synchronized (sLock) {
return getThumbnailNative(mFilename);
}
|
private native byte[] | getThumbnailNative(java.lang.String fileName)
|
public long[] | getThumbnailRange()Returns the offset and length of thumbnail inside the JPEG file, or
{@code null} if there is no thumbnail.
synchronized (sLock) {
return getThumbnailRangeNative(mFilename);
}
|
private native long[] | getThumbnailRangeNative(java.lang.String fileName)
|
public boolean | hasThumbnail()Returns true if the JPEG file has a thumbnail.
return mHasThumbnail;
|
private void | loadAttributes()Initialize mAttributes with the attributes from the file mFilename.
mAttributes is a HashMap which stores the Exif attributes of the file.
The key is the standard tag name and the value is the tag's value: e.g.
Model -> Nikon. Numeric values are stored as strings.
This function also initialize mHasThumbnail to indicate whether the
file has a thumbnail inside.
// format of string passed from native C code:
// "attrCnt attr1=valueLen value1attr2=value2Len value2..."
// example:
// "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
mAttributes = new HashMap<String, String>();
String attrStr;
synchronized (sLock) {
attrStr = getAttributesNative(mFilename);
}
// get count
int ptr = attrStr.indexOf(' ");
int count = Integer.parseInt(attrStr.substring(0, ptr));
// skip past the space between item count and the rest of the attributes
++ptr;
for (int i = 0; i < count; i++) {
// extract the attribute name
int equalPos = attrStr.indexOf('=", ptr);
String attrName = attrStr.substring(ptr, equalPos);
ptr = equalPos + 1; // skip past =
// extract the attribute value length
int lenPos = attrStr.indexOf(' ", ptr);
int attrLen = Integer.parseInt(attrStr.substring(ptr, lenPos));
ptr = lenPos + 1; // skip pas the space
// extract the attribute value
String attrValue = attrStr.substring(ptr, ptr + attrLen);
ptr += attrLen;
if (attrName.equals("hasThumbnail")) {
mHasThumbnail = attrValue.equalsIgnoreCase("true");
} else {
mAttributes.put(attrName, attrValue);
}
}
|
public void | saveAttributes()Save the tag data into the JPEG file. This is expensive because it involves
copying all the JPG data from one file to another and deleting the old file
and renaming the other. It's best to use {@link #setAttribute(String,String)}
to set all attributes to write and make a single call rather than multiple
calls for each attribute.
// format of string passed to native C code:
// "attrCnt attr1=valueLen value1attr2=value2Len value2..."
// example:
// "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
StringBuilder sb = new StringBuilder();
int size = mAttributes.size();
if (mAttributes.containsKey("hasThumbnail")) {
--size;
}
sb.append(size + " ");
for (Map.Entry<String, String> iter : mAttributes.entrySet()) {
String key = iter.getKey();
if (key.equals("hasThumbnail")) {
// this is a fake attribute not saved as an exif tag
continue;
}
String val = iter.getValue();
sb.append(key + "=");
sb.append(val.length() + " ");
sb.append(val);
}
String s = sb.toString();
synchronized (sLock) {
saveAttributesNative(mFilename, s);
commitChangesNative(mFilename);
}
|
private native void | saveAttributesNative(java.lang.String fileName, java.lang.String compressedAttributes)
|
public void | setAttribute(java.lang.String tag, java.lang.String value)Set the value of the specified tag.
mAttributes.put(tag, value);
|