diff options
author | Hung-ying Tyan <tyanh@google.com> | 2012-10-19 20:50:50 +0800 |
---|---|---|
committer | Hung-ying Tyan <tyanh@google.com> | 2012-10-22 10:50:20 +0800 |
commit | e686a42b89aaa6e4286833a361066e7d372522ce (patch) | |
tree | f5bd47709e56aeba0c8cfdcc1b1468dfe836c3cc /gallerycommon/src/com/android/gallery3d/exif/ExifData.java | |
parent | c778aab129fb001fdff1ccf167867fc40fbf7523 (diff) | |
download | android_packages_apps_Gallery2-e686a42b89aaa6e4286833a361066e7d372522ce.tar.gz android_packages_apps_Gallery2-e686a42b89aaa6e4286833a361066e7d372522ce.tar.bz2 android_packages_apps_Gallery2-e686a42b89aaa6e4286833a361066e7d372522ce.zip |
Move new exif lib to gallerycommon.
https://googleplex-android-review.googlesource.com/#/c/242047 depends on this.
Bug: 6667860
Change-Id: Iac937e2eea94f0f5ffde876235b1c2ee748e7570
Diffstat (limited to 'gallerycommon/src/com/android/gallery3d/exif/ExifData.java')
-rw-r--r-- | gallerycommon/src/com/android/gallery3d/exif/ExifData.java | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifData.java b/gallerycommon/src/com/android/gallery3d/exif/ExifData.java new file mode 100644 index 000000000..39eb57455 --- /dev/null +++ b/gallerycommon/src/com/android/gallery3d/exif/ExifData.java @@ -0,0 +1,261 @@ +/* + * 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. The original tag will be replaced by the new tag. 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 = ExifTag.buildTag(tagId); + ifdData.setTag(tag); + return tag; + } + + /** + * Adds a thumbnail-related tag with the given tag ID. The original tag will be replaced + * by the new tag. + * @exception IllegalArgumentException if the tag ID is invalid. + */ + public ExifTag addThumbnailTag(short tagId) { + IfdData ifdData = getOrCreateIfdData(IfdId.TYPE_IFD_1); + ExifTag tag = ExifTag.buildThumbnailTag(tagId); + ifdData.setTag(tag); + return tag; + } + + /** + * Adds an interoperability-related tag with the given tag ID. The original tag will be + * replaced by the new tag. + * @exception IllegalArgumentException if the tag ID is invalid. + */ + public ExifTag addInteroperabilityTag(short tagId) { + IfdData ifdData = getOrCreateIfdData(IfdId.TYPE_IFD_INTEROPERABILITY); + ExifTag tag = ExifTag.buildInteroperabilityTag(tagId); + ifdData.setTag(tag); + return tag; + } + + public void removeThumbnailData() { + mThumbnail = null; + mStripBytes.clear(); + mIfdDatas[IfdId.TYPE_IFD_1] = null; + } +}
\ No newline at end of file |