diff options
author | Hung-ying Tyan <tyanh@google.com> | 2012-10-22 16:23:41 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-10-22 16:23:41 -0700 |
commit | f9b86094984f2ca74538267c6e71e8381422642e (patch) | |
tree | 849bf7b1fe06fb7ed0da2db6d1e2ac642bf8be25 /src | |
parent | 8c18fb9269c4fdd72a48ec76851e293950190b29 (diff) | |
parent | 4e791ba2c3992d948c0ac4c70c2dafd289386c21 (diff) | |
download | android_packages_apps_Snap-f9b86094984f2ca74538267c6e71e8381422642e.tar.gz android_packages_apps_Snap-f9b86094984f2ca74538267c6e71e8381422642e.tar.bz2 android_packages_apps_Snap-f9b86094984f2ca74538267c6e71e8381422642e.zip |
am bdc0f6f2: Merge "Move new exif lib to gallerycommon." into gb-ub-photos-arches
* commit 'bdc0f6f2784b46ebe5d33d5e7e85bc347f07c468':
Move new exif lib to gallerycommon.
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/gallery3d/exif/CountedDataInputStream.java | 136 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifData.java | 273 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifInvalidFormatException.java | 23 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifOutputStream.java | 377 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifParser.java | 752 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifReader.java | 74 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/ExifTag.java | 1478 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/IfdData.java | 122 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/IfdId.java | 26 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/JpegHeader.java | 39 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/OrderedDataOutputStream.java | 52 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/Rational.java | 45 | ||||
-rw-r--r-- | src/com/android/gallery3d/exif/Util.java | 34 |
13 files changed, 0 insertions, 3431 deletions
diff --git a/src/com/android/gallery3d/exif/CountedDataInputStream.java b/src/com/android/gallery3d/exif/CountedDataInputStream.java deleted file mode 100644 index dfd4a1a10..000000000 --- a/src/com/android/gallery3d/exif/CountedDataInputStream.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.EOFException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.Charset; - -class CountedDataInputStream extends FilterInputStream { - - private int mCount = 0; - - // allocate a byte buffer for a long value; - private final byte mByteArray[] = new byte[8]; - private final ByteBuffer mByteBuffer = ByteBuffer.wrap(mByteArray); - - protected CountedDataInputStream(InputStream in) { - super(in); - } - - public int getReadByteCount() { - return mCount; - } - - @Override - public int read(byte[] b) throws IOException { - int r = in.read(b); - mCount += (r >= 0) ? r : 0; - return r; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int r = in.read(b, off, len); - mCount += (r >= 0) ? r : 0; - return r; - } - - @Override - public int read() throws IOException { - int r = in.read(); - mCount += (r >= 0) ? 1 : 0; - return r; - } - - @Override - public long skip(long length) throws IOException { - long skip = in.skip(length); - mCount += skip; - return skip; - } - - public void skipOrThrow(long length) throws IOException { - if (skip(length) != length) throw new EOFException(); - } - - public void skipTo(long target) throws IOException { - long cur = mCount; - long diff = target - cur; - assert(diff >= 0); - skipOrThrow(diff); - } - - public void readOrThrow(byte[] b, int off, int len) throws IOException { - int r = read(b, off, len); - if (r != len) throw new EOFException(); - } - - public void readOrThrow(byte[] b) throws IOException { - readOrThrow(b, 0, b.length); - } - - public void setByteOrder(ByteOrder order) { - mByteBuffer.order(order); - } - - public ByteOrder getByteOrder() { - return mByteBuffer.order(); - } - - public short readShort() throws IOException { - readOrThrow(mByteArray, 0 ,2); - mByteBuffer.rewind(); - return mByteBuffer.getShort(); - } - - public int readUnsignedShort() throws IOException { - return readShort() & 0xffff; - } - - public int readInt() throws IOException { - readOrThrow(mByteArray, 0 , 4); - mByteBuffer.rewind(); - return mByteBuffer.getInt(); - } - - public long readUnsignedInt() throws IOException { - return readInt() & 0xffffffffL; - } - - public long readLong() throws IOException { - readOrThrow(mByteArray, 0 , 8); - mByteBuffer.rewind(); - return mByteBuffer.getLong(); - } - - public String readString(int n) throws IOException { - byte buf[] = new byte[n]; - readOrThrow(buf); - return new String(buf, "UTF8"); - } - - public String readString(int n, Charset charset) throws IOException { - byte buf[] = new byte[n]; - readOrThrow(buf); - return new String(buf, charset); - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/ExifData.java b/src/com/android/gallery3d/exif/ExifData.java deleted file mode 100644 index 7f7971384..000000000 --- a/src/com/android/gallery3d/exif/ExifData.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2012 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 java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * This class stores the EXIF header in IFDs according to the JPEG specification. - * It is the result produced by {@link ExifReader}. - * @see ExifReader - * @see IfdData - */ -public class ExifData { - private final IfdData[] mIfdDatas = new IfdData[IfdId.TYPE_IFD_COUNT]; - private byte[] mThumbnail; - private ArrayList<byte[]> mStripBytes = new ArrayList<byte[]>(); - private final ByteOrder mByteOrder; - - public ExifData(ByteOrder order) { - mByteOrder = order; - } - - IfdData getIfdData(int ifdId) { - return mIfdDatas[ifdId]; - } - - /** - * Adds IFD data. If IFD data of the same type already exists, - * it will be replaced by the new data. - */ - void addIfdData(IfdData data) { - mIfdDatas[data.getId()] = data; - } - - /** - * Gets the compressed thumbnail. Returns null if there is no compressed thumbnail. - * - * @see #hasCompressedThumbnail() - */ - public byte[] getCompressedThumbnail() { - return mThumbnail; - } - - /** - * Sets the compressed thumbnail. - */ - public void setCompressedThumbnail(byte[] thumbnail) { - mThumbnail = thumbnail; - } - - /** - * Returns true it this header contains a compressed thumbnail. - */ - public boolean hasCompressedThumbnail() { - return mThumbnail != null; - } - - /** - * Adds an uncompressed strip. - */ - public void setStripBytes(int index, byte[] strip) { - if (index < mStripBytes.size()) { - mStripBytes.set(index, strip); - } else { - for (int i = mStripBytes.size(); i < index; i++) { - mStripBytes.add(null); - } - mStripBytes.add(strip); - } - } - - /** - * Gets the strip count. - */ - public int getStripCount() { - return mStripBytes.size(); - } - - /** - * Gets the strip at the specified index. - * @exceptions #IndexOutOfBoundException - */ - public byte[] getStrip(int index) { - return mStripBytes.get(index); - } - - /** - * Gets the byte order. - */ - public ByteOrder getByteOrder() { - return mByteOrder; - } - - /** - * Returns true if this header contains uncompressed strip of thumbnail. - */ - public boolean hasUncompressedStrip() { - return mStripBytes.size() != 0; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExifData) { - ExifData data = (ExifData) obj; - if (data.mByteOrder != mByteOrder - || !Arrays.equals(data.mThumbnail, mThumbnail) - || data.mStripBytes.size() != mStripBytes.size()) return false; - - for (int i = 0; i < mStripBytes.size(); i++) { - if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) return false; - } - - for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { - if (!Util.equals(data.getIfdData(i), getIfdData(i))) return false; - } - return true; - } - return false; - } - - /** - * Adds {@link ExifTag#TAG_GPS_LATITUDE}, {@link ExifTag#TAG_GPS_LONGITUDE}, - * {@link ExifTag#TAG_GPS_LATITUDE_REF} and {@link ExifTag#TAG_GPS_LONGITUDE_REF} with the - * given latitude and longitude. - */ - public void addGpsTags(double latitude, double longitude) { - IfdData gpsIfd = getIfdData(IfdId.TYPE_IFD_GPS); - if (gpsIfd == null) { - gpsIfd = new IfdData(IfdId.TYPE_IFD_GPS); - addIfdData(gpsIfd); - } - ExifTag latTag = new ExifTag(ExifTag.TAG_GPS_LATITUDE, ExifTag.TYPE_RATIONAL, - 3, IfdId.TYPE_IFD_GPS); - ExifTag longTag = new ExifTag(ExifTag.TAG_GPS_LONGITUDE, ExifTag.TYPE_RATIONAL, - 3, IfdId.TYPE_IFD_GPS); - ExifTag latRefTag = new ExifTag(ExifTag.TAG_GPS_LATITUDE_REF, - ExifTag.TYPE_ASCII, 2, IfdId.TYPE_IFD_GPS); - ExifTag longRefTag = new ExifTag(ExifTag.TAG_GPS_LONGITUDE_REF, - ExifTag.TYPE_ASCII, 2, IfdId.TYPE_IFD_GPS); - latTag.setValue(toExifLatLong(latitude)); - longTag.setValue(toExifLatLong(longitude)); - latRefTag.setValue(latitude >= 0 - ? ExifTag.GpsLatitudeRef.NORTH - : ExifTag.GpsLatitudeRef.SOUTH); - longRefTag.setValue(longitude >= 0 - ? ExifTag.GpsLongitudeRef.EAST - : ExifTag.GpsLongitudeRef.WEST); - gpsIfd.setTag(latTag); - gpsIfd.setTag(longTag); - gpsIfd.setTag(latRefTag); - gpsIfd.setTag(longRefTag); - } - - private static Rational[] toExifLatLong(double value) { - // convert to the format dd/1 mm/1 ssss/100 - value = Math.abs(value); - int degrees = (int) value; - value = (value - degrees) * 60; - int minutes = (int) value; - value = (value - minutes) * 6000; - int seconds = (int) value; - return new Rational[] { - new Rational(degrees, 1), new Rational(minutes, 1), new Rational(seconds, 100)}; - } - - private IfdData getOrCreateIfdData(int ifdId) { - IfdData ifdData = mIfdDatas[ifdId]; - if (ifdData == null) { - ifdData = new IfdData(ifdId); - mIfdDatas[ifdId] = ifdData; - } - return ifdData; - } - - /** - * Gets the tag with the given tag ID. Returns null if the tag does not exist. For tags - * related to interoperability or thumbnail, call {@link #getInteroperabilityTag(short)} and - * {@link #getThumbnailTag(short)} respectively. - */ - public ExifTag getTag(short tagId) { - int ifdId = ExifTag.getIfdIdFromTagId(tagId); - IfdData ifdData = mIfdDatas[ifdId]; - return (ifdData == null) ? null : ifdData.getTag(tagId); - } - - /** - * Gets the thumbnail-related tag with the given tag ID. - */ - public ExifTag getThumbnailTag(short tagId) { - IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_1]; - return (ifdData == null) ? null : ifdData.getTag(tagId); - } - - /** - * Gets the interoperability-related tag with the given tag ID. - */ - public ExifTag getInteroperabilityTag(short tagId) { - IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_INTEROPERABILITY]; - return (ifdData == null) ? null : ifdData.getTag(tagId); - } - - /** - * 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. - */ - public ExifTag addTag(short tagId) { - int ifdId = ExifTag.getIfdIdFromTagId(tagId); - IfdData ifdData = getOrCreateIfdData(ifdId); - 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. 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 = 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. 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 = ifdData.getTag(tagId); - if (tag == null) { - tag = ExifTag.buildInteroperabilityTag(tagId); - ifdData.setTag(tag); - } - return tag; - } - - public void removeThumbnailData() { - mThumbnail = null; - mStripBytes.clear(); - mIfdDatas[IfdId.TYPE_IFD_1] = null; - } -} diff --git a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java b/src/com/android/gallery3d/exif/ExifInvalidFormatException.java deleted file mode 100644 index bf923ec26..000000000 --- a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 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; - -public class ExifInvalidFormatException extends Exception { - public ExifInvalidFormatException(String meg) { - super(meg); - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/ExifOutputStream.java b/src/com/android/gallery3d/exif/ExifOutputStream.java deleted file mode 100644 index b8db8e34c..000000000 --- a/src/com/android/gallery3d/exif/ExifOutputStream.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public class ExifOutputStream extends FilterOutputStream { - private static final String TAG = "ExifOutputStream"; - - private static final int STATE_SOI = 0; - private static final int STATE_FRAME_HEADER = 1; - private static final int STATE_JPEG_DATA = 2; - - private static final int EXIF_HEADER = 0x45786966; - private static final short TIFF_HEADER = 0x002A; - private static final short TIFF_BIG_ENDIAN = 0x4d4d; - private static final short TIFF_LITTLE_ENDIAN = 0x4949; - private static final short TAG_SIZE = 12; - private static final short TIFF_HEADER_SIZE = 8; - - private ExifData mExifData; - private int mState = STATE_SOI; - private int mByteToSkip; - private int mByteToCopy; - private ByteBuffer mBuffer = ByteBuffer.allocate(4); - - public ExifOutputStream(OutputStream ou) { - super(ou); - } - - public void setExifData(ExifData exifData) { - mExifData = exifData; - } - - public ExifData getExifData() { - return mExifData; - } - - private int requestByteToBuffer(int requestByteCount, byte[] buffer - , int offset, int length) { - int byteNeeded = requestByteCount - mBuffer.position(); - int byteToRead = length > byteNeeded ? byteNeeded : length; - mBuffer.put(buffer, offset, byteToRead); - return byteToRead; - } - - @Override - public void write(byte[] buffer, int offset, int length) throws IOException { - while((mByteToSkip > 0 || mByteToCopy > 0 || mState != STATE_JPEG_DATA) - && length > 0) { - if (mByteToSkip > 0) { - int byteToProcess = length > mByteToSkip ? mByteToSkip : length; - length -= byteToProcess; - mByteToSkip -= byteToProcess; - offset += byteToProcess; - } - if (mByteToCopy > 0) { - int byteToProcess = length > mByteToCopy ? mByteToCopy : length; - out.write(buffer, offset, byteToProcess); - length -= byteToProcess; - mByteToCopy -= byteToProcess; - offset += byteToProcess; - } - if (length == 0) return; - switch (mState) { - case STATE_SOI: - int byteRead = requestByteToBuffer(2, buffer, offset, length); - offset += byteRead; - length -= byteRead; - if (mBuffer.position() < 2) return; - mBuffer.rewind(); - assert(mBuffer.getShort() == JpegHeader.SOI); - out.write(mBuffer.array(), 0 ,2); - mState = STATE_FRAME_HEADER; - mBuffer.rewind(); - writeExifData(); - break; - case STATE_FRAME_HEADER: - // We ignore the APP1 segment and copy all other segments until SOF tag. - byteRead = requestByteToBuffer(4, buffer, offset, length); - offset += byteRead; - length -= byteRead; - // Check if this image data doesn't contain SOF. - if (mBuffer.position() == 2) { - short tag = mBuffer.getShort(); - if (tag == JpegHeader.EOI) { - out.write(mBuffer.array(), 0, 2); - mBuffer.rewind(); - } - } - if (mBuffer.position() < 4) return; - mBuffer.rewind(); - short marker = mBuffer.getShort(); - if (marker == JpegHeader.APP1) { - mByteToSkip = (mBuffer.getShort() & 0xff) - 2; - mState = STATE_JPEG_DATA; - } else if (!JpegHeader.isSofMarker(marker)) { - out.write(mBuffer.array(), 0, 4); - mByteToCopy = (mBuffer.getShort() & 0xff) - 2; - } else { - out.write(mBuffer.array(), 0, 4); - mState = STATE_JPEG_DATA; - } - mBuffer.rewind(); - } - } - if (length > 0) { - out.write(buffer, offset, length); - } - } - - @Override - public void write(int oneByte) throws IOException { - byte[] buf = new byte[] {(byte) (0xff & oneByte)}; - write(buf); - } - - @Override - public void write(byte[] buffer) throws IOException { - write(buffer, 0, buffer.length); - } - - private void writeExifData() throws IOException { - createRequiredIfdAndTag(); - int exifSize = calculateAllOffset(); - OrderedDataOutputStream dataOutputStream = new OrderedDataOutputStream(out); - dataOutputStream.setByteOrder(ByteOrder.BIG_ENDIAN); - dataOutputStream.writeShort(JpegHeader.APP1); - dataOutputStream.writeShort((short) (exifSize + 8)); - dataOutputStream.writeInt(EXIF_HEADER); - dataOutputStream.writeShort((short) 0x0000); - if (mExifData.getByteOrder() == ByteOrder.BIG_ENDIAN) { - dataOutputStream.writeShort(TIFF_BIG_ENDIAN); - } else { - dataOutputStream.writeShort(TIFF_LITTLE_ENDIAN); - } - dataOutputStream.setByteOrder(mExifData.getByteOrder()); - dataOutputStream.writeShort(TIFF_HEADER); - dataOutputStream.writeInt(8); - writeAllTags(dataOutputStream); - writeThumbnail(dataOutputStream); - } - - private void writeThumbnail(OrderedDataOutputStream dataOutputStream) throws IOException { - if (mExifData.hasCompressedThumbnail()) { - dataOutputStream.write(mExifData.getCompressedThumbnail()); - } else if (mExifData.hasUncompressedStrip()) { - for (int i = 0; i < mExifData.getStripCount(); i++) { - dataOutputStream.write(mExifData.getStrip(i)); - } - } - } - - private void writeAllTags(OrderedDataOutputStream dataOutputStream) throws IOException { - writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_0), dataOutputStream); - writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_EXIF), dataOutputStream); - IfdData interoperabilityIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY); - if (interoperabilityIfd != null) { - writeIfd(interoperabilityIfd, dataOutputStream); - } - IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS); - if (gpsIfd != null) { - writeIfd(gpsIfd, dataOutputStream); - } - IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1); - if (ifd1 != null) { - writeIfd(mExifData.getIfdData(IfdId.TYPE_IFD_1), dataOutputStream); - } - } - - private void writeIfd(IfdData ifd, OrderedDataOutputStream dataOutputStream) - throws IOException { - ExifTag[] tags = ifd.getAllTags(); - dataOutputStream.writeShort((short) tags.length); - for (ExifTag tag: tags) { - dataOutputStream.writeShort(tag.getTagId()); - dataOutputStream.writeShort(tag.getDataType()); - dataOutputStream.writeInt(tag.getComponentCount()); - if (tag.getDataSize() > 4) { - dataOutputStream.writeInt(tag.getOffset()); - } else { - writeTagValue(tag, dataOutputStream); - for (int i = 0, n = 4 - tag.getDataSize(); i < n; i++) { - dataOutputStream.write(0); - } - } - } - dataOutputStream.writeInt(ifd.getOffsetToNextIfd()); - for (ExifTag tag: tags) { - if (tag.getDataSize() > 4) { - writeTagValue(tag, dataOutputStream); - } - } - } - - private void writeTagValue(ExifTag tag, OrderedDataOutputStream dataOutputStream) - throws IOException { - switch (tag.getDataType()) { - case ExifTag.TYPE_ASCII: - dataOutputStream.write(tag.getString().getBytes()); - int remain = tag.getComponentCount() - tag.getString().length(); - for (int i = 0; i < remain; i++) { - dataOutputStream.write(0); - } - break; - case ExifTag.TYPE_LONG: - for (int i = 0, n = tag.getComponentCount(); i < n; i++) { - dataOutputStream.writeInt(tag.getLong(i)); - } - break; - case ExifTag.TYPE_RATIONAL: - case ExifTag.TYPE_UNSIGNED_RATIONAL: - for (int i = 0, n = tag.getComponentCount(); i < n; i++) { - dataOutputStream.writeRational(tag.getRational(i)); - } - break; - case ExifTag.TYPE_UNDEFINED: - case ExifTag.TYPE_UNSIGNED_BYTE: - byte[] buf = new byte[tag.getComponentCount()]; - tag.getBytes(buf); - dataOutputStream.write(buf); - break; - case ExifTag.TYPE_UNSIGNED_LONG: - for (int i = 0, n = tag.getComponentCount(); i < n; i++) { - dataOutputStream.writeInt((int) tag.getUnsignedLong(i)); - } - break; - case ExifTag.TYPE_UNSIGNED_SHORT: - for (int i = 0, n = tag.getComponentCount(); i < n; i++) { - dataOutputStream.writeShort((short) tag.getUnsignedShort(i)); - } - break; - } - } - - private int calculateOffsetOfIfd(IfdData ifd, int offset) { - offset += 2 + ifd.getTagCount() * TAG_SIZE + 4; - ExifTag[] tags = ifd.getAllTags(); - for(ExifTag tag: tags) { - if (tag.getDataSize() > 4) { - tag.setOffset(offset); - offset += tag.getDataSize(); - } - } - return offset; - } - - private void createRequiredIfdAndTag() { - // IFD0 is required for all file - IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0); - if (ifd0 == null) { - ifd0 = new IfdData(IfdId.TYPE_IFD_0); - mExifData.addIfdData(ifd0); - } - ExifTag exifOffsetTag = new ExifTag(ExifTag.TAG_EXIF_IFD, - ExifTag.TYPE_UNSIGNED_LONG, 1, IfdId.TYPE_IFD_0); - ifd0.setTag(exifOffsetTag); - - // Exif IFD is required for all file. - IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF); - if (exifIfd == null) { - exifIfd = new IfdData(IfdId.TYPE_IFD_EXIF); - mExifData.addIfdData(exifIfd); - } - - // GPS IFD - IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS); - if (gpsIfd != null) { - ExifTag gpsOffsetTag = new ExifTag(ExifTag.TAG_GPS_IFD, - ExifTag.TYPE_UNSIGNED_LONG, 1, IfdId.TYPE_IFD_0); - ifd0.setTag(gpsOffsetTag); - } - - // Interoperability IFD - IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY); - if (interIfd != null) { - ExifTag interOffsetTag = new ExifTag(ExifTag.TAG_INTEROPERABILITY_IFD, - ExifTag.TYPE_UNSIGNED_LONG, 1, IfdId.TYPE_IFD_EXIF); - exifIfd.setTag(interOffsetTag); - } - - IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1); - - // thumbnail - if (mExifData.hasCompressedThumbnail()) { - if (ifd1 == null) { - ifd1 = new IfdData(IfdId.TYPE_IFD_1); - mExifData.addIfdData(ifd1); - } - ExifTag offsetTag = new ExifTag(ExifTag.TAG_JPEG_INTERCHANGE_FORMAT, - ExifTag.TYPE_UNSIGNED_LONG, 1, IfdId.TYPE_IFD_1); - ifd1.setTag(offsetTag); - ExifTag lengthTag = new ExifTag(ExifTag.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, - ExifTag.TYPE_UNSIGNED_LONG, 1, IfdId.TYPE_IFD_1); - lengthTag.setValue(mExifData.getCompressedThumbnail().length); - ifd1.setTag(lengthTag); - } else if (mExifData.hasUncompressedStrip()){ - if (ifd1 == null) { - ifd1 = new IfdData(IfdId.TYPE_IFD_1); - mExifData.addIfdData(ifd1); - } - int stripCount = mExifData.getStripCount(); - ExifTag offsetTag = new ExifTag(ExifTag.TAG_STRIP_OFFSETS, - ExifTag.TYPE_UNSIGNED_LONG, stripCount, IfdId.TYPE_IFD_1); - ExifTag lengthTag = new ExifTag(ExifTag.TAG_STRIP_BYTE_COUNTS, - ExifTag.TYPE_UNSIGNED_LONG, stripCount, IfdId.TYPE_IFD_1); - long[] lengths = new long[stripCount]; - for (int i = 0; i < mExifData.getStripCount(); i++) { - lengths[i] = mExifData.getStrip(i).length; - } - lengthTag.setValue(lengths); - ifd1.setTag(offsetTag); - ifd1.setTag(lengthTag); - } - } - - private int calculateAllOffset() { - int offset = TIFF_HEADER_SIZE; - IfdData ifd0 = mExifData.getIfdData(IfdId.TYPE_IFD_0); - offset = calculateOffsetOfIfd(ifd0, offset); - ifd0.getTag(ExifTag.TAG_EXIF_IFD).setValue(offset); - - IfdData exifIfd = mExifData.getIfdData(IfdId.TYPE_IFD_EXIF); - offset = calculateOffsetOfIfd(exifIfd, offset); - - IfdData interIfd = mExifData.getIfdData(IfdId.TYPE_IFD_INTEROPERABILITY); - if (interIfd != null) { - exifIfd.getTag(ExifTag.TAG_INTEROPERABILITY_IFD).setValue(offset); - offset = calculateOffsetOfIfd(interIfd, offset); - } - - IfdData gpsIfd = mExifData.getIfdData(IfdId.TYPE_IFD_GPS); - if (gpsIfd != null) { - ifd0.getTag(ExifTag.TAG_GPS_IFD).setValue(offset); - offset = calculateOffsetOfIfd(gpsIfd, offset); - } - - IfdData ifd1 = mExifData.getIfdData(IfdId.TYPE_IFD_1); - if (ifd1 != null) { - ifd0.setOffsetToNextIfd(offset); - offset = calculateOffsetOfIfd(ifd1, offset); - } - - // thumbnail - if (mExifData.hasCompressedThumbnail()) { - ifd1.getTag(ExifTag.TAG_JPEG_INTERCHANGE_FORMAT).setValue(offset); - offset += mExifData.getCompressedThumbnail().length; - } else if (mExifData.hasUncompressedStrip()){ - int stripCount = mExifData.getStripCount(); - long[] offsets = new long[stripCount]; - for (int i = 0; i < mExifData.getStripCount(); i++) { - offsets[i] = offset; - offset += mExifData.getStrip(i).length; - } - ifd1.getTag(ExifTag.TAG_STRIP_OFFSETS).setValue(offsets); - } - return offset; - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/ExifParser.java b/src/com/android/gallery3d/exif/ExifParser.java deleted file mode 100644 index f1e52c5b3..000000000 --- a/src/com/android/gallery3d/exif/ExifParser.java +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteOrder; -import java.nio.charset.Charset; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** - * This class provides a low-level EXIF parsing API. Given a JPEG format InputStream, the caller - * can request which IFD's to read via {@link #parse(InputStream, int)} with given options. - * <p> - * Below is an example of getting EXIF data from IFD 0 and EXIF IFD using the parser. - * <pre> - * void parse() { - * ExifParser parser = ExifParser.parse(mImageInputStream, - * ExifParser.OPTION_IFD_0 | ExifParser.OPTIONS_IFD_EXIF); - * 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 { - * processTag(tag); - * } - * break; - * case ExifParser.EVENT_VALUE_OF_REGISTERED_TAG: - * tag = parser.getTag(); - * if (tag.getDataType() != ExifTag.TYPE_UNDEFINED) { - * processTag(tag); - * } - * break; - * } - * event = parser.next(); - * } - * } - * - * void processTag(ExifTag tag) { - * // process the tag as you like. - * } - * </pre> - */ -public class ExifParser { - /** - * When the parser reaches a new IFD area. Call - * {@link #getCurrentIfd()} to know which IFD we are in. - */ - public static final int EVENT_START_OF_IFD = 0; - /** - * When the parser reaches a new tag. Call {@link #getTag()}to get the - * corresponding tag. - */ - public static final int EVENT_NEW_TAG = 1; - /** - * When the parser reaches the value area of tag that is registered by - * {@link #registerForTagValue(ExifTag)} previously. Call - * {@link #getTag()} to get the corresponding tag. - */ - public static final int EVENT_VALUE_OF_REGISTERED_TAG = 2; - - /** - * When the parser reaches the compressed image area. - */ - public static final int EVENT_COMPRESSED_IMAGE = 3; - /** - * When the parser reaches the uncompressed image strip. - * Call {@link #getStripIndex()} to get the index of the strip. - * @see #getStripIndex() - * @see #getStripCount() - */ - public static final int EVENT_UNCOMPRESSED_STRIP = 4; - /** - * When there is nothing more to parse. - */ - public static final int EVENT_END = 5; - - /** - * Option bit to request to parse IFD0. - */ - public static final int OPTION_IFD_0 = 1 << 0; - /** - * Option bit to request to parse IFD1. - */ - public static final int OPTION_IFD_1 = 1 << 1; - /** - * Option bit to request to parse Exif-IFD. - */ - public static final int OPTION_IFD_EXIF = 1 << 2; - /** - * Option bit to request to parse GPS-IFD. - */ - public static final int OPTION_IFD_GPS = 1 << 3; - /** - * Option bit to request to parse Interoperability-IFD. - */ - public static final int OPTION_IFD_INTEROPERABILITY = 1 << 4; - /** - * Option bit to request to parse thumbnail. - */ - public static final int OPTION_THUMBNAIL = 1 << 5; - - private static final int EXIF_HEADER = 0x45786966; // EXIF header "Exif" - private static final short EXIF_HEADER_TAIL = (short) 0x0000; // EXIF header in APP1 - - // TIFF header - private static final short LITTLE_ENDIAN_TAG = (short) 0x4949; // "II" - private static final short BIG_ENDIAN_TAG = (short) 0x4d4d; // "MM" - private static final short TIFF_HEADER_TAIL = 0x002A; - - private static final int TAG_SIZE = 12; - private static final int OFFSET_SIZE = 2; - - private final CountedDataInputStream mTiffStream; - private final int mOptions; - private int mIfdStartOffset = 0; - private int mNumOfTagInIfd = 0; - private int mIfdType; - private ExifTag mTag; - private ImageEvent mImageEvent; - private int mStripCount; - private ExifTag mStripSizeTag; - private ExifTag mJpegSizeTag; - private boolean mNeedToParseOffsetsInCurrentIfd; - private boolean mContainExifData = false; - - private final TreeMap<Integer, Object> mCorrespondingEvent = new TreeMap<Integer, Object>(); - - private boolean isIfdRequested(int ifdType) { - switch (ifdType) { - case IfdId.TYPE_IFD_0: - return (mOptions & OPTION_IFD_0) != 0; - case IfdId.TYPE_IFD_1: - return (mOptions & OPTION_IFD_1) != 0; - case IfdId.TYPE_IFD_EXIF: - return (mOptions & OPTION_IFD_EXIF) != 0; - case IfdId.TYPE_IFD_GPS: - return (mOptions & OPTION_IFD_GPS) != 0; - case IfdId.TYPE_IFD_INTEROPERABILITY: - return (mOptions & OPTION_IFD_INTEROPERABILITY) != 0; - } - return false; - } - - private boolean isThumbnailRequested() { - return (mOptions & OPTION_THUMBNAIL) != 0; - } - - private ExifParser(InputStream inputStream, int options) - throws IOException, ExifInvalidFormatException { - mContainExifData = seekTiffData(inputStream); - mTiffStream = new CountedDataInputStream(inputStream); - mOptions = options; - if (!mContainExifData) return; - if (mTiffStream.getReadByteCount() == 0) { - parseTiffHeader(); - long offset = mTiffStream.readUnsignedInt(); - registerIfd(IfdId.TYPE_IFD_0, offset); - } - } - - /** - * Parses the the given InputStream with the given options - * @exception IOException - * @exception ExifInvalidFormatException - */ - public static ExifParser parse(InputStream inputStream, int options) - throws IOException, ExifInvalidFormatException { - return new ExifParser(inputStream, options); - } - - /** - * Parses the the given InputStream with default options; that is, every IFD and thumbnaill - * will be parsed. - * @exception IOException - * @exception ExifInvalidFormatException - * @see #parse(InputStream, int) - */ - public static ExifParser parse(InputStream inputStream) - throws IOException, ExifInvalidFormatException { - return new ExifParser(inputStream, OPTION_IFD_0 | OPTION_IFD_1 - | OPTION_IFD_EXIF | OPTION_IFD_GPS | OPTION_IFD_INTEROPERABILITY - | OPTION_THUMBNAIL); - } - - /** - * Moves the parser forward and returns the next parsing event - * - * @exception IOException - * @exception ExifInvalidFormatException - * @see #EVENT_START_OF_IFD - * @see #EVENT_NEW_TAG - * @see #EVENT_VALUE_OF_REGISTERED_TAG - * @see #EVENT_COMPRESSED_IMAGE - * @see #EVENT_UNCOMPRESSED_STRIP - * @see #EVENT_END - */ - public int next() throws IOException, ExifInvalidFormatException { - if (!mContainExifData) { - return EVENT_END; - } - int offset = mTiffStream.getReadByteCount(); - int endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * mNumOfTagInIfd; - if (offset < endOfTags) { - mTag = readTag(); - if (mNeedToParseOffsetsInCurrentIfd) { - checkOffsetOrImageTag(mTag); - } - return EVENT_NEW_TAG; - } else if (offset == endOfTags) { - long ifdOffset = readUnsignedLong(); - // There is a link to ifd1 at the end of ifd0 - if (mIfdType == IfdId.TYPE_IFD_0) { - if (isIfdRequested(IfdId.TYPE_IFD_1) || isThumbnailRequested()) { - if (ifdOffset != 0) { - registerIfd(IfdId.TYPE_IFD_1, ifdOffset); - } - } - } else { - if (ifdOffset != 0) { - throw new ExifInvalidFormatException("Invalid link to next IFD"); - } - } - } - while(mCorrespondingEvent.size() != 0) { - Entry<Integer, Object> entry = mCorrespondingEvent.pollFirstEntry(); - Object event = entry.getValue(); - skipTo(entry.getKey()); - if (event instanceof IfdEvent) { - mIfdType = ((IfdEvent) event).ifd; - mNumOfTagInIfd = mTiffStream.readUnsignedShort(); - mIfdStartOffset = entry.getKey(); - mNeedToParseOffsetsInCurrentIfd = needToParseOffsetsInCurrentIfd(); - if (((IfdEvent) event).isRequested) { - return EVENT_START_OF_IFD; - } else { - skipRemainingTagsInCurrentIfd(); - } - } else if (event instanceof ImageEvent) { - mImageEvent = (ImageEvent) event; - return mImageEvent.type; - } else { - ExifTagEvent tagEvent = (ExifTagEvent) event; - mTag = tagEvent.tag; - if (mTag.getDataType() != ExifTag.TYPE_UNDEFINED) { - readFullTagValue(mTag); - checkOffsetOrImageTag(mTag); - } - if (tagEvent.isRequested) { - return EVENT_VALUE_OF_REGISTERED_TAG; - } - } - } - return EVENT_END; - } - - /** - * Skips the tags area of current IFD, if the parser is not in the tag area, nothing will - * happen. - * - * @throws IOException - * @throws ExifInvalidFormatException - */ - public void skipRemainingTagsInCurrentIfd() throws IOException, ExifInvalidFormatException { - int endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * mNumOfTagInIfd; - int offset = mTiffStream.getReadByteCount(); - if (offset > endOfTags) return; - if (mNeedToParseOffsetsInCurrentIfd) { - while (offset < endOfTags) { - mTag = readTag(); - checkOffsetOrImageTag(mTag); - offset += TAG_SIZE; - } - } else { - skipTo(endOfTags); - } - long ifdOffset = readUnsignedLong(); - // For ifd0, there is a link to ifd1 in the end of all tags - if (mIfdType == IfdId.TYPE_IFD_0 - && (isIfdRequested(IfdId.TYPE_IFD_1) || isThumbnailRequested())) { - if (ifdOffset > 0) { - registerIfd(IfdId.TYPE_IFD_1, ifdOffset); - } - } - } - - private boolean needToParseOffsetsInCurrentIfd() { - switch (mIfdType) { - case IfdId.TYPE_IFD_0: - return isIfdRequested(IfdId.TYPE_IFD_EXIF) || isIfdRequested(IfdId.TYPE_IFD_GPS) - || isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY); - case IfdId.TYPE_IFD_1: - return isThumbnailRequested(); - case IfdId.TYPE_IFD_EXIF: - // The offset to interoperability IFD is located in Exif IFD - return isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY); - default: - return false; - } - } - - /** - * If {@link #next()} return {@link #EVENT_NEW_TAG} or {@link #EVENT_VALUE_OF_REGISTERED_TAG}, - * call this function to get the corresponding tag. - * <p> - * - * For {@link #EVENT_NEW_TAG}, the tag may not contain the value if the size of the value is - * greater than 4 bytes. One should call {@link ExifTag#hasValue()} to check if the tag - * contains value. - * If there is no value,call {@link #registerForTagValue(ExifTag)} to have the parser emit - * {@link #EVENT_VALUE_OF_REGISTERED_TAG} when it reaches the area pointed by the offset. - * - * <p> - * When {@link #EVENT_VALUE_OF_REGISTERED_TAG} is emitted, the value of the tag will have - * already been read except for tags of undefined type. For tags of undefined type, call - * one of the read methods to get the value. - * - * @see #registerForTagValue(ExifTag) - * @see #read(byte[]) - * @see #read(byte[], int, int) - * @see #readLong() - * @see #readRational() - * @see #readShort() - * @see #readString(int) - * @see #readString(int, Charset) - */ - public ExifTag getTag() { - return mTag; - } - - /** - * Gets number of tags in the current IFD area. - */ - public int getTagCountInCurrentIfd() { - return mNumOfTagInIfd; - } - - /** - * Gets the ID of current IFD. - * - * @see IfdId#TYPE_IFD_0 - * @see IfdId#TYPE_IFD_1 - * @see IfdId#TYPE_IFD_GPS - * @see IfdId#TYPE_IFD_INTEROPERABILITY - * @see IfdId#TYPE_IFD_EXIF - */ - public int getCurrentIfd() { - return mIfdType; - } - - /** - * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, - * call this function to get the index of this strip. - * @see #getStripCount() - */ - public int getStripIndex() { - return mImageEvent.stripIndex; - } - - /** - * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, call this function to get the number - * of strip data. - * @see #getStripIndex() - */ - public int getStripCount() { - return mStripCount; - } - - /** - * When receiving {@link #EVENT_UNCOMPRESSED_STRIP}, call this function to get the strip size. - */ - public int getStripSize() { - if (mStripSizeTag == null) return 0; - if (mStripSizeTag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { - return mStripSizeTag.getUnsignedShort(mImageEvent.stripIndex); - } else { - // Cast unsigned int to int since the strip size is always smaller - // than the size of APP1 (65536) - return (int) mStripSizeTag.getUnsignedLong(mImageEvent.stripIndex); - } - } - - /** - * When receiving {@link #EVENT_COMPRESSED_IMAGE}, call this function to get the image data - * size. - */ - public int getCompressedImageSize() { - if (mJpegSizeTag == null) return 0; - // Cast unsigned int to int since the thumbnail is always smaller - // than the size of APP1 (65536) - return (int) mJpegSizeTag.getUnsignedLong(0); - } - - private void skipTo(int offset) throws IOException { - mTiffStream.skipTo(offset); - while (!mCorrespondingEvent.isEmpty() && mCorrespondingEvent.firstKey() < offset) { - mCorrespondingEvent.pollFirstEntry(); - } - } - - /** - * When getting {@link #EVENT_NEW_TAG} in the tag area of IFD, - * the tag may not contain the value if the size of the value is greater than 4 bytes. - * When the value is not available here, call this method so that the parser will emit - * {@link #EVENT_VALUE_OF_REGISTERED_TAG} when it reaches the area where the value is located. - - * @see #EVENT_VALUE_OF_REGISTERED_TAG - */ - public void registerForTagValue(ExifTag tag) { - mCorrespondingEvent.put(tag.getOffset(), new ExifTagEvent(tag, true)); - } - - private void registerIfd(int ifdType, long offset) { - // Cast unsigned int to int since the offset is always smaller - // than the size of APP1 (65536) - mCorrespondingEvent.put((int) offset, new IfdEvent(ifdType, isIfdRequested(ifdType))); - } - - private void registerCompressedImage(long offset) { - mCorrespondingEvent.put((int) offset, new ImageEvent(EVENT_COMPRESSED_IMAGE)); - } - - private void registerUncompressedStrip(int stripIndex, long offset) { - mCorrespondingEvent.put((int) offset, new ImageEvent(EVENT_UNCOMPRESSED_STRIP - , stripIndex)); - } - - private ExifTag readTag() throws IOException, ExifInvalidFormatException { - short tagId = mTiffStream.readShort(); - short dataFormat = mTiffStream.readShort(); - long numOfComp = mTiffStream.readUnsignedInt(); - if (numOfComp > Integer.MAX_VALUE) { - throw new ExifInvalidFormatException( - "Number of component is larger then Integer.MAX_VALUE"); - } - ExifTag tag = new ExifTag(tagId, dataFormat, (int) numOfComp, mIfdType); - int dataSize = tag.getDataSize(); - if (dataSize > 4) { - long offset = mTiffStream.readUnsignedInt(); - if (offset > Integer.MAX_VALUE) { - throw new ExifInvalidFormatException( - "offset is larger then Integer.MAX_VALUE"); - } - tag.setOffset((int) offset); - } else { - readFullTagValue(tag); - mTiffStream.skip(4 - dataSize); - } - return tag; - } - - /** - * Check the tag, if the tag is one of the offset tag that points to the IFD or image the - * caller is interested in, register the IFD or image. - */ - private void checkOffsetOrImageTag(ExifTag tag) { - switch (tag.getTagId()) { - case ExifTag.TAG_EXIF_IFD: - if (isIfdRequested(IfdId.TYPE_IFD_EXIF) - || isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) { - registerIfd(IfdId.TYPE_IFD_EXIF, tag.getUnsignedLong(0)); - } - break; - case ExifTag.TAG_GPS_IFD: - if (isIfdRequested(IfdId.TYPE_IFD_GPS)) { - registerIfd(IfdId.TYPE_IFD_GPS, tag.getUnsignedLong(0)); - } - break; - case ExifTag.TAG_INTEROPERABILITY_IFD: - if (isIfdRequested(IfdId.TYPE_IFD_INTEROPERABILITY)) { - registerIfd(IfdId.TYPE_IFD_INTEROPERABILITY, tag.getUnsignedLong(0)); - } - break; - case ExifTag.TAG_JPEG_INTERCHANGE_FORMAT: - if (isThumbnailRequested()) { - registerCompressedImage(tag.getUnsignedLong(0)); - } - break; - case ExifTag.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: - if (isThumbnailRequested()) { - mJpegSizeTag = tag; - } - break; - case ExifTag.TAG_STRIP_OFFSETS: - if (isThumbnailRequested()) { - if (tag.hasValue()) { - for (int i = 0; i < tag.getComponentCount(); i++) { - if (tag.getDataType() == ExifTag.TYPE_UNSIGNED_SHORT) { - registerUncompressedStrip(i, tag.getUnsignedShort(i)); - } else { - registerUncompressedStrip(i, tag.getUnsignedLong(i)); - } - } - } else { - mCorrespondingEvent.put(tag.getOffset(), new ExifTagEvent(tag, false)); - } - } - break; - case ExifTag.TAG_STRIP_BYTE_COUNTS: - if (isThumbnailRequested()) { - if (tag.hasValue()) { - mStripSizeTag = tag; - } - } - break; - } - } - - private void readFullTagValue(ExifTag tag) throws IOException { - switch(tag.getDataType()) { - case ExifTag.TYPE_UNSIGNED_BYTE: - case ExifTag.TYPE_UNDEFINED: - { - byte buf[] = new byte[tag.getComponentCount()]; - read(buf); - tag.setValue(buf); - } - break; - case ExifTag.TYPE_ASCII: - tag.setValue(readString(tag.getComponentCount())); - break; - case ExifTag.TYPE_UNSIGNED_LONG: - { - long value[] = new long[tag.getComponentCount()]; - for (int i = 0, n = value.length; i < n; i++) { - value[i] = readUnsignedLong(); - } - tag.setValue(value); - } - break; - case ExifTag.TYPE_UNSIGNED_RATIONAL: - { - Rational value[] = new Rational[tag.getComponentCount()]; - for (int i = 0, n = value.length; i < n; i++) { - value[i] = readUnsignedRational(); - } - tag.setValue(value); - } - break; - case ExifTag.TYPE_UNSIGNED_SHORT: - { - int value[] = new int[tag.getComponentCount()]; - for (int i = 0, n = value.length; i < n; i++) { - value[i] = readUnsignedShort(); - } - tag.setValue(value); - } - break; - case ExifTag.TYPE_LONG: - { - int value[] = new int[tag.getComponentCount()]; - for (int i = 0, n = value.length; i < n; i++) { - value[i] = readLong(); - } - tag.setValue(value); - } - break; - case ExifTag.TYPE_RATIONAL: - { - Rational value[] = new Rational[tag.getComponentCount()]; - for (int i = 0, n = value.length; i < n; i++) { - value[i] = readRational(); - } - tag.setValue(value); - } - break; - } - } - - private void parseTiffHeader() throws IOException, - ExifInvalidFormatException { - short byteOrder = mTiffStream.readShort(); - ByteOrder order; - if (LITTLE_ENDIAN_TAG == byteOrder) { - mTiffStream.setByteOrder(ByteOrder.LITTLE_ENDIAN); - } else if (BIG_ENDIAN_TAG == byteOrder) { - mTiffStream.setByteOrder(ByteOrder.BIG_ENDIAN); - } else { - throw new ExifInvalidFormatException("Invalid TIFF header"); - } - - if (mTiffStream.readShort() != TIFF_HEADER_TAIL) { - throw new ExifInvalidFormatException("Invalid TIFF header"); - } - } - - private boolean seekTiffData(InputStream inputStream) throws IOException, - ExifInvalidFormatException { - DataInputStream dataStream = new DataInputStream(inputStream); - - // SOI and APP1 - if (dataStream.readShort() != JpegHeader.SOI) { - throw new ExifInvalidFormatException("Invalid JPEG format"); - } - - short marker = dataStream.readShort(); - while(marker != JpegHeader.APP1 && marker != JpegHeader.EOI - && !JpegHeader.isSofMarker(marker)) { - int length = dataStream.readUnsignedShort(); - if ((length - 2) != dataStream.skip(length - 2)) { - throw new EOFException(); - } - marker = dataStream.readShort(); - } - - if (marker != JpegHeader.APP1) return false; // No APP1 segment - - // APP1 length, it's not used for us - dataStream.readShort(); - - // Exif header - return (dataStream.readInt() == EXIF_HEADER - && dataStream.readShort() == EXIF_HEADER_TAIL); - } - - /** - * Reads bytes from the InputStream. - */ - public int read(byte[] buffer, int offset, int length) throws IOException { - return mTiffStream.read(buffer, offset, length); - } - - /** - * Equivalent to read(buffer, 0, buffer.length). - */ - public int read(byte[] buffer) throws IOException { - return mTiffStream.read(buffer); - } - - /** - * Reads a String from the InputStream with UTF8 charset. - * This is used for reading values of type {@link ExifTag#TYPE_ASCII}. - */ - public String readString(int n) throws IOException { - if (n > 0) { - byte[] buf = new byte[n]; - mTiffStream.readOrThrow(buf); - return new String(buf, 0, n - 1, "UTF8"); - } else { - return ""; - } - } - - /** - * Reads a String from the InputStream with the given charset. - * This is used for reading values of type {@link ExifTag#TYPE_ASCII}. - */ - public String readString(int n, Charset charset) throws IOException { - byte[] buf = new byte[n]; - mTiffStream.readOrThrow(buf); - return new String(buf, 0, n - 1, charset); - } - - /** - * Reads value of type {@link ExifTag#TYPE_UNSIGNED_SHORT} from the InputStream. - */ - public int readUnsignedShort() throws IOException { - return mTiffStream.readShort() & 0xffff; - } - - /** - * Reads value of type {@link ExifTag#TYPE_UNSIGNED_LONG} from the InputStream. - */ - public long readUnsignedLong() throws IOException { - return readLong() & 0xffffffffL; - } - - /** - * Reads value of type {@link ExifTag#TYPE_UNSIGNED_RATIONAL} from the InputStream. - */ - public Rational readUnsignedRational() throws IOException { - long nomi = readUnsignedLong(); - long denomi = readUnsignedLong(); - return new Rational(nomi, denomi); - } - - /** - * Reads value of type {@link ExifTag#TYPE_LONG} from the InputStream. - */ - public int readLong() throws IOException { - return mTiffStream.readInt(); - } - - /** - * Reads value of type {@link ExifTag#TYPE_RATIONAL} from the InputStream. - */ - public Rational readRational() throws IOException { - int nomi = readLong(); - int denomi = readLong(); - return new Rational(nomi, denomi); - } - - private static class ImageEvent { - int stripIndex; - int type; - ImageEvent(int type) { - this.stripIndex = 0; - this.type = type; - } - ImageEvent(int type, int stripIndex) { - this.type = type; - this.stripIndex = stripIndex; - } - } - - private static class IfdEvent { - int ifd; - boolean isRequested; - IfdEvent(int ifd, boolean isInterestedIfd) { - this.ifd = ifd; - this.isRequested = isInterestedIfd; - } - } - - private static class ExifTagEvent { - ExifTag tag; - boolean isRequested; - ExifTagEvent(ExifTag tag, boolean isRequireByUser) { - this.tag = tag; - this.isRequested = isRequireByUser; - } - } - - /** - * Gets the byte order of the current InputStream. - */ - public ByteOrder getByteOrder() { - return mTiffStream.getByteOrder(); - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/ExifReader.java b/src/com/android/gallery3d/exif/ExifReader.java deleted file mode 100644 index d8083b2dd..000000000 --- a/src/com/android/gallery3d/exif/ExifReader.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.IOException; -import java.io.InputStream; - -/** - * This class reads the EXIF header of a JPEG file and stores it in {@link ExifData}. - */ -public class ExifReader { - /** - * Parses the inputStream and and returns the EXIF data in an {@link ExifData}. - * @throws ExifInvalidFormatException - * @throws IOException - */ - public ExifData read(InputStream inputStream) throws ExifInvalidFormatException, - IOException { - ExifParser parser = ExifParser.parse(inputStream); - ExifData exifData = new ExifData(parser.getByteOrder()); - - int event = parser.next(); - while (event != ExifParser.EVENT_END) { - switch (event) { - case ExifParser.EVENT_START_OF_IFD: - exifData.addIfdData(new IfdData(parser.getCurrentIfd())); - break; - case ExifParser.EVENT_NEW_TAG: - ExifTag tag = parser.getTag(); - if (!tag.hasValue()) { - parser.registerForTagValue(tag); - } else { - exifData.getIfdData(tag.getIfd()).setTag(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); - } - exifData.getIfdData(tag.getIfd()).setTag(tag); - break; - case ExifParser.EVENT_COMPRESSED_IMAGE: - byte buf[] = new byte[parser.getCompressedImageSize()]; - parser.read(buf); - exifData.setCompressedThumbnail(buf); - break; - case ExifParser.EVENT_UNCOMPRESSED_STRIP: - buf = new byte[parser.getStripSize()]; - parser.read(buf); - exifData.setStripBytes(parser.getStripIndex(), buf); - break; - } - event = parser.next(); - } - return exifData; - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/src/com/android/gallery3d/exif/ExifTag.java deleted file mode 100644 index def80a939..000000000 --- a/src/com/android/gallery3d/exif/ExifTag.java +++ /dev/null @@ -1,1478 +0,0 @@ -/* - * Copyright (C) 2012 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.util.SparseArray; - -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; - -/** - * This class stores information of an EXIF tag. - * @see ExifParser - * @see ExifReader - * @see IfdData - * @see ExifData - */ -public class ExifTag { - // Tiff Tags - public static final short TAG_IMAGE_WIDTH = 0x100; - /* - * The height of the image. - */ - public static final short TAG_IMAGE_LENGTH = 0x101; - public static final short TAG_BITS_PER_SAMPLE = 0x102; - public static final short TAG_COMPRESSION = 0x103; - public static final short TAG_PHOTOMETRIC_INTERPRETATION = 0x106; - public static final short TAG_IMAGE_DESCRIPTION = 0x10E; - public static final short TAG_MAKE = 0x10F; - public static final short TAG_MODEL = 0x110; - public static final short TAG_STRIP_OFFSETS = 0x111; - public static final short TAG_ORIENTATION = 0x112; - public static final short TAG_SAMPLES_PER_PIXEL = 0x115; - public static final short TAG_ROWS_PER_STRIP = 0x116; - public static final short TAG_STRIP_BYTE_COUNTS = 0x117; - public static final short TAG_X_RESOLUTION = 0x11A; - public static final short TAG_Y_RESOLUTION = 0x11B; - public static final short TAG_PLANAR_CONFIGURATION = 0x11C; - public static final short TAG_RESOLUTION_UNIT = 0x128; - public static final short TAG_TRANSFER_FUNCTION = 0x12D; - public static final short TAG_SOFTWARE = 0x131; - public static final short TAG_DATE_TIME = 0x132; - public static final short TAG_ARTIST = 0x13B; - public static final short TAG_WHITE_POINT = 0x13E; - public static final short TAG_PRIMARY_CHROMATICITIES = 0x13F; - public static final short TAG_JPEG_INTERCHANGE_FORMAT = 0x201; - public static final short TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x202; - public static final short TAG_Y_CB_CR_COEFFICIENTS = 0x211; - public static final short TAG_Y_CB_CR_SUB_SAMPLING = 0x212; - public static final short TAG_Y_CB_CR_POSITIONING = 0x213; - public static final short TAG_REFERENCE_BLACK_WHITE = 0x214; - public static final short TAG_COPYRIGHT = (short) 0x8298; - public static final short TAG_EXIF_IFD = (short) 0x8769; - public static final short TAG_GPS_IFD = (short) 0x8825; - - // Exif Tags - public static final short TAG_EXPOSURE_TIME = (short) 0x829A; - public static final short TAG_F_NUMBER = (short) 0x829D; - public static final short TAG_EXPOSURE_PROGRAM = (short) 0x8822; - public static final short TAG_SPECTRAL_SENSITIVITY = (short) 0x8824; - public static final short TAG_ISO_SPEED_RATINGS = (short) 0x8827; - public static final short TAG_OECF = (short) 0x8828; - public static final short TAG_EXIF_VERSION = (short) 0x9000; - public static final short TAG_DATE_TIME_ORIGINAL = (short) 0x9003; - public static final short TAG_DATE_TIME_DIGITIZED = (short) 0x9004; - public static final short TAG_COMPONENTS_CONFIGURATION = (short) 0x9101; - public static final short TAG_COMPRESSED_BITS_PER_PIXEL = (short) 0x9102; - public static final short TAG_SHUTTER_SPEED_VALUE = (short) 0x9201; - public static final short TAG_APERTURE_VALUE = (short) 0x9202; - public static final short TAG_BRIGHTNESS_VALUE = (short) 0x9203; - public static final short TAG_EXPOSURE_BIAS_VALUE = (short) 0x9204; - public static final short TAG_MAX_APERTURE_VALUE = (short) 0x9205; - public static final short TAG_SUBJECT_DISTANCE = (short) 0x9206; - public static final short TAG_METERING_MODE = (short) 0x9207; - public static final short TAG_LIGHT_SOURCE = (short) 0x9208; - public static final short TAG_FLASH = (short) 0x9209; - public static final short TAG_FOCAL_LENGTH = (short) 0x920A; - public static final short TAG_SUBJECT_AREA = (short) 0x9214; - public static final short TAG_MAKER_NOTE = (short) 0x927C; - public static final short TAG_USER_COMMENT = (short) 0x9286; - public static final short TAG_SUB_SEC_TIME = (short) 0x9290; - public static final short TAG_SUB_SEC_TIME_ORIGINAL = (short) 0x9291; - public static final short TAG_SUB_SEC_TIME_DIGITIZED = (short) 0x9292; - public static final short TAG_FLASHPIX_VERSION = (short) 0xA000; - public static final short TAG_COLOR_SPACE = (short) 0xA001; - public static final short TAG_PIXEL_X_DIMENSION = (short) 0xA002; - public static final short TAG_PIXEL_Y_DIMENSION = (short) 0xA003; - public static final short TAG_RELATED_SOUND_FILE = (short) 0xA004; - public static final short TAG_INTEROPERABILITY_IFD = (short) 0xA005; - public static final short TAG_FLASH_ENERGY = (short) 0xA20B; - public static final short TAG_SPATIAL_FREQUENCY_RESPONSE = (short) 0xA20C; - public static final short TAG_FOCAL_PLANE_X_RESOLUTION = (short) 0xA20E; - public static final short TAG_FOCAL_PLANE_Y_RESOLUTION = (short) 0xA20F; - public static final short TAG_FOCAL_PLANE_RESOLUTION_UNIT = (short) 0xA210; - public static final short TAG_SUBJECT_LOCATION = (short) 0xA214; - public static final short TAG_EXPOSURE_INDEX = (short) 0xA215; - public static final short TAG_SENSING_METHOD = (short) 0xA217; - public static final short TAG_FILE_SOURCE = (short) 0xA300; - public static final short TAG_SCENE_TYPE = (short) 0xA301; - public static final short TAG_CFA_PATTERN = (short) 0xA302; - public static final short TAG_CUSTOM_RENDERED = (short) 0xA401; - public static final short TAG_EXPOSURE_MODE = (short) 0xA402; - public static final short TAG_WHITE_BALANCE = (short) 0xA403; - public static final short TAG_DIGITAL_ZOOM_RATIO = (short) 0xA404; - public static final short TAG_FOCAL_LENGTH_IN_35_MM_FILE = (short) 0xA405; - public static final short TAG_SCENE_CAPTURE_TYPE = (short) 0xA406; - public static final short TAG_GAIN_CONTROL = (short) 0xA407; - public static final short TAG_CONTRAST = (short) 0xA408; - public static final short TAG_SATURATION = (short) 0xA409; - public static final short TAG_SHARPNESS = (short) 0xA40A; - public static final short TAG_DEVICE_SETTING_DESCRIPTION = (short) 0xA40B; - public static final short TAG_SUBJECT_DISTANCE_RANGE = (short) 0xA40C; - public static final short TAG_IMAGE_UNIQUE_ID = (short) 0xA420; - - // GPS tags - public static final short TAG_GPS_VERSION_ID = 0; - public static final short TAG_GPS_LATITUDE_REF = 1; - public static final short TAG_GPS_LATITUDE = 2; - public static final short TAG_GPS_LONGITUDE_REF = 3; - public static final short TAG_GPS_LONGITUDE = 4; - public static final short TAG_GPS_ALTITUDE_REF = 5; - public static final short TAG_GPS_ALTITUDE = 6; - public static final short TAG_GPS_TIME_STAMP = 7; - public static final short TAG_GPS_SATTELLITES = 8; - public static final short TAG_GPS_STATUS = 9; - public static final short TAG_GPS_MEASURE_MODE = 10; - public static final short TAG_GPS_DOP = 11; - public static final short TAG_GPS_SPEED_REF = 12; - public static final short TAG_GPS_SPEED = 13; - public static final short TAG_GPS_TRACK_REF = 14; - public static final short TAG_GPS_TRACK = 15; - public static final short TAG_GPS_IMG_DIRECTION_REF = 16; - public static final short TAG_GPS_IMG_DIRECTION = 17; - public static final short TAG_GPS_MAP_DATUM = 18; - public static final short TAG_GPS_DEST_LATITUDE_REF = 19; - public static final short TAG_GPS_DEST_LATITUDE = 20; - public static final short TAG_GPS_DEST_LONGITUDE_REF = 21; - public static final short TAG_GPS_DEST_LONGITUDE = 22; - public static final short TAG_GPS_DEST_BEARING_REF = 23; - public static final short TAG_GPS_DEST_BEARING = 24; - public static final short TAG_GPS_DEST_DISTANCE_REF = 25; - public static final short TAG_GPS_DEST_DISTANCE = 26; - public static final short TAG_GPS_PROCESSING_METHOD = 27; - public static final short TAG_GPS_AREA_INFORMATION = 28; - public static final short TAG_GPS_DATA_STAMP = 29; - public static final short TAG_GPS_DIFFERENTIAL = 30; - - // Interoperability tag - public static final short TAG_INTEROPERABILITY_INDEX = 1; - - /** - * Constants for {@link #TAG_ORIENTATION} - */ - public static interface Orientation { - public static final short TOP_LEFT = 1; - public static final short TOP_RIGHT = 2; - public static final short BOTTOM_LEFT = 3; - public static final short BOTTOM_RIGHT = 4; - public static final short LEFT_TOP = 5; - public static final short RIGHT_TOP = 6; - public static final short LEFT_BOTTOM = 7; - public static final short RIGHT_BOTTOM = 8; - } - - /** - * Constants for {@link #TAG_Y_CB_CR_POSITIONING} - */ - public static interface YCbCrPositioning { - public static final short CENTERED = 1; - public static final short CO_SITED = 2; - } - - /** - * Constants for {@link #TAG_COMPRESSION} - */ - public static interface Compression { - public static final short UNCOMPRESSION = 1; - public static final short JPEG = 6; - } - - /** - * Constants for {@link #TAG_RESOLUTION_UNIT} - */ - public static interface ResolutionUnit { - public static final short INCHES = 2; - public static final short CENTIMETERS = 3; - } - - /** - * Constants for {@link #TAG_PHOTOMETRIC_INTERPRETATION} - */ - public static interface PhotometricInterpretation { - public static final short RGB = 2; - public static final short YCBCR = 6; - } - - /** - * Constants for {@link #TAG_PLANAR_CONFIGURATION} - */ - public static interface PlanarConfiguration { - public static final short CHUNKY = 1; - public static final short PLANAR = 2; - } - - /** - * Constants for {@link #TAG_EXPOSURE_PROGRAM} - */ - public static interface ExposureProgram { - public static final short NOT_DEFINED = 0; - public static final short MANUAL = 1; - public static final short NORMAL_PROGRAM = 2; - public static final short APERTURE_PRIORITY = 3; - public static final short SHUTTER_PRIORITY = 4; - public static final short CREATIVE_PROGRAM = 5; - public static final short ACTION_PROGRAM = 6; - public static final short PROTRAIT_MODE = 7; - public static final short LANDSCAPE_MODE = 8; - } - - /** - * Constants for {@link #TAG_METERING_MODE} - */ - public static interface MeteringMode { - public static final short UNKNOWN = 0; - public static final short AVERAGE = 1; - public static final short CENTER_WEIGHTED_AVERAGE = 2; - public static final short SPOT = 3; - public static final short MULTISPOT = 4; - public static final short PATTERN = 5; - public static final short PARTAIL = 6; - public static final short OTHER = 255; - } - - /** - * Constants for {@link #TAG_FLASH} As the definition in Jeita EXIF 2.2 standard, we can - * treat this constant as bitwise flag. - * <p> - * e.g. - * <p> - * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED | MODE_AUTO_MODE - */ - public static interface Flash { - // LSB - public static final short DID_NOT_FIRED = 0; - public static final short FIRED = 1; - // 1st~2nd bits - public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1; - public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1; - public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1; - // 3rd~4th bits - public static final short MODE_UNKNOWN = 0 << 3; - public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3; - public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3; - public static final short MODE_AUTO_MODE = 3 << 3; - // 5th bit - public static final short FUNCTION_PRESENT = 0 << 5; - public static final short FUNCTION_NO_FUNCTION = 1 << 5; - // 6th bit - public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6; - public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6; - } - - /** - * Constants for {@link #TAG_COLOR_SPACE} - */ - public static interface ColorSpace { - public static final short SRGB = 1; - public static final short UNCALIBRATED = (short) 0xFFFF; - } - - /** - * Constants for {@link #TAG_EXPOSURE_MODE} - */ - public static interface ExposureMode { - public static final short AUTO_EXPOSURE = 0; - public static final short MANUAL_EXPOSURE = 1; - public static final short AUTO_BRACKET = 2; - } - - /** - * Constants for {@link #TAG_WHITE_BALANCE} - */ - public static interface WhiteBalance { - public static final short AUTO = 0; - public static final short MANUAL = 1; - } - - /** - * Constants for {@link #TAG_SCENE_CAPTURE_TYPE} - */ - public static interface SceneCapture { - public static final short STANDARD = 0; - public static final short LANDSCAPE = 1; - public static final short PROTRAIT = 2; - public static final short NIGHT_SCENE = 3; - } - - /** - * Constants for {@link #TAG_COMPONENTS_CONFIGURATION} - */ - public static interface ComponentsConfiguration { - public static final short NOT_EXIST = 0; - public static final short Y = 1; - public static final short CB = 2; - public static final short CR = 3; - public static final short R = 4; - public static final short G = 5; - public static final short B = 6; - } - - /** - * Constants for {@link #TAG_LIGHT_SOURCE} - */ - public static interface LightSource { - public static final short UNKNOWN = 0; - public static final short DAYLIGHT = 1; - public static final short FLUORESCENT = 2; - public static final short TUNGSTEN = 3; - public static final short FLASH = 4; - public static final short FINE_WEATHER = 9; - public static final short CLOUDY_WEATHER = 10; - public static final short SHADE = 11; - public static final short DAYLIGHT_FLUORESCENT = 12; - public static final short DAY_WHITE_FLUORESCENT = 13; - public static final short COOL_WHITE_FLUORESCENT = 14; - public static final short WHITE_FLUORESCENT = 15; - public static final short STANDARD_LIGHT_A = 17; - public static final short STANDARD_LIGHT_B = 18; - public static final short STANDARD_LIGHT_C = 19; - public static final short D55 = 20; - public static final short D65 = 21; - public static final short D75 = 22; - public static final short D50 = 23; - public static final short ISO_STUDIO_TUNGSTEN = 24; - public static final short OTHER = 255; - } - - /** - * Constants for {@link #TAG_SENSING_METHOD} - */ - public static interface SensingMethod { - public static final short NOT_DEFINED = 1; - public static final short ONE_CHIP_COLOR = 2; - public static final short TWO_CHIP_COLOR = 3; - public static final short THREE_CHIP_COLOR = 4; - public static final short COLOR_SEQUENTIAL_AREA = 5; - public static final short TRILINEAR = 7; - public static final short COLOR_SEQUENTIAL_LINEAR = 8; - } - - /** - * Constants for {@link #TAG_FILE_SOURCE} - */ - public static interface FileSource { - public static final short DSC = 3; - } - - /** - * Constants for {@link #TAG_SCENE_TYPE} - */ - public static interface SceneType { - public static final short DIRECT_PHOTOGRAPHED = 1; - } - - /** - * Constants for {@link #TAG_GAIN_CONTROL} - */ - public static interface GainControl { - public static final short NONE = 0; - public static final short LOW_UP = 1; - public static final short HIGH_UP = 2; - public static final short LOW_DOWN = 3; - public static final short HIGH_DOWN = 4; - } - - /** - * Constants for {@link #TAG_CONTRAST} - */ - public static interface Contrast { - public static final short NORMAL = 0; - public static final short SOFT = 1; - public static final short HARD = 2; - } - - /** - * Constants for {@link #TAG_SATURATION} - */ - public static interface Saturation { - public static final short NORMAL = 0; - public static final short LOW = 1; - public static final short HIGH = 2; - } - - /** - * Constants for {@link #TAG_SHARPNESS} - */ - public static interface Sharpness { - public static final short NORMAL = 0; - public static final short SOFT = 1; - public static final short HARD = 2; - } - - /** - * Constants for {@link #TAG_SUBJECT_DISTANCE} - */ - public static interface SubjectDistance { - public static final short UNKNOWN = 0; - public static final short MACRO = 1; - public static final short CLOSE_VIEW = 2; - public static final short DISTANT_VIEW = 3; - } - - /** - * Constants for {@link #TAG_GPS_LATITUDE_REF}, {@link #TAG_GPS_DEST_LATITUDE_REF} - */ - public static interface GpsLatitudeRef { - public static final String NORTH = "N"; - public static final String SOUTH = "S"; - } - - /** - * Constants for {@link #TAG_GPS_LONGITUDE_REF}, {@link #TAG_GPS_DEST_LONGITUDE_REF} - */ - public static interface GpsLongitudeRef { - public static final String EAST = "E"; - public static final String WEST = "W"; - } - - /** - * Constants for {@link #TAG_GPS_ALTITUDE_REF} - */ - public static interface GpsAltitudeRef { - public static final short SEA_LEVEL = 0; - public static final short SEA_LEVEL_NEGATIVE = 1; - } - - /** - * Constants for {@link #TAG_GPS_STATUS} - */ - public static interface GpsStatus { - public static final String IN_PROGRESS = "A"; - public static final String INTEROPERABILITY = "V"; - } - - /** - * Constants for {@link #TAG_GPS_MEASURE_MODE} - */ - public static interface GpsMeasureMode { - public static final String MODE_2_DIMENSIONAL = "2"; - public static final String MODE_3_DIMENSIONAL = "3"; - } - - /** - * Constants for {@link #TAG_GPS_SPEED_REF}, {@link #TAG_GPS_DEST_DISTANCE_REF} - */ - public static interface GpsSpeedRef { - public static final String KILOMETERS = "K"; - public static final String MILES = "M"; - public static final String KNOTS = "N"; - } - - /** - * Constants for {@link #TAG_GPS_TRACK_REF}, {@link #TAG_GPS_IMG_DIRECTION_REF}, - * {@link #TAG_GPS_DEST_BEARING_REF} - */ - public static interface GpsTrackRef { - public static final String TRUE_DIRECTION = "T"; - public static final String MAGNETIC_DIRECTION = "M"; - } - - /** - * Constants for {@link #TAG_GPS_DIFFERENTIAL} - */ - public static interface GpsDifferential { - public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0; - public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1; - } - - /** - * The BYTE type in the EXIF standard. An 8-bit unsigned integer. - */ - public static final short TYPE_UNSIGNED_BYTE = 1; - /** - * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit ASCII code. - * The final byte is terminated with NULL. - */ - public static final short TYPE_ASCII = 2; - /** - * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer - */ - public static final short TYPE_UNSIGNED_SHORT = 3; - /** - * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer - */ - public static final short TYPE_UNSIGNED_LONG = 4; - /** - * The RATIONAL type of EXIF standard. It consists of two LONGs. The first one is the numerator - * and the second one expresses the denominator. - */ - public static final short TYPE_UNSIGNED_RATIONAL = 5; - /** - * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any value - * depending on the field definition. - */ - public static final short TYPE_UNDEFINED = 7; - /** - * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer - * (2's complement notation). - */ - public static final short TYPE_LONG = 9; - /** - * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first one is the - * numerator and the second one is the denominator. - */ - public static final short TYPE_RATIONAL = 10; - - private static final int TYPE_TO_SIZE_MAP[] = new int[11]; - static { - TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1; - TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1; - TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2; - TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4; - TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8; - TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1; - TYPE_TO_SIZE_MAP[TYPE_LONG] = 4; - TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8; - } - - /** - * Gets the element size of the given data type. - * - * @see #TYPE_ASCII - * @see #TYPE_LONG - * @see #TYPE_RATIONAL - * @see #TYPE_UNDEFINED - * @see #TYPE_UNSIGNED_BYTE - * @see #TYPE_UNSIGNED_LONG - * @see #TYPE_UNSIGNED_RATIONAL - * @see #TYPE_UNSIGNED_SHORT - */ - public static int getElementSize(short type) { - return TYPE_TO_SIZE_MAP[type]; - } - - private static volatile SparseArray<Integer> sTagInfo = null; - private static volatile SparseArray<Integer> sInteroperTagInfo = null; - private static final int SIZE_UNDEFINED = 0; - - private static SparseArray<Integer> getTagInfo() { - if (sTagInfo == null) { - synchronized(ExifTag.class) { - if (sTagInfo == null) { - sTagInfo = new SparseArray<Integer>(); - initTagInfo(); - } - } - } - return sTagInfo; - } - - private static SparseArray<Integer> getInteroperTagInfo() { - if (sInteroperTagInfo == null) { - synchronized(ExifTag.class) { - if (sInteroperTagInfo == null) { - sInteroperTagInfo = new SparseArray<Integer>(); - sInteroperTagInfo.put(TAG_INTEROPERABILITY_INDEX, - (IfdId.TYPE_IFD_INTEROPERABILITY << 24) - | TYPE_ASCII << 16 | SIZE_UNDEFINED); - } - } - } - return sInteroperTagInfo; - } - - private static void initTagInfo() { - /** - * We put tag information in a 4-bytes integer. The first byte is the - * IFD of the tag, and the second byte is the default data type. The - * last two byte are a short value indicating the component count of this - * tag. - */ - sTagInfo.put(TAG_MAKE, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_IMAGE_WIDTH, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_IMAGE_LENGTH, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_BITS_PER_SAMPLE, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3); - sTagInfo.put(TAG_COMPRESSION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_PHOTOMETRIC_INTERPRETATION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_ORIENTATION, (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SAMPLES_PER_PIXEL, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_PLANAR_CONFIGURATION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_Y_CB_CR_SUB_SAMPLING, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 2); - sTagInfo.put(TAG_Y_CB_CR_POSITIONING, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_X_RESOLUTION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_Y_RESOLUTION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_RESOLUTION_UNIT, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_STRIP_OFFSETS, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_ROWS_PER_STRIP, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_STRIP_BYTE_COUNTS, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_TRANSFER_FUNCTION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3 * 256); - sTagInfo.put(TAG_WHITE_POINT, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 2); - sTagInfo.put(TAG_PRIMARY_CHROMATICITIES, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6); - sTagInfo.put(TAG_Y_CB_CR_COEFFICIENTS, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3); - sTagInfo.put(TAG_REFERENCE_BLACK_WHITE, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6); - sTagInfo.put(TAG_DATE_TIME, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | 20); - sTagInfo.put(TAG_IMAGE_DESCRIPTION, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_MAKE, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_MODEL, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_SOFTWARE, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_ARTIST, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_COPYRIGHT, - (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_EXIF_IFD, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_GPS_IFD, - (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - - // EXIF TAG - sTagInfo.put(TAG_EXIF_VERSION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4); - sTagInfo.put(TAG_FLASHPIX_VERSION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4); - sTagInfo.put(TAG_COLOR_SPACE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_COMPONENTS_CONFIGURATION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4); - sTagInfo.put(TAG_COMPRESSED_BITS_PER_PIXEL, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_PIXEL_X_DIMENSION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_PIXEL_Y_DIMENSION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1); - sTagInfo.put(TAG_MAKER_NOTE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_USER_COMMENT, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_RELATED_SOUND_FILE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 13); - sTagInfo.put(TAG_DATE_TIME_ORIGINAL, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20); - sTagInfo.put(TAG_DATE_TIME_DIGITIZED, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20); - sTagInfo.put(TAG_SUB_SEC_TIME, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_SUB_SEC_TIME_ORIGINAL, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_SUB_SEC_TIME_DIGITIZED, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_IMAGE_UNIQUE_ID, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 33); - sTagInfo.put(TAG_EXPOSURE_TIME, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_F_NUMBER, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_EXPOSURE_PROGRAM, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SPECTRAL_SENSITIVITY, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_ISO_SPEED_RATINGS, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_OECF, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_SHUTTER_SPEED_VALUE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1); - sTagInfo.put(TAG_APERTURE_VALUE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_BRIGHTNESS_VALUE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1); - sTagInfo.put(TAG_EXPOSURE_BIAS_VALUE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1); - sTagInfo.put(TAG_MAX_APERTURE_VALUE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_SUBJECT_DISTANCE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_METERING_MODE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_LIGHT_SOURCE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_FLASH, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_FOCAL_LENGTH, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_SUBJECT_AREA, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_FLASH_ENERGY, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_SPATIAL_FREQUENCY_RESPONSE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_FOCAL_PLANE_X_RESOLUTION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_FOCAL_PLANE_Y_RESOLUTION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_FOCAL_PLANE_RESOLUTION_UNIT, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SUBJECT_LOCATION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 2); - sTagInfo.put(TAG_EXPOSURE_INDEX, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_SENSING_METHOD, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_FILE_SOURCE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1); - sTagInfo.put(TAG_SCENE_TYPE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1); - sTagInfo.put(TAG_CFA_PATTERN, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_CUSTOM_RENDERED, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_EXPOSURE_MODE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_WHITE_BALANCE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_DIGITAL_ZOOM_RATIO, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_FOCAL_LENGTH_IN_35_MM_FILE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SCENE_CAPTURE_TYPE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_GAIN_CONTROL, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_CONTRAST, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SATURATION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_SHARPNESS, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - sTagInfo.put(TAG_DEVICE_SETTING_DESCRIPTION, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_SUBJECT_DISTANCE_RANGE, - (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1); - // GPS tag - sTagInfo.put(TAG_GPS_VERSION_ID, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 4); - sTagInfo.put(TAG_GPS_LATITUDE_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_LONGITUDE_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_LATITUDE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3); - sTagInfo.put(TAG_GPS_LONGITUDE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3); - sTagInfo.put(TAG_GPS_ALTITUDE_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 1); - sTagInfo.put(TAG_GPS_ALTITUDE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_TIME_STAMP, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3); - sTagInfo.put(TAG_GPS_SATTELLITES, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_GPS_STATUS, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_MEASURE_MODE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_DOP, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_SPEED_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_SPEED, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_TRACK_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_TRACK, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_IMG_DIRECTION_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_IMG_DIRECTION, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_MAP_DATUM, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_GPS_DEST_LATITUDE_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_DEST_LATITUDE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_DEST_BEARING_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_DEST_BEARING, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_DEST_DISTANCE_REF, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2); - sTagInfo.put(TAG_GPS_DEST_DISTANCE, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1); - sTagInfo.put(TAG_GPS_PROCESSING_METHOD, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_GPS_AREA_INFORMATION, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED); - sTagInfo.put(TAG_GPS_DATA_STAMP, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 11); - sTagInfo.put(TAG_GPS_DIFFERENTIAL, - (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_SHORT << 16 | 11); - } - - private final short mTagId; - private final short mDataType; - private final int mIfd; - private final boolean mComponentCountDefined; - private int mComponentCount; - private Object mValue; - private int mOffset; - - static private short getTypeFromInfo(int info) { - return (short) ((info >> 16) & 0xff); - } - - static private int getComponentCountFromInfo(int info) { - return info & 0xffff; - } - - static private int getIfdIdFromInfo(int info) { - return (info >> 24) & 0xff; - } - - static private boolean getComponentCountDefined(short tagId, int ifd) { - Integer info = (ifd == IfdId.TYPE_IFD_INTEROPERABILITY) ? - getInteroperTagInfo().get(tagId) : getTagInfo().get(tagId); - if (info == null) return false; - return getComponentCountFromInfo(info) != SIZE_UNDEFINED; - } - - static int getIfdIdFromTagId(short tagId) { - Integer info = getTagInfo().get(tagId); - if (info == null) { - throw new IllegalArgumentException("Unknown Tag ID: " + tagId); - } - return getIfdIdFromInfo(info); - } - - /** - * Create a tag with given ID. For tags related to interoperability and thumbnail, call - * {@link #buildInteroperabilityTag(short)} and {@link #buildThumbnailTag(short)} respectively. - * @exception IllegalArgumentException If the ID is invalid. - */ - static public ExifTag buildTag(short tagId) { - Integer info = getTagInfo().get(tagId); - if (info == null) { - throw new IllegalArgumentException("Unknown Tag ID: " + tagId); - } - return new ExifTag(tagId, getTypeFromInfo(info), - getComponentCountFromInfo(info), - getIfdIdFromInfo(info)); - } - - /** - * Create a tag related to thumbnail with given ID. - * @exception IllegalArgumentException If the ID is invalid. - */ - static public ExifTag buildThumbnailTag(short tagId) { - Integer info = getTagInfo().get(tagId); - if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_0) { - throw new IllegalArgumentException("Unknown Thumnail Tag ID: " + tagId); - } - return new ExifTag(tagId, getTypeFromInfo(info), - getComponentCountFromInfo(info), - IfdId.TYPE_IFD_1); - } - - /** - * Create a tag related to interoperability with given ID. - * @exception IllegalArgumentException If the ID is invalid. - */ - static public ExifTag buildInteroperabilityTag(short tagId) { - Integer info = getInteroperTagInfo().get(tagId); - if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_INTEROPERABILITY) { - throw new RuntimeException("Unknown Interoperability Tag ID: " + tagId); - } - return new ExifTag(tagId, getTypeFromInfo(info), - getComponentCountFromInfo(info), - IfdId.TYPE_IFD_INTEROPERABILITY); - } - - ExifTag(short tagId, short type, int componentCount, int ifd) { - mTagId = tagId; - mDataType = type; - mComponentCount = componentCount; - mComponentCountDefined = getComponentCountDefined(tagId, ifd); - mIfd = ifd; - } - - /** - * Returns the ID of the IFD this tag belongs to. - * - * @see IfdId#TYPE_IFD_0 - * @see IfdId#TYPE_IFD_1 - * @see IfdId#TYPE_IFD_EXIF - * @see IfdId#TYPE_IFD_GPS - * @see IfdId#TYPE_IFD_INTEROPERABILITY - */ - public int getIfd() { - return mIfd; - } - - /** - * Gets the ID of this tag. - */ - public short getTagId() { - return mTagId; - } - - /** - * Gets the data type of this tag - * - * @see #TYPE_ASCII - * @see #TYPE_LONG - * @see #TYPE_RATIONAL - * @see #TYPE_UNDEFINED - * @see #TYPE_UNSIGNED_BYTE - * @see #TYPE_UNSIGNED_LONG - * @see #TYPE_UNSIGNED_RATIONAL - * @see #TYPE_UNSIGNED_SHORT - */ - public short getDataType() { - return mDataType; - } - - /** - * Gets the total data size in bytes of the value of this tag. - */ - public int getDataSize() { - return getComponentCount() * getElementSize(getDataType()); - } - - /** - * Gets the component count of this tag. - */ - public int getComponentCount() { - return mComponentCount; - } - - /** - * Returns true if this ExifTag contains value; otherwise, this tag will contain an offset value - * that links to the area where the actual value is located. - * - * @see #getOffset() - */ - public boolean hasValue() { - return mValue != null; - } - - /** - * Gets the offset of this tag. This is only valid if this data size > 4 and contains an offset - * to the location of the actual value. - */ - public int getOffset() { - return mOffset; - } - - /** - * Sets the offset of this tag. - */ - void setOffset(int offset) { - mOffset = offset; - } - - private void checkComponentCountOrThrow(int count) - throws IllegalArgumentException { - if (mComponentCountDefined && (mComponentCount != count)) { - throw new IllegalArgumentException("Tag " + mTagId + ": Required " - + mComponentCount + " components but was given " + count - + " component(s)"); - } - } - - private void throwTypeNotMatchedException(String className) - throws IllegalArgumentException { - throw new IllegalArgumentException("Tag " + mTagId + ": expect type " + - convertTypeToString(mDataType) + " but got " + className); - } - - private static String convertTypeToString(short type) { - switch (type) { - case TYPE_UNSIGNED_BYTE: - return "UNSIGNED_BYTE"; - case TYPE_ASCII: - return "ASCII"; - case TYPE_UNSIGNED_SHORT: - return "UNSIGNED_SHORT"; - case TYPE_UNSIGNED_LONG: - return "UNSIGNED_LONG"; - case TYPE_UNSIGNED_RATIONAL: - return "UNSIGNED_RATIONAL"; - case TYPE_UNDEFINED: - return "UNDEFINED"; - case TYPE_LONG: - return "LONG"; - case TYPE_RATIONAL: - return "RATIONAL"; - default: - return ""; - } - } - - private static final int UNSIGNED_SHORT_MAX = 65535; - private static final long UNSIGNED_LONG_MAX = 4294967295L; - private static final long LONG_MAX = Integer.MAX_VALUE; - private static final long LONG_MIN = Integer.MIN_VALUE; - - private void checkOverflowForUnsignedShort(int[] value) { - for (int v : value) { - if (v > UNSIGNED_SHORT_MAX || v < 0) { - throw new IllegalArgumentException( - "Tag " + mTagId+ ": Value" + v + - " is illegal for type UNSIGNED_SHORT"); - } - } - } - - private void checkOverflowForUnsignedLong(long[] value) { - for (long v: value) { - if (v < 0 || v > UNSIGNED_LONG_MAX) { - throw new IllegalArgumentException( - "Tag " + mTagId+ ": Value" + v + - " is illegal for type UNSIGNED_LONG"); - } - } - } - - private void checkOverflowForUnsignedLong(int[] value) { - for (int v: value) { - if (v < 0) { - throw new IllegalArgumentException( - "Tag " + mTagId+ ": Value" + v + - " is illegal for type UNSIGNED_LONG"); - } - } - } - - private void checkOverflowForUnsignedRational(Rational[] value) { - for (Rational v: value) { - if (v.getNominator() < 0 || v.getDenominator() < 0 - || v.getNominator() > UNSIGNED_LONG_MAX - || v.getDenominator() > UNSIGNED_LONG_MAX) { - throw new IllegalArgumentException( - "Tag " + mTagId+ ": Value" + v + - " is illegal for type UNSIGNED_RATIONAL"); - } - } - } - - private void checkOverflowForRational(Rational[] value) { - for (Rational v: value) { - if (v.getNominator() < LONG_MIN || v.getDenominator() < LONG_MIN - || v.getNominator() > LONG_MAX - || v.getDenominator() > LONG_MAX) { - throw new IllegalArgumentException( - "Tag " + mTagId+ ": Value" + v + - " is illegal for type RATIONAL"); - } - } - } - - /** - * Sets integer values into this tag. - * @exception IllegalArgumentException for the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT}, - * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li> - * <li>The value overflows. </li> - * <li>The value.length does NOT match the definition of component count in - * EXIF standard.</li> - * </ul> - */ - public void setValue(int[] value) { - checkComponentCountOrThrow(value.length); - if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG && - mDataType != TYPE_UNSIGNED_LONG) { - throwTypeNotMatchedException("int"); - } - if (mDataType == TYPE_UNSIGNED_SHORT) { - checkOverflowForUnsignedShort(value); - } else if (mDataType == TYPE_UNSIGNED_LONG) { - checkOverflowForUnsignedLong(value); - } - - long[] data = new long[value.length]; - for (int i = 0; i < value.length; i++) { - data[i] = value[i]; - } - mValue = data; - mComponentCount = value.length; - } - - /** - * Sets integer values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT}, - * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li> - * <li>The value overflows.</li> - * <li>The component count in the definition of EXIF standard is not 1.</li> - * </ul> - */ - public void setValue(int value) { - checkComponentCountOrThrow(1); - setValue(new int[] {value}); - } - - /** - * Sets long values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li> - * <li>The value overflows. </li> - * <li>The value.length does NOT match the definition of component count in - * EXIF standard.</li> - * </ul> - */ - public void setValue(long[] value) { - checkComponentCountOrThrow(value.length); - if (mDataType != TYPE_UNSIGNED_LONG) { - throwTypeNotMatchedException("long"); - } - checkOverflowForUnsignedLong(value); - mValue = value; - mComponentCount = value.length; - } - - /** - * Sets long values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li> - * <li>The value overflows. </li> - * <li>The component count in the definition of EXIF standard is not 1.</li> - * </ul> - */ - public void setValue(long value) { - setValue(new long[] {value}); - } - - /** - * Sets string values into this tag. - * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII} - * or value.length() + 1 does NOT fit the definition of the component count in the - * EXIF standard. - */ - public void setValue(String value) { - checkComponentCountOrThrow(value.length() + 1); - if (mDataType != TYPE_ASCII) { - throwTypeNotMatchedException("String"); - } - mComponentCount = value.length() + 1; - mValue = value; - } - - /** - * Sets Rational values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or - * {@link #TYPE_RATIONAL} .</li> - * <li>The value overflows. </li> - * <li>The value.length does NOT match the definition of component count in - * EXIF standard.</li> - * </ul> - */ - public void setValue(Rational[] value) { - if (mDataType == TYPE_UNSIGNED_RATIONAL) { - checkOverflowForUnsignedRational(value); - } else if (mDataType == TYPE_RATIONAL) { - checkOverflowForRational(value); - } else { - throwTypeNotMatchedException("Rational"); - } - checkComponentCountOrThrow(value.length); - mValue = value; - mComponentCount = value.length; - } - - /** - * Sets Rational values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or - * {@link #TYPE_RATIONAL} .</li> - * <li>The value overflows. </li> - * <li>The component count in the definition of EXIF standard is not 1.</li> - * </ul> - * */ - public void setValue(Rational value) { - setValue(new Rational[] {value}); - } - - /** - * Sets byte values into this tag. - * @exception IllegalArgumentException For the following situation: - * <ul> - * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or - * {@link #TYPE_UNDEFINED} .</li> - * <li>The length does NOT match the definition of component count in EXIF standard.</li> - * </ul> - * */ - public void setValue(byte[] value, int offset, int length) { - checkComponentCountOrThrow(length); - if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) { - throwTypeNotMatchedException("byte"); - } - mValue = new byte[length]; - System.arraycopy(value, offset, mValue, 0, length); - mComponentCount = length; - } - - /** - * Equivalent to setValue(value, 0, value.length). - */ - public void setValue(byte[] value) { - setValue(value, 0, value.length); - } - - private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss"); - - /** - * Sets a timestamp to this tag. The method converts the timestamp with the format of - * "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}. - * - * @param time the number of milliseconds since Jan. 1, 1970 GMT - * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII} - * or the component count of this tag is not 20 or undefined - */ - public void setTimeValue(long time) { - // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe - synchronized (TIME_FORMAT) { - setValue(TIME_FORMAT.format(new Date(time))); - } - } - - /** - * Gets the {@link #TYPE_UNSIGNED_SHORT} data. - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_SHORT}. - */ - public int getUnsignedShort(int index) { - if (mDataType != TYPE_UNSIGNED_SHORT) { - throw new IllegalArgumentException("Cannot get UNSIGNED_SHORT value from " - + convertTypeToString(mDataType)); - } - return (int) (((long[]) mValue) [index]); - } - - /** - * Gets the {@link #TYPE_LONG} data. - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_LONG}. - */ - public int getLong(int index) { - if (mDataType != TYPE_LONG) { - throw new IllegalArgumentException("Cannot get LONG value from " - + convertTypeToString(mDataType)); - } - return (int) (((long[]) mValue) [index]); - } - - /** - * Gets the {@link #TYPE_UNSIGNED_LONG} data. - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_LONG}. - */ - public long getUnsignedLong(int index) { - if (mDataType != TYPE_UNSIGNED_LONG) { - throw new IllegalArgumentException("Cannot get UNSIGNED LONG value from " - + convertTypeToString(mDataType)); - } - return ((long[]) mValue) [index]; - } - - /** - * Gets the {@link #TYPE_ASCII} data. - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_ASCII}. - */ - public String getString() { - if (mDataType != TYPE_ASCII) { - throw new IllegalArgumentException("Cannot get ASCII value from " - + convertTypeToString(mDataType)); - } - return (String) mValue; - } - - /** - * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data. - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_RATIONAL} or - * {@link #TYPE_UNSIGNED_RATIONAL}. - */ - public Rational getRational(int index) { - if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) { - throw new IllegalArgumentException("Cannot get RATIONAL value from " - + convertTypeToString(mDataType)); - } - return ((Rational[]) mValue) [index]; - } - - /** - * Equivalent to getBytes(buffer, 0, buffer.length). - */ - public void getBytes(byte[] buf) { - getBytes(buf, 0, buf.length); - } - - /** - * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data. - * - * @param buf the byte array in which to store the bytes read. - * @param offset the initial position in buffer to store the bytes. - * @param length the maximum number of bytes to store in buffer. If length > component count, - * only the valid bytes will be stored. - * - * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNDEFINED} or - * {@link #TYPE_UNSIGNED_BYTE}. - */ - public void getBytes(byte[] buf, int offset, int length) { - if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) { - throw new IllegalArgumentException("Cannot get BYTE value from " - + convertTypeToString(mDataType)); - } - System.arraycopy(mValue, 0, buf, offset, - (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. - */ - String valueToString() { - StringBuilder sbuilder = new StringBuilder(); - switch (getDataType()) { - case ExifTag.TYPE_UNDEFINED: - sbuilder.append(undefinedTypeValueToString()); - break; - case ExifTag.TYPE_UNSIGNED_BYTE: - 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: - 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++) { - if(i != 0) sbuilder.append(" "); - sbuilder.append(getUnsignedLong(i)); - } - break; - case ExifTag.TYPE_RATIONAL: - case ExifTag.TYPE_UNSIGNED_RATIONAL: - 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, n = getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); - sbuilder.append(getUnsignedShort(i)); - } - break; - case ExifTag.TYPE_LONG: - for(int i = 0, n = getComponentCount(); i < n; i++) { - if(i != 0) sbuilder.append(" "); - sbuilder.append(getLong(i)); - } - break; - } - return sbuilder.toString(); - } - - /** - * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD}, - * {@link #TAG_GPS_IFD}, {@link #TAG_JPEG_INTERCHANGE_FORMAT}, - * {@link #TAG_STRIP_OFFSETS}, {@link #TAG_INTEROPERABILITY_IFD} - */ - static boolean isOffsetTag(short tagId) { - return tagId == TAG_EXIF_IFD - || tagId == TAG_GPS_IFD - || tagId == TAG_JPEG_INTERCHANGE_FORMAT - || tagId == TAG_STRIP_OFFSETS - || 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) { - ExifTag tag = (ExifTag) obj; - if (mValue != null) { - if (mValue instanceof long[]) { - if (!(tag.mValue instanceof long[])) return false; - return Arrays.equals((long[]) mValue, (long[]) tag.mValue); - } else if (mValue instanceof Rational[]) { - if (!(tag.mValue instanceof Rational[])) return false; - return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue); - } else if (mValue instanceof byte[]) { - if (!(tag.mValue instanceof byte[])) return false; - return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue); - } else { - return mValue.equals(tag.mValue); - } - } else { - return tag.mValue == null; - } - } - return false; - } -} diff --git a/src/com/android/gallery3d/exif/IfdData.java b/src/com/android/gallery3d/exif/IfdData.java deleted file mode 100644 index 78f9173cc..000000000 --- a/src/com/android/gallery3d/exif/IfdData.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2012 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 java.util.HashMap; -import java.util.Map; - -/** - * This class stores all the tags in an IFD. - * - * @see ExifData - * @see ExifTag - */ -class IfdData { - - private final int mIfdId; - private final Map<Short, ExifTag> mExifTags = new HashMap<Short, ExifTag>(); - private int mOffsetToNextIfd = 0; - - /** - * Creates an IfdData with given IFD ID. - * - * @see IfdId#TYPE_IFD_0 - * @see IfdId#TYPE_IFD_1 - * @see IfdId#TYPE_IFD_EXIF - * @see IfdId#TYPE_IFD_GPS - * @see IfdId#TYPE_IFD_INTEROPERABILITY - */ - public IfdData(int ifdId) { - mIfdId = ifdId; - } - - /** - * Get a array the contains all {@link ExifTag} in this IFD. - */ - public ExifTag[] getAllTags() { - return mExifTags.values().toArray(new ExifTag[mExifTags.size()]); - } - - /** - * Gets the ID of this IFD. - * - * @see IfdId#TYPE_IFD_0 - * @see IfdId#TYPE_IFD_1 - * @see IfdId#TYPE_IFD_EXIF - * @see IfdId#TYPE_IFD_GPS - * @see IfdId#TYPE_IFD_INTEROPERABILITY - */ - public int getId() { - return mIfdId; - } - - /** - * Gets the {@link ExifTag} with given tag id. Return null if there is no such tag. - */ - public ExifTag getTag(short tagId) { - return mExifTags.get(tagId); - } - - /** - * Adds or replaces a {@link ExifTag}. - */ - public void setTag(ExifTag tag) { - mExifTags.put(tag.getTagId(), tag); - } - - /** - * Gets the tags count in the IFD. - */ - public int getTagCount() { - return mExifTags.size(); - } - - /** - * Sets the offset of next IFD. - */ - void setOffsetToNextIfd(int offset) { - mOffsetToNextIfd = offset; - } - - /** - * Gets the offset of next IFD. - */ - int getOffsetToNextIfd() { - return mOffsetToNextIfd; - } - - /** - * Returns true if all tags in this two IFDs are equal. Note that tags of IFDs offset or - * thumbnail offset will be ignored. - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof IfdData) { - IfdData data = (IfdData) obj; - if (data.getId() == mIfdId && data.getTagCount() == getTagCount()) { - ExifTag[] tags = data.getAllTags(); - for (ExifTag tag: tags) { - if (ExifTag.isOffsetTag(tag.getTagId())) continue; - ExifTag tag2 = mExifTags.get(tag.getTagId()); - if (!tag.equals(tag2)) return false; - } - return true; - } - } - return false; - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/IfdId.java b/src/com/android/gallery3d/exif/IfdId.java deleted file mode 100644 index 1b9634369..000000000 --- a/src/com/android/gallery3d/exif/IfdId.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 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; - -public interface IfdId { - public static final int TYPE_IFD_0 = 0; - public static final int TYPE_IFD_1 = 1; - public static final int TYPE_IFD_EXIF = 2; - public static final int TYPE_IFD_INTEROPERABILITY = 3; - public static final int TYPE_IFD_GPS = 4; - /* This is use in ExifData to allocate enough IfdData */ - static final int TYPE_IFD_COUNT = 5; -} diff --git a/src/com/android/gallery3d/exif/JpegHeader.java b/src/com/android/gallery3d/exif/JpegHeader.java deleted file mode 100644 index e3e787eff..000000000 --- a/src/com/android/gallery3d/exif/JpegHeader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 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; - -class JpegHeader { - public static final short SOI = (short) 0xFFD8; - public static final short APP1 = (short) 0xFFE1; - public static final short APP0 = (short) 0xFFE0; - public static final short EOI = (short) 0xFFD9; - - /** - * SOF (start of frame). All value between SOF0 and SOF15 is SOF marker except for DHT, JPG, - * and DAC marker. - */ - public static final short SOF0 = (short) 0xFFC0; - public static final short SOF15 = (short) 0xFFCF; - public static final short DHT = (short) 0xFFC4; - public static final short JPG = (short) 0xFFC8; - public static final short DAC = (short) 0xFFCC; - - public static final boolean isSofMarker(short marker) { - return marker >= SOF0 && marker <= SOF15 && marker != DHT && marker != JPG - && marker != DAC; - } -} diff --git a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java b/src/com/android/gallery3d/exif/OrderedDataOutputStream.java deleted file mode 100644 index 4f785a889..000000000 --- a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -class OrderedDataOutputStream extends FilterOutputStream { - private final ByteBuffer mByteBuffer = ByteBuffer.allocate(4); - - public OrderedDataOutputStream(OutputStream out) { - super(out); - } - - public void setByteOrder(ByteOrder order) { - mByteBuffer.order(order); - } - - public void writeShort(short value) throws IOException { - mByteBuffer.rewind(); - mByteBuffer.putShort(value); - out.write(mByteBuffer.array(), 0, 2); - } - - public void writeInt(int value) throws IOException { - mByteBuffer.rewind(); - mByteBuffer.putInt(value); - out.write(mByteBuffer.array()); - } - - public void writeRational(Rational rational) throws IOException { - writeInt((int) rational.getNominator()); - writeInt((int) rational.getDenominator()); - } -} diff --git a/src/com/android/gallery3d/exif/Rational.java b/src/com/android/gallery3d/exif/Rational.java deleted file mode 100644 index 7d9026261..000000000 --- a/src/com/android/gallery3d/exif/Rational.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2012 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; - -public class Rational { - - private final long mNominator; - private final long mDenominator; - - public Rational(long nominator, long denominator) { - mNominator = nominator; - mDenominator = denominator; - } - - public long getNominator() { - return mNominator; - } - - public long getDenominator() { - return mDenominator; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Rational) { - Rational data = (Rational) obj; - return mNominator == data.mNominator && mDenominator == data.mDenominator; - } - return false; - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/exif/Util.java b/src/com/android/gallery3d/exif/Util.java deleted file mode 100644 index 594d6fc7f..000000000 --- a/src/com/android/gallery3d/exif/Util.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 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 java.io.Closeable; - -class Util { - public static boolean equals(Object a, Object b) { - return (a == b) || (a == null ? false : a.equals(b)); - } - - public static void closeSilently(Closeable c) { - if (c == null) return; - try { - c.close(); - } catch (Throwable t) { - // do nothing - } - } -} |