16e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk/*
26e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Copyright (C) 2013 The Android Open Source Project
36e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk *
46e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
56e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * you may not use this file except in compliance with the License.
66e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * You may obtain a copy of the License at
76e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk *
86e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
96e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk *
106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Unless required by applicable law or agreed to in writing, software
116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * See the License for the specific language governing permissions and
146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * limitations under the License.
156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk */
166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkpackage com.android.gallery3d.exif;
186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport android.graphics.Bitmap;
206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport android.graphics.BitmapFactory;
216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport android.util.SparseIntArray;
226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
234bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunkimport java.io.BufferedInputStream;
246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.ByteArrayInputStream;
256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.ByteArrayOutputStream;
266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.Closeable;
276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.File;
286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.FileInputStream;
296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.FileNotFoundException;
306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.FileOutputStream;
316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.IOException;
326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.InputStream;
336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.OutputStream;
346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.io.RandomAccessFile;
356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.nio.ByteBuffer;
366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.nio.ByteOrder;
376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.nio.channels.FileChannel.MapMode;
386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.text.DateFormat;
396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.text.SimpleDateFormat;
406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.ArrayList;
416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.Arrays;
426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.Calendar;
436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.Collection;
446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.HashSet;
456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.List;
466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkimport java.util.TimeZone;
476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk/**
496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * This class provides methods and constants for reading and writing jpeg file
506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * metadata. It contains a collection of ExifTags, and a collection of
516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * definitions for creating valid ExifTags. The collection of ExifTags can be
526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * updated by: reading new ones from a file, deleting or adding existing ones,
536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * or building new ExifTags from a tag definition. These ExifTags can be written
546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * to a valid jpeg image as exif metadata.
556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * <p>
566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * Each ExifTag has a tag ID (TID) and is stored in a specific image file
576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * directory (IFD) as specified by the exif standard. A tag definition can be
586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * looked up with a constant that is a combination of TID and IFD. This
596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * definition has information about the type, number of components, and valid
606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * IFDs for a tag.
616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk *
626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk * @see ExifTag
636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk */
646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunkpublic class ExifInterface {
656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_NULL = -1;
666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int IFD_NULL = -1;
676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int DEFINITION_NULL = 0;
686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Tag constants for Jeita EXIF 2.2
716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // IFD 0
746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_IMAGE_WIDTH =
756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0100);
766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_IMAGE_LENGTH =
776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0101); // Image height
786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_BITS_PER_SAMPLE =
796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0102);
806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_COMPRESSION =
816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0103);
826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_PHOTOMETRIC_INTERPRETATION =
836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0106);
846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_IMAGE_DESCRIPTION =
856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x010E);
866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_MAKE =
876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x010F);
886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_MODEL =
896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0110);
906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_STRIP_OFFSETS =
916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0111);
926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_ORIENTATION =
936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0112);
946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SAMPLES_PER_PIXEL =
956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0115);
966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_ROWS_PER_STRIP =
976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0116);
986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_STRIP_BYTE_COUNTS =
996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0117);
1006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_X_RESOLUTION =
1016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011A);
1026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_Y_RESOLUTION =
1036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011B);
1046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_PLANAR_CONFIGURATION =
1056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011C);
1066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_RESOLUTION_UNIT =
1076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0128);
1086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_TRANSFER_FUNCTION =
1096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x012D);
1106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SOFTWARE =
1116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0131);
1126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_DATE_TIME =
1136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0132);
1146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_ARTIST =
1156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013B);
1166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_WHITE_POINT =
1176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013E);
1186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_PRIMARY_CHROMATICITIES =
1196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013F);
1206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_Y_CB_CR_COEFFICIENTS =
1216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0211);
1226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_Y_CB_CR_SUB_SAMPLING =
1236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0212);
1246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_Y_CB_CR_POSITIONING =
1256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0213);
1266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_REFERENCE_BLACK_WHITE =
1276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0214);
1286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_COPYRIGHT =
1296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8298);
1306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXIF_IFD =
1316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8769);
1326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_IFD =
1336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8825);
1346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // IFD 1
1356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_JPEG_INTERCHANGE_FORMAT =
1366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_1, (short) 0x0201);
1376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH =
1386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_1, (short) 0x0202);
1396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // IFD Exif Tags
1406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXPOSURE_TIME =
1416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829A);
1426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_F_NUMBER =
1436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829D);
1446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXPOSURE_PROGRAM =
1456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8822);
1466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SPECTRAL_SENSITIVITY =
1476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8824);
1486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_ISO_SPEED_RATINGS =
1496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8827);
1506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_OECF =
1516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8828);
1526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXIF_VERSION =
1536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9000);
1546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_DATE_TIME_ORIGINAL =
1556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9003);
1566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_DATE_TIME_DIGITIZED =
1576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9004);
1586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_COMPONENTS_CONFIGURATION =
1596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9101);
1606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_COMPRESSED_BITS_PER_PIXEL =
1616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9102);
1626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SHUTTER_SPEED_VALUE =
1636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9201);
1646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_APERTURE_VALUE =
1656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9202);
1666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_BRIGHTNESS_VALUE =
1676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9203);
1686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXPOSURE_BIAS_VALUE =
1696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9204);
1706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_MAX_APERTURE_VALUE =
1716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9205);
1726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUBJECT_DISTANCE =
1736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9206);
1746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_METERING_MODE =
1756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9207);
1766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_LIGHT_SOURCE =
1776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9208);
1786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FLASH =
1796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9209);
1806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FOCAL_LENGTH =
1816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x920A);
1826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUBJECT_AREA =
1836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9214);
1846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_MAKER_NOTE =
1856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x927C);
1866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_USER_COMMENT =
1876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9286);
1886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUB_SEC_TIME =
1896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9290);
1906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUB_SEC_TIME_ORIGINAL =
1916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9291);
1926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUB_SEC_TIME_DIGITIZED =
1936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9292);
1946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FLASHPIX_VERSION =
1956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA000);
1966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_COLOR_SPACE =
1976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA001);
1986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_PIXEL_X_DIMENSION =
1996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA002);
2006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_PIXEL_Y_DIMENSION =
2016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA003);
2026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_RELATED_SOUND_FILE =
2036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA004);
2046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_INTEROPERABILITY_IFD =
2056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA005);
2066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FLASH_ENERGY =
2076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20B);
2086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SPATIAL_FREQUENCY_RESPONSE =
2096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20C);
2106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FOCAL_PLANE_X_RESOLUTION =
2116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20E);
2126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FOCAL_PLANE_Y_RESOLUTION =
2136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20F);
2146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT =
2156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA210);
2166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUBJECT_LOCATION =
2176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA214);
2186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXPOSURE_INDEX =
2196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA215);
2206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SENSING_METHOD =
2216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA217);
2226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FILE_SOURCE =
2236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA300);
2246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SCENE_TYPE =
2256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA301);
2266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_CFA_PATTERN =
2276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA302);
2286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_CUSTOM_RENDERED =
2296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA401);
2306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_EXPOSURE_MODE =
2316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA402);
2326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_WHITE_BALANCE =
2336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA403);
2346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_DIGITAL_ZOOM_RATIO =
2356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA404);
2366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_FOCAL_LENGTH_IN_35_MM_FILE =
2376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA405);
2386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SCENE_CAPTURE_TYPE =
2396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA406);
2406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GAIN_CONTROL =
2416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA407);
2426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_CONTRAST =
2436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA408);
2446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SATURATION =
2456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA409);
2466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SHARPNESS =
2476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40A);
2486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_DEVICE_SETTING_DESCRIPTION =
2496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40B);
2506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_SUBJECT_DISTANCE_RANGE =
2516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40C);
2526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_IMAGE_UNIQUE_ID =
2536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA420);
2546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // IFD GPS tags
2556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_VERSION_ID =
2566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 0);
2576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_LATITUDE_REF =
2586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 1);
2596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_LATITUDE =
2606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 2);
2616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_LONGITUDE_REF =
2626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 3);
2636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_LONGITUDE =
2646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 4);
2656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_ALTITUDE_REF =
2666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 5);
2676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_ALTITUDE =
2686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 6);
2696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_TIME_STAMP =
2706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 7);
2716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_SATTELLITES =
2726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 8);
2736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_STATUS =
2746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 9);
2756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_MEASURE_MODE =
2766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 10);
2776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DOP =
2786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 11);
2796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_SPEED_REF =
2806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 12);
2816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_SPEED =
2826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 13);
2836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_TRACK_REF =
2846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 14);
2856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_TRACK =
2866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 15);
2876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_IMG_DIRECTION_REF =
2886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 16);
2896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_IMG_DIRECTION =
2906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 17);
2916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_MAP_DATUM =
2926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 18);
2936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_LATITUDE_REF =
2946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 19);
2956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_LATITUDE =
2966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 20);
2976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_LONGITUDE_REF =
2986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 21);
2996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_LONGITUDE =
3006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 22);
3016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_BEARING_REF =
3026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 23);
3036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_BEARING =
3046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 24);
3056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_DISTANCE_REF =
3066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 25);
3076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DEST_DISTANCE =
3086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 26);
3096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_PROCESSING_METHOD =
3106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 27);
3116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_AREA_INFORMATION =
3126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 28);
3136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DATE_STAMP =
3146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 29);
3156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_GPS_DIFFERENTIAL =
3166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 30);
3176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // IFD Interoperability tags
3186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final int TAG_INTEROPERABILITY_INDEX =
3196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 1);
3206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Tags that contain offset markers. These are included in the banned
3236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * defines.
3246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private static HashSet<Short> sOffsetTags = new HashSet<Short>();
3266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    static {
3276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sOffsetTags.add(getTrueTagKey(TAG_GPS_IFD));
3286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sOffsetTags.add(getTrueTagKey(TAG_EXIF_IFD));
3296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sOffsetTags.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT));
3306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sOffsetTags.add(getTrueTagKey(TAG_INTEROPERABILITY_IFD));
3316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sOffsetTags.add(getTrueTagKey(TAG_STRIP_OFFSETS));
3326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Tags with definitions that cannot be overridden (banned defines).
3366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static HashSet<Short> sBannedDefines = new HashSet<Short>(sOffsetTags);
3386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    static {
3396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sBannedDefines.add(getTrueTagKey(TAG_NULL));
3406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sBannedDefines.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH));
3416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        sBannedDefines.add(getTrueTagKey(TAG_STRIP_BYTE_COUNTS));
3426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the constant representing a tag with a given TID and default IFD.
3466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static int defineTag(int ifdId, short tagId) {
3486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return (tagId & 0x0000ffff) | (ifdId << 16);
3496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the TID for a tag constant.
3536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static short getTrueTagKey(int tag) {
3556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // Truncate
3566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return (short) tag;
3576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the default IFD for a tag constant.
3616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static int getTrueIfd(int tag) {
3636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return tag >>> 16;
3646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_ORIENTATION}. They can be interpreted as
3686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * follows:
3696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <ul>
3706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>TOP_LEFT is the normal orientation.</li>
3716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>TOP_RIGHT is a left-right mirror.</li>
3726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>BOTTOM_LEFT is a 180 degree rotation.</li>
3736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>BOTTOM_RIGHT is a top-bottom mirror.</li>
3746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>LEFT_TOP is mirrored about the top-left<->bottom-right axis.</li>
3756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>RIGHT_TOP is a 90 degree clockwise rotation.</li>
3766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>LEFT_BOTTOM is mirrored about the top-right<->bottom-left axis.</li>
3776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <li>RIGHT_BOTTOM is a 270 degree clockwise rotation.</li>
3786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * </ul>
3796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Orientation {
3816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short TOP_LEFT = 1;
3826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short TOP_RIGHT = 2;
3836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short BOTTOM_LEFT = 3;
3846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short BOTTOM_RIGHT = 4;
3856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LEFT_TOP = 5;
3866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RIGHT_TOP = 6;
3876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LEFT_BOTTOM = 7;
3886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RIGHT_BOTTOM = 8;
3896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
3926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_Y_CB_CR_POSITIONING}
3936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
3946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface YCbCrPositioning {
3956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CENTERED = 1;
3966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CO_SITED = 2;
3976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
3986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
3996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_COMPRESSION}
4016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Compression {
4036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short UNCOMPRESSION = 1;
4046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short JPEG = 6;
4056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_RESOLUTION_UNIT}
4096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface ResolutionUnit {
4116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short INCHES = 2;
4126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CENTIMETERS = 3;
4136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_PHOTOMETRIC_INTERPRETATION}
4176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface PhotometricInterpretation {
4196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RGB = 2;
4206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short YCBCR = 6;
4216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_PLANAR_CONFIGURATION}
4256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface PlanarConfiguration {
4276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CHUNKY = 1;
4286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short PLANAR = 2;
4296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_EXPOSURE_PROGRAM}
4336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface ExposureProgram {
4356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NOT_DEFINED = 0;
4366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MANUAL = 1;
4376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NORMAL_PROGRAM = 2;
4386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short APERTURE_PRIORITY = 3;
4396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SHUTTER_PRIORITY = 4;
4406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CREATIVE_PROGRAM = 5;
4416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short ACTION_PROGRAM = 6;
4426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short PROTRAIT_MODE = 7;
4436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LANDSCAPE_MODE = 8;
4446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_METERING_MODE}
4486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface MeteringMode {
4506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short UNKNOWN = 0;
4516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short AVERAGE = 1;
4526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CENTER_WEIGHTED_AVERAGE = 2;
4536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SPOT = 3;
4546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MULTISPOT = 4;
4556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short PATTERN = 5;
4566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short PARTAIL = 6;
4576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short OTHER = 255;
4586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_FLASH} As the definition in Jeita EXIF 2.2
4626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * standard, we can treat this constant as bitwise flag.
4636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <p>
4646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * e.g.
4656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <p>
4666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED |
4676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * MODE_AUTO_MODE
4686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Flash {
4706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // LSB
4716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DID_NOT_FIRED = 0;
4726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FIRED = 1;
4736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // 1st~2nd bits
4746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1;
4756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1;
4766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1;
4776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // 3rd~4th bits
4786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MODE_UNKNOWN = 0 << 3;
4796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3;
4806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3;
4816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MODE_AUTO_MODE = 3 << 3;
4826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // 5th bit
4836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FUNCTION_PRESENT = 0 << 5;
4846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FUNCTION_NO_FUNCTION = 1 << 5;
4856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // 6th bit
4866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
4876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
4886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_COLOR_SPACE}
4926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
4936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface ColorSpace {
4946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SRGB = 1;
4956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short UNCALIBRATED = (short) 0xFFFF;
4966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
4976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
4986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
4996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_EXPOSURE_MODE}
5006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface ExposureMode {
5026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short AUTO_EXPOSURE = 0;
5036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MANUAL_EXPOSURE = 1;
5046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short AUTO_BRACKET = 2;
5056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_WHITE_BALANCE}
5096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface WhiteBalance {
5116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short AUTO = 0;
5126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MANUAL = 1;
5136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SCENE_CAPTURE_TYPE}
5176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface SceneCapture {
5196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short STANDARD = 0;
5206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LANDSCAPE = 1;
5216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short PROTRAIT = 2;
5226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NIGHT_SCENE = 3;
5236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_COMPONENTS_CONFIGURATION}
5276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface ComponentsConfiguration {
5296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NOT_EXIST = 0;
5306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short Y = 1;
5316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CB = 2;
5326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CR = 3;
5336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short R = 4;
5346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short G = 5;
5356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short B = 6;
5366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_LIGHT_SOURCE}
5406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface LightSource {
5426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short UNKNOWN = 0;
5436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DAYLIGHT = 1;
5446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FLUORESCENT = 2;
5456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short TUNGSTEN = 3;
5466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FLASH = 4;
5476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short FINE_WEATHER = 9;
5486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CLOUDY_WEATHER = 10;
5496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SHADE = 11;
5506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DAYLIGHT_FLUORESCENT = 12;
5516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DAY_WHITE_FLUORESCENT = 13;
5526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short COOL_WHITE_FLUORESCENT = 14;
5536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short WHITE_FLUORESCENT = 15;
5546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short STANDARD_LIGHT_A = 17;
5556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short STANDARD_LIGHT_B = 18;
5566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short STANDARD_LIGHT_C = 19;
5576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short D55 = 20;
5586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short D65 = 21;
5596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short D75 = 22;
5606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short D50 = 23;
5616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short ISO_STUDIO_TUNGSTEN = 24;
5626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short OTHER = 255;
5636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SENSING_METHOD}
5676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface SensingMethod {
5696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NOT_DEFINED = 1;
5706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short ONE_CHIP_COLOR = 2;
5716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short TWO_CHIP_COLOR = 3;
5726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short THREE_CHIP_COLOR = 4;
5736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short COLOR_SEQUENTIAL_AREA = 5;
5746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short TRILINEAR = 7;
5756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short COLOR_SEQUENTIAL_LINEAR = 8;
5766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_FILE_SOURCE}
5806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface FileSource {
5826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DSC = 3;
5836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SCENE_TYPE}
5876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface SceneType {
5896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DIRECT_PHOTOGRAPHED = 1;
5906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
5916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
5926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
5936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GAIN_CONTROL}
5946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
5956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GainControl {
5966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NONE = 0;
5976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LOW_UP = 1;
5986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short HIGH_UP = 2;
5996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LOW_DOWN = 3;
6006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short HIGH_DOWN = 4;
6016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_CONTRAST}
6056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Contrast {
6076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NORMAL = 0;
6086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SOFT = 1;
6096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short HARD = 2;
6106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SATURATION}
6146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Saturation {
6166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NORMAL = 0;
6176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short LOW = 1;
6186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short HIGH = 2;
6196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SHARPNESS}
6236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface Sharpness {
6256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short NORMAL = 0;
6266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SOFT = 1;
6276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short HARD = 2;
6286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_SUBJECT_DISTANCE}
6326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface SubjectDistance {
6346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short UNKNOWN = 0;
6356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short MACRO = 1;
6366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short CLOSE_VIEW = 2;
6376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DISTANT_VIEW = 3;
6386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_LATITUDE_REF},
6426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_GPS_DEST_LATITUDE_REF}
6436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsLatitudeRef {
6456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String NORTH = "N";
6466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String SOUTH = "S";
6476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_LONGITUDE_REF},
6516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_GPS_DEST_LONGITUDE_REF}
6526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsLongitudeRef {
6546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String EAST = "E";
6556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String WEST = "W";
6566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_ALTITUDE_REF}
6606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsAltitudeRef {
6626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SEA_LEVEL = 0;
6636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short SEA_LEVEL_NEGATIVE = 1;
6646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_STATUS}
6686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsStatus {
6706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String IN_PROGRESS = "A";
6716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String INTEROPERABILITY = "V";
6726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_MEASURE_MODE}
6766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsMeasureMode {
6786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String MODE_2_DIMENSIONAL = "2";
6796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String MODE_3_DIMENSIONAL = "3";
6806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_SPEED_REF},
6846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_GPS_DEST_DISTANCE_REF}
6856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsSpeedRef {
6876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String KILOMETERS = "K";
6886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String MILES = "M";
6896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String KNOTS = "N";
6906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
6916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
6926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
6936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_TRACK_REF},
6946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_GPS_IMG_DIRECTION_REF}, {@link TAG_GPS_DEST_BEARING_REF}
6956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
6966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsTrackRef {
6976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String TRUE_DIRECTION = "T";
6986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final String MAGNETIC_DIRECTION = "M";
6996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Constants for {@link TAG_GPS_DIFFERENTIAL}
7036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static interface GpsDifferential {
7056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
7066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
7076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private static final String NULL_ARGUMENT_STRING = "Argument is null";
7106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private ExifData mData = new ExifData(DEFAULT_BYTE_ORDER);
7116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN;
7126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifInterface() {
7146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mGPSDateStampFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
7156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Reads the exif tags from a byte array, clearing this ExifInterface
7196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * object's existing exif tags.
7206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
7216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
7226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
7236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void readExif(byte[] jpeg) throws IOException {
7256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        readExif(new ByteArrayInputStream(jpeg));
7266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Reads the exif tags from an InputStream, clearing this ExifInterface
7306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * object's existing exif tags.
7316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
7326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param inStream an InputStream containing a jpeg compressed image.
7336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
7346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void readExif(InputStream inStream) throws IOException {
7366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (inStream == null) {
7376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
7386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
7396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifData d = null;
7406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
7416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            d = new ExifReader(this).read(inStream);
7426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (ExifInvalidFormatException e) {
7436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IOException("Invalid exif format : " + e);
7446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
7456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData = d;
7466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Reads the exif tags from a file, clearing this ExifInterface object's
7506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * existing exif tags.
7516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
7526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param inFileName a string representing the filepath to jpeg file.
7536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
7546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
7556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void readExif(String inFileName) throws FileNotFoundException, IOException {
7576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (inFileName == null) {
7586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
7596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
7606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        InputStream is = null;
7616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
7624bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunk            is = (InputStream) new BufferedInputStream(new FileInputStream(inFileName));
7636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            readExif(is);
7646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
7656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(is);
7666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
7676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
7686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        is.close();
7696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Sets the exif tags, clearing this ExifInterface object's existing exif
7736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * tags.
7746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
7756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tags a collection of exif tags to set.
7766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void setExif(Collection<ExifTag> tags) {
7786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        clearExif();
7796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTags(tags);
7806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Clears this ExifInterface object's existing exif tags.
7846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void clearExif() {
7866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData = new ExifData(DEFAULT_BYTE_ORDER);
7876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
7886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
7896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
7906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg image,
7916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * removing prior exif tags.
7926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
7936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
7946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutStream an OutputStream to which the jpeg image with added
7956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            exif tags will be written.
7966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
7976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
7986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(byte[] jpeg, OutputStream exifOutStream) throws IOException {
7996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (jpeg == null || exifOutStream == null) {
8006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
8016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
8036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        s.write(jpeg, 0, jpeg.length);
8044bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunk        s.flush();
8056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
8066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
8076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
8086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg compressed
8096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * bitmap, removing prior exif tags.
8106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
8116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param bmap a bitmap to compress and write exif into.
8126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutStream the OutputStream to which the jpeg image with added
8136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            exif tags will be written.
8146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
8156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
8166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(Bitmap bmap, OutputStream exifOutStream) throws IOException {
8176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (bmap == null || exifOutStream == null) {
8186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
8196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
8216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
8224bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunk        s.flush();
8236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
8246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
8256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
8266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg stream,
8276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * removing prior exif tags.
8286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
8296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpegStream an InputStream containing a jpeg compressed image.
8306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutStream an OutputStream to which the jpeg image with added
8316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            exif tags will be written.
8326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
8336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
8346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(InputStream jpegStream, OutputStream exifOutStream) throws IOException {
8356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (jpegStream == null || exifOutStream == null) {
8366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
8376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
8396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        doExifStreamIO(jpegStream, s);
8404bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunk        s.flush();
8416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
8426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
8436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
8446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg image,
8456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * removing prior exif tags.
8466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
8476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
8486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
8496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            image with added exif tags will be written.
8506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
8516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
8526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
8536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(byte[] jpeg, String exifOutFileName) throws FileNotFoundException,
8546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IOException {
8556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (jpeg == null || exifOutFileName == null) {
8566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
8576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = null;
8596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
8606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s = getExifWriterStream(exifOutFileName);
8616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s.write(jpeg, 0, jpeg.length);
8626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s.flush();
8636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
8646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(s);
8656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
8666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        s.close();
8686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
8696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
8706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
8716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg compressed
8726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * bitmap, removing prior exif tags.
8736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
8746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param bmap a bitmap to compress and write exif into.
8756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
8766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            image with added exif tags will be written.
8776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
8786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
8796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
8806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(Bitmap bmap, String exifOutFileName) throws FileNotFoundException,
8816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IOException {
8826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (bmap == null || exifOutFileName == null) {
8836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
8846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = null;
8866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
8876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s = getExifWriterStream(exifOutFileName);
8886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
8896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s.flush();
8906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
8916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(s);
8926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
8936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
8946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        s.close();
8956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
8966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
8976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
8986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg stream,
8996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * removing prior exif tags.
9006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
9016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpegStream an InputStream containing a jpeg compressed image.
9026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
9036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            image with added exif tags will be written.
9046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
9056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
9066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
9076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(InputStream jpegStream, String exifOutFileName)
9086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throws FileNotFoundException, IOException {
9096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (jpegStream == null || exifOutFileName == null) {
9106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
9116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream s = null;
9136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
9146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s = getExifWriterStream(exifOutFileName);
9156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            doExifStreamIO(jpegStream, s);
9166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            s.flush();
9176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
9186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(s);
9196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
9206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        s.close();
9226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
9236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
9246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
9256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Writes the tags from this ExifInterface object into a jpeg file, removing
9266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * prior exif tags.
9276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
9286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param jpegFileName a String containing the filepath for a jpeg file.
9296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
9306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            image with added exif tags will be written.
9316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
9326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
9336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
9346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void writeExif(String jpegFileName, String exifOutFileName)
9356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throws FileNotFoundException, IOException {
9366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (jpegFileName == null || exifOutFileName == null) {
9376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
9386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        InputStream is = null;
9406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
9416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            is = new FileInputStream(jpegFileName);
9426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            writeExif(is, exifOutFileName);
9436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
9446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(is);
9456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
9466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        is.close();
9486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
9496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
9506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
9516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Wraps an OutputStream object with an ExifOutputStream. Exif tags in this
9526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * ExifInterface object will be added to a jpeg image written to this
9536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * stream, removing prior exif tags. Other methods of this ExifInterface
9546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * object should not be called until the returned OutputStream has been
9556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * closed.
9566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
9576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param outStream an OutputStream to wrap.
9586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an OutputStream that wraps the outStream parameter, and adds exif
9596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         metadata. A jpeg image should be written to this stream.
9606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
9616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public OutputStream getExifWriterStream(OutputStream outStream) {
9626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (outStream == null) {
9636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
9646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifOutputStream eos = new ExifOutputStream(outStream, this);
9666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        eos.setExifData(mData);
9676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return eos;
9686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
9696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
9706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
9716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns an OutputStream object that writes to a file. Exif tags in this
9726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * ExifInterface object will be added to a jpeg image written to this
9736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * stream, removing prior exif tags. Other methods of this ExifInterface
9746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * object should not be called until the returned OutputStream has been
9756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * closed.
9766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
9776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param exifOutFileName an String containing a filepath for a jpeg file.
9786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an OutputStream that writes to the exifOutFileName file, and adds
9796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         exif metadata. A jpeg image should be written to this stream.
9806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
9816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
9826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public OutputStream getExifWriterStream(String exifOutFileName) throws FileNotFoundException {
9836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (exifOutFileName == null) {
9846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
9856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        OutputStream out = null;
9876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
9886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            out = (OutputStream) new FileOutputStream(exifOutFileName);
9896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (FileNotFoundException e) {
9906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(out);
9916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
9926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
9936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getExifWriterStream(out);
9946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
9956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
9966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
9976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Attempts to do an in-place rewrite the exif metadata in a file for the
9986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * given tags. If tags do not exist or do not have the same size as the
9996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * existing exif tags, this method will fail.
10006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
10016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param filename a String containing a filepath for a jpeg file with exif
10026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            tags to rewrite.
10036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tags tags that will be written into the jpeg file over existing
10046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            tags if possible.
10056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if could not overwrite. If false, no
10066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         changes are made to the file.
10076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
10086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
10096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
10106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean rewriteExif(String filename, Collection<ExifTag> tags)
10116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throws FileNotFoundException, IOException {
10126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        RandomAccessFile file = null;
10136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        InputStream is = null;
10146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        boolean ret;
10156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
10166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            File temp = new File(filename);
10174bee0f203dc96652aca02516f6f2d7d2493fab52Ruben Brunk            is = new BufferedInputStream(new FileInputStream(temp));
10186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Parse beginning of APP1 in exif to find size of exif header.
10206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ExifParser parser = null;
10216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            try {
10226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                parser = ExifParser.parse(is, this);
10236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            } catch (ExifInvalidFormatException e) {
10246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                throw new IOException("Invalid exif format : ", e);
10256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
10266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            long exifSize = parser.getOffsetToExifEndFromSOF();
10276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Free up resources
10296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            is.close();
10306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            is = null;
10316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Open file for memory mapping.
10336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            file = new RandomAccessFile(temp, "rw");
10346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            long fileLength = file.length();
10356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (fileLength < exifSize) {
10366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                throw new IOException("Filesize changed during operation");
10376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
10386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Map only exif header into memory.
10406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize);
10416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Attempt to overwrite tag values without changing lengths (avoids
10436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // file copy).
10446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ret = rewriteExif(buf, tags);
10456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (IOException e) {
10466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(file);
10476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw e;
10486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } finally {
10496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            closeSilently(is);
10506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
10516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        file.close();
10526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return ret;
10536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
10546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
10566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Attempts to do an in-place rewrite the exif metadata in a ByteBuffer for
10576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * the given tags. If tags do not exist or do not have the same size as the
10586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * existing exif tags, this method will fail.
10596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
10606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param buf a ByteBuffer containing a jpeg file with existing exif tags to
10616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            rewrite.
10626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tags tags that will be written into the jpeg ByteBuffer over
10636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            existing tags if possible.
10646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if could not overwrite. If false, no
10656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         changes are made to the ByteBuffer.
10666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
10676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
10686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean rewriteExif(ByteBuffer buf, Collection<ExifTag> tags) throws IOException {
10696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifModifier mod = null;
10706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
10716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            mod = new ExifModifier(buf, this);
10726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            for (ExifTag t : tags) {
10736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                mod.modifyTag(t);
10746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
10756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return mod.commit();
10766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (ExifInvalidFormatException e) {
10776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IOException("Invalid exif format : " + e);
10786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
10796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
10806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
10816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
10826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Attempts to do an in-place rewrite of the exif metadata. If this fails,
10836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * fall back to overwriting file. This preserves tags that are not being
10846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * rewritten.
10856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
10866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param filename a String containing a filepath for a jpeg file.
10876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tags tags that will be written into the jpeg file over existing
10886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            tags if possible.
10896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
10906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
10916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #rewriteExif
10926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
10936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void forceRewriteExif(String filename, Collection<ExifTag> tags)
10946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throws FileNotFoundException,
10956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IOException {
10966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // Attempt in-place write
10976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (!rewriteExif(filename, tags)) {
10986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Fall back to doing a copy
10996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ExifData tempData = mData;
11006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            mData = new ExifData(DEFAULT_BYTE_ORDER);
11016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            FileInputStream is = null;
11026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ByteArrayOutputStream bytes = null;
11036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            try {
11046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                is = new FileInputStream(filename);
11056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                bytes = new ByteArrayOutputStream();
11066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                doExifStreamIO(is, bytes);
11076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                byte[] imageBytes = bytes.toByteArray();
11086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                readExif(imageBytes);
11096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                setTags(tags);
11106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                writeExif(imageBytes, filename);
11116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            } catch (IOException e) {
11126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                closeSilently(is);
11136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                throw e;
11146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            } finally {
11156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                is.close();
11166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                // Prevent clobbering of mData
11176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                mData = tempData;
11186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
11196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
11206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Attempts to do an in-place rewrite of the exif metadata using the tags in
11246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * this ExifInterface object. If this fails, fall back to overwriting file.
11256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * This preserves tags that are not being rewritten.
11266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param filename a String containing a filepath for a jpeg file.
11286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws FileNotFoundException
11296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @throws IOException
11306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #rewriteExif
11316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void forceRewriteExif(String filename) throws FileNotFoundException, IOException {
11336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        forceRewriteExif(filename, getAllTags());
11346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Get the exif tags in this ExifInterface object or null if none exist.
11386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return a List of {@link ExifTag}s.
11406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public List<ExifTag> getAllTags() {
11426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getAllTags();
11436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns a list of ExifTags that share a TID (which can be obtained by
11476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * calling {@link #getTrueTagKey} on a defined tag constant) or null if none
11486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * exist.
11496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a TID as defined in the exif standard (or with
11516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            {@link #defineTag}).
11526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return a List of {@link ExifTag}s.
11536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public List<ExifTag> getTagsForTagId(short tagId) {
11556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getAllTagsForTagId(tagId);
11566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns a list of ExifTags that share an IFD (which can be obtained by
11606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * calling {@link #getTrueIFD} on a defined tag constant) or null if none
11616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * exist.
11626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param ifdId an IFD as defined in the exif standard (or with
11646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            {@link #defineTag}).
11656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return a List of {@link ExifTag}s.
11666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public List<ExifTag> getTagsForIfdId(int ifdId) {
11686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getAllTagsForIfd(ifdId);
11696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets an ExifTag for an IFD other than the tag's default.
11736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTag
11756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifTag getTag(int tagId, int ifdId) {
11776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (!ExifTag.isValidIfd(ifdId)) {
11786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
11796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
11806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getTag(getTrueTagKey(tagId), ifdId);
11816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the ExifTag in that tag's default IFD for a defined tag constant
11856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * or null if none exists.
11866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
11886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an {@link ExifTag} or null if none exists.
11896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
11906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifTag getTag(int tagId) {
11916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
11926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTag(tagId, ifdId);
11936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
11946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
11956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
11966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets a tag value for an IFD other than the tag's default.
11976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
11986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
11996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Object getTagValue(int tagId, int ifdId) {
12016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
12026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return (t == null) ? null : t.getValue();
12036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the value of the ExifTag in that tag's default IFD for a defined
12076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * tag constant or null if none exists or the value could not be cast into
12086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * the return type.
12096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
12106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
12116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the value of the ExifTag or null if none exists.
12126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Object getTagValue(int tagId) {
12146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
12156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagValue(tagId, ifdId);
12166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /*
12196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Getter methods that are similar to getTagValue. Null is returned if the
12206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * tag value cannot be cast into the return type.
12216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public String getTagStringValue(int tagId, int ifdId) {
12276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
12286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
12296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
12306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
12316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getValueAsString();
12326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public String getTagStringValue(int tagId) {
12386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
12396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagStringValue(tagId, ifdId);
12406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Long getTagLongValue(int tagId, int ifdId) {
12466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        long[] l = getTagLongValues(tagId, ifdId);
12476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (l == null || l.length <= 0) {
12486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
12496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
12506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return new Long(l[0]);
12516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Long getTagLongValue(int tagId) {
12576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
12586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagLongValue(tagId, ifdId);
12596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Integer getTagIntValue(int tagId, int ifdId) {
12656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] l = getTagIntValues(tagId, ifdId);
12666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (l == null || l.length <= 0) {
12676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
12686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
12696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return new Integer(l[0]);
12706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Integer getTagIntValue(int tagId) {
12766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
12776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagIntValue(tagId, ifdId);
12786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Byte getTagByteValue(int tagId, int ifdId) {
12846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        byte[] l = getTagByteValues(tagId, ifdId);
12856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (l == null || l.length <= 0) {
12866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
12876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
12886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return new Byte(l[0]);
12896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
12926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
12936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
12946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Byte getTagByteValue(int tagId) {
12956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
12966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagByteValue(tagId, ifdId);
12976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
12986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
12996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Rational getTagRationalValue(int tagId, int ifdId) {
13036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        Rational[] l = getTagRationalValues(tagId, ifdId);
13046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (l == null || l.length == 0) {
13056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
13066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
13076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return new Rational(l[0]);
13086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Rational getTagRationalValue(int tagId) {
13146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
13156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagRationalValue(tagId, ifdId);
13166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public long[] getTagLongValues(int tagId, int ifdId) {
13226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
13236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
13246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
13256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
13266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getValueAsLongs();
13276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public long[] getTagLongValues(int tagId) {
13336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
13346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagLongValues(tagId, ifdId);
13356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int[] getTagIntValues(int tagId, int ifdId) {
13416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
13426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
13436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
13446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
13456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getValueAsInts();
13466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int[] getTagIntValues(int tagId) {
13526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
13536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagIntValues(tagId, ifdId);
13546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public byte[] getTagByteValues(int tagId, int ifdId) {
13606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
13616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
13626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
13636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
13646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getValueAsBytes();
13656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public byte[] getTagByteValues(int tagId) {
13716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
13726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagByteValues(tagId, ifdId);
13736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Rational[] getTagRationalValues(int tagId, int ifdId) {
13796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
13806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
13816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
13826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
13836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getValueAsRationals();
13846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #getTagValue
13886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
13896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Rational[] getTagRationalValues(int tagId) {
13906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
13916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagRationalValues(tagId, ifdId);
13926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
13936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
13946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
13956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Checks whether a tag has a defined number of elements.
13966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
13976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
13986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if the tag has a defined number of elements.
13996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean isTagCountDefined(int tagId) {
14016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
14026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // No value in info can be zero, as all tags have a non-zero type
14036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == 0) {
14046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
14056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
14066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getComponentCountFromInfo(info) != ExifTag.SIZE_UNDEFINED;
14076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the defined number of elements for a tag.
14116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
14136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the number of elements or {@link ExifTag#SIZE_UNDEFINED} if the
14146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         tag or the number of elements is not defined.
14156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int getDefinedTagCount(int tagId) {
14176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
14186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == 0) {
14196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return ExifTag.SIZE_UNDEFINED;
14206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
14216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getComponentCountFromInfo(info);
14226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the number of elements for an ExifTag in a given IFD.
14266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
14286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param ifdId the IFD containing the ExifTag to check.
14296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the number of elements in the ExifTag, if the tag's size is
14306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         undefined this will return the actual number of elements that is
14316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         in the ExifTag's value.
14326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int getActualTagCount(int tagId, int ifdId) {
14346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
14356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
14366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return 0;
14376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
14386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.getComponentCount();
14396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the default IFD for a tag.
14436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
14456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the default IFD for a tag definition or {@link #IFD_NULL} if no
14466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         definition exists.
14476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int getDefinedTagDefaultIfd(int tagId) {
14496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
14506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == DEFINITION_NULL) {
14516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return IFD_NULL;
14526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
14536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTrueIfd(tagId);
14546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the defined type for a tag.
14586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
14606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the type.
14616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see ExifTag#getDataType()
14626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public short getDefinedTagType(int tagId) {
14646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
14656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == 0) {
14666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return -1;
14676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
14686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTypeFromInfo(info);
14696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns true if tag TID is one of the following: {@link TAG_EXIF_IFD},
14736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_GPS_IFD}, {@link TAG_JPEG_INTERCHANGE_FORMAT},
14746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link TAG_STRIP_OFFSETS}, {@link TAG_INTEROPERABILITY_IFD}
14756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * <p>
14766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Note: defining tags with these TID's is disallowed.
14776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tag a tag's TID (can be obtained from a defined tag constant with
14796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            {@link #getTrueTagKey}).
14806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if the TID is that of an offset tag.
14816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static boolean isOffsetTag(short tag) {
14836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return sOffsetTags.contains(tag);
14846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
14856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
14866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
14876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates a tag for a defined tag constant in a given IFD if that IFD is
14886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * allowed for the tag.  This method will fail anytime the appropriate
14896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link ExifTag#setValue} for this tag's datatype would fail.
14906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
14916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
14926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param ifdId the IFD that the tag should be in.
14936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param val the value of the tag to set.
14946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an ExifTag object or null if one could not be constructed.
14956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #buildTag
14966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
14976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifTag buildTag(int tagId, int ifdId, Object val) {
14986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
14996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == 0 || val == null) {
15006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
15016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        short type = getTypeFromInfo(info);
15036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int definedCount = getComponentCountFromInfo(info);
15046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
15056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (!ExifInterface.isIfdAllowed(info, ifdId)) {
15066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
15076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
15096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (!t.setValue(val)) {
15106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
15116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t;
15136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
15166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates a tag for a defined tag constant in the tag's default IFD.
15176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
15186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
15196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param val the tag's value.
15206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an ExifTag object.
15216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
15226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifTag buildTag(int tagId, Object val) {
15236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getTrueIfd(tagId);
15246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return buildTag(tagId, ifdId, val);
15256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected ExifTag buildUninitializedTag(int tagId) {
15286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int info = getTagInfo().get(tagId);
15296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (info == 0) {
15306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
15316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        short type = getTypeFromInfo(info);
15336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int definedCount = getComponentCountFromInfo(info);
15346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
15356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getTrueIfd(tagId);
15366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
15376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t;
15386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
15416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Sets the value of an ExifTag if it exists in the given IFD. The value
15426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * must be the correct type and length for that ExifTag.
15436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
15446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
15456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param ifdId the IFD that the ExifTag is in.
15466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param val the value to set.
15476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if the ExifTag doesn't exist or the value
15486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         is the wrong type/length.
15496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #setTagValue
15506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
15516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean setTagValue(int tagId, int ifdId, Object val) {
15526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = getTag(tagId, ifdId);
15536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
15546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
15556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return t.setValue(val);
15576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
15606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Sets the value of an ExifTag if it exists it's default IFD. The value
15616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * must be the correct type and length for that ExifTag.
15626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
15636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
15646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param val the value to set.
15656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if the ExifTag doesn't exist or the value
15666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         is the wrong type/length.
15676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
15686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean setTagValue(int tagId, Object val) {
15696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
15706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return setTagValue(tagId, ifdId, val);
15716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
15746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Puts an ExifTag into this ExifInterface object's tags, removing a
15756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * previous ExifTag with the same TID and IFD. The IFD it is put into will
15766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * be the one the tag was created with in {@link #buildTag}.
15776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
15786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tag an ExifTag to put into this ExifInterface's tags.
15796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the previous ExifTag with the same TID and IFD or null if none
15806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         exists.
15816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
15826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public ExifTag setTag(ExifTag tag) {
15836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.addTag(tag);
15846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
15876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Puts a collection of ExifTags into this ExifInterface objects's tags. Any
15886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * previous ExifTags with the same TID and IFDs will be removed.
15896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
15906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tags a Collection of ExifTags.
15916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #setTag
15926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
15936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void setTags(Collection<ExifTag> tags) {
15946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (ExifTag t : tags) {
15956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            setTag(t);
15966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
15976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
15986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
15996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
16006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Removes the ExifTag for a tag constant from the given IFD.
16016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
16026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
16036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param ifdId the IFD of the ExifTag to remove.
16046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
16056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void deleteTag(int tagId, int ifdId) {
16066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData.removeTag(getTrueTagKey(tagId), ifdId);
16076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
16086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
16106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Removes the ExifTag for a tag constant from that tag's default IFD.
16116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
16126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
16136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
16146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void deleteTag(int tagId) {
16156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
16166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        deleteTag(tagId, ifdId);
16176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
16186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
16206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates a new tag definition in this ExifInterface object for a given TID
16216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * and default IFD. Creating a definition with the same TID and default IFD
16226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * as a previous definition will override it.
16236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
16246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId the TID for the tag.
16256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param defaultIfd the default IFD for the tag.
16266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagType the type of the tag (see {@link ExifTag#getDataType()}).
16276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param defaultComponentCount the number of elements of this tag's type in
16286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            the tags value.
16296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param allowedIfds the IFD's this tag is allowed to be put in.
16306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the defined tag constant (e.g. {@link #TAG_IMAGE_WIDTH}) or
16316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         {@link #TAG_NULL} if the definition could not be made.
16326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
16336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public int setTagDefinition(short tagId, int defaultIfd, short tagType,
16346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            short defaultComponentCount, int[] allowedIfds) {
16356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (sBannedDefines.contains(tagId)) {
16366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return TAG_NULL;
16376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
16386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (ExifTag.isValidType(tagType) && ExifTag.isValidIfd(defaultIfd)) {
16396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int tagDef = defineTag(defaultIfd, tagId);
16406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (tagDef == TAG_NULL) {
16416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return TAG_NULL;
16426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
16436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int[] otherDefs = getTagDefinitionsForTagId(tagId);
16446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            SparseIntArray infos = getTagInfo();
16456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Make sure defaultIfd is in allowedIfds
16466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            boolean defaultCheck = false;
16476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            for (int i : allowedIfds) {
16486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                if (defaultIfd == i) {
16496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    defaultCheck = true;
16506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                }
16516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                if (!ExifTag.isValidIfd(i)) {
16526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    return TAG_NULL;
16536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                }
16546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
16556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (!defaultCheck) {
16566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return TAG_NULL;
16576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
16586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int ifdFlags = getFlagsFromAllowedIfds(allowedIfds);
16606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // Make sure no identical tags can exist in allowedIfds
16616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (otherDefs != null) {
16626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                for (int def : otherDefs) {
16636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    int tagInfo = infos.get(def);
16646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    int allowedFlags = getAllowedIfdFlagsFromInfo(tagInfo);
16656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    if ((ifdFlags & allowedFlags) != 0) {
16666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                        return TAG_NULL;
16676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    }
16686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                }
16696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
16706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            getTagInfo().put(tagDef, ifdFlags << 24 | (tagType << 16) | defaultComponentCount);
16716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return tagDef;
16726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
16736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return TAG_NULL;
16746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
16756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected int getTagDefinition(short tagId, int defaultIfd) {
16776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagInfo().get(defineTag(defaultIfd, tagId));
16786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
16796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected int[] getTagDefinitionsForTagId(short tagId) {
16816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifds = IfdData.getIfds();
16826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] defs = new int[ifds.length];
16836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int counter = 0;
16846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        SparseIntArray infos = getTagInfo();
16856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i : ifds) {
16866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int def = defineTag(i, tagId);
16876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (infos.get(def) != DEFINITION_NULL) {
16886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                defs[counter++] = def;
16896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
16906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
16916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (counter == 0) {
16926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
16936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
16946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return Arrays.copyOfRange(defs, 0, counter);
16966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
16976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
16986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected int getTagDefinitionForTag(ExifTag tag) {
16996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        short type = tag.getDataType();
17006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int count = tag.getComponentCount();
17016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifd = tag.getIfd();
17026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return getTagDefinitionForTag(tag.getTagId(), type, count, ifd);
17036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected int getTagDefinitionForTag(short tagId, short type, int count, int ifd) {
17066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] defs = getTagDefinitionsForTagId(tagId);
17076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (defs == null) {
17086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return TAG_NULL;
17096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
17106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        SparseIntArray infos = getTagInfo();
17116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ret = TAG_NULL;
17126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i : defs) {
17136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int info = infos.get(i);
17146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            short def_type = getTypeFromInfo(info);
17156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int def_count = getComponentCountFromInfo(info);
17166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int[] def_ifds = getAllowedIfdsFromInfo(info);
17176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            boolean valid_ifd = false;
17186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            for (int j : def_ifds) {
17196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                if (j == ifd) {
17206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    valid_ifd = true;
17216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    break;
17226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                }
17236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
17246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (valid_ifd && type == def_type
17256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    && (count == def_count || def_count == ExifTag.SIZE_UNDEFINED)) {
17266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ret = i;
17276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                break;
17286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
17296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
17306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return ret;
17316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Removes a tag definition for given defined tag constant.
17356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
17366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
17376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void removeTagDefinition(int tagId) {
17396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        getTagInfo().delete(tagId);
17406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Resets tag definitions to the default ones.
17446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void resetTagDefinitions() {
17466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo = null;
17476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the thumbnail from IFD1 as a bitmap, or null if none exists.
17516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
17526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the thumbnail as a bitmap.
17536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public Bitmap getThumbnailBitmap() {
17556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (mData.hasCompressedThumbnail()) {
17566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            byte[] thumb = mData.getCompressedThumbnail();
17576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return BitmapFactory.decodeByteArray(thumb, 0, thumb.length);
17586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else if (mData.hasUncompressedStrip()) {
17596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // TODO: implement uncompressed
17606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
17616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return null;
17626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the thumbnail from IFD1 as a byte array, or null if none exists.
17666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * The bytes may either be an uncompressed strip as specified in the exif
17676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * standard or a jpeg compressed image.
17686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
17696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the thumbnail as a byte array.
17706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public byte[] getThumbnailBytes() {
17726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (mData.hasCompressedThumbnail()) {
17736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return mData.getCompressedThumbnail();
17746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else if (mData.hasUncompressedStrip()) {
17756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            // TODO: implement this
17766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
17776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return null;
17786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the thumbnail if it is jpeg compressed, or null if none exists.
17826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
17836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the thumbnail as a byte array.
17846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public byte[] getThumbnail() {
17866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getCompressedThumbnail();
17876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Check if thumbnail is compressed.
17916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
17926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if the thumbnail is compressed.
17936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
17946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean isThumbnailCompressed() {
17956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.hasCompressedThumbnail();
17966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
17976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
17986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
17996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Check if thumbnail exists.
18006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
18016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if a compressed thumbnail exists.
18026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean hasThumbnail() {
18046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // TODO: add back in uncompressed strip
18056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.hasCompressedThumbnail();
18066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // TODO: uncompressed thumbnail setters
18096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Sets the thumbnail to be a jpeg compressed image. Clears any prior
18126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * thumbnail.
18136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
18146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param thumb a byte array containing a jpeg compressed image.
18156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if the thumbnail was set.
18166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean setCompressedThumbnail(byte[] thumb) {
18186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData.clearThumbnailAndStrips();
18196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData.setCompressedThumbnail(thumb);
18206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return true;
18216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Sets the thumbnail to be a jpeg compressed bitmap. Clears any prior
18256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * thumbnail.
18266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
18276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param thumb a bitmap to compress to a jpeg thumbnail.
18286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if the thumbnail was set.
18296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean setCompressedThumbnail(Bitmap thumb) {
18316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ByteArrayOutputStream thumbnail = new ByteArrayOutputStream();
18326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (!thumb.compress(Bitmap.CompressFormat.JPEG, 90, thumbnail)) {
18336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
18346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
18356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return setCompressedThumbnail(thumbnail.toByteArray());
18366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Clears the compressed thumbnail if it exists.
18406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public void removeCompressedThumbnail() {
18426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mData.setCompressedThumbnail(null);
18436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    // Convenience methods:
18466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Decodes the user comment tag into string as specified in the EXIF
18496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * standard. Returns null if decoding failed.
18506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public String getUserComment() {
18526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mData.getUserComment();
18536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the Orientation ExifTag value for a given number of degrees.
18576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
18586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param degrees the amount an image is rotated in degrees.
18596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static short getOrientationValueForRotation(int degrees) {
18616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        degrees %= 360;
18626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (degrees < 0) {
18636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            degrees += 360;
18646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
18656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (degrees < 90) {
18666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return Orientation.TOP_LEFT; // 0 degrees
18676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else if (degrees < 180) {
18686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return Orientation.RIGHT_TOP; // 90 degrees cw
18696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else if (degrees < 270) {
18706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return Orientation.BOTTOM_LEFT; // 180 degrees
18716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else {
18726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return Orientation.RIGHT_BOTTOM; // 270 degrees cw
18736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
18746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Returns the rotation degrees corresponding to an ExifTag Orientation
18786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * value.
18796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
18806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param orientation the ExifTag Orientation value.
18816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
18826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static int getRotationForOrientationValue(short orientation) {
18836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        switch (orientation) {
18846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            case Orientation.TOP_LEFT:
18856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return 0;
18866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            case Orientation.RIGHT_TOP:
18876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return 90;
18886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            case Orientation.BOTTOM_LEFT:
18896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return 180;
18906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            case Orientation.RIGHT_BOTTOM:
18916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return 270;
18926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            default:
18936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return 0;
18946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
18956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
18966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
18976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
18986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the double representation of the GPS latitude or longitude
18996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * coordinate.
19006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
19016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param coordinate an array of 3 Rationals representing the degrees,
19026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            minutes, and seconds of the GPS location as defined in the
19036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            exif specification.
19046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param reference a GPS reference reperesented by a String containing "N",
19056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *            "S", "E", or "W".
19066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return the GPS coordinate represented as degrees + minutes/60 +
19076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         seconds/3600
19086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
19096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public static double convertLatOrLongToDouble(Rational[] coordinate, String reference) {
19106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        try {
19116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            double degrees = coordinate[0].toDouble();
19126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            double minutes = coordinate[1].toDouble();
19136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            double seconds = coordinate[2].toDouble();
19146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            double result = degrees + minutes / 60.0 + seconds / 3600.0;
19156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if ((reference.equals("S") || reference.equals("W"))) {
19166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return -result;
19176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
19186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return result;
19196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } catch (ArrayIndexOutOfBoundsException e) {
19206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            throw new IllegalArgumentException();
19216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
19226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
19236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
19246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
19256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Gets the GPS latitude and longitude as a pair of doubles from this
19266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * ExifInterface object's tags, or null if the necessary tags do not exist.
19276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
19286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return an array of 2 doubles containing the latitude, and longitude
19296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *         respectively.
19306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @see #convertLatOrLongToDouble
19316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
19326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public double[] getLatLongAsDoubles() {
19336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        Rational[] latitude = getTagRationalValues(TAG_GPS_LATITUDE);
19346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        String latitudeRef = getTagStringValue(TAG_GPS_LATITUDE_REF);
19356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        Rational[] longitude = getTagRationalValues(TAG_GPS_LONGITUDE);
19366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        String longitudeRef = getTagStringValue(TAG_GPS_LONGITUDE_REF);
19376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (latitude == null || longitude == null || latitudeRef == null || longitudeRef == null
19386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                || latitude.length < 3 || longitude.length < 3) {
19396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
19406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
19416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        double[] latLon = new double[2];
19426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        latLon[0] = convertLatOrLongToDouble(latitude, latitudeRef);
19436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        latLon[1] = convertLatOrLongToDouble(longitude, longitudeRef);
19446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return latLon;
19456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
19466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
19476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
19486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private static final String DATETIME_FORMAT_STR = "yyyy:MM:dd kk:mm:ss";
19496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private final DateFormat mDateTimeStampFormat = new SimpleDateFormat(DATETIME_FORMAT_STR);
19506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private final DateFormat mGPSDateStampFormat = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
19516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private final Calendar mGPSTimeStampCalendar = Calendar
19526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            .getInstance(TimeZone.getTimeZone("UTC"));
19536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
19546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
19556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates, formats, and sets the DateTimeStamp tag for one of:
19566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link #TAG_DATE_TIME}, {@link #TAG_DATE_TIME_DIGITIZED},
19576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * {@link #TAG_DATE_TIME_ORIGINAL}.
19586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
19596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param tagId one of the DateTimeStamp tags.
19606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param timestamp a timestamp to format.
19616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param timezone a TimeZone object.
19626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if the tag could not be set.
19636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
19646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean addDateTimeStampTag(int tagId, long timestamp, TimeZone timezone) {
19656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (tagId == TAG_DATE_TIME || tagId == TAG_DATE_TIME_DIGITIZED
19666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                || tagId == TAG_DATE_TIME_ORIGINAL) {
19676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            mDateTimeStampFormat.setTimeZone(timezone);
19686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ExifTag t = buildTag(tagId, mDateTimeStampFormat.format(timestamp));
19696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (t == null) {
19706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return false;
19716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
19726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            setTag(t);
19736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        } else {
19746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
19756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
19766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return true;
19776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
19786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
19796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
19806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates and sets all to the GPS tags for a give latitude and longitude.
19816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
19826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param latitude a GPS latitude coordinate.
19836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param longitude a GPS longitude coordinate.
19846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if they could not be created or set.
19856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
19866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean addGpsTags(double latitude, double longitude) {
19876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag latTag = buildTag(TAG_GPS_LATITUDE, toExifLatLong(latitude));
19886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag longTag = buildTag(TAG_GPS_LONGITUDE, toExifLatLong(longitude));
19896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag latRefTag = buildTag(TAG_GPS_LATITUDE_REF,
19906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                latitude >= 0 ? ExifInterface.GpsLatitudeRef.NORTH
19916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                        : ExifInterface.GpsLatitudeRef.SOUTH);
19926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag longRefTag = buildTag(TAG_GPS_LONGITUDE_REF,
19936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                longitude >= 0 ? ExifInterface.GpsLongitudeRef.EAST
19946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                        : ExifInterface.GpsLongitudeRef.WEST);
19956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (latTag == null || longTag == null || latRefTag == null || longRefTag == null) {
19966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
19976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
19986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(latTag);
19996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(longTag);
20006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(latRefTag);
20016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(longRefTag);
20026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return true;
20036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    /**
20066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * Creates and sets the GPS timestamp tag.
20076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     *
20086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @param timestamp a GPS timestamp.
20096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     * @return true if success, false if could not be created or set.
20106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk     */
20116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    public boolean addGpsDateTimeStampTag(long timestamp) {
20126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ExifTag t = buildTag(TAG_GPS_DATE_STAMP, mGPSDateStampFormat.format(timestamp));
20136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
20146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
20156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
20166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(t);
20176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mGPSTimeStampCalendar.setTimeInMillis(timestamp);
20186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        t = buildTag(TAG_GPS_TIME_STAMP, new Rational[] {
20196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.HOUR_OF_DAY), 1),
20206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.MINUTE), 1),
20216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.SECOND), 1)
20226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        });
20236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (t == null) {
20246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return false;
20256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
20266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        setTag(t);
20276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return true;
20286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private static Rational[] toExifLatLong(double value) {
20316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // convert to the format dd/1 mm/1 ssss/100
20326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        value = Math.abs(value);
20336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int degrees = (int) value;
20346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        value = (value - degrees) * 60;
20356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int minutes = (int) value;
20366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        value = (value - minutes) * 6000;
20376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int seconds = (int) value;
20386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return new Rational[] {
20396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                new Rational(degrees, 1), new Rational(minutes, 1), new Rational(seconds, 100)
20406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
20416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private void doExifStreamIO(InputStream is, OutputStream os) throws IOException {
20446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        byte[] buf = new byte[1024];
20456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ret = is.read(buf, 0, 1024);
20466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        while (ret != -1) {
20476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            os.write(buf, 0, ret);
20486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ret = is.read(buf, 0, 1024);
20496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
20506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static void closeSilently(Closeable c) {
20536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (c != null) {
20546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            try {
20556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                c.close();
20566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            } catch (Throwable e) {
20576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                // ignored
20586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
20596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
20606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private SparseIntArray mTagInfo = null;
20636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected SparseIntArray getTagInfo() {
20656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (mTagInfo == null) {
20666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            mTagInfo = new SparseIntArray();
20676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            initTagInfo();
20686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
20696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return mTagInfo;
20706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
20716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
20726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    private void initTagInfo() {
20736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        /**
20746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk         * We put tag information in a 4-bytes integer. The first byte a bitmask
20756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk         * representing the allowed IFDs of the tag, the second byte is the data
20766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk         * type, and the last two byte are a short value indicating the default
20776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk         * component count of this tag.
20786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk         */
20796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // IFD0 tags
20806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifdAllowedIfds = {
20816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_1
20826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
20836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdFlags = getFlagsFromAllowedIfds(ifdAllowedIfds) << 24;
20846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_MAKE,
20856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
20866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_WIDTH,
20876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
20886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_LENGTH,
20896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
20906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_BITS_PER_SAMPLE,
20916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3);
20926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_COMPRESSION,
20936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
20946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_PHOTOMETRIC_INTERPRETATION,
20956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
20966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_ORIENTATION, ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16
20976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                | 1);
20986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SAMPLES_PER_PIXEL,
20996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_PLANAR_CONFIGURATION,
21016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_SUB_SAMPLING,
21036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
21046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_POSITIONING,
21056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_X_RESOLUTION,
21076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
21086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_Y_RESOLUTION,
21096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
21106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_RESOLUTION_UNIT,
21116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_STRIP_OFFSETS,
21136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
21146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_ROWS_PER_STRIP,
21156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_STRIP_BYTE_COUNTS,
21176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
21186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_TRANSFER_FUNCTION,
21196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3 * 256);
21206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_WHITE_POINT,
21216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 2);
21226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_PRIMARY_CHROMATICITIES,
21236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
21246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_COEFFICIENTS,
21256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
21266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_REFERENCE_BLACK_WHITE,
21276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
21286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME,
21296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | 20);
21306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_DESCRIPTION,
21316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_MAKE,
21336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_MODEL,
21356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SOFTWARE,
21376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_ARTIST,
21396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_COPYRIGHT,
21416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXIF_IFD,
21436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IFD,
21456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // IFD1 tags
21476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifd1AllowedIfds = {
21486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IfdId.TYPE_IFD_1
21496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
21506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdFlags1 = getFlagsFromAllowedIfds(ifd1AllowedIfds) << 24;
21516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT,
21526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
21546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // Exif tags
21566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] exifAllowedIfds = {
21576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IfdId.TYPE_IFD_EXIF
21586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
21596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int exifFlags = getFlagsFromAllowedIfds(exifAllowedIfds) << 24;
21606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXIF_VERSION,
21616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
21626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FLASHPIX_VERSION,
21636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
21646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_COLOR_SPACE,
21656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_COMPONENTS_CONFIGURATION,
21676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
21686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_COMPRESSED_BITS_PER_PIXEL,
21696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
21706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_PIXEL_X_DIMENSION,
21716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_PIXEL_Y_DIMENSION,
21736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
21746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_MAKER_NOTE,
21756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
21766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_USER_COMMENT,
21776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
21786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_RELATED_SOUND_FILE,
21796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 13);
21806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME_ORIGINAL,
21816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
21826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME_DIGITIZED,
21836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
21846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME,
21856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_ORIGINAL,
21876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_DIGITIZED,
21896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
21906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_UNIQUE_ID,
21916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 33);
21926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_TIME,
21936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
21946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_F_NUMBER,
21956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
21966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_PROGRAM,
21976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
21986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SPECTRAL_SENSITIVITY,
21996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
22006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_ISO_SPEED_RATINGS,
22016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
22026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_OECF,
22036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
22046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE,
22056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
22066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_APERTURE_VALUE,
22076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_BRIGHTNESS_VALUE,
22096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
22106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_BIAS_VALUE,
22116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
22126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_MAX_APERTURE_VALUE,
22136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE,
22156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_METERING_MODE,
22176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_LIGHT_SOURCE,
22196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FLASH,
22216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH,
22236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_AREA,
22256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
22266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FLASH_ENERGY,
22276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SPATIAL_FREQUENCY_RESPONSE,
22296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
22306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION,
22316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION,
22336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT,
22356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_LOCATION,
22376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
22386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_INDEX,
22396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SENSING_METHOD,
22416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FILE_SOURCE,
22436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
22446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SCENE_TYPE,
22456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
22466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_CFA_PATTERN,
22476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
22486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_CUSTOM_RENDERED,
22496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_MODE,
22516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_WHITE_BALANCE,
22536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_DIGITAL_ZOOM_RATIO,
22556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH_IN_35_MM_FILE,
22576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SCENE_CAPTURE_TYPE,
22596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GAIN_CONTROL,
22616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_CONTRAST,
22636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SATURATION,
22656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SHARPNESS,
22676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION,
22696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
22706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE_RANGE,
22716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
22726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_INTEROPERABILITY_IFD, exifFlags
22736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
22746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // GPS tag
22756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] gpsAllowedIfds = {
22766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IfdId.TYPE_IFD_GPS
22776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
22786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int gpsFlags = getFlagsFromAllowedIfds(gpsAllowedIfds) << 24;
22796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_VERSION_ID,
22806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 4);
22816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE_REF,
22826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
22836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE_REF,
22846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
22856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE,
22866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
22876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE,
22886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
22896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE_REF,
22906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 1);
22916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE,
22926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
22936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TIME_STAMP,
22946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
22956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SATTELLITES,
22966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
22976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_STATUS,
22986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
22996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_MEASURE_MODE,
23006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DOP,
23026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SPEED_REF,
23046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SPEED,
23066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TRACK_REF,
23086e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23096e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TRACK,
23106e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23116e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
23126e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23136e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION,
23146e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23156e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_MAP_DATUM,
23166e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
23176e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
23186e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23196e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE,
23206e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23216e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING_REF,
23226e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23236e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING,
23246e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23256e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
23266e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
23276e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE,
23286e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
23296e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_PROCESSING_METHOD,
23306e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
23316e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_AREA_INFORMATION,
23326e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
23336e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DATE_STAMP,
23346e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 11);
23356e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DIFFERENTIAL,
23366e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 11);
23376e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        // Interoperability tag
23386e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] interopAllowedIfds = {
23396e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            IfdId.TYPE_IFD_INTEROPERABILITY
23406e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        };
23416e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int interopFlags = getFlagsFromAllowedIfds(interopAllowedIfds) << 24;
23426e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        mTagInfo.put(TAG_INTEROPERABILITY_INDEX, interopFlags | ExifTag.TYPE_ASCII << 16
23436e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                | ExifTag.SIZE_UNDEFINED);
23446e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
23456e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
23466e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static int getAllowedIfdFlagsFromInfo(int info) {
23476e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return info >>> 24;
23486e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
23496e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
23506e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static int[] getAllowedIfdsFromInfo(int info) {
23516e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
23526e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifds = IfdData.getIfds();
23536e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        ArrayList<Integer> l = new ArrayList<Integer>();
23546e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
23556e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            int flag = (ifdFlags >> i) & 1;
23566e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (flag == 1) {
23576e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                l.add(ifds[i]);
23586e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
23596e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23606e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (l.size() <= 0) {
23616e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return null;
23626e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23636e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ret = new int[l.size()];
23646e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int j = 0;
23656e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i : l) {
23666e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            ret[j++] = i;
23676e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23686e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return ret;
23696e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
23706e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
23716e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static boolean isIfdAllowed(int info, int ifd) {
23726e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifds = IfdData.getIfds();
23736e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
23746e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i = 0; i < ifds.length; i++) {
23756e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            if (ifd == ifds[i] && ((ifdFlags >> i) & 1) == 1) {
23766e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                return true;
23776e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
23786e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23796e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return false;
23806e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
23816e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
23826e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static int getFlagsFromAllowedIfds(int[] allowedIfds) {
23836e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        if (allowedIfds == null || allowedIfds.length == 0) {
23846e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            return 0;
23856e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23866e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int flags = 0;
23876e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        int[] ifds = IfdData.getIfds();
23886e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
23896e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            for (int j : allowedIfds) {
23906e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                if (ifds[i] == j) {
23916e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    flags |= 1 << i;
23926e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                    break;
23936e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk                }
23946e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk            }
23956e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        }
23966e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return flags;
23976e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
23986e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
23996e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static short getTypeFromInfo(int info) {
24006e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return (short) ((info >> 16) & 0x0ff);
24016e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
24026e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
24036e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    protected static int getComponentCountFromInfo(int info) {
24046e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk        return info & 0x0ffff;
24056e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk    }
24066e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk
24076e6a524390d8ddebce5de0dcc8ae258e652ec80aRuben Brunk}
2408