1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/* 2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2012 The Android Open Source Project 3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License"); 5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License. 6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at 7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * http://www.apache.org/licenses/LICENSE-2.0 9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software 11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS, 12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and 14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License. 15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 16104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 17104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.gallery3d.exif; 18104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport android.util.Log; 20104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.UnsupportedEncodingException; 22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.ByteOrder; 23104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.ArrayList; 24104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.Arrays; 25104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.util.List; 26104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 27104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/** 28104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * This class stores the EXIF header in IFDs according to the JPEG 29104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * specification. It is the result produced by {@link ExifReader}. 30104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 31104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * @see ExifReader 32104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * @see IfdData 33104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 34104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaclass ExifData { 35104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final String TAG = "ExifData"; 36104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final byte[] USER_COMMENT_ASCII = { 37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 38104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 39104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final byte[] USER_COMMENT_JIS = { 40104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00 41104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 42104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private static final byte[] USER_COMMENT_UNICODE = { 43104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00 44104c45677660586026a7e74ef8c47d396403d50eMichael Jurka }; 45104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final IfdData[] mIfdDatas = new IfdData[IfdId.TYPE_IFD_COUNT]; 47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private byte[] mThumbnail; 48104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private ArrayList<byte[]> mStripBytes = new ArrayList<byte[]>(); 49104c45677660586026a7e74ef8c47d396403d50eMichael Jurka private final ByteOrder mByteOrder; 50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifData(ByteOrder order) { 52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mByteOrder = order; 53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Gets the compressed thumbnail. Returns null if there is no compressed 57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * thumbnail. 58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * @see #hasCompressedThumbnail() 60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected byte[] getCompressedThumbnail() { 62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mThumbnail; 63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 66104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Sets the compressed thumbnail. 67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void setCompressedThumbnail(byte[] thumbnail) { 69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mThumbnail = thumbnail; 70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns true it this header contains a compressed thumbnail. 74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected boolean hasCompressedThumbnail() { 76104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mThumbnail != null; 77104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 79104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 80104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Adds an uncompressed strip. 81104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void setStripBytes(int index, byte[] strip) { 83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (index < mStripBytes.size()) { 84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mStripBytes.set(index, strip); 85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (int i = mStripBytes.size(); i < index; i++) { 87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mStripBytes.add(null); 88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 89104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mStripBytes.add(strip); 90104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 91104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 92104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 93104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 94104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Gets the strip count. 95104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 96104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected int getStripCount() { 97104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mStripBytes.size(); 98104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 99104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 100104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 101104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Gets the strip at the specified index. 102104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * 103104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * @exceptions #IndexOutOfBoundException 104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected byte[] getStrip(int index) { 106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mStripBytes.get(index); 107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 108104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 109104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns true if this header contains uncompressed strip. 111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected boolean hasUncompressedStrip() { 113104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mStripBytes.size() != 0; 114104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 115104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 116104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 117104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Gets the byte order. 118104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 119104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected ByteOrder getByteOrder() { 120104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mByteOrder; 121104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 122104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 123104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 124104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns the {@link IfdData} object corresponding to a given IFD if it 125104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * exists or null. 126104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected IfdData getIfdData(int ifdId) { 128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ExifTag.isValidIfd(ifdId)) { 129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return mIfdDatas[ifdId]; 130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Adds IFD data. If IFD data of the same type already exists, it will be 136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * replaced by the new data. 137104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 138104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void addIfdData(IfdData data) { 139104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mIfdDatas[data.getId()] = data; 140104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 141104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 142104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 143104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns the {@link IfdData} object corresponding to a given IFD or 144104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * generates one if none exist. 145104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 146104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected IfdData getOrCreateIfdData(int ifdId) { 147104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifdData = mIfdDatas[ifdId]; 148104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ifdData == null) { 149104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ifdData = new IfdData(ifdId); 150104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mIfdDatas[ifdId] = ifdData; 151104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 152104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return ifdData; 153104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 154104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 155104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 156104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns the tag with a given TID in the given IFD if the tag exists. 157104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Otherwise returns null. 158104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 159104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected ExifTag getTag(short tag, int ifd) { 160104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifdData = mIfdDatas[ifd]; 161104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return (ifdData == null) ? null : ifdData.getTag(tag); 162104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 163104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 164104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 165104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Adds the given ExifTag to its default IFD and returns an existing ExifTag 166104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * with the same TID or null if none exist. 167104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 168104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected ExifTag addTag(ExifTag tag) { 169104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tag != null) { 170104c45677660586026a7e74ef8c47d396403d50eMichael Jurka int ifd = tag.getIfd(); 171104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return addTag(tag, ifd); 172104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 173104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 174104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 175104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 176104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 177104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Adds the given ExifTag to the given IFD and returns an existing ExifTag 178104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * with the same TID or null if none exist. 179104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 180104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected ExifTag addTag(ExifTag tag, int ifdId) { 181104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tag != null && ExifTag.isValidIfd(ifdId)) { 182104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifdData = getOrCreateIfdData(ifdId); 183104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return ifdData.setTag(tag); 184104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 185104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 186104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 187104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 188104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void clearThumbnailAndStrips() { 189104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mThumbnail = null; 190104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mStripBytes.clear(); 191104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 192104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 193104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 194104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Removes the thumbnail and its related tags. IFD1 will be removed. 195104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 196104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void removeThumbnailData() { 197104c45677660586026a7e74ef8c47d396403d50eMichael Jurka clearThumbnailAndStrips(); 198104c45677660586026a7e74ef8c47d396403d50eMichael Jurka mIfdDatas[IfdId.TYPE_IFD_1] = null; 199104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 200104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 201104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 202104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Removes the tag with a given TID and IFD. 203104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 204104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected void removeTag(short tagId, int ifdId) { 205104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifdData = mIfdDatas[ifdId]; 206104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ifdData == null) { 207104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return; 208104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 209104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ifdData.removeTag(tagId); 210104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 211104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 212104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 213104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Decodes the user comment tag into string as specified in the EXIF 214104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * standard. Returns null if decoding failed. 215104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 216104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected String getUserComment() { 217104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifdData = mIfdDatas[IfdId.TYPE_IFD_0]; 218104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ifdData == null) { 219104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 220104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 221104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifTag tag = ifdData.getTag(ExifInterface.getTrueTagKey(ExifInterface.TAG_USER_COMMENT)); 222104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tag == null) { 223104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 224104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 225104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tag.getComponentCount() < 8) { 226104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 227104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 228104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 229104c45677660586026a7e74ef8c47d396403d50eMichael Jurka byte[] buf = new byte[tag.getComponentCount()]; 230104c45677660586026a7e74ef8c47d396403d50eMichael Jurka tag.getBytes(buf); 231104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 232104c45677660586026a7e74ef8c47d396403d50eMichael Jurka byte[] code = new byte[8]; 233104c45677660586026a7e74ef8c47d396403d50eMichael Jurka System.arraycopy(buf, 0, code, 0, 8); 234104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 235104c45677660586026a7e74ef8c47d396403d50eMichael Jurka try { 236104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (Arrays.equals(code, USER_COMMENT_ASCII)) { 237104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return new String(buf, 8, buf.length - 8, "US-ASCII"); 238104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else if (Arrays.equals(code, USER_COMMENT_JIS)) { 239104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return new String(buf, 8, buf.length - 8, "EUC-JP"); 240104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else if (Arrays.equals(code, USER_COMMENT_UNICODE)) { 241104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return new String(buf, 8, buf.length - 8, "UTF-16"); 242104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } else { 243104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 244104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 245104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } catch (UnsupportedEncodingException e) { 246104c45677660586026a7e74ef8c47d396403d50eMichael Jurka Log.w(TAG, "Failed to decode the user comment"); 247104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 248104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 249104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 250104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 251104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 252104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns a list of all {@link ExifTag}s in the ExifData or null if there 253104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * are none. 254104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 255104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected List<ExifTag> getAllTags() { 256104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 257104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (IfdData d : mIfdDatas) { 258104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (d != null) { 259104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifTag[] tags = d.getAllTags(); 260104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tags != null) { 261104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (ExifTag t : tags) { 262104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ret.add(t); 263104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 264104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 265104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 266104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 267104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ret.size() == 0) { 268104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 269104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 270104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return ret; 271104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 272104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 273104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 274104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns a list of all {@link ExifTag}s in a given IFD or null if there 275104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * are none. 276104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 277104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected List<ExifTag> getAllTagsForIfd(int ifd) { 278104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData d = mIfdDatas[ifd]; 279104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (d == null) { 280104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 281104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 282104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifTag[] tags = d.getAllTags(); 283104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (tags == null) { 284104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 285104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 286104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(tags.length); 287104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (ExifTag t : tags) { 288104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ret.add(t); 289104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 290104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ret.size() == 0) { 291104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 292104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 293104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return ret; 294104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 295104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 296104c45677660586026a7e74ef8c47d396403d50eMichael Jurka /** 297104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Returns a list of all {@link ExifTag}s with a given TID or null if there 298104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * are none. 299104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */ 300104c45677660586026a7e74ef8c47d396403d50eMichael Jurka protected List<ExifTag> getAllTagsForTagId(short tag) { 301104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ArrayList<ExifTag> ret = new ArrayList<ExifTag>(); 302104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (IfdData d : mIfdDatas) { 303104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (d != null) { 304104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifTag t = d.getTag(tag); 305104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (t != null) { 306104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ret.add(t); 307104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 308104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 309104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 310104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ret.size() == 0) { 311104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return null; 312104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 313104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return ret; 314104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 315104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 316104c45677660586026a7e74ef8c47d396403d50eMichael Jurka @Override 317104c45677660586026a7e74ef8c47d396403d50eMichael Jurka public boolean equals(Object obj) { 318104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (this == obj) { 319104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return true; 320104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 321104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (obj == null) { 322104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return false; 323104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 324104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (obj instanceof ExifData) { 325104c45677660586026a7e74ef8c47d396403d50eMichael Jurka ExifData data = (ExifData) obj; 326104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (data.mByteOrder != mByteOrder || 327104c45677660586026a7e74ef8c47d396403d50eMichael Jurka data.mStripBytes.size() != mStripBytes.size() || 328104c45677660586026a7e74ef8c47d396403d50eMichael Jurka !Arrays.equals(data.mThumbnail, mThumbnail)) { 329104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return false; 330104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 331104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (int i = 0; i < mStripBytes.size(); i++) { 332104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (!Arrays.equals(data.mStripBytes.get(i), mStripBytes.get(i))) { 333104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return false; 334104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 335104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 336104c45677660586026a7e74ef8c47d396403d50eMichael Jurka for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { 337104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifd1 = data.getIfdData(i); 338104c45677660586026a7e74ef8c47d396403d50eMichael Jurka IfdData ifd2 = getIfdData(i); 339104c45677660586026a7e74ef8c47d396403d50eMichael Jurka if (ifd1 != ifd2 && ifd1 != null && !ifd1.equals(ifd2)) { 340104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return false; 341104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 342104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 343104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return true; 344104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 345104c45677660586026a7e74ef8c47d396403d50eMichael Jurka return false; 346104c45677660586026a7e74ef8c47d396403d50eMichael Jurka } 347104c45677660586026a7e74ef8c47d396403d50eMichael Jurka 348104c45677660586026a7e74ef8c47d396403d50eMichael Jurka} 349