summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHung-ying Tyan <tyanh@google.com>2012-10-22 16:23:41 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-10-22 16:23:41 -0700
commitf9b86094984f2ca74538267c6e71e8381422642e (patch)
tree849bf7b1fe06fb7ed0da2db6d1e2ac642bf8be25 /src
parent8c18fb9269c4fdd72a48ec76851e293950190b29 (diff)
parent4e791ba2c3992d948c0ac4c70c2dafd289386c21 (diff)
downloadandroid_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.java136
-rw-r--r--src/com/android/gallery3d/exif/ExifData.java273
-rw-r--r--src/com/android/gallery3d/exif/ExifInvalidFormatException.java23
-rw-r--r--src/com/android/gallery3d/exif/ExifOutputStream.java377
-rw-r--r--src/com/android/gallery3d/exif/ExifParser.java752
-rw-r--r--src/com/android/gallery3d/exif/ExifReader.java74
-rw-r--r--src/com/android/gallery3d/exif/ExifTag.java1478
-rw-r--r--src/com/android/gallery3d/exif/IfdData.java122
-rw-r--r--src/com/android/gallery3d/exif/IfdId.java26
-rw-r--r--src/com/android/gallery3d/exif/JpegHeader.java39
-rw-r--r--src/com/android/gallery3d/exif/OrderedDataOutputStream.java52
-rw-r--r--src/com/android/gallery3d/exif/Rational.java45
-rw-r--r--src/com/android/gallery3d/exif/Util.java34
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
- }
- }
-}