From 29fd4aa661f7e626a1d11558f09e8f7c011efcc2 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Mon, 11 Mar 2013 19:00:12 -0700 Subject: Exif parser modifications. Bug: 8018327 Change-Id: I66a2ec309f9807ac255bbf29d8f5f26de60e89b8 --- .../com/android/gallery3d/exif/ExifDataTest.java | 153 ++++-- .../android/gallery3d/exif/ExifInterfaceTest.java | 527 +++++++++++++++++++++ .../android/gallery3d/exif/ExifModifierTest.java | 110 +++-- .../gallery3d/exif/ExifOutputStreamTest.java | 67 ++- .../com/android/gallery3d/exif/ExifParserTest.java | 33 +- .../com/android/gallery3d/exif/ExifReaderTest.java | 70 ++- .../com/android/gallery3d/exif/ExifTagTest.java | 227 ++++----- .../com/android/gallery3d/exif/ExifTestRunner.java | 11 +- .../gallery3d/exif/ExifXmlDataTestCase.java | 1 - .../com/android/gallery3d/exif/ExifXmlReader.java | 4 +- tests/src/com/android/gallery3d/exif/Util.java | 114 +++-- 11 files changed, 1037 insertions(+), 280 deletions(-) create mode 100644 tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java (limited to 'tests/src') diff --git a/tests/src/com/android/gallery3d/exif/ExifDataTest.java b/tests/src/com/android/gallery3d/exif/ExifDataTest.java index fed8e1eaf..949f22c49 100644 --- a/tests/src/com/android/gallery3d/exif/ExifDataTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifDataTest.java @@ -19,36 +19,135 @@ package com.android.gallery3d.exif; import junit.framework.TestCase; import java.nio.ByteOrder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ExifDataTest extends TestCase { + Map mTestTags; + ExifInterface mInterface; + private ExifTag mVersionTag; + private ExifTag mGpsVersionTag; + private ExifTag mModelTag; + private ExifTag mDateTimeTag; + private ExifTag mCompressionTag; + private ExifTag mThumbnailFormatTag; + private ExifTag mLongitudeTag; + private ExifTag mShutterTag; + private ExifTag mInteropIndex; + + @Override + public void setUp() throws Exception { + super.setUp(); + + mInterface = new ExifInterface(); + + // TYPE_UNDEFINED with 4 components + mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] { + 5, 4, 3, 2 + }); + // TYPE_UNSIGNED_BYTE with 4 components + mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] { + 6, 7, 8, 9 + }); + // TYPE ASCII with arbitrary length + mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld"); + // TYPE_ASCII with 20 components + mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20"); + // TYPE_UNSIGNED_SHORT with 1 components + mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100); + // TYPE_UNSIGNED_LONG with 1 components + mThumbnailFormatTag = + mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100); + // TYPE_UNSIGNED_RATIONAL with 3 components + mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] { + new Rational(2, 2), new Rational(11, 11), + new Rational(102, 102) + }); + // TYPE_RATIONAL with 1 components + mShutterTag = mInterface + .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6)); + // TYPE_ASCII with arbitrary length + mInteropIndex = mInterface.buildTag(ExifInterface.TAG_INTEROPERABILITY_INDEX, "foo"); + + mTestTags = new HashMap(); + + mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag); + mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag); + mTestTags.put(ExifInterface.TAG_MODEL, mModelTag); + mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag); + mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag); + mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag); + mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag); + mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag); + mTestTags.put(ExifInterface.TAG_INTEROPERABILITY_INDEX, mInteropIndex); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + mInterface = null; + mTestTags = null; + } + public void testAddTag() { ExifData exifData = new ExifData(ByteOrder.BIG_ENDIAN); - // IFD0 tag - exifData.addTag(ExifTag.TAG_MAKE).setValue("test"); - exifData.addTag(ExifTag.TAG_IMAGE_WIDTH).setValue(1000); - - // EXIF tag - exifData.addTag(ExifTag.TAG_ISO_SPEED_RATINGS).setValue(1); - - // GPS tag - exifData.addTag(ExifTag.TAG_GPS_ALTITUDE).setValue(new Rational(10, 100)); - - // Interoperability tag - exifData.addInteroperabilityTag(ExifTag.TAG_INTEROPERABILITY_INDEX).setValue("inter_test"); - - // IFD1 tag - exifData.addThumbnailTag(ExifTag.TAG_MAKE).setValue("test_thumb"); - exifData.addThumbnailTag(ExifTag.TAG_IMAGE_WIDTH).setValue(100); - - // check data - assertEquals("test", exifData.getTag(ExifTag.TAG_MAKE).getString()); - assertEquals(1000, (int) exifData.getTag(ExifTag.TAG_IMAGE_WIDTH).getValueAt(0)); - assertEquals(1, (int) exifData.getTag(ExifTag.TAG_ISO_SPEED_RATINGS).getValueAt(0)); - assertEquals(new Rational(10, 100), - exifData.getTag(ExifTag.TAG_GPS_ALTITUDE).getRational(0)); - assertEquals("inter_test", - exifData.getInteroperabilityTag(ExifTag.TAG_INTEROPERABILITY_INDEX).getString()); - assertEquals("test_thumb", exifData.getThumbnailTag(ExifTag.TAG_MAKE).getString()); - assertEquals(100, (int) exifData.getThumbnailTag(ExifTag.TAG_IMAGE_WIDTH).getValueAt(0)); + + // Add all test tags + for (ExifTag t : mTestTags.values()) { + assertTrue(exifData.addTag(t) == null); + } + + // Make sure no initial thumbnails + assertFalse(exifData.hasCompressedThumbnail()); + assertFalse(exifData.hasUncompressedStrip()); + + // Check that we can set thumbnails + exifData.setStripBytes(3, new byte[] { + 1, 2, 3, 4, 5 + }); + assertTrue(exifData.hasUncompressedStrip()); + exifData.setCompressedThumbnail(new byte[] { + 1 + }); + assertTrue(exifData.hasCompressedThumbnail()); + + // Check that we can clear thumbnails + exifData.clearThumbnailAndStrips(); + assertFalse(exifData.hasCompressedThumbnail()); + assertFalse(exifData.hasUncompressedStrip()); + + // Make sure ifds exist + for (int i : IfdData.getIfds()) { + assertTrue(exifData.getIfdData(i) != null); + } + + // Get all test tags + List allTags = exifData.getAllTags(); + assertTrue(allTags != null); + + // Make sure all test tags are in data + for (ExifTag t : mTestTags.values()) { + boolean check = false; + for (ExifTag i : allTags) { + if (t.equals(i)) { + check = true; + break; + } + } + assertTrue(check); + } + + // Check if getting tags for a tid works + List tidTags = exifData.getAllTagsForTagId(ExifInterface + .getTrueTagKey(ExifInterface.TAG_SHUTTER_SPEED_VALUE)); + assertTrue(tidTags.size() == 1); + assertTrue(tidTags.get(0).equals(mShutterTag)); + + // Check if getting tags for an ifd works + List ifdTags = exifData.getAllTagsForIfd(IfdId.TYPE_IFD_INTEROPERABILITY); + assertTrue(ifdTags.size() == 1); + assertTrue(ifdTags.get(0).equals(mInteropIndex)); + } } diff --git a/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java b/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java new file mode 100644 index 000000000..af1ccfb3f --- /dev/null +++ b/tests/src/com/android/gallery3d/exif/ExifInterfaceTest.java @@ -0,0 +1,527 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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.IOException; +import java.io.InputStream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ExifInterfaceTest extends ExifXmlDataTestCase { + + private File mTmpFile; + private List>> mGroundTruth; + private ExifInterface mInterface; + private ExifTag mVersionTag; + private ExifTag mGpsVersionTag; + private ExifTag mModelTag; + private ExifTag mDateTimeTag; + private ExifTag mCompressionTag; + private ExifTag mThumbnailFormatTag; + private ExifTag mLongitudeTag; + private ExifTag mShutterTag; + Map mTestTags; + Map mTagDefinitions; + + public ExifInterfaceTest(int imageRes, int xmlRes) { + super(imageRes, xmlRes); + } + + public ExifInterfaceTest(String imagePath, String xmlPath) { + super(imagePath, xmlPath); + } + + public void testInterface() throws Exception { + + InputStream imageInputStream = null; + try { + // Basic checks + + // Check if bitmap is valid + byte[] imgData = Util.readToByteArray(getImageInputStream()); + imageInputStream = new ByteArrayInputStream(imgData); + checkBitmap(imageInputStream); + + // Check defines + int tag = ExifInterface.defineTag(1, (short) 0x0100); + assertTrue(getImageTitle(), tag == 0x00010100); + int tagDef = mInterface.getTagDefinition((short) 0x0100, IfdId.TYPE_IFD_0); + assertTrue(getImageTitle(), tagDef == 0x03040001); + int[] allowed = ExifInterface.getAllowedIfdsFromInfo(mInterface.getTagInfo().get( + ExifInterface.TAG_IMAGE_WIDTH)); + assertTrue(getImageTitle(), allowed.length == 2 && allowed[0] == IfdId.TYPE_IFD_0 + && allowed[1] == IfdId.TYPE_IFD_1); + + // Check if there are any initial tags + assertTrue(getImageTitle(), mInterface.getAllTags() == null); + + // ///////// Basic read/write testing + + // Make sure we can read + imageInputStream = new ByteArrayInputStream(imgData); + mInterface.readExif(imageInputStream); + + // Check tags against ground truth + checkTagsAgainstXml(mInterface.getAllTags()); + + // Make sure clearing Exif works + mInterface.clearExif(); + assertTrue(getImageTitle(), mInterface.getAllTags() == null); + + // Make sure setting tags works + mInterface.setTags(mTestTags.values()); + checkTagsAgainstHash(mInterface.getAllTags(), mTestTags); + + // Try writing over bitmap exif + ByteArrayOutputStream imgModified = new ByteArrayOutputStream(); + mInterface.writeExif(imgData, imgModified); + + // Check if bitmap is valid + byte[] imgData2 = imgModified.toByteArray(); + imageInputStream = new ByteArrayInputStream(imgData2); + checkBitmap(imageInputStream); + + // Make sure we get the same tags out + imageInputStream = new ByteArrayInputStream(imgData2); + mInterface.readExif(imageInputStream); + checkTagsAgainstHash(mInterface.getAllTags(), mTestTags); + + // Reread original image + imageInputStream = new ByteArrayInputStream(imgData); + mInterface.readExif(imageInputStream); + + // Write out with original exif + imgModified = new ByteArrayOutputStream(); + mInterface.writeExif(imgData2, imgModified); + + // Read back in exif and check tags + imgData2 = imgModified.toByteArray(); + imageInputStream = new ByteArrayInputStream(imgData2); + mInterface.readExif(imageInputStream); + checkTagsAgainstXml(mInterface.getAllTags()); + + // Check if bitmap is valid + imageInputStream = new ByteArrayInputStream(imgData2); + checkBitmap(imageInputStream); + + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } finally { + Util.closeSilently(imageInputStream); + } + } + + public void testInterfaceModify() throws Exception { + + // TODO: This test is dependent on galaxy_nexus jpeg/xml file. + InputStream imageInputStream = null; + try { + // Check if bitmap is valid + byte[] imgData = Util.readToByteArray(getImageInputStream()); + imageInputStream = new ByteArrayInputStream(imgData); + checkBitmap(imageInputStream); + + // ///////// Exif modifier testing. + + // Read exif and write to temp file + imageInputStream = new ByteArrayInputStream(imgData); + mInterface.readExif(imageInputStream); + mInterface.writeExif(imgData, mTmpFile.getPath()); + + // Check if bitmap is valid + imageInputStream = new FileInputStream(mTmpFile); + checkBitmap(imageInputStream); + + // Create some tags to overwrite with + ArrayList tags = new ArrayList(); + tags.add(mInterface.buildTag(ExifInterface.TAG_ORIENTATION, + ExifInterface.Orientation.RIGHT_TOP)); + tags.add(mInterface.buildTag(ExifInterface.TAG_USER_COMMENT, "goooooooooooooooooogle")); + + // Attempt to rewrite tags + assertTrue(getImageTitle(), mInterface.rewriteExif(mTmpFile.getPath(), tags)); + + imageInputStream.close(); + // Check if bitmap is valid + imageInputStream = new FileInputStream(mTmpFile); + checkBitmap(imageInputStream); + + // Read tags and check against xml + mInterface.readExif(mTmpFile.getPath()); + for (ExifTag t : mInterface.getAllTags()) { + short tid = t.getTagId(); + if (tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_ORIENTATION) + && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)) { + checkTagAgainstXml(t); + } + } + assertTrue(getImageTitle(), mInterface.getTagIntValue(ExifInterface.TAG_ORIENTATION) + .shortValue() == ExifInterface.Orientation.RIGHT_TOP); + String valString = mInterface.getTagStringValue(ExifInterface.TAG_USER_COMMENT); + assertTrue(getImageTitle(), valString.equals("goooooooooooooooooogle")); + + // Test forced modify + + // Create some tags to overwrite with + tags = new ArrayList(); + tags.add(mInterface.buildTag(ExifInterface.TAG_SOFTWARE, "magic super photomaker pro")); + tags.add(mInterface.buildTag(ExifInterface.TAG_USER_COMMENT, "noodles")); + tags.add(mInterface.buildTag(ExifInterface.TAG_ORIENTATION, + ExifInterface.Orientation.TOP_LEFT)); + + // Force rewrite tags + mInterface.forceRewriteExif(mTmpFile.getPath(), tags); + + imageInputStream.close(); + // Check if bitmap is valid + imageInputStream = new FileInputStream(mTmpFile); + checkBitmap(imageInputStream); + + // Read tags and check against xml + mInterface.readExif(mTmpFile.getPath()); + for (ExifTag t : mInterface.getAllTags()) { + short tid = t.getTagId(); + if (!ExifInterface.isOffsetTag(tid) + && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_SOFTWARE) + && tid != ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)) { + checkTagAgainstXml(t); + } + } + valString = mInterface.getTagStringValue(ExifInterface.TAG_SOFTWARE); + String compareString = "magic super photomaker pro\0"; + assertTrue(getImageTitle(), valString.equals(compareString)); + valString = mInterface.getTagStringValue(ExifInterface.TAG_USER_COMMENT); + assertTrue(getImageTitle(), valString.equals("noodles")); + + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } finally { + Util.closeSilently(imageInputStream); + } + } + + public void testInterfaceDefines() throws Exception { + + InputStream imageInputStream = null; + try { + // Check if bitmap is valid + byte[] imgData = Util.readToByteArray(getImageInputStream()); + imageInputStream = new ByteArrayInputStream(imgData); + checkBitmap(imageInputStream); + + // Set some tags. + mInterface.setTags(mTestTags.values()); + + // Check tag definitions against default + for (Integer i : mTestTags.keySet()) { + int check = mTagDefinitions.get(i).intValue(); + int actual = mInterface.getTagInfo().get(i); + assertTrue(check == actual); + } + + // Check defines + int tag1 = ExifInterface.defineTag(IfdId.TYPE_IFD_1, (short) 42); + int tag2 = ExifInterface.defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 43); + assertTrue(tag1 == 0x0001002a); + assertTrue(tag2 == 0x0003002b); + + // Define some non-standard tags + assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1, + ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] { + IfdId.TYPE_IFD_1 + }) == tag1); + assertTrue(mInterface.getTagInfo().get(tag1) == 0x02010010); + assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_INTEROPERABILITY, + ExifTag.TYPE_ASCII, (short) 5, new int[] { + IfdId.TYPE_IFD_GPS, IfdId.TYPE_IFD_INTEROPERABILITY + }) == tag2); + assertTrue(mInterface.getTagInfo().get(tag2) == 0x18020005); + + // Make sure these don't work + assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1, + ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] { + IfdId.TYPE_IFD_0 + }) == ExifInterface.TAG_NULL); + assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1, (short) 0, + (short) 16, new int[] { + IfdId.TYPE_IFD_1 + }) == ExifInterface.TAG_NULL); + assertTrue(mInterface.setTagDefinition((short) 42, 5, ExifTag.TYPE_UNSIGNED_BYTE, + (short) 16, new int[] { + 5 + }) == ExifInterface.TAG_NULL); + assertTrue(mInterface.setTagDefinition((short) 42, IfdId.TYPE_IFD_1, + ExifTag.TYPE_UNSIGNED_BYTE, (short) 16, new int[] { + -1 + }) == ExifInterface.TAG_NULL); + assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_GPS, + ExifTag.TYPE_ASCII, (short) 5, new int[] { + IfdId.TYPE_IFD_GPS + }) == ExifInterface.TAG_NULL); + assertTrue(mInterface.setTagDefinition((short) 43, IfdId.TYPE_IFD_0, + ExifTag.TYPE_ASCII, (short) 5, new int[] { + IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_GPS + }) == ExifInterface.TAG_NULL); + + // Set some tags + mInterface.setTags(mTestTags.values()); + checkTagsAgainstHash(mInterface.getAllTags(), mTestTags); + + // Make some tags using new defines + ExifTag defTag0 = mInterface.buildTag(tag1, new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + }); + assertTrue(defTag0 != null); + ExifTag defTag1 = mInterface.buildTag(tag2, "hihi"); + assertTrue(defTag1 != null); + ExifTag defTag2 = mInterface.buildTag(tag2, IfdId.TYPE_IFD_GPS, "byte"); + assertTrue(defTag2 != null); + + // Make sure these don't work + ExifTag badTag = mInterface.buildTag(tag1, new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + }); + assertTrue(badTag == null); + badTag = mInterface.buildTag(tag1, IfdId.TYPE_IFD_0, new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + }); + assertTrue(badTag == null); + badTag = mInterface.buildTag(0x0002002a, new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + }); + assertTrue(badTag == null); + badTag = mInterface.buildTag(tag2, new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 + }); + assertTrue(badTag == null); + + // Set the tags + assertTrue(mInterface.setTag(defTag0) == null); + assertTrue(mInterface.setTag(defTag1) == null); + assertTrue(mInterface.setTag(defTag2) == null); + assertTrue(mInterface.setTag(defTag0).equals(defTag0)); + assertTrue(mInterface.setTag(null) == null); + assertTrue(mInterface.setTagValue(tag2, "yoyo") == true); + assertTrue(mInterface.setTagValue(tag2, "yaaarggg") == false); + assertTrue(mInterface.getTagStringValue(tag2).equals("yoyo\0")); + + // Try writing over bitmap exif + ByteArrayOutputStream imgModified = new ByteArrayOutputStream(); + mInterface.writeExif(imgData, imgModified); + + // Check if bitmap is valid + byte[] imgData2 = imgModified.toByteArray(); + imageInputStream = new ByteArrayInputStream(imgData2); + checkBitmap(imageInputStream); + + // Read back in the tags + mInterface.readExif(imgData2); + + // Check tags + for (ExifTag t : mInterface.getAllTags()) { + int tid = t.getTagId(); + if (tid != ExifInterface.getTrueTagKey(tag1) + && tid != ExifInterface.getTrueTagKey(tag2)) { + checkTagAgainstHash(t, mTestTags); + } + } + assertTrue(Arrays.equals(mInterface.getTagByteValues(tag1), new byte[] { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + })); + assertTrue(mInterface.getTagStringValue(tag2).equals("yoyo\0")); + assertTrue(mInterface.getTagStringValue(tag2, IfdId.TYPE_IFD_GPS).equals("byte\0")); + + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } finally { + Util.closeSilently(imageInputStream); + } + } + + public void testInterfaceThumbnails() throws Exception { + + InputStream imageInputStream = null; + try { + // Check if bitmap is valid + byte[] imgData = Util.readToByteArray(getImageInputStream()); + imageInputStream = new ByteArrayInputStream(imgData); + checkBitmap(imageInputStream); + + // Check thumbnails + mInterface.readExif(imgData); + Bitmap bmap = mInterface.getThumbnailBitmap(); + assertTrue(getImageTitle(), bmap != null); + + // Make a new thumbnail and set it + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inSampleSize = 16; + Bitmap thumb = BitmapFactory.decodeByteArray(imgData, 0, imgData.length, opts); + assertTrue(getImageTitle(), thumb != null); + assertTrue(getImageTitle(), mInterface.setCompressedThumbnail(thumb) == true); + + // Write out image + ByteArrayOutputStream outData = new ByteArrayOutputStream(); + mInterface.writeExif(imgData, outData); + + // Make sure bitmap is still valid + byte[] imgData2 = outData.toByteArray(); + imageInputStream = new ByteArrayInputStream(imgData2); + checkBitmap(imageInputStream); + + // Read in bitmap and make sure thumbnail is still valid + mInterface.readExif(imgData2); + bmap = mInterface.getThumbnailBitmap(); + assertTrue(getImageTitle(), bmap != null); + + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } finally { + Util.closeSilently(imageInputStream); + } + } + + @Override + public void setUp() throws Exception { + super.setUp(); + mTmpFile = File.createTempFile("exif_test", ".jpg"); + mGroundTruth = ExifXmlReader.readXml(getXmlParser()); + + mInterface = new ExifInterface(); + + // TYPE_UNDEFINED with 4 components + mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] { + 5, 4, 3, 2 + }); + // TYPE_UNSIGNED_BYTE with 4 components + mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] { + 6, 7, 8, 9 + }); + // TYPE ASCII with arbitary length + mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld"); + // TYPE_ASCII with 20 components + mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20"); + // TYPE_UNSIGNED_SHORT with 1 components + mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100); + // TYPE_UNSIGNED_LONG with 1 components + mThumbnailFormatTag = + mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100); + // TYPE_UNSIGNED_RATIONAL with 3 components + mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] { + new Rational(2, 2), new Rational(11, 11), + new Rational(102, 102) + }); + // TYPE_RATIONAL with 1 components + mShutterTag = mInterface + .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6)); + + mTestTags = new HashMap(); + + mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag); + mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag); + mTestTags.put(ExifInterface.TAG_MODEL, mModelTag); + mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag); + mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag); + mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag); + mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag); + mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag); + + mTagDefinitions = new HashMap(); + mTagDefinitions.put(ExifInterface.TAG_EXIF_VERSION, 0x04070004); + mTagDefinitions.put(ExifInterface.TAG_GPS_VERSION_ID, 0x10010004); + mTagDefinitions.put(ExifInterface.TAG_MODEL, 0x03020000); + mTagDefinitions.put(ExifInterface.TAG_DATE_TIME, 0x03020014); + mTagDefinitions.put(ExifInterface.TAG_COMPRESSION, 0x03030001); + mTagDefinitions.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 0x02040001); + mTagDefinitions.put(ExifInterface.TAG_GPS_LONGITUDE, 0x100a0003); + mTagDefinitions.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, 0x040a0001); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + mTmpFile.delete(); + } + + // Helper functions + + private void checkTagAgainstXml(ExifTag tag) { + List truth = mGroundTruth.get(tag.getIfd()).get(tag.getTagId()); + + if (truth == null) { + fail(String.format("Unknown Tag %02x", tag.getTagId()) + ", " + getImageTitle()); + } + + // No value from exiftool. + if (truth.contains(null)) + return; + + String dataString = Util.tagValueToString(tag).trim(); + assertTrue(String.format("Tag %02x", tag.getTagId()) + ", " + getImageTitle() + + ": " + dataString, + truth.contains(dataString)); + } + + private void checkTagsAgainstXml(List tags) { + for (ExifTag t : tags) { + checkTagAgainstXml(t); + } + } + + private void checkTagAgainstHash(ExifTag tag, Map testTags) { + int tagdef = mInterface.getTagDefinitionForTag(tag); + assertTrue(getImageTitle(), tagdef != ExifInterface.TAG_NULL); + ExifTag t = testTags.get(tagdef); + // Ignore offset tags & other special tags + if (!ExifInterface.sBannedDefines.contains(tag.getTagId())) { + assertTrue(getImageTitle(), t != null); + } else { + return; + } + if (t == tag) + return; + assertTrue(getImageTitle(), tag.equals(t)); + assertTrue(getImageTitle(), tag.getDataType() == t.getDataType()); + assertTrue(getImageTitle(), tag.getTagId() == t.getTagId()); + assertTrue(getImageTitle(), tag.getIfd() == t.getIfd()); + assertTrue(getImageTitle(), tag.getComponentCount() == t.getComponentCount()); + } + + private void checkTagsAgainstHash(List tags, Map testTags) { + for (ExifTag t : tags) { + checkTagAgainstHash(t, testTags); + } + } + + private void checkBitmap(InputStream inputStream) throws IOException { + Bitmap bmp = BitmapFactory.decodeStream(inputStream); + assertTrue(getImageTitle(), bmp != null); + } + +} diff --git a/tests/src/com/android/gallery3d/exif/ExifModifierTest.java b/tests/src/com/android/gallery3d/exif/ExifModifierTest.java index 14e956fd3..713a9d94f 100644 --- a/tests/src/com/android/gallery3d/exif/ExifModifierTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifModifierTest.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.gallery3d.exif; import java.io.File; @@ -30,47 +31,16 @@ public class ExifModifierTest extends ExifXmlDataTestCase { private File mTmpFile; private List>> mGroundTruth; - - // TYPE_UNDEFINED with 4 components - private static final ExifTag sVersionTag = ExifTag.buildTag(ExifTag.TAG_EXIF_VERSION); - // TYPE_UNSIGNED_BYTE with 4 components - private static final ExifTag sGpsVersionTag = ExifTag.buildTag(ExifTag.TAG_GPS_VERSION_ID); - // TYPE ASCII with arbitary length - private static final ExifTag sModelTag = ExifTag.buildTag(ExifTag.TAG_MODEL); - // TYPE_ASCII with 20 components - private static final ExifTag sDateTimeTag = ExifTag.buildTag(ExifTag.TAG_DATE_TIME); - // TYPE_UNSIGNED_SHORT with 1 components - private static final ExifTag sCompressionTag = ExifTag.buildTag(ExifTag.TAG_COMPRESSION); - // TYPE_UNSIGNED_LONG with 1 components - private static final ExifTag sThumbnailFormatTag = - ExifTag.buildTag(ExifTag.TAG_JPEG_INTERCHANGE_FORMAT); - // TYPE_UNSIGNED_RATIONAL with 3 components - private static final ExifTag sLongitudeTag = ExifTag.buildTag(ExifTag.TAG_GPS_LONGITUDE); - // TYPE_RATIONAL with 1 components - private static final ExifTag sShutterTag = ExifTag.buildTag(ExifTag.TAG_SHUTTER_SPEED_VALUE); - - private static final Map sTestTags = new HashMap(); - - static { - sVersionTag.setValue(new byte[] {1, 2, 3, 4}); - sGpsVersionTag.setValue(new byte[] {4, 3, 2, 1}); - sModelTag.setValue("end-of-the-world"); - sDateTimeTag.setValue("2012:12:31 23:59:59"); - sCompressionTag.setValue(100); - sThumbnailFormatTag.setValue(100); - sLongitudeTag.setValue(new Rational[] {new Rational(1, 1), new Rational(10, 10), - new Rational(100, 100)}); - sShutterTag.setValue(new Rational(1, 1)); - - sTestTags.put(sVersionTag.getTagId(), sVersionTag); - sTestTags.put(sGpsVersionTag.getTagId(), sGpsVersionTag); - sTestTags.put(sModelTag.getTagId(), sModelTag); - sTestTags.put(sDateTimeTag.getTagId(), sDateTimeTag); - sTestTags.put(sCompressionTag.getTagId(), sCompressionTag); - sTestTags.put(sThumbnailFormatTag.getTagId(), sThumbnailFormatTag); - sTestTags.put(sLongitudeTag.getTagId(), sLongitudeTag); - sTestTags.put(sShutterTag.getTagId(), sShutterTag); - } + private ExifInterface mInterface; + private Map mTestTags; + ExifTag mVersionTag; + ExifTag mGpsVersionTag; + ExifTag mModelTag; + ExifTag mDateTimeTag; + ExifTag mCompressionTag; + ExifTag mThumbnailFormatTag; + ExifTag mLongitudeTag; + ExifTag mShutterTag; @Override public void setUp() throws Exception { @@ -89,14 +59,53 @@ public class ExifModifierTest extends ExifXmlDataTestCase { } finally { Util.closeSilently(os); } + + // TYPE_UNDEFINED with 4 components + mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] { + 1, 2, 3, 4 + }); + // TYPE_UNSIGNED_BYTE with 4 components + mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] { + 4, 3, 2, 1 + }); + // TYPE ASCII with arbitary length + mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "end-of-the-world"); + // TYPE_ASCII with 20 components + mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2012:12:31 23:59:59"); + // TYPE_UNSIGNED_SHORT with 1 components + mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100); + // TYPE_UNSIGNED_LONG with 1 components + mThumbnailFormatTag = + mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100); + // TYPE_UNSIGNED_RATIONAL with 3 components + mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] { + new Rational(1, 1), new Rational(10, 10), + new Rational(100, 100) + }); + // TYPE_RATIONAL with 1 components + mShutterTag = mInterface + .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(1, 1)); + + mTestTags = new HashMap(); + + mTestTags.put(mVersionTag.getTagId(), mVersionTag); + mTestTags.put(mGpsVersionTag.getTagId(), mGpsVersionTag); + mTestTags.put(mModelTag.getTagId(), mModelTag); + mTestTags.put(mDateTimeTag.getTagId(), mDateTimeTag); + mTestTags.put(mCompressionTag.getTagId(), mCompressionTag); + mTestTags.put(mThumbnailFormatTag.getTagId(), mThumbnailFormatTag); + mTestTags.put(mLongitudeTag.getTagId(), mLongitudeTag); + mTestTags.put(mShutterTag.getTagId(), mShutterTag); } public ExifModifierTest(int imageRes, int xmlRes) { super(imageRes, xmlRes); + mInterface = new ExifInterface(); } public ExifModifierTest(String imagePath, String xmlPath) { super(imagePath, xmlPath); + mInterface = new ExifInterface(); } public void testModify() throws Exception { @@ -106,8 +115,8 @@ public class ExifModifierTest extends ExifXmlDataTestCase { try { file = new RandomAccessFile(mTmpFile, "rw"); MappedByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, file.length()); - for (ExifTag tag: sTestTags.values()) { - ExifModifier modifier = new ExifModifier(buf); + for (ExifTag tag : mTestTags.values()) { + ExifModifier modifier = new ExifModifier(buf, mInterface); modifier.modifyTag(tag); boolean result = modifier.commit(); results.put(tag.getTagId(), result); @@ -116,8 +125,8 @@ public class ExifModifierTest extends ExifXmlDataTestCase { if (!result) { List value = mGroundTruth.get(tag.getIfd()).get(tag.getTagId()); - assertTrue (String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), - value == null || tag.getTagId() == ExifTag.TAG_MODEL); + assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), + value == null || tag.getTagId() == ExifInterface.TAG_MODEL); } } } finally { @@ -128,7 +137,7 @@ public class ExifModifierTest extends ExifXmlDataTestCase { InputStream is = null; try { is = new FileInputStream(mTmpFile); - ExifData data = new ExifReader().read(is); + ExifData data = new ExifReader(mInterface).read(is); for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { checkIfd(data.getIfdData(i), mGroundTruth.get(i), results); } @@ -138,20 +147,21 @@ public class ExifModifierTest extends ExifXmlDataTestCase { } - private void checkIfd(IfdData ifd, Map> ifdValue, Map results) { if (ifd == null) { - assertEquals(getImageTitle(), 0 ,ifdValue.size()); + assertEquals(getImageTitle(), 0, ifdValue.size()); return; } ExifTag[] tags = ifd.getAllTags(); for (ExifTag tag : tags) { List truth = ifdValue.get(tag.getTagId()); assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth); - if (truth.contains(null)) continue; + if (truth.contains(null)) { + continue; + } - ExifTag newTag = sTestTags.get(tag.getTagId()); + ExifTag newTag = mTestTags.get(tag.getTagId()); if (newTag != null && results.get(tag.getTagId())) { assertEquals(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java index 789fd3563..8c4fc3dea 100644 --- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java @@ -20,17 +20,18 @@ 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; -import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; public class ExifOutputStreamTest extends ExifXmlDataTestCase { private File mTmpFile; + private ExifInterface mInterface; + @Override public void setUp() throws Exception { super.setUp(); @@ -39,10 +40,12 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { public ExifOutputStreamTest(int imgRes, int xmlRes) { super(imgRes, xmlRes); + mInterface = new ExifInterface(); } public ExifOutputStreamTest(String imgPath, String xmlPath) { super(imgPath, xmlPath); + mInterface = new ExifInterface(); } public void testExifOutputStream() throws Exception { @@ -50,58 +53,84 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { InputStream exifInputStream = null; FileInputStream reDecodeInputStream = null; FileInputStream reParseInputStream = null; + + InputStream dangerInputStream = null; + OutputStream dangerOutputStream = null; try { try { - byte[] imgData = readToByteArray(getImageInputStream()); + byte[] imgData = Util.readToByteArray(getImageInputStream()); imageInputStream = new ByteArrayInputStream(imgData); exifInputStream = new ByteArrayInputStream(imgData); // Read the image data Bitmap bmp = BitmapFactory.decodeStream(imageInputStream); // The image is invalid - if (bmp == null) return; + if (bmp == null) { + return; + } // Read exif data - ExifData exifData = new ExifReader().read(exifInputStream); + ExifData exifData = new ExifReader(mInterface).read(exifInputStream); // Encode the image with the exif data FileOutputStream outputStream = new FileOutputStream(mTmpFile); - ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream); + ExifOutputStream exifOutputStream = new ExifOutputStream(outputStream, mInterface); exifOutputStream.setExifData(exifData); - bmp.compress(Bitmap.CompressFormat.JPEG, 100, exifOutputStream); + bmp.compress(Bitmap.CompressFormat.JPEG, 90, exifOutputStream); exifOutputStream.close(); + exifOutputStream = null; // Re-decode the temp file and check the data. reDecodeInputStream = new FileInputStream(mTmpFile); Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream); assertNotNull(getImageTitle(), decodedBmp); + reDecodeInputStream.close(); // Re-parse the temp file the check EXIF tag reParseInputStream = new FileInputStream(mTmpFile); - ExifData reExifData = new ExifReader().read(reParseInputStream); + ExifData reExifData = new ExifReader(mInterface).read(reParseInputStream); + assertEquals(getImageTitle(), exifData, reExifData); + reParseInputStream.close(); + + // Try writing exif to file with existing exif. + dangerOutputStream = (OutputStream) new FileOutputStream(mTmpFile); + exifOutputStream = new ExifOutputStream(dangerOutputStream, mInterface); + exifOutputStream.setExifData(exifData); + exifOutputStream.write(imgData); + // exifOutputStream.write(strippedImgData); + exifOutputStream.close(); + exifOutputStream = null; + + // Make sure it still can be parsed into a bitmap. + dangerInputStream = (InputStream) new FileInputStream(mTmpFile); + decodedBmp = null; + decodedBmp = BitmapFactory.decodeStream(dangerInputStream); + assertNotNull(getImageTitle(), decodedBmp); + dangerInputStream.close(); + dangerInputStream = null; + + // Make sure exif is still well-formatted. + dangerInputStream = (InputStream) new FileInputStream(mTmpFile); + reExifData = null; + reExifData = new ExifReader(mInterface).read(dangerInputStream); assertEquals(getImageTitle(), exifData, reExifData); + dangerInputStream.close(); + dangerInputStream = null; + } finally { Util.closeSilently(imageInputStream); Util.closeSilently(exifInputStream); Util.closeSilently(reDecodeInputStream); Util.closeSilently(reParseInputStream); + + Util.closeSilently(dangerInputStream); + Util.closeSilently(dangerOutputStream); } } catch (Exception e) { throw new Exception(getImageTitle(), e); } } - 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(); - } - @Override public void tearDown() throws Exception { super.tearDown(); diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java index 7a9d6e631..5c3fd24ef 100644 --- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifParserTest.java @@ -25,12 +25,16 @@ import java.util.Map; public class ExifParserTest extends ExifXmlDataTestCase { private static final String TAG = "ExifParserTest"; + private ExifInterface mInterface; + public ExifParserTest(int imgRes, int xmlRes) { super(imgRes, xmlRes); + mInterface = new ExifInterface(); } public ExifParserTest(String imgPath, String xmlPath) { super(imgPath, xmlPath); + mInterface = new ExifInterface(); } private List>> mGroundTruth; @@ -43,7 +47,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { public void testParse() throws Exception { try { - ExifParser parser = ExifParser.parse(getImageInputStream()); + ExifParser parser = ExifParser.parse(getImageInputStream(), mInterface); int event = parser.next(); while (event != ExifParser.EVENT_END) { switch (event) { @@ -62,7 +66,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { if (tag.getDataType() == ExifTag.TYPE_UNDEFINED) { byte[] buf = new byte[tag.getComponentCount()]; parser.read(buf); - tag.setValue(buf); + assertTrue(TAG, tag.setValue(buf)); } checkTag(tag); break; @@ -82,7 +86,9 @@ public class ExifParserTest extends ExifXmlDataTestCase { } // No value from exiftool. - if (truth.contains(null)) return; + if (truth.contains(null)) { + return; + } String dataString = Util.tagValueToString(tag).trim(); assertTrue(String.format("Tag %02x", tag.getTagId()) + ", " + getImageTitle() @@ -94,9 +100,9 @@ public class ExifParserTest extends ExifXmlDataTestCase { try { Map> expectedResult = mGroundTruth.get(ifd); int numOfTag = 0; - ExifParser parser = ExifParser.parse(getImageInputStream(), options); + ExifParser parser = ExifParser.parse(getImageInputStream(), options, mInterface); int event = parser.next(); - while(event != ExifParser.EVENT_END) { + while (event != ExifParser.EVENT_END) { switch (event) { case ExifParser.EVENT_START_OF_IFD: assertEquals(getImageTitle(), ifd, parser.getCurrentIfd()); @@ -150,10 +156,13 @@ public class ExifParserTest extends ExifXmlDataTestCase { public void testOnlyReadSomeTag() throws Exception { // Do not do this test if there is no model tag. - if (mGroundTruth.get(IfdId.TYPE_IFD_0).get(ExifTag.TAG_MODEL) == null) return; + if (mGroundTruth.get(IfdId.TYPE_IFD_0).get(ExifInterface.TAG_MODEL) == null) { + return; + } try { - ExifParser parser = ExifParser.parse(getImageInputStream(), ExifParser.OPTION_IFD_0); + ExifParser parser = ExifParser.parse(getImageInputStream(), ExifParser.OPTION_IFD_0, + mInterface); int event = parser.next(); boolean isTagFound = false; while (event != ExifParser.EVENT_END) { @@ -163,7 +172,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { break; case ExifParser.EVENT_NEW_TAG: ExifTag tag = parser.getTag(); - if (tag.getTagId() == ExifTag.TAG_MODEL) { + if (tag.getTagId() == ExifInterface.TAG_MODEL) { if (tag.hasValue()) { isTagFound = true; checkTag(tag); @@ -175,7 +184,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { break; case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: tag = parser.getTag(); - assertEquals(getImageTitle(), ExifTag.TAG_MODEL, tag.getTagId()); + assertEquals(getImageTitle(), ExifInterface.TAG_MODEL, tag.getTagId()); checkTag(tag); isTagFound = true; break; @@ -191,7 +200,7 @@ public class ExifParserTest extends ExifXmlDataTestCase { public void testReadThumbnail() throws Exception { try { ExifParser parser = ExifParser.parse(getImageInputStream(), - ExifParser.OPTION_IFD_1 | ExifParser.OPTION_THUMBNAIL); + ExifParser.OPTION_IFD_1 | ExifParser.OPTION_THUMBNAIL, mInterface); int event = parser.next(); Bitmap bmp = null; @@ -200,8 +209,8 @@ public class ExifParserTest extends ExifXmlDataTestCase { switch (event) { case ExifParser.EVENT_NEW_TAG: ExifTag tag = parser.getTag(); - if (tag.getTagId() == ExifTag.TAG_COMPRESSION) { - if (tag.getValueAt(0) == ExifTag.Compression.JPEG) { + if (tag.getTagId() == ExifInterface.TAG_COMPRESSION) { + if (tag.getValueAt(0) == ExifInterface.Compression.JPEG) { mIsContainCompressedImage = true; } } diff --git a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java index 30f34c09a..a05718626 100644 --- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java @@ -24,6 +24,7 @@ import java.util.Map; public class ExifReaderTest extends ExifXmlDataTestCase { private static final String TAG = "ExifReaderTest"; + private ExifInterface mInterface; private List>> mGroundTruth; @Override @@ -34,15 +35,17 @@ public class ExifReaderTest extends ExifXmlDataTestCase { public ExifReaderTest(int imgRes, int xmlRes) { super(imgRes, xmlRes); + mInterface = new ExifInterface(); } public ExifReaderTest(String imgPath, String xmlPath) { super(imgPath, xmlPath); + mInterface = new ExifInterface(); } public void testRead() throws Exception { try { - ExifReader reader = new ExifReader(); + ExifReader reader = new ExifReader(mInterface); ExifData exifData = reader.read(getImageInputStream()); for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { checkIfd(exifData.getIfdData(i), mGroundTruth.get(i)); @@ -56,59 +59,76 @@ public class ExifReaderTest extends ExifXmlDataTestCase { private void checkThumbnail(ExifData exifData) { Map> ifd1Truth = mGroundTruth.get(IfdId.TYPE_IFD_1); - List typeTagValue = ifd1Truth.get(ExifTag.TAG_COMPRESSION); - if (typeTagValue == null) return; + List typeTagValue = ifd1Truth.get(ExifInterface.TAG_COMPRESSION); + if (typeTagValue == null) + return; IfdData ifd1 = exifData.getIfdData(IfdId.TYPE_IFD_1); - if (ifd1 == null) fail(getImageTitle() + ": failed to find IFD1"); + if (ifd1 == null) + fail(getImageTitle() + ": failed to find IFD1"); String typeTagTruth = typeTagValue.get(0); - int type = (int) ifd1.getTag(ExifTag.TAG_COMPRESSION).getValueAt(0); + int type = (int) ifd1.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_COMPRESSION)) + .getValueAt(0); - if (String.valueOf(ExifTag.Compression.JPEG).equals(typeTagTruth)) { - assertTrue(getImageTitle(), type == ExifTag.Compression.JPEG); + if (String.valueOf(ExifInterface.Compression.JPEG).equals(typeTagTruth)) { + assertTrue(getImageTitle(), type == ExifInterface.Compression.JPEG); assertTrue(getImageTitle(), exifData.hasCompressedThumbnail()); byte[] thumbnail = exifData.getCompressedThumbnail(); assertTrue(getImageTitle(), BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length) != null); - } else if (String.valueOf(ExifTag.Compression.UNCOMPRESSION).equals(typeTagTruth)) { - assertTrue(getImageTitle(), type == ExifTag.Compression.UNCOMPRESSION); + } else if (String.valueOf(ExifInterface.Compression.UNCOMPRESSION).equals(typeTagTruth)) { + assertTrue(getImageTitle(), type == ExifInterface.Compression.UNCOMPRESSION); // Try to check the strip count with the formula provided by EXIF spec. - int planarType = ExifTag.PlanarConfiguration.CHUNKY; - ExifTag planarTag = ifd1.getTag(ExifTag.TAG_PLANAR_CONFIGURATION); + int planarType = ExifInterface.PlanarConfiguration.CHUNKY; + ExifTag planarTag = ifd1.getTag(ExifInterface + .getTrueTagKey(ExifInterface.TAG_PLANAR_CONFIGURATION)); if (planarTag != null) { planarType = (int) planarTag.getValueAt(0); } - if (!ifd1Truth.containsKey(ExifTag.TAG_IMAGE_LENGTH) || - !ifd1Truth.containsKey(ExifTag.TAG_ROWS_PER_STRIP)) return; + if (!ifd1Truth.containsKey(ExifInterface.TAG_IMAGE_LENGTH) || + !ifd1Truth.containsKey(ExifInterface.TAG_ROWS_PER_STRIP)) { + return; + } - ExifTag heightTag = ifd1.getTag(ExifTag.TAG_IMAGE_LENGTH); - ExifTag rowPerStripTag = ifd1.getTag(ExifTag.TAG_ROWS_PER_STRIP); + ExifTag heightTag = ifd1.getTag(ExifInterface + .getTrueTagKey(ExifInterface.TAG_IMAGE_LENGTH)); + ExifTag rowPerStripTag = ifd1.getTag(ExifInterface + .getTrueTagKey(ExifInterface.TAG_ROWS_PER_STRIP)); // Fail the test if required tags are missing - if (heightTag == null || rowPerStripTag == null) fail(getImageTitle()); + if (heightTag == null || rowPerStripTag == null) { + fail(getImageTitle()); + } int imageLength = (int) heightTag.getValueAt(0); int rowsPerStrip = (int) rowPerStripTag.getValueAt(0); int stripCount = ifd1.getTag( - ExifTag.TAG_STRIP_OFFSETS).getComponentCount(); + ExifInterface.getTrueTagKey(ExifInterface.TAG_STRIP_OFFSETS)) + .getComponentCount(); - if (planarType == ExifTag.PlanarConfiguration.CHUNKY) { + if (planarType == ExifInterface.PlanarConfiguration.CHUNKY) { assertTrue(getImageTitle(), stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip); } else { - if (!ifd1Truth.containsKey(ExifTag.TAG_SAMPLES_PER_PIXEL)) return; - ExifTag samplePerPixelTag = ifd1.getTag(ExifTag.TAG_SAMPLES_PER_PIXEL); + if (!ifd1Truth.containsKey(ExifInterface.TAG_SAMPLES_PER_PIXEL)) { + return; + } + ExifTag samplePerPixelTag = ifd1.getTag(ExifInterface + .getTrueTagKey(ExifInterface.TAG_SAMPLES_PER_PIXEL)); int samplePerPixel = (int) samplePerPixelTag.getValueAt(0); assertTrue(getImageTitle(), stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel); } - if (!ifd1Truth.containsKey(ExifTag.TAG_STRIP_BYTE_COUNTS)) return; - ExifTag byteCountTag = ifd1.getTag(ExifTag.TAG_STRIP_BYTE_COUNTS); + if (!ifd1Truth.containsKey(ExifInterface.TAG_STRIP_BYTE_COUNTS)) { + return; + } + ExifTag byteCountTag = ifd1.getTag(ExifInterface + .getTrueTagKey(ExifInterface.TAG_STRIP_BYTE_COUNTS)); short byteCountDataType = byteCountTag.getDataType(); for (int i = 0; i < stripCount; i++) { if (byteCountDataType == ExifTag.TYPE_UNSIGNED_SHORT) { @@ -124,14 +144,16 @@ public class ExifReaderTest extends ExifXmlDataTestCase { private void checkIfd(IfdData ifd, Map> ifdValue) { if (ifd == null) { - assertEquals(getImageTitle(), 0 ,ifdValue.size()); + assertEquals(getImageTitle(), 0, ifdValue.size()); return; } ExifTag[] tags = ifd.getAllTags(); for (ExifTag tag : tags) { List truth = ifdValue.get(tag.getTagId()); assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth); - if (truth.contains(null)) continue; + if (truth.contains(null)) { + continue; + } assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth.contains(Util.tagValueToString(tag).trim())); } diff --git a/tests/src/com/android/gallery3d/exif/ExifTagTest.java b/tests/src/com/android/gallery3d/exif/ExifTagTest.java index 128956dee..59067c3fe 100644 --- a/tests/src/com/android/gallery3d/exif/ExifTagTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifTagTest.java @@ -18,27 +18,83 @@ package com.android.gallery3d.exif; import junit.framework.TestCase; +import java.util.HashMap; +import java.util.Map; + public class ExifTagTest extends TestCase { private static long MAX_UNSIGNED_LONG = (1L << 32) - 1; private static int MAX_LONG = Integer.MAX_VALUE; private static int MIN_LONG = Integer.MIN_VALUE; - private static final ExifTag sTestTags[] = { - ExifTag.buildTag(ExifTag.TAG_EXIF_VERSION), // TYPE_UNDEFINED with 4 components - ExifTag.buildTag(ExifTag.TAG_GPS_VERSION_ID), // TYPE_UNSIGNED_BYTE with 4 components - ExifTag.buildTag(ExifTag.TAG_DATE_TIME), // TYPE_ASCII with 20 components - ExifTag.buildTag(ExifTag.TAG_COMPRESSION), // TYPE_UNSIGNED_SHORT with 1 components + Map mTestTags; + ExifInterface mInterface; + private ExifTag mVersionTag; + private ExifTag mGpsVersionTag; + private ExifTag mModelTag; + private ExifTag mDateTimeTag; + private ExifTag mCompressionTag; + private ExifTag mThumbnailFormatTag; + private ExifTag mLongitudeTag; + private ExifTag mShutterTag; + private ExifTag mInteropIndex; + + @Override + public void setUp() throws Exception { + super.setUp(); + mInterface = new ExifInterface(); + + // TYPE_UNDEFINED with 4 components + mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] { + 5, 4, 3, 2 + }); + // TYPE_UNSIGNED_BYTE with 4 components + mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] { + 6, 7, 8, 9 + }); + // TYPE ASCII with arbitrary length + mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "helloworld"); + // TYPE_ASCII with 20 components + mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2013:02:11 20:20:20"); + // TYPE_UNSIGNED_SHORT with 1 components + mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100); // TYPE_UNSIGNED_LONG with 1 components - ExifTag.buildTag(ExifTag.TAG_JPEG_INTERCHANGE_FORMAT), - ExifTag.buildTag(ExifTag.TAG_GPS_LONGITUDE), // TYPE_UNSIGNED_RATIONAL with 3 components - ExifTag.buildTag(ExifTag.TAG_SHUTTER_SPEED_VALUE), // TYPE_RATIONAL with 1 components - // There is no tag defined with TYPE_LONG. Create a dummy one for testing. - new ExifTag((short) 0, ExifTag.TYPE_LONG, 1, 0) - }; + mThumbnailFormatTag = + mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100); + // TYPE_UNSIGNED_RATIONAL with 3 components + mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] { + new Rational(2, 2), new Rational(11, 11), + new Rational(102, 102) + }); + // TYPE_RATIONAL with 1 components + mShutterTag = mInterface + .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(4, 6)); + // TYPE_ASCII with arbitrary length + mInteropIndex = mInterface.buildTag(ExifInterface.TAG_INTEROPERABILITY_INDEX, "foo"); + + mTestTags = new HashMap(); + + mTestTags.put(ExifInterface.TAG_EXIF_VERSION, mVersionTag); + mTestTags.put(ExifInterface.TAG_GPS_VERSION_ID, mGpsVersionTag); + mTestTags.put(ExifInterface.TAG_MODEL, mModelTag); + mTestTags.put(ExifInterface.TAG_DATE_TIME, mDateTimeTag); + mTestTags.put(ExifInterface.TAG_COMPRESSION, mCompressionTag); + mTestTags.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, mThumbnailFormatTag); + mTestTags.put(ExifInterface.TAG_GPS_LONGITUDE, mLongitudeTag); + mTestTags.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, mShutterTag); + mTestTags.put(ExifInterface.TAG_INTEROPERABILITY_INDEX, mInteropIndex); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + mInterface = null; + mTestTags = null; + } public void testValueType() { - for (ExifTag tag: sTestTags) { + for (ExifTag tag : mTestTags.values()) { + assertTrue(tag != null); int count = tag.getComponentCount(); int intBuf[] = new int[count]; long longBuf[] = new long[count]; @@ -51,7 +107,11 @@ public class ExifTagTest extends TestCase { byteBuf[i] = 0; rationalBuf[i] = new Rational(0, 0); // The string size should equal to component count - 1 - if (i != 0) sb.append("*"); + if (i != count - 1) { + sb.append("*"); + } else { + sb.append("\0"); + } } String strBuf = sb.toString(); @@ -66,141 +126,90 @@ public class ExifTagTest extends TestCase { } private void checkTypeByte(ExifTag tag, byte[] buf) { - boolean excepThrow = false; short type = tag.getDataType(); - try { - tag.setValue(buf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - assertTrue("Tag ID: " + tag.getTagId(), - (type == ExifTag.TYPE_UNDEFINED || type == ExifTag.TYPE_UNSIGNED_BYTE) - ^ excepThrow); + assertFalse("\nTag: " + tag.toString(), tag.setValue(buf) + ^ (type == ExifTag.TYPE_UNDEFINED || type == ExifTag.TYPE_UNSIGNED_BYTE)); } private void checkTypeAscii(ExifTag tag, String str) { - boolean excepThrow = false; - try { - tag.setValue(str); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - assertTrue("Tag ID: " + tag.getTagId(), - tag.getDataType() == ExifTag.TYPE_ASCII ^ excepThrow); + short type = tag.getDataType(); + assertFalse("\nTag: " + tag.toString(), tag.setValue(str) + ^ (type == ExifTag.TYPE_ASCII || type == ExifTag.TYPE_UNDEFINED)); } private void checkTypeUnsignedShort(ExifTag tag, int[] intBuf) { - boolean excepThrow = false; short type = tag.getDataType(); - try { - tag.setValue(intBuf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - assertTrue("Tag ID: " + tag.getTagId(), - (type == ExifTag.TYPE_UNSIGNED_SHORT - || type == ExifTag.TYPE_UNSIGNED_LONG || type == ExifTag.TYPE_LONG) ^ excepThrow); + assertFalse("\nTag: " + tag.toString(), + tag.setValue(intBuf) + ^ (type == ExifTag.TYPE_UNSIGNED_SHORT + || type == ExifTag.TYPE_UNSIGNED_LONG + || type == ExifTag.TYPE_LONG)); } private void checkTypeUnsignedLong(ExifTag tag, int[] intBuf, long[] longBuf) { // Test value only for unsigned long. - boolean excepThrow = false; int count = intBuf.length; - try { - intBuf[count - 1] = MAX_LONG; - tag.setValue(intBuf); - longBuf[count - 1] = MAX_UNSIGNED_LONG; - tag.setValue(longBuf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - intBuf[count - 1] = 0; - assertTrue("Tag ID: " + tag.getTagId(), - tag.getDataType() == ExifTag.TYPE_UNSIGNED_LONG ^ excepThrow); + intBuf[count - 1] = MAX_LONG; + tag.setValue(intBuf); + longBuf[count - 1] = MAX_UNSIGNED_LONG; + assertFalse("\nTag: " + tag.toString(), tag.setValue(longBuf) + ^ (tag.getDataType() == ExifTag.TYPE_UNSIGNED_LONG)); + intBuf[count - 1] = 0; // Test invalid value for all type. - try { - longBuf[count - 1] = MAX_UNSIGNED_LONG + 1; - tag.setValue(longBuf); - fail(); - } catch (IllegalArgumentException expected) {} + longBuf[count - 1] = MAX_UNSIGNED_LONG + 1; + assertFalse(tag.setValue(longBuf)); longBuf[count - 1] = 0; } private void checkTypeLong(ExifTag tag, int[] intBuf) { - boolean excepThrow = false; int count = intBuf.length; - try { - intBuf[count - 1] = MAX_LONG; - tag.setValue(intBuf); - intBuf[count - 1] = MIN_LONG; - tag.setValue(intBuf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } + intBuf[count - 1] = MAX_LONG; + tag.setValue(intBuf); + intBuf[count - 1] = MIN_LONG; + + assertFalse("\nTag: " + tag.toString(), tag.setValue(intBuf) + ^ (tag.getDataType() == ExifTag.TYPE_LONG)); intBuf[count - 1] = 0; - assertTrue("Tag ID: " + tag.getTagId(), - tag.getDataType() == ExifTag.TYPE_LONG ^ excepThrow); } private void checkTypeRational(ExifTag tag, Rational rationalBuf[]) { - boolean excepThrow = false; int count = rationalBuf.length; Rational r = rationalBuf[count - 1]; - try { - rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG); - tag.setValue(rationalBuf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - assertTrue("Tag ID: " + tag.getTagId(), - tag.getDataType() == ExifTag.TYPE_RATIONAL ^ excepThrow); + rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG); + + assertFalse("\nTag: " + tag.toString(), tag.setValue(rationalBuf) + ^ (tag.getDataType() == ExifTag.TYPE_RATIONAL)); - if(tag.getDataType() == ExifTag.TYPE_RATIONAL) { + if (tag.getDataType() == ExifTag.TYPE_RATIONAL) { // check overflow - try { - rationalBuf[count - 1] = new Rational(MAX_LONG + 1L, MIN_LONG); - tag.setValue(rationalBuf); - fail(); - } catch (IllegalArgumentException expected) {} - - try { - rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG - 1L); - tag.setValue(rationalBuf); - fail(); - } catch (IllegalArgumentException expected) {} + + rationalBuf[count - 1] = new Rational(MAX_LONG + 1L, MIN_LONG); + assertFalse(tag.setValue(rationalBuf)); + + rationalBuf[count - 1] = new Rational(MAX_LONG, MIN_LONG - 1L); + assertFalse(tag.setValue(rationalBuf)); } rationalBuf[count - 1] = r; } private void checkTypeUnsignedRational(ExifTag tag, Rational rationalBuf[]) { - boolean excepThrow = false; int count = rationalBuf.length; Rational r = rationalBuf[count - 1]; - try { - rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, MAX_UNSIGNED_LONG); - tag.setValue(rationalBuf); - } catch (IllegalArgumentException e) { - excepThrow = true; - } - assertTrue("Tag ID: " + tag.getTagId(), - tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL ^ excepThrow); + rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, MAX_UNSIGNED_LONG); - if(tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL) { + assertFalse("\nTag: " + tag.toString(), tag.setValue(rationalBuf) + ^ (tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL)); + + if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_RATIONAL) { // check overflow - try { - rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG + 1, 0); - tag.setValue(rationalBuf); - fail(); - } catch (IllegalArgumentException expected) {} - - try { - rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, -1); - tag.setValue(rationalBuf); - fail(); - } catch (IllegalArgumentException expected) {} + rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG + 1, 0); + assertFalse(tag.setValue(rationalBuf)); + + rationalBuf[count - 1] = new Rational(MAX_UNSIGNED_LONG, -1); + assertFalse(tag.setValue(rationalBuf)); } rationalBuf[count - 1] = r; } diff --git a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java index b09426328..162baea29 100644 --- a/tests/src/com/android/gallery3d/exif/ExifTestRunner.java +++ b/tests/src/com/android/gallery3d/exif/ExifTestRunner.java @@ -37,11 +37,11 @@ public class ExifTestRunner extends InstrumentationTestRunner { private static final String TAG = "ExifTestRunner"; private static final int[] IMG_RESOURCE = { - R.raw.galaxy_nexus + R.raw.galaxy_nexus }; private static final int[] EXIF_DATA_RESOURCE = { - R.xml.galaxy_nexus + R.xml.galaxy_nexus }; private static List mTestImgPath = new ArrayList(); @@ -57,6 +57,7 @@ public class ExifTestRunner extends InstrumentationTestRunner { addAllTestsFromExifTestCase(ExifReaderTest.class, suite); addAllTestsFromExifTestCase(ExifOutputStreamTest.class, suite); addAllTestsFromExifTestCase(ExifModifierTest.class, suite); + addAllTestsFromExifTestCase(ExifInterfaceTest.class, suite); return suite; } @@ -67,8 +68,10 @@ public class ExifTestRunner extends InstrumentationTestRunner { if (imgDir != null && xmlDir != null) { String[] imgs = imgDir.list(); - if (imgs == null) return; - for (String imgName: imgs) { + 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()) { diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java index 811b0a6c3..5f200ea92 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.android.gallery3d.exif; import android.content.res.Resources; diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java index bb08ccd1c..12e9cf77e 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlReader.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlReader.java @@ -110,14 +110,14 @@ public class ExifXmlReader { } else if (INTEROP_IFD.equals(prefix)) { return IfdId.TYPE_IFD_INTEROPERABILITY; } else { - assert(false); + assert (false); return -1; } } static public int getTrueTagNumber(Map> ifdData) { int size = 0; - for (List tag: ifdData.values()) { + for (List tag : ifdData.values()) { size += tag.size(); } return size; diff --git a/tests/src/com/android/gallery3d/exif/Util.java b/tests/src/com/android/gallery3d/exif/Util.java index 0e51fd7bf..15de00714 100644 --- a/tests/src/com/android/gallery3d/exif/Util.java +++ b/tests/src/com/android/gallery3d/exif/Util.java @@ -16,7 +16,11 @@ package com.android.gallery3d.exif; +import java.io.ByteArrayOutputStream; import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; class Util { public static boolean equals(Object a, Object b) { @@ -24,7 +28,8 @@ class Util { } public static void closeSilently(Closeable c) { - if (c == null) return; + if (c == null) + return; try { c.close(); } catch (Throwable t) { @@ -32,6 +37,17 @@ class Util { } } + public static 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(); + } + /** * Tags that are not defined in the spec. */ @@ -45,27 +61,30 @@ class Util { StringBuilder sbuilder = new StringBuilder(); byte[] buf = new byte[tag.getComponentCount()]; tag.getBytes(buf); - switch (tag.getTagId()) { - case ExifTag.TAG_COMPONENTS_CONFIGURATION: - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); - sbuilder.append(buf[i]); + short tagId = tag.getTagId(); + if (tagId == ExifInterface.getTrueTagKey(ExifInterface.TAG_COMPONENTS_CONFIGURATION)) { + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + if (i != 0) { + sbuilder.append(" "); } - break; - default: - 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('.'); - } + sbuilder.append(buf[i]); + } + } else { + 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(); } @@ -81,15 +100,16 @@ class Util { sbuilder.append(tagUndefinedTypeValueToString(tag)); break; case ExifTag.TYPE_UNSIGNED_BYTE: - if (id == ExifTag.TAG_MAKER_NOTE || id == TAG_XP_TITLE || + if (id == ExifInterface.TAG_MAKER_NOTE || id == TAG_XP_TITLE || id == TAG_XP_COMMENT || id == TAG_XP_AUTHOR || id == TAG_XP_KEYWORDS || id == TAG_XP_SUBJECT) { sbuilder.append(tagUndefinedTypeValueToString(tag)); } else { byte[] buf = new byte[tag.getComponentCount()]; tag.getBytes(buf); - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + if (i != 0) + sbuilder.append(" "); sbuilder.append(buf[i]); } } @@ -100,7 +120,8 @@ class Util { byte code = buf[i]; if (code == 0) { // Treat some tag as undefined type data. - if (id == ExifTag.TAG_COPYRIGHT || id == ExifTag.TAG_GPS_DATE_STAMP) { + if (id == ExifInterface.TAG_COPYRIGHT + || id == ExifInterface.TAG_GPS_DATE_STAMP) { continue; } else { break; @@ -114,32 +135,61 @@ class Util { } break; case ExifTag.TYPE_UNSIGNED_LONG: - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + if (i != 0) { + sbuilder.append(" "); + } sbuilder.append(tag.getValueAt(i)); } break; case ExifTag.TYPE_RATIONAL: case ExifTag.TYPE_UNSIGNED_RATIONAL: - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { Rational r = tag.getRational(i); - if(i != 0) sbuilder.append(" "); - sbuilder.append(r.getNominator()).append("/").append(r.getDenominator()); + if (i != 0) { + sbuilder.append(" "); + } + sbuilder.append(r.getNumerator()).append("/").append(r.getDenominator()); } break; case ExifTag.TYPE_UNSIGNED_SHORT: - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + if (i != 0) { + sbuilder.append(" "); + } sbuilder.append((int) tag.getValueAt(i)); } break; case ExifTag.TYPE_LONG: - for(int i = 0, n = tag.getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); + for (int i = 0, n = tag.getComponentCount(); i < n; i++) { + if (i != 0) { + sbuilder.append(" "); + } sbuilder.append((int) tag.getValueAt(i)); } break; } return sbuilder.toString(); } + + public static String valueToString(Object obj) { + if (obj instanceof int[]) { + return Arrays.toString((int[]) obj); + } else if (obj instanceof Integer[]) { + return Arrays.toString((Integer[]) obj); + } else if (obj instanceof long[]) { + return Arrays.toString((long[]) obj); + } else if (obj instanceof Long[]) { + return Arrays.toString((Long[]) obj); + } else if (obj instanceof Rational) { + return ((Rational) obj).toString(); + } else if (obj instanceof Rational[]) { + return Arrays.toString((Rational[]) obj); + } else if (obj instanceof byte[]) { + return Arrays.toString((byte[]) obj); + } else if (obj != null) { + return obj.toString(); + } + return ""; + } } -- cgit v1.2.3