From fdff8bc8658c541d00aefdfa74ac9d61b1853eed Mon Sep 17 00:00:00 2001 From: Earl Ou Date: Fri, 5 Oct 2012 15:22:33 +0800 Subject: Use exiftool as ground truth for Exif API test The ground truth XML file was generated by parsing the output from Phil Harvey's exiftool. Then we can test photos from 5000+ different camera provided by exiftool's website. Change-Id: Ida2c0409929be450a3cbb4331504aadb41138bea --- .../com/android/gallery3d/exif/ExifParserTest.java | 61 ++++------- .../com/android/gallery3d/exif/ExifReaderTest.java | 26 +++-- .../com/android/gallery3d/exif/ExifXmlReader.java | 119 +++++++++++---------- 3 files changed, 97 insertions(+), 109 deletions(-) (limited to 'tests/src/com/android/gallery3d') diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java index c1ad8341b..8d4bc3db3 100644 --- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifParserTest.java @@ -16,21 +16,18 @@ package com.android.gallery3d.exif; -import android.content.res.XmlResourceParser; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ExifParserTest extends ExifXmlDataTestCase { private static final String TAG = "ExifParserTest"; - private HashMap mIfd0Value = new HashMap(); - private HashMap mIfd1Value = new HashMap(); - private HashMap mExifIfdValue = new HashMap(); - private HashMap mInteroperabilityIfdValue = new HashMap(); + private List> mGroundTruth; private InputStream mImageInputStream; @@ -43,12 +40,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { mImageInputStream = getInstrumentation() .getContext().getResources().openRawResource(mImageResourceId); - XmlResourceParser parser = - getInstrumentation().getContext().getResources().getXml(mXmlResourceId); - - ExifXmlReader.readXml(parser, mIfd0Value, mIfd1Value, mExifIfdValue - , mInteroperabilityIfdValue); - parser.close(); + mGroundTruth = ExifXmlReader.readXml(getInstrumentation().getContext(), mXmlResourceId); } public void testParse() throws IOException, ExifInvalidFormatException { @@ -80,33 +72,25 @@ public class ExifParserTest extends ExifXmlDataTestCase { } } + private void checkTag(ExifTag tag) { - HashMap truth = null; - switch (tag.getIfd()) { - case IfdId.TYPE_IFD_0: - truth = mIfd0Value; - break; - case IfdId.TYPE_IFD_1: - truth = mIfd1Value; - break; - case IfdId.TYPE_IFD_EXIF: - truth = mExifIfdValue; - break; - case IfdId.TYPE_IFD_INTEROPERABILITY: - truth = mInteroperabilityIfdValue; - break; - } + // Ignore offset tags since the ground-truth from exiftool doesn't have it. + // We can verify it by examining the sub-IFD or thumbnail itself. + if (ExifTag.isSubIfdOffsetTag(tag.getTagId())) return; + + String truthString = mGroundTruth.get(tag.getIfd()).get(tag.getTagId()); - String truthString = truth.get(tag.getTagId()); - String dataString = tag.valueToString().trim(); if (truthString == null) { fail(String.format("Unknown Tag %02x", tag.getTagId())); } + + String dataString = tag.valueToString().trim(); assertEquals(String.format("Tag %02x", tag.getTagId()), truthString, dataString); } - private void parseOneIfd(int ifd, int options, HashMap expectedResult) + private void parseOneIfd(int ifd, int options) throws IOException, ExifInvalidFormatException { + Map expectedResult = mGroundTruth.get(ifd); int numOfTag = 0; ExifParser parser = ExifParser.parse(mImageInputStream, options); int event = parser.next(); @@ -116,8 +100,8 @@ public class ExifParserTest extends ExifXmlDataTestCase { assertEquals(ifd, parser.getCurrentIfd()); break; case ExifParser.EVENT_NEW_TAG: - numOfTag++; ExifTag tag = parser.getTag(); + if (!ExifTag.isSubIfdOffsetTag(tag.getTagId())) numOfTag++; if (tag.hasValue()) { checkTag(tag); } else { @@ -144,20 +128,19 @@ public class ExifParserTest extends ExifXmlDataTestCase { } public void testOnlyExifIfd() throws IOException, ExifInvalidFormatException { - parseOneIfd(IfdId.TYPE_IFD_EXIF, ExifParser.OPTION_IFD_EXIF, mExifIfdValue); + parseOneIfd(IfdId.TYPE_IFD_EXIF, ExifParser.OPTION_IFD_EXIF); } public void testOnlyIfd0() throws IOException, ExifInvalidFormatException { - parseOneIfd(IfdId.TYPE_IFD_0, ExifParser.OPTION_IFD_0, mIfd0Value); + parseOneIfd(IfdId.TYPE_IFD_0, ExifParser.OPTION_IFD_0); } public void testOnlyIfd1() throws IOException, ExifInvalidFormatException { - parseOneIfd(IfdId.TYPE_IFD_1, ExifParser.OPTION_IFD_1, mIfd1Value); + parseOneIfd(IfdId.TYPE_IFD_1, ExifParser.OPTION_IFD_1); } public void testOnlyInteroperabilityIfd() throws IOException, ExifInvalidFormatException { - parseOneIfd(IfdId.TYPE_IFD_INTEROPERABILITY, ExifParser.OPTION_IFD_INTEROPERABILITY - , mInteroperabilityIfdValue); + parseOneIfd(IfdId.TYPE_IFD_INTEROPERABILITY, ExifParser.OPTION_IFD_INTEROPERABILITY); } public void testOnlyReadSomeTag() throws IOException, ExifInvalidFormatException { @@ -227,8 +210,6 @@ public class ExifParserTest extends ExifXmlDataTestCase { @Override protected void tearDown() throws IOException { mImageInputStream.close(); - mIfd0Value.clear(); - mIfd1Value.clear(); - mExifIfdValue.clear(); + mGroundTruth.clear(); } -} \ No newline at end of file +} diff --git a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java index 269120870..1300af0e9 100644 --- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java @@ -21,15 +21,13 @@ import android.graphics.BitmapFactory; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ExifReaderTest extends ExifXmlDataTestCase { private static final String TAG = "ExifReaderTest"; - private final HashMap mIfd0Value = new HashMap(); - private final HashMap mIfd1Value = new HashMap(); - private final HashMap mExifIfdValue = new HashMap(); - private final HashMap mInteroperabilityIfdValue = new HashMap(); + private List> mGroundTruth; private InputStream mImageInputStream; @@ -45,19 +43,16 @@ public class ExifReaderTest extends ExifXmlDataTestCase { XmlResourceParser parser = getInstrumentation().getContext().getResources().getXml(mXmlResourceId); - ExifXmlReader.readXml(parser, mIfd0Value, mIfd1Value, mExifIfdValue - , mInteroperabilityIfdValue); + mGroundTruth = ExifXmlReader.readXml(getInstrumentation().getContext(), mXmlResourceId); parser.close(); } public void testRead() throws ExifInvalidFormatException, IOException { ExifReader reader = new ExifReader(); ExifData exifData = reader.read(mImageInputStream); - checkIfd(exifData.getIfdData(IfdId.TYPE_IFD_0), mIfd0Value); - checkIfd(exifData.getIfdData(IfdId.TYPE_IFD_1), mIfd1Value); - checkIfd(exifData.getIfdData(IfdId.TYPE_IFD_EXIF), mExifIfdValue); - checkIfd(exifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY), - mInteroperabilityIfdValue); + for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { + checkIfd(exifData.getIfdData(i), mGroundTruth.get(i)); + } checkThumbnail(exifData); } @@ -115,16 +110,19 @@ public class ExifReaderTest extends ExifXmlDataTestCase { } } - private void checkIfd(IfdData ifd, HashMap ifdValue) { + private void checkIfd(IfdData ifd, Map ifdValue) { if (ifd == null) { assertEquals(0 ,ifdValue.size()); return; } ExifTag[] tags = ifd.getAllTags(); + int size = 0; for (ExifTag tag : tags) { + if (ExifTag.isSubIfdOffsetTag(tag.getTagId())) continue; assertEquals(ifdValue.get(tag.getTagId()), tag.valueToString().trim()); + size++; } - assertEquals(ifdValue.size(), tags.length); + assertEquals(ifdValue.size(), size); } @Override diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java index 72dd31373..8e2ad3f30 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java @@ -16,82 +16,91 @@ package com.android.gallery3d.exif; +import android.content.Context; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ExifXmlReader { + private static final String TAG_EXIF = "exif"; + private static final String TAG_TAG = "tag"; + + private static final String IFD0 = "IFD0"; + private static final String EXIF_IFD = "ExifIFD"; + private static final String GPS_IFD = "GPS"; + private static final String IFD1 = "IFD1"; + private static final String PREFIX_INTEROP_IFD = "InteropIFD"; + + private static final String ATTR_ID = "id"; + private static final String ATTR_IFD = "ifd"; - private static final String XML_EXIF_TAG = "exif"; - private static final String XML_IFD_TAG = "ifd"; - private static final String XML_IFD_NAME = "name"; - private static final String XML_TAG = "tag"; - private static final String XML_IFD0 = "ifd0"; - private static final String XML_IFD1 = "ifd1"; - private static final String XML_EXIF_IFD = "exif-ifd"; - private static final String XML_INTEROPERABILITY_IFD = "interoperability-ifd"; - private static final String XML_TAG_ID = "id"; - - public static void readXml(XmlPullParser parser, HashMap ifd0, - HashMap ifd1, HashMap exifIfd, - HashMap interoperabilityIfd) throws XmlPullParserException, - IOException { + /** + * This function read the ground truth XML. + * + * @throws XmlPullParserException + * @throws IOException + */ + static public List> readXml(Context context, int xmlResId) + throws XmlPullParserException, IOException { + XmlPullParser parser = context.getResources().getXml(xmlResId); + + List> exifData = + new ArrayList>(IfdId.TYPE_IFD_COUNT); + for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { + exifData.add(new HashMap()); + } while (parser.next() != XmlPullParser.END_DOCUMENT) { if (parser.getEventType() == XmlPullParser.START_TAG) { break; } } + parser.require(XmlPullParser.START_TAG, null, TAG_EXIF); - assert(parser.getName().equals(XML_EXIF_TAG)); - - parser.require(XmlPullParser.START_TAG, null, XML_EXIF_TAG); while (parser.next() != XmlPullParser.END_TAG) { - if (parser.getEventType() == XmlPullParser.START_TAG) { - readXmlIfd(parser, ifd0, ifd1, exifIfd, interoperabilityIfd); + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; } - } - parser.require(XmlPullParser.END_TAG, null, XML_EXIF_TAG); - } - private static void readXmlIfd(XmlPullParser parser, HashMap ifd0, - HashMap ifd1, HashMap exifIfd, - HashMap interoperabilityIfd) throws XmlPullParserException, - IOException { - parser.require(XmlPullParser.START_TAG, null, XML_IFD_TAG); - String name = parser.getAttributeValue(null, XML_IFD_NAME); - HashMap ifdData = null; - if (XML_IFD0.equals(name)) { - ifdData = ifd0; - } else if (XML_IFD1.equals(name)) { - ifdData = ifd1; - } else if (XML_EXIF_IFD.equals(name)) { - ifdData = exifIfd; - } else if (XML_INTEROPERABILITY_IFD.equals(name)) { - ifdData = interoperabilityIfd; - } else { - throw new RuntimeException("Unknown IFD name in xml file: " + name); - } - while (parser.next() != XmlPullParser.END_TAG) { - if (parser.getEventType() == XmlPullParser.START_TAG) { - readXmlTag(parser, ifdData); + parser.require(XmlPullParser.START_TAG, null, TAG_TAG); + + int ifdId = getIfdIdFromString(parser.getAttributeValue(null, ATTR_IFD)); + short id = Integer.decode(parser.getAttributeValue(null, ATTR_ID)).shortValue(); + + String value = ""; + if (parser.next() == XmlPullParser.TEXT) { + value = parser.getText(); + parser.next(); } + + exifData.get(ifdId).put(id, value); + + parser.require(XmlPullParser.END_TAG, null, null); } - parser.require(XmlPullParser.END_TAG, null, XML_IFD_TAG); + return exifData; } - private static void readXmlTag(XmlPullParser parser, HashMap data) - throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, null, XML_TAG); - short id = Integer.decode(parser.getAttributeValue(null, XML_TAG_ID)).shortValue(); - String value = ""; - if (parser.next() == XmlPullParser.TEXT) { - value = parser.getText(); - parser.next(); + static private int getIfdIdFromString(String prefix) { + if (IFD0.equals(prefix)) { + return IfdId.TYPE_IFD_0; + } else if (EXIF_IFD.equals(prefix)) { + return IfdId.TYPE_IFD_EXIF; + } else if (GPS_IFD.equals(prefix)) { + return IfdId.TYPE_IFD_GPS; + } else if (IFD1.equals(prefix)) { + return IfdId.TYPE_IFD_1; + } else if (PREFIX_INTEROP_IFD.equals(prefix)) { + return IfdId.TYPE_IFD_INTEROPERABILITY; + } else { + assert(false); + return -1; } - data.put(id, value); - parser.require(XmlPullParser.END_TAG, null, XML_TAG); } -} \ No newline at end of file +} -- cgit v1.2.3