diff options
-rw-r--r-- | AndroidManifest.xml | 11 | ||||
-rw-r--r-- | src/com/android/gallery3d/app/SlideshowDream.java | 22 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifData.java | 36 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifTag.java | 45 | ||||
-rw-r--r-- | tests/res/xml/galaxy_nexus.xml | 86 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java | 82 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifParserTest.java | 336 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifReaderTest.java | 90 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifTestRunner.java | 48 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java | 65 | ||||
-rw-r--r-- | tests/src/com/android/gallery3d/exif/ExifXmlReader.java | 126 |
11 files changed, 579 insertions, 368 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 88981d175..be6408d6b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -267,6 +267,17 @@ <uses-library android:name="com.google.android.media.effects" android:required="false" /> + <activity android:name="com.android.gallery3d.app.SlideshowDream" + android:label="@string/slideshow_dream_name" + android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" + android:hardwareAccelerated="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.DREAM" /> + </intent-filter> + </activity> + <activity android:name="com.android.gallery3d.settings.GallerySettings" android:theme="@style/Theme.Gallery" android:configChanges="orientation|keyboardHidden|screenSize" /> diff --git a/src/com/android/gallery3d/app/SlideshowDream.java b/src/com/android/gallery3d/app/SlideshowDream.java new file mode 100644 index 000000000..9963da688 --- /dev/null +++ b/src/com/android/gallery3d/app/SlideshowDream.java @@ -0,0 +1,22 @@ +package com.android.gallery3d.app; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v13.dreams.BasicDream; + +public class SlideshowDream extends BasicDream { + @Override + public void onCreate(Bundle bndl) { + super.onCreate(bndl); + Intent i = new Intent( + Intent.ACTION_VIEW, + android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI) +// Uri.fromFile(Environment.getExternalStoragePublicDirectory( +// Environment.DIRECTORY_PICTURES))) + .putExtra(Gallery.EXTRA_SLIDESHOW, true) + .putExtra(Gallery.EXTRA_DREAM, true) + .setFlags(getIntent().getFlags()); + startActivity(i); + finish(); + } +} diff --git a/src/com/android/gallery3d/exif/ExifData.java b/src/com/android/gallery3d/exif/ExifData.java index 39eb57455..7f7971384 100644 --- a/src/com/android/gallery3d/exif/ExifData.java +++ b/src/com/android/gallery3d/exif/ExifData.java @@ -216,7 +216,8 @@ public class ExifData { } /** - * Adds a tag with the given tag ID. The original tag will be replaced by the new tag. For tags + * Adds a tag with the given tag ID. If the tag of the given ID already exists, + * the original tag will be returned. Otherwise, a new ExifTag will be created. For tags * related to interoperability or thumbnail, call {@link #addInteroperabilityTag(short)} or * {@link #addThumbnailTag(short)} respectively. * @exception IllegalArgumentException if the tag ID is invalid. @@ -224,32 +225,43 @@ public class ExifData { public ExifTag addTag(short tagId) { int ifdId = ExifTag.getIfdIdFromTagId(tagId); IfdData ifdData = getOrCreateIfdData(ifdId); - ExifTag tag = ExifTag.buildTag(tagId); - ifdData.setTag(tag); + ExifTag tag = ifdData.getTag(tagId); + if (tag == null) { + tag = ExifTag.buildTag(tagId); + ifdData.setTag(tag); + } return tag; } /** - * Adds a thumbnail-related tag with the given tag ID. The original tag will be replaced - * by the new tag. + * Adds a thumbnail-related tag with the given tag ID. If the tag of the given ID + * already exists, the original tag will be returned. Otherwise, a new ExifTag will + * be created. * @exception IllegalArgumentException if the tag ID is invalid. */ public ExifTag addThumbnailTag(short tagId) { IfdData ifdData = getOrCreateIfdData(IfdId.TYPE_IFD_1); - ExifTag tag = ExifTag.buildThumbnailTag(tagId); - ifdData.setTag(tag); + ExifTag tag = ifdData.getTag(tagId); + if (tag == null) { + tag = ExifTag.buildThumbnailTag(tagId); + ifdData.setTag(tag); + } return tag; } /** - * Adds an interoperability-related tag with the given tag ID. The original tag will be - * replaced by the new tag. + * Adds an interoperability-related tag with the given tag ID. If the tag of the given ID + * already exists, the original tag will be returned. Otherwise, a new ExifTag will + * be created. * @exception IllegalArgumentException if the tag ID is invalid. */ public ExifTag addInteroperabilityTag(short tagId) { IfdData ifdData = getOrCreateIfdData(IfdId.TYPE_IFD_INTEROPERABILITY); - ExifTag tag = ExifTag.buildInteroperabilityTag(tagId); - ifdData.setTag(tag); + ExifTag tag = ifdData.getTag(tagId); + if (tag == null) { + tag = ExifTag.buildInteroperabilityTag(tagId); + ifdData.setTag(tag); + } return tag; } @@ -258,4 +270,4 @@ public class ExifData { mStripBytes.clear(); mIfdDatas[IfdId.TYPE_IFD_1] = null; } -}
\ No newline at end of file +} diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/src/com/android/gallery3d/exif/ExifTag.java index 49cb6edbc..def80a939 100644 --- a/src/com/android/gallery3d/exif/ExifTag.java +++ b/src/com/android/gallery3d/exif/ExifTag.java @@ -1354,23 +1354,51 @@ public class ExifTag { (length > mComponentCount) ? mComponentCount : length); } + private String undefinedTypeValueToString() { + StringBuilder sbuilder = new StringBuilder(); + 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)); + } + return sbuilder.toString(); + } + /** * Returns a string representation of the value of this tag. */ - public String valueToString() { + String valueToString() { StringBuilder sbuilder = new StringBuilder(); switch (getDataType()) { case ExifTag.TYPE_UNDEFINED: + sbuilder.append(undefinedTypeValueToString()); + break; case ExifTag.TYPE_UNSIGNED_BYTE: - byte buf[] = new byte[getComponentCount()]; - getBytes(buf); + byte buf[] = (byte[]) mValue; for(int i = 0, n = getComponentCount(); i < n; i++) { if(i != 0) sbuilder.append(" "); sbuilder.append(String.format("%02x", buf[i])); } break; case ExifTag.TYPE_ASCII: - sbuilder.append(getString()); + String s = getString(); + for (int i = 0, n = s.length(); i < n; i++) { + int code = s.codePointAt(i); + if (code == 0) continue; + if (code > 31 && code < 127) { + sbuilder.append((char) code); + } else { + sbuilder.append('.'); + } + } break; case ExifTag.TYPE_UNSIGNED_LONG: for(int i = 0, n = getComponentCount(); i < n; i++) { @@ -1415,6 +1443,15 @@ public class ExifTag { || tagId == TAG_INTEROPERABILITY_IFD; } + /** + * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD}, + * {@link #TAG_GPS_IFD}, {@link #TAG_INTEROPERABILITY_IFD} + */ + static boolean isSubIfdOffsetTag(short tagId) { + return tagId == TAG_EXIF_IFD + || tagId == TAG_GPS_IFD + || tagId == TAG_INTEROPERABILITY_IFD; + } @Override public boolean equals(Object obj) { if (obj instanceof ExifTag) { diff --git a/tests/res/xml/galaxy_nexus.xml b/tests/res/xml/galaxy_nexus.xml index cefd07848..0c80cb8c4 100644 --- a/tests/res/xml/galaxy_nexus.xml +++ b/tests/res/xml/galaxy_nexus.xml @@ -1,48 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> <exif> - <ifd name="ifd0"> - <tag id="0x100" name="ImageWidth">2560</tag> - <tag id="0x101" name="ImageHeight">1920</tag> - <tag id="0x10f" name="Make">google</tag> - <tag id="0x110" name="Model">Nexus S</tag> - <tag id="0x112" name="Orientation">1</tag> - <tag id="0x131" name="Software">MASTER</tag> - <tag id="0x132" name="DateTime">2012:07:30 16:28:42</tag> - <tag id="0x213" name="YCbCrPositioning">1</tag> - <tag id="0x8769" name="ExifOffset">164</tag> - </ifd> - <ifd name="exif-ifd"> - <tag id="0x829A" name="ExposureTime">1/40</tag> - <tag id="0x829D" name="FNumber">26/10</tag> - <tag id="0x8822" name="ExposureProgram">3</tag> - <tag id="0x8827" name="IsoSpeedRatings">100</tag> - <tag id="0x9000" name="ExifVersion">30 32 32 30</tag> - <tag id="0x9003" name="DateTimeTimeOriginal">2012:07:30 16:28:42</tag> - <tag id="0x9004" name="DateTimeTimeDigitized">2012:07:30 16:28:42</tag> - <tag id="0x9201" name="ShutterSpeed">50/10</tag> - <tag id="0x9202" name="ApertureValue">30/10</tag> - <tag id="0x9203" name="BrightnessValue">30/10</tag> - <tag id="0x9204" name="ExposureBiasValue">0/0</tag> - <tag id="0x9205" name="MaxApertureValue">30/10</tag> - <tag id="0x9207" name="MeteringMode">2</tag> - <tag id="0x9209" name="Flash">0</tag> - <tag id="0x920A" name="FocalLength">343/100</tag> - <tag id="0x9286" name="UserComment">00 00 00 49 49 43 53 41 55 73 65 72 20 63 6f 6d 6d 65 6e 74 73 00</tag> - <tag id="0xA001" name="ColoSpace">1</tag> - <tag id="0xA002" name="PixelXDimension">2560</tag> - <tag id="0xA003" name="PixelYDimension">1920</tag> - <tag id="0xA402" name="ExposureMode">0</tag> - <tag id="0xA403" name="WhithBalance">0</tag> - <tag id="0xA406" name="SceneCaptureType">0</tag> - </ifd> - <ifd name="ifd1"> - <tag id="0x103" name="Compression">6</tag> - <tag id="0x11A" name="XResolution">72/1</tag> - <tag id="0x11B" name="YResolution">72/1</tag> - <tag id="0x128" name="ResolutionUnit">2</tag> - <tag id="0x100" name="ImageWidth">320</tag> - <tag id="0x101" name="ImageHeight">240</tag> - <tag id="0x112" name="Orientation">1</tag> - <tag id="0x201" name="JpegInterchangeFormat">690</tag> - <tag id="0x202" name="JpegInterchangeFormatLength">10447</tag> - </ifd> + <tag ifd="IFD0" id="0x0100" name="ImageWidth">2560</tag> + <tag ifd="IFD0" id="0x0101" name="ImageHeight">1920</tag> + <tag ifd="IFD0" id="0x010f" name="Make">google</tag> + <tag ifd="IFD0" id="0x0110" name="Model">Nexus S</tag> + <tag ifd="IFD0" id="0x0112" name="Orientation">1</tag> + <tag ifd="IFD0" id="0x0131" name="Software">MASTER</tag> + <tag ifd="IFD0" id="0x0132" name="ModifyDate">2012:07:30 16:28:42</tag> + <tag ifd="IFD0" id="0x0213" name="YCbCrPositioning">1</tag> + <tag ifd="ExifIFD" id="0x829a" name="ExposureTime">1/40</tag> + <tag ifd="ExifIFD" id="0x829d" name="FNumber">26/10</tag> + <tag ifd="ExifIFD" id="0x8822" name="ExposureProgram">3</tag> + <tag ifd="ExifIFD" id="0x8827" name="ISO">100</tag> + <tag ifd="ExifIFD" id="0x9000" name="ExifVersion">0220</tag> + <tag ifd="ExifIFD" id="0x9003" name="DateTimeOriginal">2012:07:30 16:28:42</tag> + <tag ifd="ExifIFD" id="0x9004" name="CreateDate">2012:07:30 16:28:42</tag> + <tag ifd="ExifIFD" id="0x9201" name="ShutterSpeedValue">50/10</tag> + <tag ifd="ExifIFD" id="0x9202" name="ApertureValue">30/10</tag> + <tag ifd="ExifIFD" id="0x9203" name="BrightnessValue">30/10</tag> + <tag ifd="ExifIFD" id="0x9204" name="ExposureCompensation">0/0</tag> + <tag ifd="ExifIFD" id="0x9205" name="MaxApertureValue">30/10</tag> + <tag ifd="ExifIFD" id="0x9207" name="MeteringMode">2</tag> + <tag ifd="ExifIFD" id="0x9209" name="Flash">0</tag> + <tag ifd="ExifIFD" id="0x920a" name="FocalLength">343/100</tag> + <tag ifd="ExifIFD" id="0x9286" name="UserComment">IICSAUser comments</tag> + <tag ifd="ExifIFD" id="0xa001" name="ColorSpace">1</tag> + <tag ifd="ExifIFD" id="0xa002" name="ExifImageWidth">2560</tag> + <tag ifd="ExifIFD" id="0xa003" name="ExifImageHeight">1920</tag> + <tag ifd="ExifIFD" id="0xa402" name="ExposureMode">0</tag> + <tag ifd="ExifIFD" id="0xa403" name="WhiteBalance">0</tag> + <tag ifd="ExifIFD" id="0xa406" name="SceneCaptureType">0</tag> + <tag ifd="IFD1" id="0x0100" name="ImageWidth">320</tag> + <tag ifd="IFD1" id="0x0101" name="ImageHeight">240</tag> + <tag ifd="IFD1" id="0x0103" name="Compression">6</tag> + <tag ifd="IFD1" id="0x0112" name="Orientation">1</tag> + <tag ifd="IFD1" id="0x011a" name="XResolution">72/1</tag> + <tag ifd="IFD1" id="0x011b" name="YResolution">72/1</tag> + <tag ifd="IFD1" id="0x0128" name="ResolutionUnit">2</tag> + <tag ifd="IFD1" id="0x0201" name="ThumbnailOffset">690</tag> + <tag ifd="IFD1" id="0x0202" name="ThumbnailLength">10447</tag> </exif> diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java index ad603df39..51375e139 100644 --- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java @@ -19,6 +19,8 @@ package com.android.gallery3d.exif; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -26,48 +28,66 @@ import java.io.IOException; import java.io.InputStream; public class ExifOutputStreamTest extends ExifXmlDataTestCase { - public ExifOutputStreamTest(int imageResourceId, int xmlResourceId) { - super(imageResourceId, xmlResourceId); + public ExifOutputStreamTest(int imgRes, int xmlRes) { + super(imgRes, xmlRes); } - public void testExifOutputStream() throws IOException, ExifInvalidFormatException { + public ExifOutputStreamTest(String imgPath, String xmlPath) { + super(imgPath, xmlPath); + } + + public void testExifOutputStream() throws Exception { File file = File.createTempFile("exif_test", ".jpg"); InputStream imageInputStream = null; InputStream exifInputStream = null; FileInputStream reDecodeInputStream = null; FileInputStream reParseInputStream = null; try { - // Read the image - imageInputStream = getInstrumentation() - .getContext().getResources().openRawResource(mImageResourceId); - Bitmap bmp = BitmapFactory.decodeStream(imageInputStream); + try { + byte[] imgData = readToByteArray(getImageInputStream()); + imageInputStream = new ByteArrayInputStream(imgData); + exifInputStream = new ByteArrayInputStream(imgData); + + // Read the image data + Bitmap bmp = BitmapFactory.decodeStream(imageInputStream); + // Read exif data + ExifData exifData = new ExifReader().read(exifInputStream); - // Read exif data - exifInputStream = getInstrumentation() - .getContext().getResources().openRawResource(mImageResourceId); - ExifData exifData = new ExifReader().read(exifInputStream); + // Encode the image with the exif data + FileOutputStream outputStream = new FileOutputStream(file); + ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream); + exifOutputStream.setExifData(exifData); + bmp.compress(Bitmap.CompressFormat.JPEG, 100, exifOutputStream); + exifOutputStream.close(); - // Encode the image with the exif data - FileOutputStream outputStream = new FileOutputStream(file); - ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream); - exifOutputStream.setExifData(exifData); - bmp.compress(Bitmap.CompressFormat.JPEG, 100, exifOutputStream); - exifOutputStream.close(); + // Re-decode the temp file and check the data. + reDecodeInputStream = new FileInputStream(file); + Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream); + assertNotNull(decodedBmp); - // Re-decode the temp file and check the data. - reDecodeInputStream = new FileInputStream(file); - Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream); - assertNotNull(decodedBmp); + // Re-parse the temp file the check EXIF tag + reParseInputStream = new FileInputStream(file); + ExifData reExifData = new ExifReader().read(reParseInputStream); + assertEquals(exifData, reExifData); + } finally { + Util.closeSilently(imageInputStream); + Util.closeSilently(exifInputStream); + Util.closeSilently(reDecodeInputStream); + Util.closeSilently(reParseInputStream); + } + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } + } - // Re-parse the temp file the check EXIF tag - reParseInputStream = new FileInputStream(file); - ExifData reExifData = new ExifReader().read(reParseInputStream); - assertEquals(exifData, reExifData); - } finally { - Util.closeSilently(imageInputStream); - Util.closeSilently(exifInputStream); - Util.closeSilently(reDecodeInputStream); - Util.closeSilently(reParseInputStream); + private byte[] readToByteArray(InputStream is) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int len; + byte[] buf = new byte[1024]; + while ((len = is.read(buf)) > -1) { + bos.write(buf, 0, len); } + bos.flush(); + return bos.toByteArray(); } -}
\ No newline at end of file +} diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java index c1ad8341b..c93e09a4c 100644 --- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifParserTest.java @@ -16,219 +16,215 @@ 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; +import java.util.Set; public class ExifParserTest extends ExifXmlDataTestCase { private static final String TAG = "ExifParserTest"; - private HashMap<Short, String> mIfd0Value = new HashMap<Short, String>(); - private HashMap<Short, String> mIfd1Value = new HashMap<Short, String>(); - private HashMap<Short, String> mExifIfdValue = new HashMap<Short, String>(); - private HashMap<Short, String> mInteroperabilityIfdValue = new HashMap<Short, String>(); - - private InputStream mImageInputStream; - - public ExifParserTest(int imageResourceId, int xmlResourceId) { - super(imageResourceId, xmlResourceId); + public ExifParserTest(int imgRes, int xmlRes) { + super(imgRes, xmlRes); } - @Override - protected void setUp() throws Exception { - mImageInputStream = getInstrumentation() - .getContext().getResources().openRawResource(mImageResourceId); + public ExifParserTest(String imgPath, String xmlPath) { + super(imgPath, xmlPath); + } - XmlResourceParser parser = - getInstrumentation().getContext().getResources().getXml(mXmlResourceId); + private List<Map<Short, Set<String>>> mGroundTruth; - ExifXmlReader.readXml(parser, mIfd0Value, mIfd1Value, mExifIfdValue - , mInteroperabilityIfdValue); - parser.close(); + @Override + public void setUp() throws Exception { + super.setUp(); + mGroundTruth = ExifXmlReader.readXml(getXmlParser()); } - public void testParse() throws IOException, ExifInvalidFormatException { - ExifParser parser = ExifParser.parse(mImageInputStream); - int event = parser.next(); - while (event != ExifParser.EVENT_END) { - switch (event) { - case ExifParser.EVENT_START_OF_IFD: - break; - case ExifParser.EVENT_NEW_TAG: - ExifTag tag = parser.getTag(); - if (!tag.hasValue()) { - parser.registerForTagValue(tag); - } else { + public void testParse() throws Exception { + try { + ExifParser parser = ExifParser.parse(getImageInputStream()); + int event = parser.next(); + while (event != ExifParser.EVENT_END) { + switch (event) { + case ExifParser.EVENT_START_OF_IFD: + break; + case ExifParser.EVENT_NEW_TAG: + ExifTag tag = parser.getTag(); + if (!tag.hasValue()) { + parser.registerForTagValue(tag); + } else { + checkTag(tag); + } + break; + case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: + tag = parser.getTag(); + if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) { + byte[] buf = new byte[tag.getComponentCount()]; + parser.read(buf); + tag.setValue(buf); + } checkTag(tag); - } - break; - case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: - tag = parser.getTag(); - if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) { - byte[] buf = new byte[tag.getComponentCount()]; - parser.read(buf); - tag.setValue(buf); - } - checkTag(tag); - break; + break; + } + event = parser.next(); } - event = parser.next(); + } catch (Exception e) { + throw new Exception(getImageTitle(), e); } } private void checkTag(ExifTag tag) { - HashMap<Short, String> 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; + + // TODO: Test MakerNote and UserComment + if (tag.getTagId() == ExifTag.TAG_MAKER_NOTE + || tag.getTagId() == ExifTag.TAG_USER_COMMENT) return; + + Set<String> truth = mGroundTruth.get(tag.getIfd()).get(tag.getTagId()); + + if (truth == null) { + fail(String.format("Unknown Tag %02x", tag.getTagId()) + ", " + getImageTitle()); } - String truthString = truth.get(tag.getTagId()); String dataString = tag.valueToString().trim(); - if (truthString == null) { - fail(String.format("Unknown Tag %02x", tag.getTagId())); - } - assertEquals(String.format("Tag %02x", tag.getTagId()), truthString, dataString); + assertTrue(String.format("Tag %02x", tag.getTagId()) + ", " + getImageTitle() + + ": " + dataString, + truth.contains(dataString)); } - private void parseOneIfd(int ifd, int options, HashMap<Short, String> expectedResult) - throws IOException, ExifInvalidFormatException { - int numOfTag = 0; - ExifParser parser = ExifParser.parse(mImageInputStream, options); - int event = parser.next(); - while(event != ExifParser.EVENT_END) { - switch (event) { - case ExifParser.EVENT_START_OF_IFD: - assertEquals(ifd, parser.getCurrentIfd()); - break; - case ExifParser.EVENT_NEW_TAG: - numOfTag++; - ExifTag tag = parser.getTag(); - if (tag.hasValue()) { + private void parseOneIfd(int ifd, int options) throws Exception { + try { + Map<Short, Set<String>> expectedResult = mGroundTruth.get(ifd); + int numOfTag = 0; + ExifParser parser = ExifParser.parse(getImageInputStream(), options); + int event = parser.next(); + while(event != ExifParser.EVENT_END) { + switch (event) { + case ExifParser.EVENT_START_OF_IFD: + assertEquals(getImageTitle(), ifd, parser.getCurrentIfd()); + break; + case ExifParser.EVENT_NEW_TAG: + ExifTag tag = parser.getTag(); + // The exiftool doesn't provide MakerNote tag + if (!ExifTag.isSubIfdOffsetTag(tag.getTagId()) + && tag.getTagId() != ExifTag.TAG_MAKER_NOTE) numOfTag++; + if (tag.hasValue()) { + checkTag(tag); + } else { + parser.registerForTagValue(tag); + } + break; + case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: + tag = parser.getTag(); + if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) { + byte[] buf = new byte[tag.getComponentCount()]; + parser.read(buf); + tag.setValue(buf); + } checkTag(tag); - } else { - parser.registerForTagValue(tag); - } - break; - case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: - tag = parser.getTag(); - if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) { - byte[] buf = new byte[tag.getComponentCount()]; - parser.read(buf); - tag.setValue(buf); - } - checkTag(tag); - break; - case ExifParser.EVENT_COMPRESSED_IMAGE: - case ExifParser.EVENT_UNCOMPRESSED_STRIP: - fail("Invalid Event type: " + event); - break; + break; + case ExifParser.EVENT_COMPRESSED_IMAGE: + case ExifParser.EVENT_UNCOMPRESSED_STRIP: + fail("Invalid Event type: " + event + ", " + getImageTitle()); + break; + } + event = parser.next(); } - event = parser.next(); + assertEquals(expectedResult.size(), numOfTag); + } catch (Exception e) { + throw new Exception(getImageTitle(), e); } - assertEquals(expectedResult.size(), numOfTag); } - public void testOnlyExifIfd() throws IOException, ExifInvalidFormatException { - parseOneIfd(IfdId.TYPE_IFD_EXIF, ExifParser.OPTION_IFD_EXIF, mExifIfdValue); + public void testOnlyExifIfd() throws Exception { + 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); + public void testOnlyIfd0() throws Exception { + 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); + public void testOnlyIfd1() throws Exception { + 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); + public void testOnlyInteroperabilityIfd() throws Exception { + parseOneIfd(IfdId.TYPE_IFD_INTEROPERABILITY, ExifParser.OPTION_IFD_INTEROPERABILITY); } - public void testOnlyReadSomeTag() throws IOException, ExifInvalidFormatException { - ExifParser parser = ExifParser.parse(mImageInputStream, ExifParser.OPTION_IFD_0); - int event = parser.next(); - boolean isTagFound = false; - while (event != ExifParser.EVENT_END) { - switch (event) { - case ExifParser.EVENT_START_OF_IFD: - assertEquals(IfdId.TYPE_IFD_0, parser.getCurrentIfd()); - break; - case ExifParser.EVENT_NEW_TAG: - ExifTag tag = parser.getTag(); - if (tag.getTagId() == ExifTag.TAG_MODEL) { - if (tag.hasValue()) { - isTagFound = true; - checkTag(tag); - } else { - parser.registerForTagValue(tag); + public void testOnlyReadSomeTag() throws Exception { + try { + ExifParser parser = ExifParser.parse(getImageInputStream(), ExifParser.OPTION_IFD_0); + int event = parser.next(); + boolean isTagFound = false; + while (event != ExifParser.EVENT_END) { + switch (event) { + case ExifParser.EVENT_START_OF_IFD: + assertEquals(getImageTitle(), IfdId.TYPE_IFD_0, parser.getCurrentIfd()); + break; + case ExifParser.EVENT_NEW_TAG: + ExifTag tag = parser.getTag(); + if (tag.getTagId() == ExifTag.TAG_MODEL) { + if (tag.hasValue()) { + isTagFound = true; + checkTag(tag); + } else { + parser.registerForTagValue(tag); + } + parser.skipRemainingTagsInCurrentIfd(); } - parser.skipRemainingTagsInCurrentIfd(); - } - break; - case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: - tag = parser.getTag(); - assertEquals(ExifTag.TAG_MODEL, tag.getTagId()); - checkTag(tag); - isTagFound = true; - break; + break; + case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: + tag = parser.getTag(); + assertEquals(getImageTitle(), ExifTag.TAG_MODEL, tag.getTagId()); + checkTag(tag); + isTagFound = true; + break; + } + event = parser.next(); } - event = parser.next(); + assertTrue(getImageTitle(), isTagFound); + } catch (Exception e) { + throw new Exception(getImageTitle(), e); } - assertTrue(isTagFound); } - public void testReadThumbnail() throws ExifInvalidFormatException, IOException { - ExifParser parser = ExifParser.parse(mImageInputStream, - ExifParser.OPTION_IFD_1 | ExifParser.OPTION_THUMBNAIL); - - int event = parser.next(); - Bitmap bmp = null; - boolean mIsContainCompressedImage = false; - while (event != ExifParser.EVENT_END) { - switch (event) { - case ExifParser.EVENT_NEW_TAG: - ExifTag tag = parser.getTag(); - if (tag.getTagId() == ExifTag.TAG_COMPRESSION) { - if (tag.getUnsignedShort(0) == ExifTag.Compression.JPEG) { - mIsContainCompressedImage = true; + public void testReadThumbnail() throws Exception { + try { + ExifParser parser = ExifParser.parse(getImageInputStream(), + ExifParser.OPTION_IFD_1 | ExifParser.OPTION_THUMBNAIL); + + int event = parser.next(); + Bitmap bmp = null; + boolean mIsContainCompressedImage = false; + while (event != ExifParser.EVENT_END) { + switch (event) { + case ExifParser.EVENT_NEW_TAG: + ExifTag tag = parser.getTag(); + if (tag.getTagId() == ExifTag.TAG_COMPRESSION) { + if (tag.getUnsignedShort(0) == ExifTag.Compression.JPEG) { + mIsContainCompressedImage = true; + } } - } - break; - case ExifParser.EVENT_COMPRESSED_IMAGE: - int imageSize = parser.getCompressedImageSize(); - byte buf[] = new byte[imageSize]; - parser.read(buf); - bmp = BitmapFactory.decodeByteArray(buf, 0, imageSize); - break; + break; + case ExifParser.EVENT_COMPRESSED_IMAGE: + int imageSize = parser.getCompressedImageSize(); + byte buf[] = new byte[imageSize]; + parser.read(buf); + bmp = BitmapFactory.decodeByteArray(buf, 0, imageSize); + break; + } + event = parser.next(); } - event = parser.next(); - } - if (mIsContainCompressedImage) { - assertNotNull(bmp); + if (mIsContainCompressedImage) { + assertNotNull(getImageTitle(), bmp); + } + } catch (Exception e) { + throw new Exception(getImageTitle(), e); } } - - @Override - protected void tearDown() throws IOException { - mImageInputStream.close(); - mIfd0Value.clear(); - mIfd1Value.clear(); - mExifIfdValue.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..40d269ef6 100644 --- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java @@ -16,49 +16,35 @@ package com.android.gallery3d.exif; -import android.content.res.XmlResourceParser; import android.graphics.BitmapFactory; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; public class ExifReaderTest extends ExifXmlDataTestCase { private static final String TAG = "ExifReaderTest"; - private final HashMap<Short, String> mIfd0Value = new HashMap<Short, String>(); - private final HashMap<Short, String> mIfd1Value = new HashMap<Short, String>(); - private final HashMap<Short, String> mExifIfdValue = new HashMap<Short, String>(); - private final HashMap<Short, String> mInteroperabilityIfdValue = new HashMap<Short, String>(); - - private InputStream mImageInputStream; - - public ExifReaderTest(int imageResourceId, int xmlResourceId) { - super(imageResourceId, xmlResourceId); + public ExifReaderTest(int imgRes, int xmlRes) { + super(imgRes, xmlRes); } - @Override - public void setUp() throws Exception { - mImageInputStream = getInstrumentation() - .getContext().getResources().openRawResource(mImageResourceId); - - XmlResourceParser parser = - getInstrumentation().getContext().getResources().getXml(mXmlResourceId); - - ExifXmlReader.readXml(parser, mIfd0Value, mIfd1Value, mExifIfdValue - , mInteroperabilityIfdValue); - parser.close(); + public ExifReaderTest(String imgPath, String xmlPath) { + super(imgPath, xmlPath); } - 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); - checkThumbnail(exifData); + public void testRead() throws Exception { + try { + ExifReader reader = new ExifReader(); + ExifData exifData = reader.read(getImageInputStream()); + List<Map<Short, Set<String>>> groundTruth = ExifXmlReader.readXml(getXmlParser()); + for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { + checkIfd(exifData.getIfdData(i), groundTruth.get(i)); + } + checkThumbnail(exifData); + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } } private void checkThumbnail(ExifData exifData) { @@ -66,9 +52,10 @@ public class ExifReaderTest extends ExifXmlDataTestCase { if (ifd1 != null) { if (ifd1.getTag(ExifTag.TAG_COMPRESSION).getUnsignedShort(0) == ExifTag.Compression.JPEG) { - assertTrue(exifData.hasCompressedThumbnail()); + assertTrue(getImageTitle(), exifData.hasCompressedThumbnail()); byte[] thumbnail = exifData.getCompressedThumbnail(); - assertTrue(BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length) != null); + assertTrue(getImageTitle(), + BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length) != null); } else { // Try to check the strip count with the formula provided by EXIF spec. int planarType = ExifTag.PlanarConfiguration.CHUNKY; @@ -86,20 +73,23 @@ public class ExifReaderTest extends ExifXmlDataTestCase { ExifTag.TAG_STRIP_OFFSETS).getComponentCount(); if (planarType == ExifTag.PlanarConfiguration.CHUNKY) { - assertTrue(stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip); + assertTrue(getImageTitle(), + stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip); } else { ExifTag samplePerPixelTag = ifd1.getTag(ExifTag.TAG_SAMPLES_PER_PIXEL); int samplePerPixel = samplePerPixelTag.getUnsignedShort(0); - assertTrue(stripCount == + assertTrue(getImageTitle(), + stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel); } for (int i = 0; i < stripCount; i++) { ExifTag byteCountTag = ifd1.getTag(ExifTag.TAG_STRIP_BYTE_COUNTS); if (byteCountTag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { - assertEquals(byteCountTag.getUnsignedShort(i), exifData.getStrip(i).length); + assertEquals(getImageTitle(), + byteCountTag.getUnsignedShort(i), exifData.getStrip(i).length); } else { - assertEquals( + assertEquals(getImageTitle(), byteCountTag.getUnsignedLong(i), exifData.getStrip(i).length); } } @@ -115,20 +105,24 @@ public class ExifReaderTest extends ExifXmlDataTestCase { } } - private void checkIfd(IfdData ifd, HashMap<Short, String> ifdValue) { + private void checkIfd(IfdData ifd, Map<Short, Set<String>> ifdValue) { if (ifd == null) { - assertEquals(0 ,ifdValue.size()); + assertEquals(getImageTitle(), 0 ,ifdValue.size()); return; } ExifTag[] tags = ifd.getAllTags(); + int size = 0; for (ExifTag tag : tags) { - assertEquals(ifdValue.get(tag.getTagId()), tag.valueToString().trim()); + if (ExifTag.isSubIfdOffsetTag(tag.getTagId()) + || tag.getTagId() == ExifTag.TAG_MAKER_NOTE) continue; + if (tag.getTagId() != ExifTag.TAG_USER_COMMENT) { + Set<String> truth = ifdValue.get(tag.getTagId()); + assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth); + assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), + truth.contains(tag.valueToString().trim())); + } + size++; } - assertEquals(ifdValue.size(), tags.length); - } - - @Override - public void tearDown() throws Exception { - mImageInputStream.close(); + assertEquals(getImageTitle(), ifdValue.size(), size); } } diff --git a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java index 57a7111ad..519e87107 100644 --- a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java +++ b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java @@ -16,6 +16,8 @@ package com.android.gallery3d.exif; +import android.content.Context; +import android.os.Environment; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; import android.util.Log; @@ -25,8 +27,11 @@ import com.android.gallery3d.tests.R; import junit.framework.TestCase; import junit.framework.TestSuite; +import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; public class ExifTestRunner extends InstrumentationTestRunner { private static final String TAG = "ExifTestRunner"; @@ -34,12 +39,17 @@ public class ExifTestRunner extends InstrumentationTestRunner { private static final int[] IMG_RESOURCE = { R.raw.galaxy_nexus }; + private static final int[] EXIF_DATA_RESOURCE = { R.xml.galaxy_nexus }; + private static List<String> mTestImgPath = new ArrayList<String>(); + private static List<String> mTestXmlPath = new ArrayList<String>(); + @Override public TestSuite getAllTests() { + getTestImagePath(); TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(ExifDataTest.class); suite.addTestSuite(ExifTagTest.class); @@ -49,6 +59,25 @@ public class ExifTestRunner extends InstrumentationTestRunner { return suite; } + private void getTestImagePath() { + Context context = getContext(); + File imgDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); + File xmlDir = new File(context.getExternalFilesDir(null).getPath(), "Xml"); + + if (imgDir != null && xmlDir != null) { + String[] imgs = imgDir.list(); + if (imgs == null) return; + for (String imgName: imgs) { + String xmlName = imgName.substring(0, imgName.lastIndexOf('.')) + ".xml"; + File xmlFile = new File(xmlDir, xmlName); + if (xmlFile.exists()) { + mTestImgPath.add(new File(imgDir, imgName).getAbsolutePath()); + mTestXmlPath.add(xmlFile.getAbsolutePath()); + } + } + } + } + private void addAllTestsFromExifTestCase(Class<? extends ExifXmlDataTestCase> testClass, TestSuite suite) { for (Method method : testClass.getDeclaredMethods()) { @@ -72,6 +101,25 @@ public class ExifTestRunner extends InstrumentationTestRunner { Log.e(TAG, "Failed to create test case", e); } } + for (int i = 0, n = mTestImgPath.size(); i < n; i++) { + TestCase test; + try { + test = testClass.getDeclaredConstructor(String.class, String.class). + newInstance(mTestImgPath.get(i), mTestXmlPath.get(i)); + test.setName(method.getName()); + suite.addTest(test); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Failed to create test case", e); + } catch (InstantiationException e) { + Log.e(TAG, "Failed to create test case", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Failed to create test case", e); + } catch (InvocationTargetException e) { + Log.e(TAG, "Failed to create test case", e); + } catch (NoSuchMethodException e) { + Log.e(TAG, "Failed to create test case", e); + } + } } } } diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java index 41b315181..5b61778bd 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java @@ -17,14 +17,75 @@ package com.android.gallery3d.exif; +import android.content.res.Resources; import android.test.InstrumentationTestCase; +import android.util.Xml; + +import org.xmlpull.v1.XmlPullParser; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; public class ExifXmlDataTestCase extends InstrumentationTestCase { - protected final int mImageResourceId; - protected final int mXmlResourceId; + + private static final String RES_ID_TITLE = "Resource ID: %x"; + + private InputStream mImageInputStream; + private InputStream mXmlInputStream; + private XmlPullParser mXmlParser; + private final String mImagePath; + private final String mXmlPath; + private final int mImageResourceId; + private final int mXmlResourceId; public ExifXmlDataTestCase(int imageRes, int xmlRes) { + mImagePath = null; + mXmlPath = null; mImageResourceId = imageRes; mXmlResourceId = xmlRes; } + + public ExifXmlDataTestCase(String imagePath, String xmlPath) { + mImagePath = imagePath; + mXmlPath = xmlPath; + mImageResourceId = 0; + mXmlResourceId = 0; + } + + protected InputStream getImageInputStream() { + return mImageInputStream; + } + + protected XmlPullParser getXmlParser() { + return mXmlParser; + } + + @Override + public void setUp() throws Exception { + if (mImagePath != null) { + mImageInputStream = new FileInputStream(mImagePath); + mXmlInputStream = new FileInputStream(mXmlPath); + mXmlParser = Xml.newPullParser(); + mXmlParser.setInput(new InputStreamReader(mXmlInputStream)); + } else { + Resources res = getInstrumentation().getContext().getResources(); + mImageInputStream = res.openRawResource(mImageResourceId); + mXmlParser = res.getXml(mXmlResourceId); + } + } + + @Override + public void tearDown() throws Exception { + Util.closeSilently(mImageInputStream); + Util.closeSilently(mXmlInputStream); + } + + protected String getImageTitle() { + if (mImagePath != null) { + return mImagePath; + } else { + return String.format(RES_ID_TITLE, mImageResourceId); + } + } } diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java index 72dd31373..54def2756 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java @@ -20,78 +20,94 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; public class ExifXmlReader { + private static final String TAG_EXIF = "exif"; + private static final String TAG_TAG = "tag"; - 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<Short, String> ifd0, - HashMap<Short, String> ifd1, HashMap<Short, String> exifIfd, - HashMap<Short, String> interoperabilityIfd) throws XmlPullParserException, - IOException { + 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 INTEROP_IFD = "InteropIFD"; + + private static final String ATTR_ID = "id"; + private static final String ATTR_IFD = "ifd"; + + /** + * This function read the ground truth XML. + * + * @throws XmlPullParserException + * @throws IOException + */ + static public List<Map<Short, Set<String>>> readXml(XmlPullParser parser) + throws XmlPullParserException, IOException { + + List<Map<Short, Set<String>>> exifData = + new ArrayList<Map<Short, Set<String>>>(IfdId.TYPE_IFD_COUNT); + for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { + exifData.add(new HashMap<Short, Set<String>>()); + } 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<Short, String> ifd0, - HashMap<Short, String> ifd1, HashMap<Short, String> exifIfd, - HashMap<Short, String> interoperabilityIfd) throws XmlPullParserException, - IOException { - parser.require(XmlPullParser.START_TAG, null, XML_IFD_TAG); - String name = parser.getAttributeValue(null, XML_IFD_NAME); - HashMap<Short, String> 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(); } + + if (ifdId < 0) { + // TODO: the MarkerNote segment. + } else { + Set<String> tagData = exifData.get(ifdId).get(id); + if (tagData == null) { + tagData = new HashSet<String>(); + exifData.get(ifdId).put(id, tagData); + } + tagData.add(value.trim()); + } + + 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<Short, String> 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 (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 +} |