1c274ded801f745d6318186958107622e7a4fef33Ruben Brunk/*
2c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * Copyright (C) 2013 The Android Open Source Project
3c274ded801f745d6318186958107622e7a4fef33Ruben Brunk *
4c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * you may not use this file except in compliance with the License.
6c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * You may obtain a copy of the License at
7c274ded801f745d6318186958107622e7a4fef33Ruben Brunk *
8c274ded801f745d6318186958107622e7a4fef33Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9c274ded801f745d6318186958107622e7a4fef33Ruben Brunk *
10c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * See the License for the specific language governing permissions and
14c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * limitations under the License.
15c274ded801f745d6318186958107622e7a4fef33Ruben Brunk */
16c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
17a16e7b50f3148f581439509279f242092e254309ztenghuipackage com.android.camera.exif;
18c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
19c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport android.graphics.Bitmap;
20c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport android.graphics.BitmapFactory;
21c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport android.util.SparseIntArray;
22c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2343b9c0c3fce9cb877ca73cb34917fb2c7556c4d4Ruben Brunkimport java.io.BufferedInputStream;
24c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.ByteArrayInputStream;
25c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.ByteArrayOutputStream;
26c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.Closeable;
27c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.File;
28c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.FileInputStream;
29c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.FileNotFoundException;
30c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.FileOutputStream;
31c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.IOException;
32c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.InputStream;
33c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.OutputStream;
34c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.io.RandomAccessFile;
35c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.nio.ByteBuffer;
36c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.nio.ByteOrder;
37c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.nio.channels.FileChannel.MapMode;
38c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.text.DateFormat;
39c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.text.SimpleDateFormat;
40c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.ArrayList;
41c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.Arrays;
42c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.Calendar;
43c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.Collection;
44c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.HashSet;
45c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.List;
46c274ded801f745d6318186958107622e7a4fef33Ruben Brunkimport java.util.TimeZone;
47c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
48c274ded801f745d6318186958107622e7a4fef33Ruben Brunk/**
49c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * This class provides methods and constants for reading and writing jpeg file
50c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * metadata. It contains a collection of ExifTags, and a collection of
51c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * definitions for creating valid ExifTags. The collection of ExifTags can be
52c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * updated by: reading new ones from a file, deleting or adding existing ones,
53c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * or building new ExifTags from a tag definition. These ExifTags can be written
54c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * to a valid jpeg image as exif metadata.
55c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * <p>
56c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * Each ExifTag has a tag ID (TID) and is stored in a specific image file
57c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * directory (IFD) as specified by the exif standard. A tag definition can be
58c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * looked up with a constant that is a combination of TID and IFD. This
59c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * definition has information about the type, number of components, and valid
60c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * IFDs for a tag.
61c274ded801f745d6318186958107622e7a4fef33Ruben Brunk *
62c274ded801f745d6318186958107622e7a4fef33Ruben Brunk * @see ExifTag
63c274ded801f745d6318186958107622e7a4fef33Ruben Brunk */
64c274ded801f745d6318186958107622e7a4fef33Ruben Brunkpublic class ExifInterface {
65c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_NULL = -1;
66c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int IFD_NULL = -1;
67c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int DEFINITION_NULL = 0;
68c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
69c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
70c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Tag constants for Jeita EXIF 2.2
71c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
72c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
73c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // IFD 0
74c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_IMAGE_WIDTH =
75c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0100);
76c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_IMAGE_LENGTH =
77c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0101); // Image height
78c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_BITS_PER_SAMPLE =
79c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0102);
80c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_COMPRESSION =
81c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0103);
82c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_PHOTOMETRIC_INTERPRETATION =
83c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0106);
84c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_IMAGE_DESCRIPTION =
85c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x010E);
86c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_MAKE =
87c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x010F);
88c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_MODEL =
89c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0110);
90c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_STRIP_OFFSETS =
91c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0111);
92c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_ORIENTATION =
93c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0112);
94c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SAMPLES_PER_PIXEL =
95c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0115);
96c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_ROWS_PER_STRIP =
97c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0116);
98c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_STRIP_BYTE_COUNTS =
99c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0117);
100c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_X_RESOLUTION =
101c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011A);
102c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_Y_RESOLUTION =
103c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011B);
104c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_PLANAR_CONFIGURATION =
105c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x011C);
106c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_RESOLUTION_UNIT =
107c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0128);
108c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_TRANSFER_FUNCTION =
109c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x012D);
110c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SOFTWARE =
111c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0131);
112c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_DATE_TIME =
113c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0132);
114c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_ARTIST =
115c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013B);
116c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_WHITE_POINT =
117c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013E);
118c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_PRIMARY_CHROMATICITIES =
119c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x013F);
120c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_Y_CB_CR_COEFFICIENTS =
121c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0211);
122c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_Y_CB_CR_SUB_SAMPLING =
123c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0212);
124c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_Y_CB_CR_POSITIONING =
125c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0213);
126c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_REFERENCE_BLACK_WHITE =
127c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x0214);
128c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_COPYRIGHT =
129c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8298);
130c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXIF_IFD =
131c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8769);
132c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_IFD =
133c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_0, (short) 0x8825);
134c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // IFD 1
135c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_JPEG_INTERCHANGE_FORMAT =
136c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_1, (short) 0x0201);
137c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH =
138c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_1, (short) 0x0202);
139c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // IFD Exif Tags
140c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXPOSURE_TIME =
141c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829A);
142c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_F_NUMBER =
143c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829D);
144c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXPOSURE_PROGRAM =
145c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8822);
146c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SPECTRAL_SENSITIVITY =
147c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8824);
148c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_ISO_SPEED_RATINGS =
149c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8827);
150c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_OECF =
151c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8828);
152c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXIF_VERSION =
153c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9000);
154c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_DATE_TIME_ORIGINAL =
155c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9003);
156c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_DATE_TIME_DIGITIZED =
157c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9004);
158c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_COMPONENTS_CONFIGURATION =
159c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9101);
160c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_COMPRESSED_BITS_PER_PIXEL =
161c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9102);
162c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SHUTTER_SPEED_VALUE =
163c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9201);
164c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_APERTURE_VALUE =
165c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9202);
166c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_BRIGHTNESS_VALUE =
167c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9203);
168c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXPOSURE_BIAS_VALUE =
169c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9204);
170c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_MAX_APERTURE_VALUE =
171c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9205);
172c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUBJECT_DISTANCE =
173c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9206);
174c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_METERING_MODE =
175c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9207);
176c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_LIGHT_SOURCE =
177c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9208);
178c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FLASH =
179c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9209);
180c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FOCAL_LENGTH =
181c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x920A);
182c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUBJECT_AREA =
183c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9214);
184c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_MAKER_NOTE =
185c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x927C);
186c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_USER_COMMENT =
187c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9286);
188c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUB_SEC_TIME =
189c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9290);
190c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUB_SEC_TIME_ORIGINAL =
191c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9291);
192c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUB_SEC_TIME_DIGITIZED =
193c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9292);
194c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FLASHPIX_VERSION =
195c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA000);
196c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_COLOR_SPACE =
197c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA001);
198c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_PIXEL_X_DIMENSION =
199c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA002);
200c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_PIXEL_Y_DIMENSION =
201c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA003);
202c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_RELATED_SOUND_FILE =
203c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA004);
204c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_INTEROPERABILITY_IFD =
205c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA005);
206c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FLASH_ENERGY =
207c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20B);
208c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SPATIAL_FREQUENCY_RESPONSE =
209c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20C);
210c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FOCAL_PLANE_X_RESOLUTION =
211c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20E);
212c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FOCAL_PLANE_Y_RESOLUTION =
213c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20F);
214c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT =
215c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA210);
216c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUBJECT_LOCATION =
217c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA214);
218c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXPOSURE_INDEX =
219c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA215);
220c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SENSING_METHOD =
221c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA217);
222c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FILE_SOURCE =
223c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA300);
224c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SCENE_TYPE =
225c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA301);
226c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_CFA_PATTERN =
227c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA302);
228c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_CUSTOM_RENDERED =
229c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA401);
230c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_EXPOSURE_MODE =
231c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA402);
232c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_WHITE_BALANCE =
233c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA403);
234c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_DIGITAL_ZOOM_RATIO =
235c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA404);
236c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_FOCAL_LENGTH_IN_35_MM_FILE =
237c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA405);
238c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SCENE_CAPTURE_TYPE =
239c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA406);
240c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GAIN_CONTROL =
241c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA407);
242c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_CONTRAST =
243c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA408);
244c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SATURATION =
245c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA409);
246c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SHARPNESS =
247c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40A);
248c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_DEVICE_SETTING_DESCRIPTION =
249c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40B);
250c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_SUBJECT_DISTANCE_RANGE =
251c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40C);
252c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_IMAGE_UNIQUE_ID =
253c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA420);
254c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // IFD GPS tags
255c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_VERSION_ID =
256c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 0);
257c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_LATITUDE_REF =
258c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 1);
259c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_LATITUDE =
260c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 2);
261c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_LONGITUDE_REF =
262c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 3);
263c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_LONGITUDE =
264c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 4);
265c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_ALTITUDE_REF =
266c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 5);
267c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_ALTITUDE =
268c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 6);
269c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_TIME_STAMP =
270c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 7);
271c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_SATTELLITES =
272c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 8);
273c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_STATUS =
274c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 9);
275c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_MEASURE_MODE =
276c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 10);
277c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DOP =
278c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 11);
279c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_SPEED_REF =
280c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 12);
281c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_SPEED =
282c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 13);
283c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_TRACK_REF =
284c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 14);
285c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_TRACK =
286c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 15);
287c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_IMG_DIRECTION_REF =
288c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 16);
289c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_IMG_DIRECTION =
290c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 17);
291c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_MAP_DATUM =
292c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 18);
293c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_LATITUDE_REF =
294c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 19);
295c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_LATITUDE =
296c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 20);
297c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_LONGITUDE_REF =
298c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 21);
299c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_LONGITUDE =
300c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 22);
301c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_BEARING_REF =
302c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 23);
303c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_BEARING =
304c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 24);
305c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_DISTANCE_REF =
306c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 25);
307c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DEST_DISTANCE =
308c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 26);
309c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_PROCESSING_METHOD =
310c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 27);
311c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_AREA_INFORMATION =
312c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 28);
313c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DATE_STAMP =
314c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 29);
315c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_GPS_DIFFERENTIAL =
316c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_GPS, (short) 30);
317c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // IFD Interoperability tags
318c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final int TAG_INTEROPERABILITY_INDEX =
319c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 1);
320c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
321c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
322c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Tags that contain offset markers. These are included in the banned
323c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * defines.
324c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
325c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private static HashSet<Short> sOffsetTags = new HashSet<Short>();
326c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    static {
327c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sOffsetTags.add(getTrueTagKey(TAG_GPS_IFD));
328c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sOffsetTags.add(getTrueTagKey(TAG_EXIF_IFD));
329c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sOffsetTags.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT));
330c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sOffsetTags.add(getTrueTagKey(TAG_INTEROPERABILITY_IFD));
331c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sOffsetTags.add(getTrueTagKey(TAG_STRIP_OFFSETS));
332c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
333c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
334c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
335c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Tags with definitions that cannot be overridden (banned defines).
336c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
337c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static HashSet<Short> sBannedDefines = new HashSet<Short>(sOffsetTags);
338c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    static {
339c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sBannedDefines.add(getTrueTagKey(TAG_NULL));
340c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sBannedDefines.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH));
341c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        sBannedDefines.add(getTrueTagKey(TAG_STRIP_BYTE_COUNTS));
342c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
343c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
344c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
345c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the constant representing a tag with a given TID and default IFD.
346c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
347c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static int defineTag(int ifdId, short tagId) {
348c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return (tagId & 0x0000ffff) | (ifdId << 16);
349c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
350c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
351c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
352c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the TID for a tag constant.
353c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
354c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static short getTrueTagKey(int tag) {
355c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // Truncate
356c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return (short) tag;
357c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
358c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
359c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
360c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the default IFD for a tag constant.
361c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
362c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static int getTrueIfd(int tag) {
363c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return tag >>> 16;
364c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
365c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
366c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
367c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_ORIENTATION}. They can be interpreted as
368c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * follows:
369c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <ul>
370c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>TOP_LEFT is the normal orientation.</li>
371c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>TOP_RIGHT is a left-right mirror.</li>
372c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>BOTTOM_LEFT is a 180 degree rotation.</li>
373c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>BOTTOM_RIGHT is a top-bottom mirror.</li>
374c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>LEFT_TOP is mirrored about the top-left<->bottom-right axis.</li>
375c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>RIGHT_TOP is a 90 degree clockwise rotation.</li>
376c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>LEFT_BOTTOM is mirrored about the top-right<->bottom-left axis.</li>
377c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <li>RIGHT_BOTTOM is a 270 degree clockwise rotation.</li>
378c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * </ul>
379c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
380c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Orientation {
381c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short TOP_LEFT = 1;
382c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short TOP_RIGHT = 2;
383c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short BOTTOM_LEFT = 3;
384c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short BOTTOM_RIGHT = 4;
385c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LEFT_TOP = 5;
386c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RIGHT_TOP = 6;
387c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LEFT_BOTTOM = 7;
388c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RIGHT_BOTTOM = 8;
389c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
390c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
391c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
392c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_Y_CB_CR_POSITIONING}
393c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
394c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface YCbCrPositioning {
395c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CENTERED = 1;
396c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CO_SITED = 2;
397c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
398c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
399c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
400c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_COMPRESSION}
401c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
402c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Compression {
403c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short UNCOMPRESSION = 1;
404c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short JPEG = 6;
405c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
406c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
407c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
408c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_RESOLUTION_UNIT}
409c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
410c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface ResolutionUnit {
411c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short INCHES = 2;
412c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CENTIMETERS = 3;
413c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
414c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
415c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
416c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_PHOTOMETRIC_INTERPRETATION}
417c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
418c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface PhotometricInterpretation {
419c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RGB = 2;
420c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short YCBCR = 6;
421c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
422c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
423c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
424c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_PLANAR_CONFIGURATION}
425c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
426c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface PlanarConfiguration {
427c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CHUNKY = 1;
428c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short PLANAR = 2;
429c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
430c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
431c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
432c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_EXPOSURE_PROGRAM}
433c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
434c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface ExposureProgram {
435c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NOT_DEFINED = 0;
436c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MANUAL = 1;
437c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NORMAL_PROGRAM = 2;
438c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short APERTURE_PRIORITY = 3;
439c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SHUTTER_PRIORITY = 4;
440c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CREATIVE_PROGRAM = 5;
441c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short ACTION_PROGRAM = 6;
442c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short PROTRAIT_MODE = 7;
443c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LANDSCAPE_MODE = 8;
444c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
445c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
446c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
447c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_METERING_MODE}
448c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
449c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface MeteringMode {
450c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short UNKNOWN = 0;
451c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short AVERAGE = 1;
452c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CENTER_WEIGHTED_AVERAGE = 2;
453c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SPOT = 3;
454c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MULTISPOT = 4;
455c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short PATTERN = 5;
456c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short PARTAIL = 6;
457c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short OTHER = 255;
458c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
459c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
460c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
461c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_FLASH} As the definition in Jeita EXIF 2.2
462c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * standard, we can treat this constant as bitwise flag.
463c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <p>
464c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * e.g.
465c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <p>
466c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED |
467c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * MODE_AUTO_MODE
468c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
469c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Flash {
470c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // LSB
471c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DID_NOT_FIRED = 0;
472c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FIRED = 1;
473c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // 1st~2nd bits
474c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1;
475c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1;
476c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1;
477c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // 3rd~4th bits
478c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MODE_UNKNOWN = 0 << 3;
479c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3;
480c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3;
481c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MODE_AUTO_MODE = 3 << 3;
482c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // 5th bit
483c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FUNCTION_PRESENT = 0 << 5;
484c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FUNCTION_NO_FUNCTION = 1 << 5;
485c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // 6th bit
486c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
487c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
488c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
489c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
490c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
491c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_COLOR_SPACE}
492c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
493c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface ColorSpace {
494c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SRGB = 1;
495c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short UNCALIBRATED = (short) 0xFFFF;
496c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
497c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
498c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
499c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_EXPOSURE_MODE}
500c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
501c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface ExposureMode {
502c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short AUTO_EXPOSURE = 0;
503c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MANUAL_EXPOSURE = 1;
504c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short AUTO_BRACKET = 2;
505c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
506c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
507c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
508c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_WHITE_BALANCE}
509c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
510c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface WhiteBalance {
511c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short AUTO = 0;
512c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MANUAL = 1;
513c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
514c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
515c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
516c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SCENE_CAPTURE_TYPE}
517c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
518c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface SceneCapture {
519c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short STANDARD = 0;
520c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LANDSCAPE = 1;
521c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short PROTRAIT = 2;
522c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NIGHT_SCENE = 3;
523c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
524c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
525c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
526c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_COMPONENTS_CONFIGURATION}
527c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
528c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface ComponentsConfiguration {
529c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NOT_EXIST = 0;
530c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short Y = 1;
531c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CB = 2;
532c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CR = 3;
533c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short R = 4;
534c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short G = 5;
535c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short B = 6;
536c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
537c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
538c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
539c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_LIGHT_SOURCE}
540c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
541c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface LightSource {
542c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short UNKNOWN = 0;
543c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DAYLIGHT = 1;
544c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FLUORESCENT = 2;
545c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short TUNGSTEN = 3;
546c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FLASH = 4;
547c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short FINE_WEATHER = 9;
548c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CLOUDY_WEATHER = 10;
549c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SHADE = 11;
550c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DAYLIGHT_FLUORESCENT = 12;
551c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DAY_WHITE_FLUORESCENT = 13;
552c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short COOL_WHITE_FLUORESCENT = 14;
553c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short WHITE_FLUORESCENT = 15;
554c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short STANDARD_LIGHT_A = 17;
555c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short STANDARD_LIGHT_B = 18;
556c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short STANDARD_LIGHT_C = 19;
557c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short D55 = 20;
558c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short D65 = 21;
559c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short D75 = 22;
560c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short D50 = 23;
561c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short ISO_STUDIO_TUNGSTEN = 24;
562c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short OTHER = 255;
563c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
564c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
565c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
566c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SENSING_METHOD}
567c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
568c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface SensingMethod {
569c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NOT_DEFINED = 1;
570c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short ONE_CHIP_COLOR = 2;
571c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short TWO_CHIP_COLOR = 3;
572c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short THREE_CHIP_COLOR = 4;
573c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short COLOR_SEQUENTIAL_AREA = 5;
574c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short TRILINEAR = 7;
575c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short COLOR_SEQUENTIAL_LINEAR = 8;
576c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
577c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
578c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
579c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_FILE_SOURCE}
580c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
581c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface FileSource {
582c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DSC = 3;
583c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
584c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
585c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
586c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SCENE_TYPE}
587c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
588c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface SceneType {
589c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DIRECT_PHOTOGRAPHED = 1;
590c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
591c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
592c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
593c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GAIN_CONTROL}
594c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
595c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GainControl {
596c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NONE = 0;
597c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LOW_UP = 1;
598c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short HIGH_UP = 2;
599c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LOW_DOWN = 3;
600c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short HIGH_DOWN = 4;
601c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
602c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
603c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
604c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_CONTRAST}
605c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
606c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Contrast {
607c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NORMAL = 0;
608c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SOFT = 1;
609c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short HARD = 2;
610c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
611c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
612c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
613c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SATURATION}
614c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
615c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Saturation {
616c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NORMAL = 0;
617c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short LOW = 1;
618c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short HIGH = 2;
619c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
620c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
621c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
622c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SHARPNESS}
623c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
624c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface Sharpness {
625c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short NORMAL = 0;
626c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SOFT = 1;
627c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short HARD = 2;
628c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
629c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
630c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
631c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_SUBJECT_DISTANCE}
632c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
633c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface SubjectDistance {
634c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short UNKNOWN = 0;
635c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short MACRO = 1;
636c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short CLOSE_VIEW = 2;
637c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DISTANT_VIEW = 3;
638c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
639c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
640c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
641c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_LATITUDE_REF},
642c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_GPS_DEST_LATITUDE_REF}
643c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
644c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsLatitudeRef {
645c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String NORTH = "N";
646c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String SOUTH = "S";
647c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
648c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
649c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
650c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_LONGITUDE_REF},
651c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_GPS_DEST_LONGITUDE_REF}
652c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
653c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsLongitudeRef {
654c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String EAST = "E";
655c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String WEST = "W";
656c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
657c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
658c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
659c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_ALTITUDE_REF}
660c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
661c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsAltitudeRef {
662c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SEA_LEVEL = 0;
663c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short SEA_LEVEL_NEGATIVE = 1;
664c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
665c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
666c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
667c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_STATUS}
668c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
669c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsStatus {
670c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String IN_PROGRESS = "A";
671c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String INTEROPERABILITY = "V";
672c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
673c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
674c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
675c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_MEASURE_MODE}
676c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
677c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsMeasureMode {
678c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String MODE_2_DIMENSIONAL = "2";
679c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String MODE_3_DIMENSIONAL = "3";
680c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
681c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
682c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
683c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_SPEED_REF},
684c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_GPS_DEST_DISTANCE_REF}
685c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
686c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsSpeedRef {
687c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String KILOMETERS = "K";
688c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String MILES = "M";
689c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String KNOTS = "N";
690c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
691c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
692c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
693c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_TRACK_REF},
694c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_GPS_IMG_DIRECTION_REF}, {@link TAG_GPS_DEST_BEARING_REF}
695c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
696c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsTrackRef {
697c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String TRUE_DIRECTION = "T";
698c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final String MAGNETIC_DIRECTION = "M";
699c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
700c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
701c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
702c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Constants for {@link TAG_GPS_DIFFERENTIAL}
703c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
704c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static interface GpsDifferential {
705c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
706c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
707c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
708c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
709c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private static final String NULL_ARGUMENT_STRING = "Argument is null";
710c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private ExifData mData = new ExifData(DEFAULT_BYTE_ORDER);
711c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN;
712c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
713c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifInterface() {
714c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mGPSDateStampFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
715c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
716c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
717c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
718c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Reads the exif tags from a byte array, clearing this ExifInterface
719c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * object's existing exif tags.
720c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
721c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
722c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
723c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
724c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void readExif(byte[] jpeg) throws IOException {
725c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        readExif(new ByteArrayInputStream(jpeg));
726c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
727c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
728c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
729c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Reads the exif tags from an InputStream, clearing this ExifInterface
730c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * object's existing exif tags.
731c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
732c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param inStream an InputStream containing a jpeg compressed image.
733c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
734c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
735c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void readExif(InputStream inStream) throws IOException {
736c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (inStream == null) {
737c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
738c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
739c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifData d = null;
740c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
741c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            d = new ExifReader(this).read(inStream);
742c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (ExifInvalidFormatException e) {
743c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IOException("Invalid exif format : " + e);
744c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
745c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData = d;
746c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
747c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
748c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
749c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Reads the exif tags from a file, clearing this ExifInterface object's
750c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * existing exif tags.
751c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
752c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param inFileName a string representing the filepath to jpeg file.
753c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
754c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
755c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
756c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void readExif(String inFileName) throws FileNotFoundException, IOException {
757c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (inFileName == null) {
758c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
759c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
760c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        InputStream is = null;
761c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
762a16e7b50f3148f581439509279f242092e254309ztenghui            is = new BufferedInputStream(new FileInputStream(inFileName));
763c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            readExif(is);
764c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
765c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(is);
766c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
767c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
768c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        is.close();
769c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
770c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
771c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
772c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Sets the exif tags, clearing this ExifInterface object's existing exif
773c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * tags.
774c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
775c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tags a collection of exif tags to set.
776c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
777c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void setExif(Collection<ExifTag> tags) {
778c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        clearExif();
779c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTags(tags);
780c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
781c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
782c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
783c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Clears this ExifInterface object's existing exif tags.
784c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
785c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void clearExif() {
786c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData = new ExifData(DEFAULT_BYTE_ORDER);
787c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
788c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
789c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
790c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg image,
791c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * removing prior exif tags.
792c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
793c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
794c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutStream an OutputStream to which the jpeg image with added
795c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            exif tags will be written.
796c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
797c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
798c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(byte[] jpeg, OutputStream exifOutStream) throws IOException {
799c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (jpeg == null || exifOutStream == null) {
800c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
801c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
802c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
803c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        s.write(jpeg, 0, jpeg.length);
80443b9c0c3fce9cb877ca73cb34917fb2c7556c4d4Ruben Brunk        s.flush();
805c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
806c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
807c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
808c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg compressed
809c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * bitmap, removing prior exif tags.
810c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
811c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param bmap a bitmap to compress and write exif into.
812c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutStream the OutputStream to which the jpeg image with added
813c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            exif tags will be written.
814c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
815c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
816c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(Bitmap bmap, OutputStream exifOutStream) throws IOException {
817c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (bmap == null || exifOutStream == null) {
818c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
819c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
820c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
821c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
82243b9c0c3fce9cb877ca73cb34917fb2c7556c4d4Ruben Brunk        s.flush();
823c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
824c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
825c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
826c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg stream,
827c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * removing prior exif tags.
828c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
829c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpegStream an InputStream containing a jpeg compressed image.
830c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutStream an OutputStream to which the jpeg image with added
831c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            exif tags will be written.
832c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
833c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
834c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(InputStream jpegStream, OutputStream exifOutStream) throws IOException {
835c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (jpegStream == null || exifOutStream == null) {
836c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
837c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
838c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = getExifWriterStream(exifOutStream);
839c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        doExifStreamIO(jpegStream, s);
84043b9c0c3fce9cb877ca73cb34917fb2c7556c4d4Ruben Brunk        s.flush();
841c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
842c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
843c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
844c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg image,
845c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * removing prior exif tags.
846c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
847c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpeg a byte array containing a jpeg compressed image.
848c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
849c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            image with added exif tags will be written.
850c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
851c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
852c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
853c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(byte[] jpeg, String exifOutFileName) throws FileNotFoundException,
854c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IOException {
855c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (jpeg == null || exifOutFileName == null) {
856c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
857c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
858c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = null;
859c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
860c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s = getExifWriterStream(exifOutFileName);
861c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s.write(jpeg, 0, jpeg.length);
862c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s.flush();
863c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
864c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(s);
865c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
866c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
867c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        s.close();
868c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
869c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
870c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
871c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg compressed
872c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * bitmap, removing prior exif tags.
873c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
874c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param bmap a bitmap to compress and write exif into.
875c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
876c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            image with added exif tags will be written.
877c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
878c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
879c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
880c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(Bitmap bmap, String exifOutFileName) throws FileNotFoundException,
881c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IOException {
882c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (bmap == null || exifOutFileName == null) {
883c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
884c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
885c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = null;
886c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
887c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s = getExifWriterStream(exifOutFileName);
888c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
889c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s.flush();
890c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
891c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(s);
892c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
893c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
894c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        s.close();
895c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
896c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
897c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
898c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg stream,
899c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * removing prior exif tags.
900c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
901c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpegStream an InputStream containing a jpeg compressed image.
902c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
903c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            image with added exif tags will be written.
904c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
905c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
906c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
907c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(InputStream jpegStream, String exifOutFileName)
908c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throws FileNotFoundException, IOException {
909c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (jpegStream == null || exifOutFileName == null) {
910c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
911c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
912c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream s = null;
913c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
914c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s = getExifWriterStream(exifOutFileName);
915c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            doExifStreamIO(jpegStream, s);
916c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            s.flush();
917c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
918c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(s);
919c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
920c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
921c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        s.close();
922c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
923c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
924c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
925c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Writes the tags from this ExifInterface object into a jpeg file, removing
926c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * prior exif tags.
927c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
928c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param jpegFileName a String containing the filepath for a jpeg file.
929c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutFileName a String containing the filepath to which the jpeg
930c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            image with added exif tags will be written.
931c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
932c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
933c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
934c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void writeExif(String jpegFileName, String exifOutFileName)
935c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throws FileNotFoundException, IOException {
936c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (jpegFileName == null || exifOutFileName == null) {
937c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
938c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
939c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        InputStream is = null;
940c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
941c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            is = new FileInputStream(jpegFileName);
942c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            writeExif(is, exifOutFileName);
943c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
944c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(is);
945c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
946c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
947c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        is.close();
948c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
949c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
950c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
951c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Wraps an OutputStream object with an ExifOutputStream. Exif tags in this
952c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * ExifInterface object will be added to a jpeg image written to this
953c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * stream, removing prior exif tags. Other methods of this ExifInterface
954c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * object should not be called until the returned OutputStream has been
955c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * closed.
956c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
957c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param outStream an OutputStream to wrap.
958c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an OutputStream that wraps the outStream parameter, and adds exif
959c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         metadata. A jpeg image should be written to this stream.
960c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
961c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public OutputStream getExifWriterStream(OutputStream outStream) {
962c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (outStream == null) {
963c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
964c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
965c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifOutputStream eos = new ExifOutputStream(outStream, this);
966c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        eos.setExifData(mData);
967c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return eos;
968c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
969c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
970c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
971c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns an OutputStream object that writes to a file. Exif tags in this
972c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * ExifInterface object will be added to a jpeg image written to this
973c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * stream, removing prior exif tags. Other methods of this ExifInterface
974c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * object should not be called until the returned OutputStream has been
975c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * closed.
976c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
977c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param exifOutFileName an String containing a filepath for a jpeg file.
978c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an OutputStream that writes to the exifOutFileName file, and adds
979c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         exif metadata. A jpeg image should be written to this stream.
980c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
981c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
982c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public OutputStream getExifWriterStream(String exifOutFileName) throws FileNotFoundException {
983c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (exifOutFileName == null) {
984c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
985c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
986c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        OutputStream out = null;
987c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
988a16e7b50f3148f581439509279f242092e254309ztenghui            out = new FileOutputStream(exifOutFileName);
989c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (FileNotFoundException e) {
990c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(out);
991c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
992c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
993c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getExifWriterStream(out);
994c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
995c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
996c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
997c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Attempts to do an in-place rewrite the exif metadata in a file for the
998c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * given tags. If tags do not exist or do not have the same size as the
999c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * existing exif tags, this method will fail.
1000c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1001c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param filename a String containing a filepath for a jpeg file with exif
1002c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            tags to rewrite.
1003c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tags tags that will be written into the jpeg file over existing
1004c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            tags if possible.
1005c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if could not overwrite. If false, no
1006c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         changes are made to the file.
1007c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
1008c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
1009c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1010c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean rewriteExif(String filename, Collection<ExifTag> tags)
1011c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throws FileNotFoundException, IOException {
1012c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        RandomAccessFile file = null;
1013c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        InputStream is = null;
1014c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        boolean ret;
1015c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
1016c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            File temp = new File(filename);
101743b9c0c3fce9cb877ca73cb34917fb2c7556c4d4Ruben Brunk            is = new BufferedInputStream(new FileInputStream(temp));
1018c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1019c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Parse beginning of APP1 in exif to find size of exif header.
1020c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ExifParser parser = null;
1021c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            try {
1022c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                parser = ExifParser.parse(is, this);
1023c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            } catch (ExifInvalidFormatException e) {
1024c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                throw new IOException("Invalid exif format : ", e);
1025c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1026c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            long exifSize = parser.getOffsetToExifEndFromSOF();
1027c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1028c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Free up resources
1029c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            is.close();
1030c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            is = null;
1031c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1032c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Open file for memory mapping.
1033c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            file = new RandomAccessFile(temp, "rw");
1034c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            long fileLength = file.length();
1035c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (fileLength < exifSize) {
1036c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                throw new IOException("Filesize changed during operation");
1037c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1038c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1039c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Map only exif header into memory.
1040c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize);
1041c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1042c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Attempt to overwrite tag values without changing lengths (avoids
1043c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // file copy).
1044c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ret = rewriteExif(buf, tags);
1045c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (IOException e) {
1046c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(file);
1047c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw e;
1048c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } finally {
1049c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            closeSilently(is);
1050c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1051c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        file.close();
1052c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return ret;
1053c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1054c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1055c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1056c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Attempts to do an in-place rewrite the exif metadata in a ByteBuffer for
1057c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * the given tags. If tags do not exist or do not have the same size as the
1058c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * existing exif tags, this method will fail.
1059c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1060c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param buf a ByteBuffer containing a jpeg file with existing exif tags to
1061c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            rewrite.
1062c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tags tags that will be written into the jpeg ByteBuffer over
1063c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            existing tags if possible.
1064c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if could not overwrite. If false, no
1065c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         changes are made to the ByteBuffer.
1066c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
1067c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1068c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean rewriteExif(ByteBuffer buf, Collection<ExifTag> tags) throws IOException {
1069c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifModifier mod = null;
1070c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
1071c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            mod = new ExifModifier(buf, this);
1072c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            for (ExifTag t : tags) {
1073c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                mod.modifyTag(t);
1074c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1075c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return mod.commit();
1076c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (ExifInvalidFormatException e) {
1077c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IOException("Invalid exif format : " + e);
1078c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1079c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1080c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1081c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1082c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Attempts to do an in-place rewrite of the exif metadata. If this fails,
1083c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * fall back to overwriting file. This preserves tags that are not being
1084c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * rewritten.
1085c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1086c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param filename a String containing a filepath for a jpeg file.
1087c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tags tags that will be written into the jpeg file over existing
1088c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            tags if possible.
1089c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
1090c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
1091c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #rewriteExif
1092c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1093c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void forceRewriteExif(String filename, Collection<ExifTag> tags)
1094c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throws FileNotFoundException,
1095c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IOException {
1096c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // Attempt in-place write
1097c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (!rewriteExif(filename, tags)) {
1098c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Fall back to doing a copy
1099c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ExifData tempData = mData;
1100c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            mData = new ExifData(DEFAULT_BYTE_ORDER);
1101c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            FileInputStream is = null;
1102c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ByteArrayOutputStream bytes = null;
1103c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            try {
1104c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                is = new FileInputStream(filename);
1105c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                bytes = new ByteArrayOutputStream();
1106c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                doExifStreamIO(is, bytes);
1107c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                byte[] imageBytes = bytes.toByteArray();
1108c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                readExif(imageBytes);
1109c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                setTags(tags);
1110c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                writeExif(imageBytes, filename);
1111c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            } catch (IOException e) {
1112c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                closeSilently(is);
1113c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                throw e;
1114c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            } finally {
1115c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                is.close();
1116c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                // Prevent clobbering of mData
1117c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                mData = tempData;
1118c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1119c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1120c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1121c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1122c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1123c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Attempts to do an in-place rewrite of the exif metadata using the tags in
1124c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * this ExifInterface object. If this fails, fall back to overwriting file.
1125c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * This preserves tags that are not being rewritten.
1126c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1127c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param filename a String containing a filepath for a jpeg file.
1128c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws FileNotFoundException
1129c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @throws IOException
1130c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #rewriteExif
1131c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1132c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void forceRewriteExif(String filename) throws FileNotFoundException, IOException {
1133c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        forceRewriteExif(filename, getAllTags());
1134c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1135c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1136c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1137c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Get the exif tags in this ExifInterface object or null if none exist.
1138c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1139c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return a List of {@link ExifTag}s.
1140c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1141c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public List<ExifTag> getAllTags() {
1142c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getAllTags();
1143c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1144c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1145c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1146c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns a list of ExifTags that share a TID (which can be obtained by
1147c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * calling {@link #getTrueTagKey} on a defined tag constant) or null if none
1148c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * exist.
1149c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1150c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a TID as defined in the exif standard (or with
1151c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            {@link #defineTag}).
1152c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return a List of {@link ExifTag}s.
1153c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1154c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public List<ExifTag> getTagsForTagId(short tagId) {
1155c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getAllTagsForTagId(tagId);
1156c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1157c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1158c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1159c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns a list of ExifTags that share an IFD (which can be obtained by
1160c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * calling {@link #getTrueIFD} on a defined tag constant) or null if none
1161c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * exist.
1162c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1163c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param ifdId an IFD as defined in the exif standard (or with
1164c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            {@link #defineTag}).
1165c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return a List of {@link ExifTag}s.
1166c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1167c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public List<ExifTag> getTagsForIfdId(int ifdId) {
1168c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getAllTagsForIfd(ifdId);
1169c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1170c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1171c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1172c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets an ExifTag for an IFD other than the tag's default.
1173c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1174c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTag
1175c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1176c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifTag getTag(int tagId, int ifdId) {
1177c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (!ExifTag.isValidIfd(ifdId)) {
1178c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1179c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1180c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getTag(getTrueTagKey(tagId), ifdId);
1181c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1182c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1183c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1184c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the ExifTag in that tag's default IFD for a defined tag constant
1185c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * or null if none exists.
1186c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1187c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1188c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an {@link ExifTag} or null if none exists.
1189c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1190c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifTag getTag(int tagId) {
1191c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1192c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTag(tagId, ifdId);
1193c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1194c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1195c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1196c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets a tag value for an IFD other than the tag's default.
1197c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1198c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1199c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1200c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Object getTagValue(int tagId, int ifdId) {
1201c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1202c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return (t == null) ? null : t.getValue();
1203c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1204c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1205c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1206c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the value of the ExifTag in that tag's default IFD for a defined
1207c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * tag constant or null if none exists or the value could not be cast into
1208c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * the return type.
1209c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1210c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1211c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the value of the ExifTag or null if none exists.
1212c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1213c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Object getTagValue(int tagId) {
1214c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1215c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagValue(tagId, ifdId);
1216c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1217c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1218c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /*
1219c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Getter methods that are similar to getTagValue. Null is returned if the
1220c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * tag value cannot be cast into the return type.
1221c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1222c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1223c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1224c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1225c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1226c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public String getTagStringValue(int tagId, int ifdId) {
1227c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1228c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1229c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1230c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1231c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getValueAsString();
1232c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1233c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1234c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1235c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1236c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1237c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public String getTagStringValue(int tagId) {
1238c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1239c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagStringValue(tagId, ifdId);
1240c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1241c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1242c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1243c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1244c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1245c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Long getTagLongValue(int tagId, int ifdId) {
1246c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        long[] l = getTagLongValues(tagId, ifdId);
1247c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (l == null || l.length <= 0) {
1248c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1249c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1250c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return new Long(l[0]);
1251c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1252c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1253c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1254c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1255c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1256c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Long getTagLongValue(int tagId) {
1257c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1258c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagLongValue(tagId, ifdId);
1259c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1260c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1261c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1262c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1263c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1264c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Integer getTagIntValue(int tagId, int ifdId) {
1265c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] l = getTagIntValues(tagId, ifdId);
1266c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (l == null || l.length <= 0) {
1267c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1268c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1269c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return new Integer(l[0]);
1270c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1271c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1272c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1273c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1274c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1275c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Integer getTagIntValue(int tagId) {
1276c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1277c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagIntValue(tagId, ifdId);
1278c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1279c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1280c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1281c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1282c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1283c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Byte getTagByteValue(int tagId, int ifdId) {
1284c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        byte[] l = getTagByteValues(tagId, ifdId);
1285c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (l == null || l.length <= 0) {
1286c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1287c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1288c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return new Byte(l[0]);
1289c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1290c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1291c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1292c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1293c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1294c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Byte getTagByteValue(int tagId) {
1295c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1296c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagByteValue(tagId, ifdId);
1297c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1298c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1299c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1300c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1301c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1302c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Rational getTagRationalValue(int tagId, int ifdId) {
1303c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        Rational[] l = getTagRationalValues(tagId, ifdId);
1304c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (l == null || l.length == 0) {
1305c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1306c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1307c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return new Rational(l[0]);
1308c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1309c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1310c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1311c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1312c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1313c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Rational getTagRationalValue(int tagId) {
1314c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1315c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagRationalValue(tagId, ifdId);
1316c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1317c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1318c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1319c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1320c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1321c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public long[] getTagLongValues(int tagId, int ifdId) {
1322c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1323c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1324c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1325c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1326c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getValueAsLongs();
1327c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1328c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1329c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1330c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1331c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1332c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public long[] getTagLongValues(int tagId) {
1333c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1334c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagLongValues(tagId, ifdId);
1335c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1336c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1337c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1338c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1339c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1340c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int[] getTagIntValues(int tagId, int ifdId) {
1341c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1342c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1343c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1344c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1345c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getValueAsInts();
1346c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1347c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1348c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1349c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1350c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1351c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int[] getTagIntValues(int tagId) {
1352c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1353c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagIntValues(tagId, ifdId);
1354c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1355c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1356c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1357c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1358c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1359c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public byte[] getTagByteValues(int tagId, int ifdId) {
1360c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1361c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1362c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1363c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1364c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getValueAsBytes();
1365c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1366c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1367c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1368c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1369c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1370c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public byte[] getTagByteValues(int tagId) {
1371c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1372c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagByteValues(tagId, ifdId);
1373c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1374c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1375c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1376c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1377c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1378c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Rational[] getTagRationalValues(int tagId, int ifdId) {
1379c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1380c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1381c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1382c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1383c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getValueAsRationals();
1384c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1385c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1386c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1387c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #getTagValue
1388c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1389c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Rational[] getTagRationalValues(int tagId) {
1390c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1391c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagRationalValues(tagId, ifdId);
1392c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1393c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1394c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1395c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Checks whether a tag has a defined number of elements.
1396c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1397c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1398c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if the tag has a defined number of elements.
1399c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1400c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean isTagCountDefined(int tagId) {
1401c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1402c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // No value in info can be zero, as all tags have a non-zero type
1403c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == 0) {
1404c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
1405c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1406c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getComponentCountFromInfo(info) != ExifTag.SIZE_UNDEFINED;
1407c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1408c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1409c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1410c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the defined number of elements for a tag.
1411c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1412c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1413c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the number of elements or {@link ExifTag#SIZE_UNDEFINED} if the
1414c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         tag or the number of elements is not defined.
1415c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1416c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int getDefinedTagCount(int tagId) {
1417c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1418c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == 0) {
1419c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return ExifTag.SIZE_UNDEFINED;
1420c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1421c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getComponentCountFromInfo(info);
1422c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1423c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1424c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1425c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the number of elements for an ExifTag in a given IFD.
1426c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1427c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1428c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param ifdId the IFD containing the ExifTag to check.
1429c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the number of elements in the ExifTag, if the tag's size is
1430c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         undefined this will return the actual number of elements that is
1431c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         in the ExifTag's value.
1432c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1433c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int getActualTagCount(int tagId, int ifdId) {
1434c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1435c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1436c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return 0;
1437c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1438c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.getComponentCount();
1439c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1440c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1441c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1442c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the default IFD for a tag.
1443c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1444c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1445c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the default IFD for a tag definition or {@link #IFD_NULL} if no
1446c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         definition exists.
1447c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1448c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int getDefinedTagDefaultIfd(int tagId) {
1449c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1450c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == DEFINITION_NULL) {
1451c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return IFD_NULL;
1452c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1453c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTrueIfd(tagId);
1454c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1455c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1456c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1457c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the defined type for a tag.
1458c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1459c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1460c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the type.
1461c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see ExifTag#getDataType()
1462c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1463c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public short getDefinedTagType(int tagId) {
1464c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1465c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == 0) {
1466c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return -1;
1467c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1468c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTypeFromInfo(info);
1469c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1470c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1471c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1472c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns true if tag TID is one of the following: {@link TAG_EXIF_IFD},
1473c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_GPS_IFD}, {@link TAG_JPEG_INTERCHANGE_FORMAT},
1474c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link TAG_STRIP_OFFSETS}, {@link TAG_INTEROPERABILITY_IFD}
1475c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * <p>
1476c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Note: defining tags with these TID's is disallowed.
1477c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1478c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tag a tag's TID (can be obtained from a defined tag constant with
1479c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            {@link #getTrueTagKey}).
1480c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if the TID is that of an offset tag.
1481c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1482c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static boolean isOffsetTag(short tag) {
1483c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return sOffsetTags.contains(tag);
1484c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1485c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1486c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1487c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates a tag for a defined tag constant in a given IFD if that IFD is
1488c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * allowed for the tag.  This method will fail anytime the appropriate
1489c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link ExifTag#setValue} for this tag's datatype would fail.
1490c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1491c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1492c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param ifdId the IFD that the tag should be in.
1493c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param val the value of the tag to set.
1494c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an ExifTag object or null if one could not be constructed.
1495c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #buildTag
1496c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1497c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifTag buildTag(int tagId, int ifdId, Object val) {
1498c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1499c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == 0 || val == null) {
1500c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1501c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1502c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        short type = getTypeFromInfo(info);
1503c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int definedCount = getComponentCountFromInfo(info);
1504c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
1505c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (!ExifInterface.isIfdAllowed(info, ifdId)) {
1506c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1507c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1508c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
1509c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (!t.setValue(val)) {
1510c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1511c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1512c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t;
1513c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1514c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1515c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1516c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates a tag for a defined tag constant in the tag's default IFD.
1517c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1518c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1519c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param val the tag's value.
1520c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an ExifTag object.
1521c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1522c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifTag buildTag(int tagId, Object val) {
1523c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getTrueIfd(tagId);
1524c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return buildTag(tagId, ifdId, val);
1525c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1526c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1527c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected ExifTag buildUninitializedTag(int tagId) {
1528c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int info = getTagInfo().get(tagId);
1529c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (info == 0) {
1530c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1531c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1532c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        short type = getTypeFromInfo(info);
1533c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int definedCount = getComponentCountFromInfo(info);
1534c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED);
1535c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getTrueIfd(tagId);
1536c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount);
1537c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t;
1538c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1539c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1540c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1541c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Sets the value of an ExifTag if it exists in the given IFD. The value
1542c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * must be the correct type and length for that ExifTag.
1543c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1544c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1545c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param ifdId the IFD that the ExifTag is in.
1546c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param val the value to set.
1547c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if the ExifTag doesn't exist or the value
1548c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         is the wrong type/length.
1549c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #setTagValue
1550c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1551c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean setTagValue(int tagId, int ifdId, Object val) {
1552c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = getTag(tagId, ifdId);
1553c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
1554c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
1555c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1556c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return t.setValue(val);
1557c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1558c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1559c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1560c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Sets the value of an ExifTag if it exists it's default IFD. The value
1561c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * must be the correct type and length for that ExifTag.
1562c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1563c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1564c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param val the value to set.
1565c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if the ExifTag doesn't exist or the value
1566c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         is the wrong type/length.
1567c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1568c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean setTagValue(int tagId, Object val) {
1569c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1570c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return setTagValue(tagId, ifdId, val);
1571c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1572c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1573c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1574c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Puts an ExifTag into this ExifInterface object's tags, removing a
1575c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * previous ExifTag with the same TID and IFD. The IFD it is put into will
1576c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * be the one the tag was created with in {@link #buildTag}.
1577c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1578c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tag an ExifTag to put into this ExifInterface's tags.
1579c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the previous ExifTag with the same TID and IFD or null if none
1580c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         exists.
1581c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1582c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public ExifTag setTag(ExifTag tag) {
1583c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.addTag(tag);
1584c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1585c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1586c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1587c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Puts a collection of ExifTags into this ExifInterface objects's tags. Any
1588c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * previous ExifTags with the same TID and IFDs will be removed.
1589c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1590c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tags a Collection of ExifTags.
1591c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #setTag
1592c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1593c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void setTags(Collection<ExifTag> tags) {
1594c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (ExifTag t : tags) {
1595c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            setTag(t);
1596c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1597c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1598c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1599c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1600c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Removes the ExifTag for a tag constant from the given IFD.
1601c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1602c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1603c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param ifdId the IFD of the ExifTag to remove.
1604c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1605c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void deleteTag(int tagId, int ifdId) {
1606c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData.removeTag(getTrueTagKey(tagId), ifdId);
1607c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1608c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1609c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1610c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Removes the ExifTag for a tag constant from that tag's default IFD.
1611c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1612c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1613c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1614c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void deleteTag(int tagId) {
1615c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdId = getDefinedTagDefaultIfd(tagId);
1616c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        deleteTag(tagId, ifdId);
1617c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1618c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1619c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1620c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates a new tag definition in this ExifInterface object for a given TID
1621c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * and default IFD. Creating a definition with the same TID and default IFD
1622c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * as a previous definition will override it.
1623c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1624c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId the TID for the tag.
1625c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param defaultIfd the default IFD for the tag.
1626c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagType the type of the tag (see {@link ExifTag#getDataType()}).
1627c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param defaultComponentCount the number of elements of this tag's type in
1628c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            the tags value.
1629c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param allowedIfds the IFD's this tag is allowed to be put in.
1630c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the defined tag constant (e.g. {@link #TAG_IMAGE_WIDTH}) or
1631c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         {@link #TAG_NULL} if the definition could not be made.
1632c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1633c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public int setTagDefinition(short tagId, int defaultIfd, short tagType,
1634c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            short defaultComponentCount, int[] allowedIfds) {
1635c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (sBannedDefines.contains(tagId)) {
1636c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return TAG_NULL;
1637c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1638c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (ExifTag.isValidType(tagType) && ExifTag.isValidIfd(defaultIfd)) {
1639c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int tagDef = defineTag(defaultIfd, tagId);
1640c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (tagDef == TAG_NULL) {
1641c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return TAG_NULL;
1642c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1643c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int[] otherDefs = getTagDefinitionsForTagId(tagId);
1644c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            SparseIntArray infos = getTagInfo();
1645c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Make sure defaultIfd is in allowedIfds
1646c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            boolean defaultCheck = false;
1647c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            for (int i : allowedIfds) {
1648c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                if (defaultIfd == i) {
1649c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    defaultCheck = true;
1650c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                }
1651c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                if (!ExifTag.isValidIfd(i)) {
1652c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    return TAG_NULL;
1653c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                }
1654c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1655c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (!defaultCheck) {
1656c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return TAG_NULL;
1657c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1658c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1659c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int ifdFlags = getFlagsFromAllowedIfds(allowedIfds);
1660c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // Make sure no identical tags can exist in allowedIfds
1661c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (otherDefs != null) {
1662c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                for (int def : otherDefs) {
1663c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    int tagInfo = infos.get(def);
1664c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    int allowedFlags = getAllowedIfdFlagsFromInfo(tagInfo);
1665c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    if ((ifdFlags & allowedFlags) != 0) {
1666c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                        return TAG_NULL;
1667c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    }
1668c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                }
1669c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1670c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            getTagInfo().put(tagDef, ifdFlags << 24 | (tagType << 16) | defaultComponentCount);
1671c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return tagDef;
1672c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1673c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return TAG_NULL;
1674c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1675c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1676c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected int getTagDefinition(short tagId, int defaultIfd) {
1677c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagInfo().get(defineTag(defaultIfd, tagId));
1678c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1679c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1680c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected int[] getTagDefinitionsForTagId(short tagId) {
1681c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifds = IfdData.getIfds();
1682c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] defs = new int[ifds.length];
1683c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int counter = 0;
1684c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        SparseIntArray infos = getTagInfo();
1685c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i : ifds) {
1686c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int def = defineTag(i, tagId);
1687c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (infos.get(def) != DEFINITION_NULL) {
1688c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                defs[counter++] = def;
1689c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1690c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1691c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (counter == 0) {
1692c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1693c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1694c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1695c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return Arrays.copyOfRange(defs, 0, counter);
1696c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1697c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1698c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected int getTagDefinitionForTag(ExifTag tag) {
1699c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        short type = tag.getDataType();
1700c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int count = tag.getComponentCount();
1701c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifd = tag.getIfd();
1702c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return getTagDefinitionForTag(tag.getTagId(), type, count, ifd);
1703c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1704c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1705c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected int getTagDefinitionForTag(short tagId, short type, int count, int ifd) {
1706c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] defs = getTagDefinitionsForTagId(tagId);
1707c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (defs == null) {
1708c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return TAG_NULL;
1709c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1710c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        SparseIntArray infos = getTagInfo();
1711c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ret = TAG_NULL;
1712c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i : defs) {
1713c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int info = infos.get(i);
1714c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            short def_type = getTypeFromInfo(info);
1715c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int def_count = getComponentCountFromInfo(info);
1716c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int[] def_ifds = getAllowedIfdsFromInfo(info);
1717c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            boolean valid_ifd = false;
1718c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            for (int j : def_ifds) {
1719c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                if (j == ifd) {
1720c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    valid_ifd = true;
1721c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    break;
1722c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                }
1723c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1724c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (valid_ifd && type == def_type
1725c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    && (count == def_count || def_count == ExifTag.SIZE_UNDEFINED)) {
1726c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ret = i;
1727c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                break;
1728c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1729c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1730c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return ret;
1731c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1732c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1733c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1734c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Removes a tag definition for given defined tag constant.
1735c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1736c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}.
1737c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1738c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void removeTagDefinition(int tagId) {
1739c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        getTagInfo().delete(tagId);
1740c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1741c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1742c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1743c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Resets tag definitions to the default ones.
1744c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1745c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void resetTagDefinitions() {
1746c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo = null;
1747c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1748c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1749c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1750c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the thumbnail from IFD1 as a bitmap, or null if none exists.
1751c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1752c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the thumbnail as a bitmap.
1753c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1754c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public Bitmap getThumbnailBitmap() {
1755c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (mData.hasCompressedThumbnail()) {
1756c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            byte[] thumb = mData.getCompressedThumbnail();
1757c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return BitmapFactory.decodeByteArray(thumb, 0, thumb.length);
1758c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else if (mData.hasUncompressedStrip()) {
1759c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // TODO: implement uncompressed
1760c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1761c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return null;
1762c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1763c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1764c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1765c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the thumbnail from IFD1 as a byte array, or null if none exists.
1766c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * The bytes may either be an uncompressed strip as specified in the exif
1767c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * standard or a jpeg compressed image.
1768c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1769c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the thumbnail as a byte array.
1770c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1771c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public byte[] getThumbnailBytes() {
1772c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (mData.hasCompressedThumbnail()) {
1773c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return mData.getCompressedThumbnail();
1774c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else if (mData.hasUncompressedStrip()) {
1775c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            // TODO: implement this
1776c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1777c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return null;
1778c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1779c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1780c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1781c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the thumbnail if it is jpeg compressed, or null if none exists.
1782c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1783c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the thumbnail as a byte array.
1784c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1785c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public byte[] getThumbnail() {
1786c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getCompressedThumbnail();
1787c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1788c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1789c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1790c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Check if thumbnail is compressed.
1791c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1792c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if the thumbnail is compressed.
1793c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1794c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean isThumbnailCompressed() {
1795c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.hasCompressedThumbnail();
1796c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1797c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1798c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1799c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Check if thumbnail exists.
1800c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1801c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if a compressed thumbnail exists.
1802c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1803c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean hasThumbnail() {
1804c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // TODO: add back in uncompressed strip
1805c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.hasCompressedThumbnail();
1806c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1807c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1808c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // TODO: uncompressed thumbnail setters
1809c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1810c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1811c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Sets the thumbnail to be a jpeg compressed image. Clears any prior
1812c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * thumbnail.
1813c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1814c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param thumb a byte array containing a jpeg compressed image.
1815c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if the thumbnail was set.
1816c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1817c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean setCompressedThumbnail(byte[] thumb) {
1818c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData.clearThumbnailAndStrips();
1819c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData.setCompressedThumbnail(thumb);
1820c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return true;
1821c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1822c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1823c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1824c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Sets the thumbnail to be a jpeg compressed bitmap. Clears any prior
1825c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * thumbnail.
1826c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1827c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param thumb a bitmap to compress to a jpeg thumbnail.
1828c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if the thumbnail was set.
1829c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1830c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean setCompressedThumbnail(Bitmap thumb) {
1831c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ByteArrayOutputStream thumbnail = new ByteArrayOutputStream();
1832c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (!thumb.compress(Bitmap.CompressFormat.JPEG, 90, thumbnail)) {
1833c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
1834c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1835c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return setCompressedThumbnail(thumbnail.toByteArray());
1836c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1837c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1838c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1839c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Clears the compressed thumbnail if it exists.
1840c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1841c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public void removeCompressedThumbnail() {
1842c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mData.setCompressedThumbnail(null);
1843c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1844c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1845c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    // Convenience methods:
1846c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1847c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1848c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Decodes the user comment tag into string as specified in the EXIF
1849c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * standard. Returns null if decoding failed.
1850c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1851c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public String getUserComment() {
1852c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mData.getUserComment();
1853c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1854c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1855c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1856c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the Orientation ExifTag value for a given number of degrees.
1857c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1858c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param degrees the amount an image is rotated in degrees.
1859c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1860c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static short getOrientationValueForRotation(int degrees) {
1861c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        degrees %= 360;
1862c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (degrees < 0) {
1863c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            degrees += 360;
1864c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1865c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (degrees < 90) {
1866c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return Orientation.TOP_LEFT; // 0 degrees
1867c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else if (degrees < 180) {
1868c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return Orientation.RIGHT_TOP; // 90 degrees cw
1869c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else if (degrees < 270) {
1870c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return Orientation.BOTTOM_LEFT; // 180 degrees
1871c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else {
1872c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return Orientation.RIGHT_BOTTOM; // 270 degrees cw
1873c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1874c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1875c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1876c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1877c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Returns the rotation degrees corresponding to an ExifTag Orientation
1878c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * value.
1879c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1880c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param orientation the ExifTag Orientation value.
1881c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1882c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static int getRotationForOrientationValue(short orientation) {
1883c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        switch (orientation) {
1884c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            case Orientation.TOP_LEFT:
1885c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return 0;
1886c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            case Orientation.RIGHT_TOP:
1887c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return 90;
1888c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            case Orientation.BOTTOM_LEFT:
1889c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return 180;
1890c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            case Orientation.RIGHT_BOTTOM:
1891c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return 270;
1892c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            default:
1893c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return 0;
1894c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1895c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1896c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1897c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1898c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the double representation of the GPS latitude or longitude
1899c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * coordinate.
1900c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1901c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param coordinate an array of 3 Rationals representing the degrees,
1902c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            minutes, and seconds of the GPS location as defined in the
1903c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            exif specification.
1904c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param reference a GPS reference reperesented by a String containing "N",
1905c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *            "S", "E", or "W".
1906c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return the GPS coordinate represented as degrees + minutes/60 +
1907c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         seconds/3600
1908c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1909c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public static double convertLatOrLongToDouble(Rational[] coordinate, String reference) {
1910c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        try {
1911c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            double degrees = coordinate[0].toDouble();
1912c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            double minutes = coordinate[1].toDouble();
1913c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            double seconds = coordinate[2].toDouble();
1914c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            double result = degrees + minutes / 60.0 + seconds / 3600.0;
1915c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if ((reference.equals("S") || reference.equals("W"))) {
1916c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return -result;
1917c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1918c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return result;
1919c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } catch (ArrayIndexOutOfBoundsException e) {
1920c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            throw new IllegalArgumentException();
1921c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1922c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1923c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1924c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1925c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Gets the GPS latitude and longitude as a pair of doubles from this
1926c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * ExifInterface object's tags, or null if the necessary tags do not exist.
1927c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1928c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return an array of 2 doubles containing the latitude, and longitude
1929c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *         respectively.
1930c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @see #convertLatOrLongToDouble
1931c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1932c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public double[] getLatLongAsDoubles() {
1933c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        Rational[] latitude = getTagRationalValues(TAG_GPS_LATITUDE);
1934c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        String latitudeRef = getTagStringValue(TAG_GPS_LATITUDE_REF);
1935c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        Rational[] longitude = getTagRationalValues(TAG_GPS_LONGITUDE);
1936c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        String longitudeRef = getTagStringValue(TAG_GPS_LONGITUDE_REF);
1937c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (latitude == null || longitude == null || latitudeRef == null || longitudeRef == null
1938c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                || latitude.length < 3 || longitude.length < 3) {
1939c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
1940c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1941c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        double[] latLon = new double[2];
1942c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        latLon[0] = convertLatOrLongToDouble(latitude, latitudeRef);
1943c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        latLon[1] = convertLatOrLongToDouble(longitude, longitudeRef);
1944c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return latLon;
1945c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1946c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1947c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
1948c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private static final String DATETIME_FORMAT_STR = "yyyy:MM:dd kk:mm:ss";
1949c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private final DateFormat mDateTimeStampFormat = new SimpleDateFormat(DATETIME_FORMAT_STR);
1950c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private final DateFormat mGPSDateStampFormat = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
1951c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private final Calendar mGPSTimeStampCalendar = Calendar
1952c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            .getInstance(TimeZone.getTimeZone("UTC"));
1953c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1954c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1955c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates, formats, and sets the DateTimeStamp tag for one of:
1956c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link #TAG_DATE_TIME}, {@link #TAG_DATE_TIME_DIGITIZED},
1957c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * {@link #TAG_DATE_TIME_ORIGINAL}.
1958c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1959c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param tagId one of the DateTimeStamp tags.
1960c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param timestamp a timestamp to format.
1961c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param timezone a TimeZone object.
1962c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if the tag could not be set.
1963c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1964c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean addDateTimeStampTag(int tagId, long timestamp, TimeZone timezone) {
1965c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (tagId == TAG_DATE_TIME || tagId == TAG_DATE_TIME_DIGITIZED
1966c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                || tagId == TAG_DATE_TIME_ORIGINAL) {
1967c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            mDateTimeStampFormat.setTimeZone(timezone);
1968c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ExifTag t = buildTag(tagId, mDateTimeStampFormat.format(timestamp));
1969c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (t == null) {
1970c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return false;
1971c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
1972c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            setTag(t);
1973c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        } else {
1974c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
1975c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1976c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return true;
1977c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
1978c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
1979c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
1980c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates and sets all to the GPS tags for a give latitude and longitude.
1981c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
1982c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param latitude a GPS latitude coordinate.
1983c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param longitude a GPS longitude coordinate.
1984c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if they could not be created or set.
1985c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
1986c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean addGpsTags(double latitude, double longitude) {
1987c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag latTag = buildTag(TAG_GPS_LATITUDE, toExifLatLong(latitude));
1988c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag longTag = buildTag(TAG_GPS_LONGITUDE, toExifLatLong(longitude));
1989c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag latRefTag = buildTag(TAG_GPS_LATITUDE_REF,
1990c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                latitude >= 0 ? ExifInterface.GpsLatitudeRef.NORTH
1991c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                        : ExifInterface.GpsLatitudeRef.SOUTH);
1992c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag longRefTag = buildTag(TAG_GPS_LONGITUDE_REF,
1993c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                longitude >= 0 ? ExifInterface.GpsLongitudeRef.EAST
1994c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                        : ExifInterface.GpsLongitudeRef.WEST);
1995c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (latTag == null || longTag == null || latRefTag == null || longRefTag == null) {
1996c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
1997c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
1998c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(latTag);
1999c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(longTag);
2000c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(latRefTag);
2001c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(longRefTag);
2002c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return true;
2003c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2004c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2005c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    /**
2006c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * Creates and sets the GPS timestamp tag.
2007c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     *
2008c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @param timestamp a GPS timestamp.
2009c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     * @return true if success, false if could not be created or set.
2010c274ded801f745d6318186958107622e7a4fef33Ruben Brunk     */
2011c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    public boolean addGpsDateTimeStampTag(long timestamp) {
2012c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ExifTag t = buildTag(TAG_GPS_DATE_STAMP, mGPSDateStampFormat.format(timestamp));
2013c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
2014c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
2015c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2016c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(t);
2017c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mGPSTimeStampCalendar.setTimeInMillis(timestamp);
2018c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        t = buildTag(TAG_GPS_TIME_STAMP, new Rational[] {
2019c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.HOUR_OF_DAY), 1),
2020c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.MINUTE), 1),
2021c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                new Rational(mGPSTimeStampCalendar.get(Calendar.SECOND), 1)
2022c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        });
2023c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (t == null) {
2024c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return false;
2025c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2026c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        setTag(t);
2027c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return true;
2028c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2029c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2030c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private static Rational[] toExifLatLong(double value) {
2031c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // convert to the format dd/1 mm/1 ssss/100
2032c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        value = Math.abs(value);
2033c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int degrees = (int) value;
2034c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        value = (value - degrees) * 60;
2035c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int minutes = (int) value;
2036c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        value = (value - minutes) * 6000;
2037c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int seconds = (int) value;
2038c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return new Rational[] {
2039c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                new Rational(degrees, 1), new Rational(minutes, 1), new Rational(seconds, 100)
2040c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2041c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2042c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2043c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private void doExifStreamIO(InputStream is, OutputStream os) throws IOException {
2044c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        byte[] buf = new byte[1024];
2045c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ret = is.read(buf, 0, 1024);
2046c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        while (ret != -1) {
2047c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            os.write(buf, 0, ret);
2048c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ret = is.read(buf, 0, 1024);
2049c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2050c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2051c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2052c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static void closeSilently(Closeable c) {
2053c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (c != null) {
2054c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            try {
2055c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                c.close();
2056c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            } catch (Throwable e) {
2057c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                // ignored
2058c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
2059c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2060c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2061c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2062c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private SparseIntArray mTagInfo = null;
2063c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2064c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected SparseIntArray getTagInfo() {
2065c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (mTagInfo == null) {
2066c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            mTagInfo = new SparseIntArray();
2067c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            initTagInfo();
2068c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2069c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return mTagInfo;
2070c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2071c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2072c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    private void initTagInfo() {
2073c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        /**
2074c274ded801f745d6318186958107622e7a4fef33Ruben Brunk         * We put tag information in a 4-bytes integer. The first byte a bitmask
2075c274ded801f745d6318186958107622e7a4fef33Ruben Brunk         * representing the allowed IFDs of the tag, the second byte is the data
2076c274ded801f745d6318186958107622e7a4fef33Ruben Brunk         * type, and the last two byte are a short value indicating the default
2077c274ded801f745d6318186958107622e7a4fef33Ruben Brunk         * component count of this tag.
2078c274ded801f745d6318186958107622e7a4fef33Ruben Brunk         */
2079c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // IFD0 tags
2080c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifdAllowedIfds = {
2081c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_1
2082c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2083c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdFlags = getFlagsFromAllowedIfds(ifdAllowedIfds) << 24;
2084c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_MAKE,
2085c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2086c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_WIDTH,
2087c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2088c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_LENGTH,
2089c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2090c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_BITS_PER_SAMPLE,
2091c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3);
2092c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_COMPRESSION,
2093c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2094c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_PHOTOMETRIC_INTERPRETATION,
2095c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2096c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_ORIENTATION, ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16
2097c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                | 1);
2098c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SAMPLES_PER_PIXEL,
2099c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2100c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_PLANAR_CONFIGURATION,
2101c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2102c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_SUB_SAMPLING,
2103c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
2104c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_POSITIONING,
2105c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2106c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_X_RESOLUTION,
2107c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2108c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_Y_RESOLUTION,
2109c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2110c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_RESOLUTION_UNIT,
2111c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2112c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_STRIP_OFFSETS,
2113c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
2114c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_ROWS_PER_STRIP,
2115c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2116c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_STRIP_BYTE_COUNTS,
2117c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED);
2118c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_TRANSFER_FUNCTION,
2119c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3 * 256);
2120c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_WHITE_POINT,
2121c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 2);
2122c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_PRIMARY_CHROMATICITIES,
2123c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
2124c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_Y_CB_CR_COEFFICIENTS,
2125c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
2126c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_REFERENCE_BLACK_WHITE,
2127c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6);
2128c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME,
2129c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | 20);
2130c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_DESCRIPTION,
2131c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2132c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_MAKE,
2133c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2134c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_MODEL,
2135c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2136c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SOFTWARE,
2137c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2138c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_ARTIST,
2139c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2140c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_COPYRIGHT,
2141c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2142c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXIF_IFD,
2143c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2144c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IFD,
2145c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2146c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // IFD1 tags
2147c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifd1AllowedIfds = {
2148c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IfdId.TYPE_IFD_1
2149c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2150c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdFlags1 = getFlagsFromAllowedIfds(ifd1AllowedIfds) << 24;
2151c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT,
2152c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2153c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
2154c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2155c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // Exif tags
2156c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] exifAllowedIfds = {
2157c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IfdId.TYPE_IFD_EXIF
2158c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2159c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int exifFlags = getFlagsFromAllowedIfds(exifAllowedIfds) << 24;
2160c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXIF_VERSION,
2161c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
2162c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FLASHPIX_VERSION,
2163c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
2164c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_COLOR_SPACE,
2165c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2166c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_COMPONENTS_CONFIGURATION,
2167c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4);
2168c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_COMPRESSED_BITS_PER_PIXEL,
2169c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2170c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_PIXEL_X_DIMENSION,
2171c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2172c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_PIXEL_Y_DIMENSION,
2173c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2174c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_MAKER_NOTE,
2175c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2176c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_USER_COMMENT,
2177c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2178c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_RELATED_SOUND_FILE,
2179c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 13);
2180c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME_ORIGINAL,
2181c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
2182c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_DATE_TIME_DIGITIZED,
2183c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 20);
2184c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME,
2185c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2186c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_ORIGINAL,
2187c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2188c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_DIGITIZED,
2189c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2190c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_IMAGE_UNIQUE_ID,
2191c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | 33);
2192c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_TIME,
2193c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2194c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_F_NUMBER,
2195c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2196c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_PROGRAM,
2197c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2198c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SPECTRAL_SENSITIVITY,
2199c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2200c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_ISO_SPEED_RATINGS,
2201c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
2202c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_OECF,
2203c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2204c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE,
2205c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
2206c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_APERTURE_VALUE,
2207c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2208c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_BRIGHTNESS_VALUE,
2209c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
2210c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_BIAS_VALUE,
2211c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1);
2212c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_MAX_APERTURE_VALUE,
2213c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2214c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE,
2215c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2216c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_METERING_MODE,
2217c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2218c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_LIGHT_SOURCE,
2219c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2220c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FLASH,
2221c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2222c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH,
2223c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2224c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_AREA,
2225c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED);
2226c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FLASH_ENERGY,
2227c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2228c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SPATIAL_FREQUENCY_RESPONSE,
2229c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2230c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION,
2231c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2232c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION,
2233c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2234c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT,
2235c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2236c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_LOCATION,
2237c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2);
2238c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_INDEX,
2239c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2240c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SENSING_METHOD,
2241c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2242c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FILE_SOURCE,
2243c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
2244c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SCENE_TYPE,
2245c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1);
2246c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_CFA_PATTERN,
2247c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2248c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_CUSTOM_RENDERED,
2249c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2250c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_EXPOSURE_MODE,
2251c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2252c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_WHITE_BALANCE,
2253c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2254c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_DIGITAL_ZOOM_RATIO,
2255c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2256c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH_IN_35_MM_FILE,
2257c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2258c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SCENE_CAPTURE_TYPE,
2259c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2260c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GAIN_CONTROL,
2261c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2262c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_CONTRAST,
2263c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2264c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SATURATION,
2265c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2266c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SHARPNESS,
2267c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2268c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION,
2269c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2270c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE_RANGE,
2271c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1);
2272c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_INTEROPERABILITY_IFD, exifFlags
2273c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1);
2274c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // GPS tag
2275c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] gpsAllowedIfds = {
2276c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IfdId.TYPE_IFD_GPS
2277c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2278c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int gpsFlags = getFlagsFromAllowedIfds(gpsAllowedIfds) << 24;
2279c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_VERSION_ID,
2280c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 4);
2281c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE_REF,
2282c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2283c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE_REF,
2284c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2285c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE,
2286c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
2287c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE,
2288c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3);
2289c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE_REF,
2290c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 1);
2291c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE,
2292c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2293c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TIME_STAMP,
2294c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3);
2295c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SATTELLITES,
2296c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2297c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_STATUS,
2298c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2299c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_MEASURE_MODE,
2300c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2301c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DOP,
2302c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2303c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SPEED_REF,
2304c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2305c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_SPEED,
2306c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2307c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TRACK_REF,
2308c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2309c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_TRACK,
2310c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2311c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
2312c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2313c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION,
2314c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2315c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_MAP_DATUM,
2316c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED);
2317c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
2318c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2319c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE,
2320c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2321c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING_REF,
2322c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2323c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING,
2324c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2325c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
2326c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 2);
2327c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE,
2328c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1);
2329c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_PROCESSING_METHOD,
2330c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2331c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_AREA_INFORMATION,
2332c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED);
2333c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DATE_STAMP,
2334c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_ASCII << 16 | 11);
2335c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(ExifInterface.TAG_GPS_DIFFERENTIAL,
2336c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                gpsFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 11);
2337c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        // Interoperability tag
2338c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] interopAllowedIfds = {
2339c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            IfdId.TYPE_IFD_INTEROPERABILITY
2340c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        };
2341c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int interopFlags = getFlagsFromAllowedIfds(interopAllowedIfds) << 24;
2342c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        mTagInfo.put(TAG_INTEROPERABILITY_INDEX, interopFlags | ExifTag.TYPE_ASCII << 16
2343c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                | ExifTag.SIZE_UNDEFINED);
2344c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2345c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2346c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static int getAllowedIfdFlagsFromInfo(int info) {
2347c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return info >>> 24;
2348c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2349c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2350c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static int[] getAllowedIfdsFromInfo(int info) {
2351c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
2352c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifds = IfdData.getIfds();
2353c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        ArrayList<Integer> l = new ArrayList<Integer>();
2354c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
2355c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            int flag = (ifdFlags >> i) & 1;
2356c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (flag == 1) {
2357c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                l.add(ifds[i]);
2358c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
2359c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2360c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (l.size() <= 0) {
2361c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return null;
2362c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2363c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ret = new int[l.size()];
2364c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int j = 0;
2365c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i : l) {
2366c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            ret[j++] = i;
2367c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2368c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return ret;
2369c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2370c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2371c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static boolean isIfdAllowed(int info, int ifd) {
2372c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifds = IfdData.getIfds();
2373c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int ifdFlags = getAllowedIfdFlagsFromInfo(info);
2374c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i = 0; i < ifds.length; i++) {
2375c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            if (ifd == ifds[i] && ((ifdFlags >> i) & 1) == 1) {
2376c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                return true;
2377c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
2378c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2379c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return false;
2380c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2381c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2382c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static int getFlagsFromAllowedIfds(int[] allowedIfds) {
2383c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        if (allowedIfds == null || allowedIfds.length == 0) {
2384c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            return 0;
2385c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2386c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int flags = 0;
2387c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        int[] ifds = IfdData.getIfds();
2388c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
2389c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            for (int j : allowedIfds) {
2390c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                if (ifds[i] == j) {
2391c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    flags |= 1 << i;
2392c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                    break;
2393c274ded801f745d6318186958107622e7a4fef33Ruben Brunk                }
2394c274ded801f745d6318186958107622e7a4fef33Ruben Brunk            }
2395c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        }
2396c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return flags;
2397c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2398c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2399c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static short getTypeFromInfo(int info) {
2400c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return (short) ((info >> 16) & 0x0ff);
2401c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2402c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2403c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    protected static int getComponentCountFromInfo(int info) {
2404c274ded801f745d6318186958107622e7a4fef33Ruben Brunk        return info & 0x0ffff;
2405c274ded801f745d6318186958107622e7a4fef33Ruben Brunk    }
2406c274ded801f745d6318186958107622e7a4fef33Ruben Brunk
2407c274ded801f745d6318186958107622e7a4fef33Ruben Brunk}
2408