From a393402c67ab65c322a1ce4c2f6714397591c363 Mon Sep 17 00:00:00 2001 From: Earl Ou Date: Wed, 29 Aug 2012 10:21:23 +0800 Subject: Redesign the set function of ExifTag Change-Id: Iaf5632d759fe14c167cba54099b99719b31e3431 --- src/com/android/gallery3d/exif/ExifParser.java | 15 +- src/com/android/gallery3d/exif/ExifTag.java | 200 +++++++++++++++------ .../com/android/gallery3d/exif/ExifParserTest.java | 2 +- .../com/android/gallery3d/exif/ExifReaderTest.java | 10 +- 4 files changed, 160 insertions(+), 67 deletions(-) diff --git a/src/com/android/gallery3d/exif/ExifParser.java b/src/com/android/gallery3d/exif/ExifParser.java index 268c989b0..f6ecd7798 100644 --- a/src/com/android/gallery3d/exif/ExifParser.java +++ b/src/com/android/gallery3d/exif/ExifParser.java @@ -405,7 +405,7 @@ public class ExifParser { */ public int getCompressedImageSize() { if (mJpegSizeTag == null) return 0; - return (int) mJpegSizeTag.getUnsignedInt(); + return (int) mJpegSizeTag.getUnsignedInt(0); } private void skipTo(int offset) throws IOException { @@ -449,7 +449,8 @@ public class ExifParser { "Number of component is larger then Integer.MAX_VALUE"); } ExifTag tag = new ExifTag(tagId, dataFormat, (int) numOfComp, mIfdType); - if (tag.getDataSize() > 4) { + int dataSize = tag.getDataSize(); + if (dataSize > 4) { long offset = mTiffStream.readUnsignedInt(); if (offset > Integer.MAX_VALUE) { throw new ExifInvalidFormatException( @@ -458,7 +459,7 @@ public class ExifParser { tag.setOffset((int) offset); } else { readFullTagValue(tag); - mTiffStream.skip(4 - tag.getDataSize()); + mTiffStream.skip(4 - dataSize); } return tag; } @@ -472,22 +473,22 @@ public class ExifParser { case ExifTag.TIFF_TAG.TAG_EXIF_IFD: if (isIfdRequested(IfdId.TYPE_IFD_EXIF) || isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) { - registerIfd(IfdId.TYPE_IFD_EXIF, tag.getUnsignedInt()); + registerIfd(IfdId.TYPE_IFD_EXIF, tag.getUnsignedInt(0)); } break; case ExifTag.TIFF_TAG.TAG_GPS_IFD: if (isIfdRequested(IfdId.TYPE_IFD_GPS)) { - registerIfd(IfdId.TYPE_IFD_GPS, tag.getUnsignedInt()); + registerIfd(IfdId.TYPE_IFD_GPS, tag.getUnsignedInt(0)); } break; case ExifTag.EXIF_TAG.TAG_INTEROPERABILITY_IFD: if (isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) { - registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getUnsignedInt()); + registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getUnsignedInt(0)); } break; case ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT: if (isThumbnailRequested()) { - registerCompressedImage(tag.getUnsignedInt()); + registerCompressedImage(tag.getUnsignedInt(0)); } break; case ExifTag.TIFF_TAG.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/src/com/android/gallery3d/exif/ExifTag.java index 7b5a2eb6b..b2cbe61d7 100644 --- a/src/com/android/gallery3d/exif/ExifTag.java +++ b/src/com/android/gallery3d/exif/ExifTag.java @@ -363,8 +363,8 @@ public class ExifTag { private final short mTagId; private final short mDataType; - private final int mComponentCount; private final int mIfd; + private int mComponentCount; private Object mValue; private int mOffset; @@ -451,83 +451,175 @@ public class ExifTag { } /** - * Sets the value of this tag. This is useful when we want to modify the tags and write it back - * to the JPEG file + * Sets integer values into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to the length. */ - public void setValue(Object object) { - if (object.getClass().isArray()) { - assert(mComponentCount == Array.getLength(object)); - mValue = object; - } else if (object instanceof String) { - assert(mComponentCount == ((String) object).length() + 1); - mValue = object; - } else { - // Wrap object with an array because user may try to get object by get method with - // index 0 when size = 1 - // e.g. getShort(0) - assert(mComponentCount == 1); - Object array = Array.newInstance(object.getClass(), 1); - Array.set(array, 0, object); - mValue = array; + public void setValue(int[] value) { + long[] data = new long[value.length]; + for (int i = 0; i < value.length; i++) { + data[i] = value[i]; } + mValue = data; + mComponentCount = value.length; } - public short getShort(int index) { - return (Short) Array.get(mValue, index); + /** + * Sets integer value into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to 1. + */ + public void setValue(int value) { + mValue = new long[] {value}; + mComponentCount = 1; } - public short getShort() { - return (Short) Array.get(mValue, 0); + /** + * Sets short values into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to the length. + */ + public void setValue(short[] value) { + long[] data = new long[value.length]; + for (int i = 0; i < value.length; i++) { + data[i] = value[i]; + } + mValue = data; + mComponentCount = value.length; } - public int getUnsignedShort(int index) { - return (Integer) Array.get(mValue, index); + /** + * Sets short value into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to 1. + */ + public void setValue(short value) { + mValue = new long[] {value}; + mComponentCount = 1; } - public int getUnsignedShort() { - return (Integer) Array.get(mValue, 0); + /** + * Sets long values into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to the length. + */ + public void setValue(long[] value) { + long[] data = new long[value.length]; + System.arraycopy(value, 0, data, 0, value.length); + mValue = data; + mComponentCount = value.length; } - public int getInt(int index) { - return (Integer) Array.get(mValue, index); + /** + * Sets long value into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to 1. + */ + public void setValue(long value) { + mValue = new long[] {value}; + mComponentCount = 1; } - public int getInt() { - return (Integer) Array.get(mValue, 0); + /** + * Sets String value into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to + * value.length() + 1. + */ + public void setValue(String value) { + mComponentCount = value.length() + 1; + mValue = value; } - public long getUnsignedInt(int index) { - return (Long) Array.get(mValue, index); + /** + * Sets Rational values into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to the length. + */ + public void setValue(Rational[] value) { + mValue = new Rational[value.length]; + System.arraycopy(value, 0, mValue, 0, value.length); + mComponentCount = value.length; } - public long getUnsignedInt() { - return (Long) Array.get(mValue, 0); + /** + * Sets Rational value into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to 1. + */ + public void setValue(Rational value) { + mValue = new Rational[] {value}; + mComponentCount = 1; } - public String getString() { - return (String) mValue; + /** + * Sets byte values into this tag. This is useful when we want to modify the tags + * and write it back to the JPEG file. The component count will be set to the length. + */ + public void setValue(byte[] value, int offset, int length) { + long[] data = new long[length]; + for (int i = 0; i < length; i++) { + data[i] = value[i + offset]; + } + mValue = data; + mComponentCount = length; } - public Rational getRational(int index) { - return ((Rational[]) mValue)[index]; + /** + * Sets the byte array as the value of this tag. + * This is equivalent to setValue(value, 0, value.length). + */ + public void setValue(byte[] value) { + setValue(value, 0, value.length); + } + + public short getShort(int index) { + if (mValue instanceof long[]) { + return (short) (((long[]) mValue) [index]); + } else { + throw new RuntimeException("There is numerical value in this tag"); + } + } + + public int getUnsignedShort(int index) { + if (mValue instanceof long[]) { + return (int) (((long[]) mValue) [index]); + } else { + throw new RuntimeException("There is numerical value in this tag"); + } + } + + public int getInt(int index) { + if (mValue instanceof long[]) { + return (int) (((long[]) mValue) [index]); + } else { + throw new RuntimeException("There is numerical value in this tag"); + } } - public Rational getRational() { - return ((Rational[]) mValue)[0]; + public long getUnsignedInt(int index) { + if (mValue instanceof long[]) { + return ((long[]) mValue) [index]; + } else { + throw new RuntimeException("There is numerical value in this tag"); + } } - public int getBytes(byte[] buf) { - return getBytes(buf, 0, buf.length); + public String getString() { + return (String) mValue; } - public int getBytes(byte[] buf, int offset, int length) { - byte[] data = (byte[]) mValue; - if (data.length < length + offset) { - System.arraycopy(data, offset, buf, 0, data.length - offset); - return data.length - offset; + public Rational getRational(int index) { + Object value = Array.get(mValue, index); + if (value instanceof Rational) { + return (Rational) value; } else { - System.arraycopy(data, offset, buf, 0, length); - return length; + throw new RuntimeException("There is no Rational value in this tag"); + } + } + + public void getBytes(byte[] buf) { + getBytes(buf, 0, buf.length); + } + + public void getBytes(byte[] buf, int offset, int length) { + if (!(mValue instanceof long[])) { + throw new RuntimeException("There is no byte value in this tag"); + } + long[] data = (long[]) mValue; + for(int i = 0; i < length; i++) { + buf[offset + i] = (byte) data[i]; } } @@ -541,7 +633,7 @@ public class ExifTag { case ExifTag.TYPE_UNSIGNED_BYTE: byte buf[] = new byte[getComponentCount()]; getBytes(buf); - for(int i = 0; i < getComponentCount(); i++) { + for(int i = 0, n = getComponentCount(); i < n; i++) { if(i != 0) sbuilder.append(" "); sbuilder.append(String.format("%02x", buf[i])); } @@ -551,27 +643,27 @@ public class ExifTag { sbuilder.append(getString().trim()); break; case ExifTag.TYPE_UNSIGNED_INT: - for(int i = 0; i < getComponentCount(); i++) { + for(int i = 0, n = getComponentCount(); i < n; i++) { if(i != 0) sbuilder.append(" "); sbuilder.append(getUnsignedInt(i)); } break; case ExifTag.TYPE_RATIONAL: case ExifTag.TYPE_UNSIGNED_RATIONAL: - for(int i = 0; i < getComponentCount(); i++) { + for(int i = 0, n = getComponentCount(); i < n; i++) { Rational r = getRational(i); if(i != 0) sbuilder.append(" "); sbuilder.append(r.getNominator()).append("/").append(r.getDenominator()); } break; case ExifTag.TYPE_UNSIGNED_SHORT: - for(int i = 0; i < getComponentCount(); i++) { + for(int i = 0, n = getComponentCount(); i < n; i++) { if(i != 0) sbuilder.append(" "); sbuilder.append(getUnsignedShort(i)); } break; case ExifTag.TYPE_INT: - for(int i = 0; i < getComponentCount(); i++) { + for(int i = 0, n = getComponentCount(); i < n; i++) { if(i != 0) sbuilder.append(" "); sbuilder.append(getInt(i)); } diff --git a/tests/src/com/android/gallery3d/exif/ExifParserTest.java b/tests/src/com/android/gallery3d/exif/ExifParserTest.java index 241aaf575..e967e3d28 100644 --- a/tests/src/com/android/gallery3d/exif/ExifParserTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifParserTest.java @@ -210,7 +210,7 @@ public class ExifParserTest extends InstrumentationTestCase { case ExifParser.EVENT_NEW_TAG: ExifTag tag = parser.getTag(); if (tag.getTagId() == ExifTag.TIFF_TAG.TAG_COMPRESSION) { - if (tag.getUnsignedShort() == ExifTag.TIFF_TAG.COMPRESSION_JPEG) { + if (tag.getUnsignedShort(0) == ExifTag.TIFF_TAG.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 67e695682..e5b51f162 100644 --- a/tests/src/com/android/gallery3d/exif/ExifReaderTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifReaderTest.java @@ -69,7 +69,7 @@ public class ExifReaderTest extends InstrumentationTestCase { private void checkThumbnail(ExifData exifData) { IfdData ifd1 = exifData.getIfdData(IfdId.TYPE_IFD_1); if (ifd1 != null) { - if (ifd1.getTag(ExifTag.TIFF_TAG.TAG_COMPRESSION).getUnsignedShort() == + if (ifd1.getTag(ExifTag.TIFF_TAG.TAG_COMPRESSION).getUnsignedShort(0) == ExifTag.TIFF_TAG.COMPRESSION_JPEG) { assertTrue(exifData.hasCompressedThumbnail()); byte[] thumbnail = exifData.getCompressedThumbnail(); @@ -79,7 +79,7 @@ public class ExifReaderTest extends InstrumentationTestCase { int planarType = ExifTag.TIFF_TAG.PLANAR_CONFIGURATION_CHUNKY; ExifTag planarTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_PLANAR_CONFIGURATION); if (planarTag != null) { - planarType = planarTag.getUnsignedShort(); + planarType = planarTag.getUnsignedShort(0); } ExifTag heightTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_IMAGE_HEIGHT); @@ -94,7 +94,7 @@ public class ExifReaderTest extends InstrumentationTestCase { assertTrue(stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip); } else { ExifTag samplePerPixelTag = ifd1.getTag(ExifTag.TIFF_TAG.TAG_SAMPLES_PER_PIXEL); - int samplePerPixel = samplePerPixelTag.getUnsignedShort(); + int samplePerPixel = samplePerPixelTag.getUnsignedShort(0); assertTrue(stripCount == (imageLength + rowsPerStrip - 1) / rowsPerStrip * samplePerPixel); } @@ -114,9 +114,9 @@ public class ExifReaderTest extends InstrumentationTestCase { private int getUnsignedIntOrShort(ExifTag tag) { if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { - return tag.getUnsignedShort(); + return tag.getUnsignedShort(0); } else { - return (int) tag.getUnsignedInt(); + return (int) tag.getUnsignedInt(0); } } -- cgit v1.2.3