From bb2a49c89d344c9cc90a19dd4900fa9d4729321c Mon Sep 17 00:00:00 2001 From: Earl Ou Date: Wed, 24 Oct 2012 13:09:39 +0800 Subject: Handle wrong thumbnail tag type Change-Id: If41834f0aa86425a06aaede815f3e0c3cdd17fd9 --- .../src/com/android/gallery3d/exif/ExifParser.java | 6 ++ .../gallery3d/exif/ExifOutputStreamTest.java | 24 ++++- .../com/android/gallery3d/exif/ExifReaderTest.java | 109 +++++++++++++-------- 3 files changed, 94 insertions(+), 45 deletions(-) diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java index 36e3b4468..a6bbda078 100644 --- a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java +++ b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java @@ -450,6 +450,12 @@ public class ExifParser { */ public int getCompressedImageSize() { if (mJpegSizeTag == null) return 0; + + // Some invalid image use short type tag + if (mJpegSizeTag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { + return mJpegSizeTag.getUnsignedShort(0); + } + // Cast unsigned int to int since the thumbnail is always smaller // than the size of APP1 (65536) return (int) mJpegSizeTag.getUnsignedLong(0); diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java index 52ae9f3bb..8c98fa037 100644 --- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java @@ -28,6 +28,15 @@ import java.io.IOException; import java.io.InputStream; public class ExifOutputStreamTest extends ExifXmlDataTestCase { + + private File mTmpFile; + + @Override + public void setUp() throws Exception { + super.setUp(); + mTmpFile = File.createTempFile("exif_test", ".jpg"); + } + public ExifOutputStreamTest(int imgRes, int xmlRes) { super(imgRes, xmlRes); } @@ -37,7 +46,6 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { } public void testExifOutputStream() throws Exception { - File file = File.createTempFile("exif_test", ".jpg"); InputStream imageInputStream = null; InputStream exifInputStream = null; FileInputStream reDecodeInputStream = null; @@ -50,23 +58,26 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { // Read the image data Bitmap bmp = BitmapFactory.decodeStream(imageInputStream); + // The image is invalid + if (bmp == null) return; + // Read exif data ExifData exifData = new ExifReader().read(exifInputStream); // Encode the image with the exif data - FileOutputStream outputStream = new FileOutputStream(file); + FileOutputStream outputStream = new FileOutputStream(mTmpFile); 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); + reDecodeInputStream = new FileInputStream(mTmpFile); Bitmap decodedBmp = BitmapFactory.decodeStream(reDecodeInputStream); assertNotNull(getImageTitle(), decodedBmp); // Re-parse the temp file the check EXIF tag - reParseInputStream = new FileInputStream(file); + reParseInputStream = new FileInputStream(mTmpFile); ExifData reExifData = new ExifReader().read(reParseInputStream); assertEquals(getImageTitle(), exifData, reExifData); } finally { @@ -90,4 +101,9 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { bos.flush(); return bos.toByteArray(); } + + @Override + public void tearDown() { + mTmpFile.delete(); + } } diff --git a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java index 45a924239..374d5b034 100644 --- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java @@ -24,6 +24,14 @@ import java.util.Map; public class ExifReaderTest extends ExifXmlDataTestCase { private static final String TAG = "ExifReaderTest"; + private List>> mGroundTruth; + + @Override + public void setUp() throws Exception { + super.setUp(); + mGroundTruth = ExifXmlReader.readXml(getXmlParser()); + } + public ExifReaderTest(int imgRes, int xmlRes) { super(imgRes, xmlRes); } @@ -36,9 +44,8 @@ public class ExifReaderTest extends ExifXmlDataTestCase { try { ExifReader reader = new ExifReader(); ExifData exifData = reader.read(getImageInputStream()); - List>> groundTruth = ExifXmlReader.readXml(getXmlParser()); for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { - checkIfd(exifData.getIfdData(i), groundTruth.get(i)); + checkIfd(exifData.getIfdData(i), mGroundTruth.get(i)); } checkThumbnail(exifData); } catch (Exception e) { @@ -47,50 +54,70 @@ 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; + IfdData ifd1 = exifData.getIfdData(IfdId.TYPE_IFD_1); - if (ifd1 != null) { - int type = ifd1.getTag(ExifTag.TAG_COMPRESSION).getUnsignedShort(0); - if (type == ExifTag.Compression.JPEG) { - assertTrue(getImageTitle(), exifData.hasCompressedThumbnail()); - byte[] thumbnail = exifData.getCompressedThumbnail(); - assertTrue(getImageTitle(), - BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length) != null); - } else if (type == ExifTag.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); - if (planarTag != null) { - planarType = planarTag.getUnsignedShort(0); - } + if (ifd1 == null) fail(getImageTitle() + ": failed to find IFD1"); - ExifTag heightTag = ifd1.getTag(ExifTag.TAG_IMAGE_LENGTH); - ExifTag rowPerStripTag = ifd1.getTag(ExifTag.TAG_ROWS_PER_STRIP); + String typeTagTruth = typeTagValue.get(0); - int imageLength = getUnsignedIntOrShort(heightTag); - int rowsPerStrip = getUnsignedIntOrShort(rowPerStripTag); - int stripCount = ifd1.getTag( - ExifTag.TAG_STRIP_OFFSETS).getComponentCount(); + ExifTag typeTag = ifd1.getTag(ExifTag.TAG_COMPRESSION); + int type = typeTag.getUnsignedShort(0); - if (planarType == ExifTag.PlanarConfiguration.CHUNKY) { - assertTrue(getImageTitle(), - stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip); - } else { - ExifTag samplePerPixelTag = ifd1.getTag(ExifTag.TAG_SAMPLES_PER_PIXEL); - int samplePerPixel = samplePerPixelTag.getUnsignedShort(0); - assertTrue(getImageTitle(), - stripCount == - (imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel); - } + if (String.valueOf(ExifTag.Compression.JPEG).equals(typeTagTruth)) { + assertTrue(getImageTitle(), type == ExifTag.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); + // 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); + if (planarTag != null) { + planarType = planarTag.getUnsignedShort(0); + } - for (int i = 0; i < stripCount; i++) { - ExifTag byteCountTag = ifd1.getTag(ExifTag.TAG_STRIP_BYTE_COUNTS); - if (byteCountTag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { - assertEquals(getImageTitle(), - byteCountTag.getUnsignedShort(i), exifData.getStrip(i).length); - } else { - assertEquals(getImageTitle(), - byteCountTag.getUnsignedLong(i), exifData.getStrip(i).length); - } + if (!ifd1Truth.containsKey(ExifTag.TAG_IMAGE_LENGTH) || + !ifd1Truth.containsKey(ExifTag.TAG_ROWS_PER_STRIP)) return; + + ExifTag heightTag = ifd1.getTag(ExifTag.TAG_IMAGE_LENGTH); + ExifTag rowPerStripTag = ifd1.getTag(ExifTag.TAG_ROWS_PER_STRIP); + + // Fail the test if required tags are missing + if (heightTag == null || rowPerStripTag == null) fail(getImageTitle()); + + int imageLength = getUnsignedIntOrShort(heightTag); + int rowsPerStrip = getUnsignedIntOrShort(rowPerStripTag); + int stripCount = ifd1.getTag( + ExifTag.TAG_STRIP_OFFSETS).getComponentCount(); + + if (planarType == ExifTag.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); + int samplePerPixel = samplePerPixelTag.getUnsignedShort(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); + short byteCountDataType = byteCountTag.getDataType(); + for (int i = 0; i < stripCount; i++) { + if (byteCountDataType == ExifTag.TYPE_UNSIGNED_SHORT) { + assertEquals(getImageTitle(), + byteCountTag.getUnsignedShort(i), exifData.getStrip(i).length); + } else { + assertEquals(getImageTitle(), + byteCountTag.getUnsignedLong(i), exifData.getStrip(i).length); } } } -- cgit v1.2.3