summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEarl Ou <shunhsingou@google.com>2012-10-19 16:50:34 +0800
committerEarl Ou <shunhsingou@google.com>2012-10-31 14:48:57 +0800
commitff0f96c07827c39df5a0b408a028e7198dc8294b (patch)
treefc3f0a9a10e5bd0528c991e0006972462dd0c554
parent4bc57f24b4ed268fdb5f0b67d3bc39f6a449b2f4 (diff)
downloadandroid_packages_apps_Snap-ff0f96c07827c39df5a0b408a028e7198dc8294b.tar.gz
android_packages_apps_Snap-ff0f96c07827c39df5a0b408a028e7198dc8294b.tar.bz2
android_packages_apps_Snap-ff0f96c07827c39df5a0b408a028e7198dc8294b.zip
Handle the last null byte in Exif tag.
Change-Id: Ic802810d11518dfeb80d1338db65b2e1e1cc8476
-rw-r--r--gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java3
-rw-r--r--gallerycommon/src/com/android/gallery3d/exif/ExifParser.java23
-rw-r--r--gallerycommon/src/com/android/gallery3d/exif/ExifTag.java77
3 files changed, 75 insertions, 28 deletions
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
index e5e776098..46cd65594 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
@@ -21,7 +21,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.nio.charset.Charset;
public class ExifOutputStream extends FilterOutputStream {
private static final String TAG = "ExifOutputStream";
@@ -216,7 +215,7 @@ public class ExifOutputStream extends FilterOutputStream {
throws IOException {
switch (tag.getDataType()) {
case ExifTag.TYPE_ASCII:
- byte buf[] = tag.getString().getBytes(Charset.forName("US-ASCII"));
+ byte buf[] = tag.getStringByte();
if (buf.length == tag.getComponentCount()) {
buf[buf.length - 1] = 0;
dataOutputStream.write(buf);
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
index edc8f190f..2f5c5438d 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
@@ -136,6 +136,8 @@ public class ExifParser {
private static final int TAG_SIZE = 12;
private static final int OFFSET_SIZE = 2;
+ private static final Charset US_ASCII = Charset.forName("US-ASCII");
+
private final CountedDataInputStream mTiffStream;
private final int mOptions;
private int mIfdStartOffset = 0;
@@ -665,26 +667,25 @@ public class ExifParser {
/**
* Reads a String from the InputStream with US-ASCII charset.
+ * The parser will read n bytes and convert it to ascii string.
* This is used for reading values of type {@link ExifTag#TYPE_ASCII}.
*/
public String readString(int n) throws IOException {
- if (n > 0) {
- byte[] buf = new byte[n];
- mTiffStream.readOrThrow(buf);
- return new String(buf, 0, n - 1, "US-ASCII");
- } else {
- return "";
- }
+ return readString(n, US_ASCII);
}
/**
* Reads a String from the InputStream with the given charset.
+ * The parser will read n bytes and convert it to string.
* This is used for reading values of type {@link ExifTag#TYPE_ASCII}.
*/
public String readString(int n, Charset charset) throws IOException {
- byte[] buf = new byte[n];
- mTiffStream.readOrThrow(buf);
- return new String(buf, 0, n - 1, charset);
+ if (n > 0) {
+ byte[] buf = new byte[n];
+ return mTiffStream.readString(n, charset);
+ } else {
+ return "";
+ }
}
/**
@@ -763,4 +764,4 @@ public class ExifParser {
public ByteOrder getByteOrder() {
return mTiffStream.getByteOrder();
}
-} \ No newline at end of file
+}
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java b/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
index 1592479e2..37b6d9fd0 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
@@ -18,6 +18,7 @@ package com.android.gallery3d.exif;
import android.util.SparseArray;
+import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@@ -833,6 +834,7 @@ public class ExifTag {
(IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_SHORT << 16 | 11);
}
+ private static Charset US_ASCII = Charset.forName("US-ASCII");
private final short mTagId;
private final short mDataType;
private final int mIfd;
@@ -970,6 +972,15 @@ public class ExifTag {
}
/**
+ * Sets the component count of this tag.
+ * Call this function before setValue() if the length of value does not
+ * match the component count.
+ */
+ public void setComponentCount(int count) {
+ mComponentCount = count;
+ }
+
+ /**
* Returns true if this ExifTag contains value; otherwise, this tag will contain an offset value
* that links to the area where the actual value is located.
*
@@ -1171,18 +1182,37 @@ public class ExifTag {
}
/**
- * Sets string values into this tag.
+ * Sets a string value into this tag. The value is treated as an ASCII string where we only
+ * preserve the lower byte of each character. The length of the string should be equal
+ * to either (component count -1) or (component count). A "0" byte will be appeneded while
+ * written to the EXIF file. If the length equals (component count), the final byte will be
+ * replaced by a "0" byte.
+ *
* @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII}
- * or value.length() + 1 does NOT fit the definition of the component count in the
- * EXIF standard.
+ * or the length of the string is not equal to (component count -1) and (component count)
*/
public void setValue(String value) {
- checkComponentCountOrThrow(value.length() + 1);
if (mDataType != TYPE_ASCII) {
throwTypeNotMatchedException("String");
}
- mComponentCount = value.length() + 1;
- mValue = value;
+
+ byte[] buf = new byte[value.length()];
+ for (int i = 0, n = value.length(); i < n; i++) {
+ buf[i] = (byte) value.charAt(i);
+ }
+
+ int count = buf.length;
+ if (mComponentCountDefined) {
+ if (mComponentCount != count && mComponentCount != count + 1) {
+ throw new IllegalArgumentException("Tag " + mTagId + ": Required "
+ + mComponentCount + " or " + (mComponentCount + 1)
+ + " components but was given " + count
+ + " component(s)");
+ }
+ } else {
+ mComponentCount = buf[count - 1] == 0 ? count : count + 1;
+ }
+ mValue = buf;
}
/**
@@ -1311,7 +1341,14 @@ public class ExifTag {
throw new IllegalArgumentException("Cannot get ASCII value from "
+ convertTypeToString(mDataType));
}
- return (String) mValue;
+ return new String((byte[]) mValue, US_ASCII);
+ }
+
+ /*
+ * Get the converted ascii byte. Used by ExifOutputStream.
+ */
+ byte[] getStringByte() {
+ return (byte[]) mValue;
}
/**
@@ -1356,18 +1393,28 @@ public class ExifTag {
private String undefinedTypeValueToString() {
StringBuilder sbuilder = new StringBuilder();
+ byte buf[] = (byte[]) mValue;
switch (mTagId) {
case TAG_COMPONENTS_CONFIGURATION:
- case TAG_FILE_SOURCE:
- case TAG_SCENE_TYPE:
- byte buf[] = (byte[]) mValue;
for(int i = 0, n = getComponentCount(); i < n; i++) {
if(i != 0) sbuilder.append(" ");
sbuilder.append(buf[i]);
}
break;
default:
- sbuilder.append(new String((byte[]) mValue));
+ if (buf.length == 1) {
+ sbuilder.append(buf[0]);
+ } else {
+ for (int i = 0, n = buf.length; i < n; i++) {
+ byte code = buf[i];
+ if (code == 0) continue;
+ if (code > 31 && code < 127) {
+ sbuilder.append((char) code);
+ } else {
+ sbuilder.append('.');
+ }
+ }
+ }
}
return sbuilder.toString();
}
@@ -1389,10 +1436,10 @@ public class ExifTag {
}
break;
case ExifTag.TYPE_ASCII:
- String s = getString();
- for (int i = 0, n = s.length(); i < n; i++) {
- int code = s.codePointAt(i);
- if (code == 0) continue;
+ buf = (byte[]) mValue;
+ for (int i = 0, n = buf.length; i < n; i++) {
+ byte code = buf[i];
+ if (code == 0) break;
if (code > 31 && code < 127) {
sbuilder.append((char) code);
} else {