From d1e20d2c7a25335bf48a125a08fde820714326d4 Mon Sep 17 00:00:00 2001 From: Jaesung Chung Date: Tue, 15 Mar 2016 12:01:06 +0900 Subject: [PATCH] ExifInterface: fix writing STRING and SRATIONAL formats This CL makes ExifInterface determine the data format of rational numbers and the values which include several components for exif entry correctly. Bug: 27614052 Change-Id: Ic3ea64889fad06ef5f636e4635ab7803a9c9ae29 --- media/java/android/media/ExifInterface.java | 42 +++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index e35fcf62f6af3..9d7fbc3482a1d 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -1995,6 +1995,12 @@ public class ExifInterface { int bytesWritten = 0; int dataFormat = getDataFormatOfExifEntryValue(entryValue); + if (dataFormat == IFD_FORMAT_STRING) { + byte[] asciiArray = (entryValue + '\0').getBytes(Charset.forName("US-ASCII")); + dataOutputStream.write(asciiArray); + return asciiArray.length; + } + // Values can be composed of several components. Each component is separated by char ','. String[] components = entryValue.split(","); for (String component : components) { @@ -2007,11 +2013,6 @@ public class ExifInterface { dataOutputStream.writeDouble(Double.parseDouble(component)); bytesWritten += 8; break; - case IFD_FORMAT_STRING: - byte[] asciiArray = (component + '\0').getBytes(Charset.forName("US-ASCII")); - dataOutputStream.write(asciiArray); - bytesWritten += asciiArray.length; - break; case IFD_FORMAT_SRATIONAL: String[] rationalNumber = component.split("/"); dataOutputStream.writeInt(Integer.parseInt(rationalNumber[0])); @@ -2030,11 +2031,31 @@ public class ExifInterface { // See TIFF 6.0 spec Types. page 15. // Take the first component if there are more than one component. if (entryValue.contains(",")) { - entryValue = entryValue.split(",")[0]; + String[] entryValues = entryValue.split(","); + int dataFormat = getDataFormatOfExifEntryValue(entryValues[0]); + if (dataFormat == IFD_FORMAT_STRING) { + return IFD_FORMAT_STRING; + } + for (int i = 1; i < entryValues.length; ++i) { + if (getDataFormatOfExifEntryValue(entryValues[i]) != dataFormat) { + return IFD_FORMAT_STRING; + } + } + return dataFormat; } if (entryValue.contains("/")) { - return IFD_FORMAT_SRATIONAL; + String[] rationalNumber = entryValue.split("/"); + if (rationalNumber.length == 2) { + try { + Integer.parseInt(rationalNumber[0]); + Integer.parseInt(rationalNumber[1]); + return IFD_FORMAT_SRATIONAL; + } catch (NumberFormatException e) { + // Ignored + } + } + return IFD_FORMAT_STRING; } try { Integer.parseInt(entryValue); @@ -2054,6 +2075,9 @@ public class ExifInterface { // Determines the size of EXIF entry value. private static int getSizeOfExifEntryValue(int dataFormat, String entryValue) { // See TIFF 6.0 spec Types page 15. + if (dataFormat == IFD_FORMAT_STRING) { + return (entryValue + '\0').getBytes(Charset.forName("US-ASCII")).length; + } int bytesEstimated = 0; String[] components = entryValue.split(","); for (String component : components) { @@ -2064,10 +2088,6 @@ public class ExifInterface { case IFD_FORMAT_DOUBLE: bytesEstimated += 8; break; - case IFD_FORMAT_STRING: - bytesEstimated - += (component + '\0').getBytes(Charset.forName("US-ASCII")).length; - break; case IFD_FORMAT_SRATIONAL: bytesEstimated += 8; break;