1321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou/* 2321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * Copyright (C) 2012 The Android Open Source Project 3321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * 4321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * Licensed under the Apache License, Version 2.0 (the "License"); 5321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * you may not use this file except in compliance with the License. 6321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * You may obtain a copy of the License at 7321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * 8321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * http://www.apache.org/licenses/LICENSE-2.0 9321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * 10321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * Unless required by applicable law or agreed to in writing, software 11321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * distributed under the License is distributed on an "AS IS" BASIS, 12321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * See the License for the specific language governing permissions and 14321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou * limitations under the License. 15321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou */ 16321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou 17321e7c477a66df696b92d1617a33f6bafab7886dEarl Oupackage com.android.gallery3d.exif; 18d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 1915438682a38ad2887426c100452a990b5e3f965dEarl Ouimport android.util.Log; 2015438682a38ad2887426c100452a990b5e3f965dEarl Ou 2115438682a38ad2887426c100452a990b5e3f965dEarl Ouimport java.io.UnsupportedEncodingException; 227973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ouimport java.nio.ByteOrder; 23d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ouimport java.util.ArrayList; 24cde6ac521216801e835df1c20b68dd21d4fd04a4Earl Ouimport java.util.Arrays; 256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.List; 26d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 274ae9b211fee74f801f003bc9ad716e214de1a4f0Earl Ou/** 286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * This class stores the EXIF header in IFDs according to the JPEG 296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * specification. It is the result produced by {@link ExifReader}. 306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * 316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * @see ExifReader 326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * @see IfdData 334ae9b211fee74f801f003bc9ad716e214de1a4f0Earl Ou */ 346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkclass ExifData { 3515438682a38ad2887426c100452a990b5e3f965dEarl Ou private static final String TAG = "ExifData"; 3615438682a38ad2887426c100452a990b5e3f965dEarl Ou private static final byte[] USER_COMMENT_ASCII = { 376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk }; 3915438682a38ad2887426c100452a990b5e3f965dEarl Ou private static final byte[] USER_COMMENT_JIS = { 406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00 416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk }; 4215438682a38ad2887426c100452a990b5e3f965dEarl Ou private static final byte[] USER_COMMENT_UNICODE = { 436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00 446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk }; 456c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou 464ae9b211fee74f801f003bc9ad716e214de1a4f0Earl Ou private final IfdData[] mIfdDatas = new IfdData[IfdId.TYPE_IFD_COUNT]; 47d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou private byte[] mThumbnail; 48d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou private ArrayList<byte[]> mStripBytes = new ArrayList<byte[]>(); 497973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou private final ByteOrder mByteOrder; 507973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou 516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifData(ByteOrder order) { 527973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou mByteOrder = order; 53321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou } 54321e7c477a66df696b92d1617a33f6bafab7886dEarl Ou 554ae9b211fee74f801f003bc9ad716e214de1a4f0Earl Ou /** 566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Gets the compressed thumbnail. Returns null if there is no compressed 576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * thumbnail. 58d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * 59d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * @see #hasCompressedThumbnail() 60d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected byte[] getCompressedThumbnail() { 62d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou return mThumbnail; 63d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 64d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 65d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou /** 66d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * Sets the compressed thumbnail. 67d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void setCompressedThumbnail(byte[] thumbnail) { 69d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou mThumbnail = thumbnail; 70d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 71d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 72d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou /** 73d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * Returns true it this header contains a compressed thumbnail. 74d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected boolean hasCompressedThumbnail() { 76d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou return mThumbnail != null; 77d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 78d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 79d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou /** 80d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * Adds an uncompressed strip. 81d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void setStripBytes(int index, byte[] strip) { 83d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou if (index < mStripBytes.size()) { 84d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou mStripBytes.set(index, strip); 85d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } else { 86d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou for (int i = mStripBytes.size(); i < index; i++) { 87d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou mStripBytes.add(null); 88d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 89d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou mStripBytes.add(strip); 90d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 91d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 92d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 93d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou /** 94e48c0f96ee3f9654c3538664dd59485927fb44d6Earl Ou * Gets the strip count. 95d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected int getStripCount() { 97d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou return mStripBytes.size(); 98d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 99d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou 100d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou /** 101d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * Gets the strip at the specified index. 1026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * 103d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou * @exceptions #IndexOutOfBoundException 104d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou */ 1056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected byte[] getStrip(int index) { 106d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou return mStripBytes.get(index); 107d83a3749f50a8b493a12dfc96aaa0da2f9a6d08bEarl Ou } 1087973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou 1097973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou /** 1106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns true if this header contains uncompressed strip. 1117973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou */ 1126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected boolean hasUncompressedStrip() { 1136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return mStripBytes.size() != 0; 1147973bc292dcacaa5e68eecaff533d19b5cffc1e8Earl Ou } 115cde6ac521216801e835df1c20b68dd21d4fd04a4Earl Ou 1164f529e7cada294befb66a1fc9b72b1aa164597dfEarl Ou /** 1176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Gets the byte order. 1184f529e7cada294befb66a1fc9b72b1aa164597dfEarl Ou */ 1196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected ByteOrder getByteOrder() { 1206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return mByteOrder; 121cde6ac521216801e835df1c20b68dd21d4fd04a4Earl Ou } 1223b8bd33be5041d77855f756fbba1993294cffac4Earl Ou 12389591324c5d1097e59217177ad3ea74598867584Earl Ou /** 1246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns the {@link IfdData} object corresponding to a given IFD if it 1256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * exists or null. 12689591324c5d1097e59217177ad3ea74598867584Earl Ou */ 1276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected IfdData getIfdData(int ifdId) { 1286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ExifTag.isValidIfd(ifdId)) { 1296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return mIfdDatas[ifdId]; 1303b8bd33be5041d77855f756fbba1993294cffac4Earl Ou } 1316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 1323b8bd33be5041d77855f756fbba1993294cffac4Earl Ou } 1333b8bd33be5041d77855f756fbba1993294cffac4Earl Ou 1346c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou /** 1356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Adds IFD data. If IFD data of the same type already exists, it will be 1366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * replaced by the new data. 1376c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou */ 1386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void addIfdData(IfdData data) { 1396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk mIfdDatas[data.getId()] = data; 1406c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou } 1416c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou 1426c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou /** 1436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns the {@link IfdData} object corresponding to a given IFD or 1446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * generates one if none exist. 1456c687a5fe5c5bad1c7c6aabceb7aec42eaed218aEarl Ou */ 1466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected IfdData getOrCreateIfdData(int ifdId) { 14789591324c5d1097e59217177ad3ea74598867584Earl Ou IfdData ifdData = mIfdDatas[ifdId]; 14889591324c5d1097e59217177ad3ea74598867584Earl Ou if (ifdData == null) { 14989591324c5d1097e59217177ad3ea74598867584Earl Ou ifdData = new IfdData(ifdId); 15089591324c5d1097e59217177ad3ea74598867584Earl Ou mIfdDatas[ifdId] = ifdData; 15189591324c5d1097e59217177ad3ea74598867584Earl Ou } 15289591324c5d1097e59217177ad3ea74598867584Earl Ou return ifdData; 15389591324c5d1097e59217177ad3ea74598867584Earl Ou } 15489591324c5d1097e59217177ad3ea74598867584Earl Ou 15589591324c5d1097e59217177ad3ea74598867584Earl Ou /** 1566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns the tag with a given TID in the given IFD if the tag exists. 1576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Otherwise returns null. 15889591324c5d1097e59217177ad3ea74598867584Earl Ou */ 1596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected ExifTag getTag(short tag, int ifd) { 1606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData ifdData = mIfdDatas[ifd]; 1616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return (ifdData == null) ? null : ifdData.getTag(tag); 16289591324c5d1097e59217177ad3ea74598867584Earl Ou } 16389591324c5d1097e59217177ad3ea74598867584Earl Ou 16489591324c5d1097e59217177ad3ea74598867584Earl Ou /** 1656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Adds the given ExifTag to its default IFD and returns an existing ExifTag 1666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * with the same TID or null if none exist. 16789591324c5d1097e59217177ad3ea74598867584Earl Ou */ 1686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected ExifTag addTag(ExifTag tag) { 1696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tag != null) { 1706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk int ifd = tag.getIfd(); 1716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return addTag(tag, ifd); 1726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 1736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 17489591324c5d1097e59217177ad3ea74598867584Earl Ou } 17589591324c5d1097e59217177ad3ea74598867584Earl Ou 17689591324c5d1097e59217177ad3ea74598867584Earl Ou /** 1776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Adds the given ExifTag to the given IFD and returns an existing ExifTag 1786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * with the same TID or null if none exist. 179b430b34197d3016d1659ed104abbd3cb5d6d881dEarl Ou */ 1806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected ExifTag addTag(ExifTag tag, int ifdId) { 1816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tag != null && ExifTag.isValidIfd(ifdId)) { 1826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData ifdData = getOrCreateIfdData(ifdId); 1836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return ifdData.setTag(tag); 1846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 1856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 186b430b34197d3016d1659ed104abbd3cb5d6d881dEarl Ou } 187b430b34197d3016d1659ed104abbd3cb5d6d881dEarl Ou 1886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void clearThumbnailAndStrips() { 1896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk mThumbnail = null; 1906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk mStripBytes.clear(); 19189591324c5d1097e59217177ad3ea74598867584Earl Ou } 19289591324c5d1097e59217177ad3ea74598867584Earl Ou 19389591324c5d1097e59217177ad3ea74598867584Earl Ou /** 1946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Removes the thumbnail and its related tags. IFD1 will be removed. 19589591324c5d1097e59217177ad3ea74598867584Earl Ou */ 1966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void removeThumbnailData() { 1976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk clearThumbnailAndStrips(); 1986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk mIfdDatas[IfdId.TYPE_IFD_1] = null; 19989591324c5d1097e59217177ad3ea74598867584Earl Ou } 200133c49e9bda0b3dcc005a0dfc7ab999926c0ef7fEarl Ou 20107ddc8ecc8a2bcc3f16bdfb712454a91726726feEarl Ou /** 2026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Removes the tag with a given TID and IFD. 20307ddc8ecc8a2bcc3f16bdfb712454a91726726feEarl Ou */ 2046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected void removeTag(short tagId, int ifdId) { 2056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData ifdData = mIfdDatas[ifdId]; 2066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ifdData == null) { 2076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return; 2086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ifdData.removeTag(tagId); 210133c49e9bda0b3dcc005a0dfc7ab999926c0ef7fEarl Ou } 21115438682a38ad2887426c100452a990b5e3f965dEarl Ou 21215438682a38ad2887426c100452a990b5e3f965dEarl Ou /** 2136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Decodes the user comment tag into string as specified in the EXIF 2146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * standard. Returns null if decoding failed. 21515438682a38ad2887426c100452a990b5e3f965dEarl Ou */ 2166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected String getUserComment() { 21715438682a38ad2887426c100452a990b5e3f965dEarl Ou IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_0]; 2186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ifdData == null) { 2196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifTag tag = ifdData.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)); 2226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tag == null) { 2236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tag.getComponentCount() < 8) { 2266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 22815438682a38ad2887426c100452a990b5e3f965dEarl Ou 22915438682a38ad2887426c100452a990b5e3f965dEarl Ou byte[] buf = new byte[tag.getComponentCount()]; 23015438682a38ad2887426c100452a990b5e3f965dEarl Ou tag.getBytes(buf); 23115438682a38ad2887426c100452a990b5e3f965dEarl Ou 23215438682a38ad2887426c100452a990b5e3f965dEarl Ou byte[] code = new byte[8]; 23315438682a38ad2887426c100452a990b5e3f965dEarl Ou System.arraycopy(buf, 0, code, 0, 8); 23415438682a38ad2887426c100452a990b5e3f965dEarl Ou 23515438682a38ad2887426c100452a990b5e3f965dEarl Ou try { 23615438682a38ad2887426c100452a990b5e3f965dEarl Ou if (Arrays.equals(code, USER_COMMENT_ASCII)) { 23715438682a38ad2887426c100452a990b5e3f965dEarl Ou return new String(buf, 8, buf.length - 8, "US-ASCII"); 23815438682a38ad2887426c100452a990b5e3f965dEarl Ou } else if (Arrays.equals(code, USER_COMMENT_JIS)) { 23915438682a38ad2887426c100452a990b5e3f965dEarl Ou return new String(buf, 8, buf.length - 8, "EUC-JP"); 24015438682a38ad2887426c100452a990b5e3f965dEarl Ou } else if (Arrays.equals(code, USER_COMMENT_UNICODE)) { 24115438682a38ad2887426c100452a990b5e3f965dEarl Ou return new String(buf, 8, buf.length - 8, "UTF-16"); 24215438682a38ad2887426c100452a990b5e3f965dEarl Ou } else { 24315438682a38ad2887426c100452a990b5e3f965dEarl Ou return null; 24415438682a38ad2887426c100452a990b5e3f965dEarl Ou } 24515438682a38ad2887426c100452a990b5e3f965dEarl Ou } catch (UnsupportedEncodingException e) { 24615438682a38ad2887426c100452a990b5e3f965dEarl Ou Log.w(TAG, "Failed to decode the user comment"); 24715438682a38ad2887426c100452a990b5e3f965dEarl Ou return null; 24815438682a38ad2887426c100452a990b5e3f965dEarl Ou } 2496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 25015438682a38ad2887426c100452a990b5e3f965dEarl Ou 2516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk /** 2526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns a list of all {@link ExifTag}s in the ExifData or null if there 2536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * are none. 2546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk */ 2556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected List<ExifTag> getAllTags() { 2566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 2576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (IfdData d : mIfdDatas) { 2586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (d != null) { 2596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifTag[] tags = d.getAllTags(); 2606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tags != null) { 2616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (ExifTag t : tags) { 2626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ret.add(t); 2636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ret.size() == 0) { 2686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return ret; 27115438682a38ad2887426c100452a990b5e3f965dEarl Ou } 2726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 2736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk /** 2746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns a list of all {@link ExifTag}s in a given IFD or null if there 2756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * are none. 2766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk */ 2776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected List<ExifTag> getAllTagsForIfd(int ifd) { 2786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData d = mIfdDatas[ifd]; 2796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (d == null) { 2806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifTag[] tags = d.getAllTags(); 2836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (tags == null) { 2846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ArrayList<ExifTag> ret = new ArrayList<ExifTag>(tags.length); 2876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (ExifTag t : tags) { 2886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ret.add(t); 2896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ret.size() == 0) { 2916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 2926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return ret; 2946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 2956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 2966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk /** 2976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Returns a list of all {@link ExifTag}s with a given TID or null if there 2986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * are none. 2996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk */ 3006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk protected List<ExifTag> getAllTagsForTagId(short tag) { 3016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 3026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (IfdData d : mIfdDatas) { 3036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (d != null) { 3046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifTag t = d.getTag(tag); 3056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (t != null) { 3066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ret.add(t); 3076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ret.size() == 0) { 3116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return null; 3126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return ret; 3146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 3166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk @Override 3176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk public boolean equals(Object obj) { 3186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (this == obj) { 3196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return true; 3206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (obj == null) { 3226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return false; 3236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (obj instanceof ExifData) { 3256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk ExifData data = (ExifData) obj; 3266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (data.mByteOrder != mByteOrder || 3276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk data.mStripBytes.size() != mStripBytes.size() || 3286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk !Arrays.equals(data.mThumbnail, mThumbnail)) { 3296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return false; 3306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (int i = 0; i < mStripBytes.size(); i++) { 3326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) { 3336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return false; 3346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { 3376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData ifd1 = data.getIfdData(i); 3386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk IfdData ifd2 = getIfdData(i); 3396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk if (ifd1 != ifd2 && ifd1 != null && !ifd1.equals(ifd2)) { 3406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return false; 3416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return true; 3446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk return false; 3466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk } 3476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk 3483d8c7829f0cdaa452cf9aaf0e68538ccc8dcde2fEarl Ou} 349