1e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/* 2e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Copyright (C) 2012 The Android Open Source Project 3e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 4e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * you may not use this file except in compliance with the License. 6e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * You may obtain a copy of the License at 7e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 8e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 10e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Unless required by applicable law or agreed to in writing, software 11e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * See the License for the specific language governing permissions and 14e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * limitations under the License. 15e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 16e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 17e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkapackage com.android.gallery3d.exif; 18e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 19e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.util.Log; 20e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 21e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.io.UnsupportedEncodingException; 22e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.nio.ByteOrder; 23e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.ArrayList; 24e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.Arrays; 25e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.List; 26e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 27e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka/** 28e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * This class stores the EXIF header in IFDs according to the JPEG 29e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * specification. It is the result produced by {@link ExifReader}. 30e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 31e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * @see ExifReader 32e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * @see IfdData 33e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 34e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaclass ExifData { 35e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final String TAG = "ExifData"; 36e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final byte[] USER_COMMENT_ASCII = { 37e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 38e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 39e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final byte[] USER_COMMENT_JIS = { 40e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00 41e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 42e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private static final byte[] USER_COMMENT_UNICODE = { 43e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00 44e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka }; 45e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 46e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final IfdData[] mIfdDatas = new IfdData[IfdId.TYPE_IFD_COUNT]; 47e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private byte[] mThumbnail; 48e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private ArrayList<byte[]> mStripBytes = new ArrayList<byte[]>(); 49e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka private final ByteOrder mByteOrder; 50e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 51e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifData(ByteOrder order) { 52e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mByteOrder = order; 53e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 54e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 55e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 56e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Gets the compressed thumbnail. Returns null if there is no compressed 57e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * thumbnail. 58e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 59e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * @see #hasCompressedThumbnail() 60e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 61e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected byte[] getCompressedThumbnail() { 62e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mThumbnail; 63e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 64e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 65e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 66e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Sets the compressed thumbnail. 67e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 68e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void setCompressedThumbnail(byte[] thumbnail) { 69e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mThumbnail = thumbnail; 70e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 71e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 72e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 73e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns true it this header contains a compressed thumbnail. 74e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 75e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected boolean hasCompressedThumbnail() { 76e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mThumbnail != null; 77e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 78e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 79e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 80e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Adds an uncompressed strip. 81e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 82e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void setStripBytes(int index, byte[] strip) { 83e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (index < mStripBytes.size()) { 84e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mStripBytes.set(index, strip); 85e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 86e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (int i = mStripBytes.size(); i < index; i++) { 87e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mStripBytes.add(null); 88e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 89e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mStripBytes.add(strip); 90e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 91e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 92e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 93e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 94e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Gets the strip count. 95e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 96e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected int getStripCount() { 97e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mStripBytes.size(); 98e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 99e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 100e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 101e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Gets the strip at the specified index. 102e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * 103e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * @exceptions #IndexOutOfBoundException 104e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 105e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected byte[] getStrip(int index) { 106e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mStripBytes.get(index); 107e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 108e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 109e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 110e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns true if this header contains uncompressed strip. 111e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 112e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected boolean hasUncompressedStrip() { 113e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mStripBytes.size() != 0; 114e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 115e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 116e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 117e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Gets the byte order. 118e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 119e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected ByteOrder getByteOrder() { 120e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mByteOrder; 121e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 122e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 123e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 124e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns the {@link IfdData} object corresponding to a given IFD if it 125e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * exists or null. 126e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 127e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected IfdData getIfdData(int ifdId) { 128e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ExifTag.isValidIfd(ifdId)) { 129e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return mIfdDatas[ifdId]; 130e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 131e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 132e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 133e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 134e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 135e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Adds IFD data. If IFD data of the same type already exists, it will be 136e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * replaced by the new data. 137e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 138e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void addIfdData(IfdData data) { 139e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mIfdDatas[data.getId()] = data; 140e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 141e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 142e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 143e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns the {@link IfdData} object corresponding to a given IFD or 144e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * generates one if none exist. 145e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 146e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected IfdData getOrCreateIfdData(int ifdId) { 147e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifdData = mIfdDatas[ifdId]; 148e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ifdData == null) { 149e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ifdData = new IfdData(ifdId); 150e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mIfdDatas[ifdId] = ifdData; 151e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 152e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return ifdData; 153e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 154e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 155e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 156e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns the tag with a given TID in the given IFD if the tag exists. 157e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Otherwise returns null. 158e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 159e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected ExifTag getTag(short tag, int ifd) { 160e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifdData = mIfdDatas[ifd]; 161e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return (ifdData == null) ? null : ifdData.getTag(tag); 162e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 163e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 164e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 165e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Adds the given ExifTag to its default IFD and returns an existing ExifTag 166e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * with the same TID or null if none exist. 167e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 168e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected ExifTag addTag(ExifTag tag) { 169e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tag != null) { 170e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka int ifd = tag.getIfd(); 171e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return addTag(tag, ifd); 172e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 173e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 174e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 175e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 176e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 177e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Adds the given ExifTag to the given IFD and returns an existing ExifTag 178e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * with the same TID or null if none exist. 179e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 180e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected ExifTag addTag(ExifTag tag, int ifdId) { 181e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tag != null && ExifTag.isValidIfd(ifdId)) { 182e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifdData = getOrCreateIfdData(ifdId); 183e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return ifdData.setTag(tag); 184e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 185e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 186e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 187e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 188e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void clearThumbnailAndStrips() { 189e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mThumbnail = null; 190e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mStripBytes.clear(); 191e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 192e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 193e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 194e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Removes the thumbnail and its related tags. IFD1 will be removed. 195e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 196e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void removeThumbnailData() { 197e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka clearThumbnailAndStrips(); 198e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka mIfdDatas[IfdId.TYPE_IFD_1] = null; 199e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 200e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 201e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 202e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Removes the tag with a given TID and IFD. 203e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 204e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected void removeTag(short tagId, int ifdId) { 205e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifdData = mIfdDatas[ifdId]; 206e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ifdData == null) { 207e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return; 208e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 209e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ifdData.removeTag(tagId); 210e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 211e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 212e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 213e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Decodes the user comment tag into string as specified in the EXIF 214e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * standard. Returns null if decoding failed. 215e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 216e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected String getUserComment() { 217e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_0]; 218e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ifdData == null) { 219e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 220e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 221e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifTag tag = ifdData.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)); 222e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tag == null) { 223e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 224e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 225e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tag.getComponentCount() < 8) { 226e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 227e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 228e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 229e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka byte[] buf = new byte[tag.getComponentCount()]; 230e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka tag.getBytes(buf); 231e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 232e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka byte[] code = new byte[8]; 233e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka System.arraycopy(buf, 0, code, 0, 8); 234e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 235e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka try { 236e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (Arrays.equals(code, USER_COMMENT_ASCII)) { 237e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return new String(buf, 8, buf.length - 8, "US-ASCII"); 238e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (Arrays.equals(code, USER_COMMENT_JIS)) { 239e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return new String(buf, 8, buf.length - 8, "EUC-JP"); 240e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else if (Arrays.equals(code, USER_COMMENT_UNICODE)) { 241e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return new String(buf, 8, buf.length - 8, "UTF-16"); 242e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } else { 243e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 244e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 245e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } catch (UnsupportedEncodingException e) { 246e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka Log.w(TAG, "Failed to decode the user comment"); 247e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 248e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 249e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 250e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 251e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 252e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns a list of all {@link ExifTag}s in the ExifData or null if there 253e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * are none. 254e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 255e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected List<ExifTag> getAllTags() { 256e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 257e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (IfdData d : mIfdDatas) { 258e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (d != null) { 259e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifTag[] tags = d.getAllTags(); 260e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tags != null) { 261e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (ExifTag t : tags) { 262e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ret.add(t); 263e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 264e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 265e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 266e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 267e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ret.size() == 0) { 268e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 269e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 270e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return ret; 271e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 272e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 273e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 274e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns a list of all {@link ExifTag}s in a given IFD or null if there 275e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * are none. 276e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 277e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected List<ExifTag> getAllTagsForIfd(int ifd) { 278e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData d = mIfdDatas[ifd]; 279e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (d == null) { 280e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 281e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 282e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifTag[] tags = d.getAllTags(); 283e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (tags == null) { 284e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 285e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 286e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(tags.length); 287e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (ExifTag t : tags) { 288e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ret.add(t); 289e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 290e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ret.size() == 0) { 291e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 292e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 293e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return ret; 294e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 295e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 296e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka /** 297e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * Returns a list of all {@link ExifTag}s with a given TID or null if there 298e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka * are none. 299e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka */ 300e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka protected List<ExifTag> getAllTagsForTagId(short tag) { 301e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 302e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (IfdData d : mIfdDatas) { 303e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (d != null) { 304e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifTag t = d.getTag(tag); 305e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (t != null) { 306e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ret.add(t); 307e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 308e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 309e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 310e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ret.size() == 0) { 311e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return null; 312e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 313e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return ret; 314e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 315e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 316e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka @Override 317e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka public boolean equals(Object obj) { 318e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (this == obj) { 319e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return true; 320e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 321e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (obj == null) { 322e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 323e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 324e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (obj instanceof ExifData) { 325e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka ExifData data = (ExifData) obj; 326e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (data.mByteOrder != mByteOrder || 327e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka data.mStripBytes.size() != mStripBytes.size() || 328e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka !Arrays.equals(data.mThumbnail, mThumbnail)) { 329e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 330e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 331e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (int i = 0; i < mStripBytes.size(); i++) { 332e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) { 333e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 334e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 335e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 336e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { 337e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifd1 = data.getIfdData(i); 338e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka IfdData ifd2 = getIfdData(i); 339e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka if (ifd1 != ifd2 && ifd1 != null && !ifd1.equals(ifd2)) { 340e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 341e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 342e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 343e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return true; 344e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 345e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka return false; 346e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka } 347e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka 348e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka} 349