1e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor/*
2e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * Copyright (C) 2012 The Android Open Source Project
3e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor *
4e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * Licensed under the Apache License, Version 2.0 (the "License");
5e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * you may not use this file except in compliance with the License.
6e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * You may obtain a copy of the License at
7e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor *
8e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor *      http://www.apache.org/licenses/LICENSE-2.0
9e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor *
10e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * Unless required by applicable law or agreed to in writing, software
11e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * distributed under the License is distributed on an "AS IS" BASIS,
12e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * See the License for the specific language governing permissions and
14e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * limitations under the License.
15e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor */
16e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
17e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorpackage com.android.mms.exif;
18e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
19e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorimport java.nio.charset.Charset;
20e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorimport java.text.SimpleDateFormat;
21e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorimport java.util.Arrays;
22e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorimport java.util.Date;
23e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
24e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor/**
25e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * This class stores information of an EXIF tag. For more information about
26e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * defined EXIF tags, please read the Jeita EXIF 2.2 standard. Tags should be
27e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * instantiated using {@link ExifInterface#buildTag}.
28e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor *
29e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor * @see ExifInterface
30e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor */
31e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylorpublic class ExifTag {
32e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
33e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
34e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
35e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_UNSIGNED_BYTE = 1;
36e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
37e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit
38e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * ASCII code. The final byte is terminated with NULL.
39e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
40e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_ASCII = 2;
41e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
42e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
43e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
44e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_UNSIGNED_SHORT = 3;
45e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
46e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
47e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
48e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_UNSIGNED_LONG = 4;
49e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
50e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The RATIONAL type of EXIF standard. It consists of two LONGs. The first
51e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * one is the numerator and the second one expresses the denominator.
52e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
53e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_UNSIGNED_RATIONAL = 5;
54e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
55e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any
56e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * value depending on the field definition.
57e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
58e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_UNDEFINED = 7;
59e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
60e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
61e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * (2's complement notation).
62e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
63e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_LONG = 9;
64e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
65e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first
66e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * one is the numerator and the second one is the denominator.
67e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
68e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static final short TYPE_RATIONAL = 10;
69e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
70e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static Charset US_ASCII = Charset.forName("US-ASCII");
71e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final int TYPE_TO_SIZE_MAP[] = new int[11];
72e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final int UNSIGNED_SHORT_MAX = 65535;
73e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final long UNSIGNED_LONG_MAX = 4294967295L;
74e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final long LONG_MAX = Integer.MAX_VALUE;
75e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final long LONG_MIN = Integer.MIN_VALUE;
76e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
77e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    static {
78e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1;
79e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1;
80e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2;
81e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4;
82e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8;
83e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1;
84e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_LONG] = 4;
85e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8;
86e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
87e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
88e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    static final int SIZE_UNDEFINED = 0;
89e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
90e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // Exif TagId
91e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private final short mTagId;
92e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // Exif Tag Type
93e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private final short mDataType;
94e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // If tag has defined count
95e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean mHasDefinedDefaultComponentCount;
96e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // Actual data count in tag (should be number of elements in value array)
97e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private int mComponentCountActual;
98e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // The ifd that this tag should be put in
99e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private int mIfd;
100e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // The value (array of elements of type Tag Type)
101e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private Object mValue;
102e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // Value offset in exif header.
103e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private int mOffset;
104e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
105e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
106e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
107e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
108e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Returns true if the given IFD is a valid IFD.
109e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
110e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static boolean isValidIfd(int ifdId) {
111e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return ifdId == IfdId.TYPE_IFD_0 || ifdId == IfdId.TYPE_IFD_1
112e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                || ifdId == IfdId.TYPE_IFD_EXIF || ifdId == IfdId.TYPE_IFD_INTEROPERABILITY
113e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                || ifdId == IfdId.TYPE_IFD_GPS;
114e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
115e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
116e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
117e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Returns true if a given type is a valid tag type.
118e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
119e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static boolean isValidType(short type) {
120e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return type == TYPE_UNSIGNED_BYTE || type == TYPE_ASCII ||
121e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                type == TYPE_UNSIGNED_SHORT || type == TYPE_UNSIGNED_LONG ||
122e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                type == TYPE_UNSIGNED_RATIONAL || type == TYPE_UNDEFINED ||
123e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                type == TYPE_LONG || type == TYPE_RATIONAL;
124e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
125e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
126e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // Use builtTag in ExifInterface instead of constructor.
127e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    ExifTag(short tagId, short type, int componentCount, int ifd,
128e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            boolean hasDefinedComponentCount) {
129e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mTagId = tagId;
130e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mDataType = type;
131e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = componentCount;
132e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mHasDefinedDefaultComponentCount = hasDefinedComponentCount;
133e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mIfd = ifd;
134e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = null;
135e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
136e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
137e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
138e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the element size of the given data type in bytes.
139e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
140e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_ASCII
141e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_LONG
142e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_RATIONAL
143e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNDEFINED
144e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_BYTE
145e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_LONG
146e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_RATIONAL
147e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_SHORT
148e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
149e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public static int getElementSize(short type) {
150e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return TYPE_TO_SIZE_MAP[type];
151e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
152e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
153e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
154e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Returns the ID of the IFD this tag belongs to.
155e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
156e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see IfdId#TYPE_IFD_0
157e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see IfdId#TYPE_IFD_1
158e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see IfdId#TYPE_IFD_EXIF
159e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see IfdId#TYPE_IFD_GPS
160e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see IfdId#TYPE_IFD_INTEROPERABILITY
161e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
162e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public int getIfd() {
163e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mIfd;
164e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
165e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
166e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void setIfd(int ifdId) {
167e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mIfd = ifdId;
168e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
169e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
170e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
171e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the TID of this tag.
172e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
173e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public short getTagId() {
174e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mTagId;
175e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
176e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
177e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
178e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the data type of this tag
179e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
180e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_ASCII
181e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_LONG
182e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_RATIONAL
183e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNDEFINED
184e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_BYTE
185e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_LONG
186e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_RATIONAL
187e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see #TYPE_UNSIGNED_SHORT
188e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
189e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public short getDataType() {
190e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mDataType;
191e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
192e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
193e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
194e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the total data size in bytes of the value of this tag.
195e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
196e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public int getDataSize() {
197e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return getComponentCount() * getElementSize(getDataType());
198e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
199e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
200e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
201e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the component count of this tag.
202e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
203e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
204e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    // TODO: fix integer overflows with this
205e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public int getComponentCount() {
206e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mComponentCountActual;
207e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
208e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
209e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
210e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets the component count of this tag. Call this function before
211e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * setValue() if the length of value does not match the component count.
212e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
213e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void forceSetComponentCount(int count) {
214e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = count;
215e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
216e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
217e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
218e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Returns true if this ExifTag contains value; otherwise, this tag will
219e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * contain an offset value that is determined when the tag is written.
220e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
221e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean hasValue() {
222e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mValue != null;
223e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
224e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
225e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
226e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets integer values into this tag. This method should be used for tags of
227e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_SHORT}. This method will fail if:
228e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
229e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
230e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
231e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
232e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value.length does NOT match the component count in the definition
233e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * for this tag.</li>
234e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
235e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
236e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(int[] value) {
237e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkBadComponentCount(value.length)) {
238e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
239e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
240e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG &&
241e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                mDataType != TYPE_UNSIGNED_LONG) {
242e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
243e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
244e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType == TYPE_UNSIGNED_SHORT && checkOverflowForUnsignedShort(value)) {
245e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
246e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mDataType == TYPE_UNSIGNED_LONG && checkOverflowForUnsignedLong(value)) {
247e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
248e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
249e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
250e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        long[] data = new long[value.length];
251e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (int i = 0; i < value.length; i++) {
252e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            data[i] = value[i];
253e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
254e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = data;
255e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = value.length;
256e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return true;
257e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
258e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
259e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
260e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets integer value into this tag. This method should be used for tags of
261e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_SHORT}, or {@link #TYPE_LONG}. This method
262e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * will fail if:
263e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
264e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
265e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
266e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
267e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component count in the definition of this tag is not 1.</li>
268e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
269e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
270e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(int value) {
271e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return setValue(new int[] {
272e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                value
273e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        });
274e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
275e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
276e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
277e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets long values into this tag. This method should be used for tags of
278e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
279e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
280e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
281e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
282e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value.length does NOT match the component count in the definition
283e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * for this tag.</li>
284e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
285e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
286e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(long[] value) {
287e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkBadComponentCount(value.length) || mDataType != TYPE_UNSIGNED_LONG) {
288e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
289e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
290e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkOverflowForUnsignedLong(value)) {
291e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
292e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
293e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = value;
294e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = value.length;
295e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return true;
296e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
297e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
298e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
299e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets long values into this tag. This method should be used for tags of
300e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_LONG}. This method will fail if:
301e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
302e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
303e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
304e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component count in the definition for this tag is not 1.</li>
305e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
306e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
307e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(long value) {
308e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return setValue(new long[] {
309e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                value
310e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        });
311e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
312e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
313e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
314e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets a string value into this tag. This method should be used for tags of
315e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_ASCII}. The string is converted to an ASCII string.
316e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Characters that cannot be converted are replaced with '?'. The length of
317e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * the string must be equal to either (component count -1) or (component
318e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * count). The final byte will be set to the string null terminator '\0',
319e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * overwriting the last character in the string if the value.length is equal
320e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * to the component count. This method will fail if:
321e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
322e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The data type is not {@link #TYPE_ASCII} or {@link #TYPE_UNDEFINED}.</li>
323e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The length of the string is not equal to (component count -1) or
324e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * (component count) in the definition for this tag.</li>
325e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
326e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
327e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(String value) {
328e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType != TYPE_ASCII && mDataType != TYPE_UNDEFINED) {
329e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
330e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
331e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
332e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        byte[] buf = value.getBytes(US_ASCII);
333e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        byte[] finalBuf = buf;
334e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (buf.length > 0) {
335e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            finalBuf = (buf[buf.length - 1] == 0 || mDataType == TYPE_UNDEFINED) ? buf : Arrays
336e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                .copyOf(buf, buf.length + 1);
337e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mDataType == TYPE_ASCII && mComponentCountActual == 1) {
338e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            finalBuf = new byte[] { 0 };
339e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
340e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        int count = finalBuf.length;
341e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkBadComponentCount(count)) {
342e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
343e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
344e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = count;
345e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = finalBuf;
346e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return true;
347e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
348e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
349e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
350e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets Rational values into this tag. This method should be used for tags
351e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
352e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * method will fail if:
353e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
354e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
355e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * or {@link #TYPE_RATIONAL}.</li>
356e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
357e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value.length does NOT match the component count in the definition
358e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * for this tag.</li>
359e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
360e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
361e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see Rational
362e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
363e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(Rational[] value) {
364e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkBadComponentCount(value.length)) {
365e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
366e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
367e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType != TYPE_UNSIGNED_RATIONAL && mDataType != TYPE_RATIONAL) {
368e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
369e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
370e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType == TYPE_UNSIGNED_RATIONAL && checkOverflowForUnsignedRational(value)) {
371e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
372e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mDataType == TYPE_RATIONAL && checkOverflowForRational(value)) {
373e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
374e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
375e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
376e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = value;
377e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = value.length;
378e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return true;
379e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
380e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
381e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
382e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets a Rational value into this tag. This method should be used for tags
383e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * of type {@link #TYPE_UNSIGNED_RATIONAL}, or {@link #TYPE_RATIONAL}. This
384e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * method will fail if:
385e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
386e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL}
387e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * or {@link #TYPE_RATIONAL}.</li>
388e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The value overflows.</li>
389e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component count in the definition for this tag is not 1.</li>
390e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
391e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
392e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @see Rational
393e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
394e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(Rational value) {
395e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return setValue(new Rational[] {
396e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                value
397e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        });
398e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
399e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
400e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
401e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets byte values into this tag. This method should be used for tags of
402e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
403e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * will fail if:
404e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
405e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
406e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNDEFINED} .</li>
407e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The length does NOT match the component count in the definition for
408e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * this tag.</li>
409e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
410e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
411e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(byte[] value, int offset, int length) {
412e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (checkBadComponentCount(length)) {
413e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
414e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
415e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) {
416e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
417e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
418e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mValue = new byte[length];
419e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        System.arraycopy(value, offset, mValue, 0, length);
420e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mComponentCountActual = length;
421e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return true;
422e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
423e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
424e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
425e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Equivalent to setValue(value, 0, value.length).
426e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
427e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(byte[] value) {
428e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return setValue(value, 0, value.length);
429e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
430e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
431e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
432e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets byte value into this tag. This method should be used for tags of
433e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_BYTE} or {@link #TYPE_UNDEFINED}. This method
434e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * will fail if:
435e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
436e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
437e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNDEFINED} .</li>
438e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The component count in the definition for this tag is not 1.</li>
439e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
440e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
441e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(byte value) {
442e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return setValue(new byte[] {
443e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                value
444e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        });
445e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
446e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
447e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
448e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets the value for this tag using an appropriate setValue method for the
449e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * given object. This method will fail if:
450e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <ul>
451e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>The corresponding setValue method for the class of the object passed
452e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * in would fail.</li>
453e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * <li>There is no obvious way to cast the object passed in into an EXIF tag
454e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type.</li>
455e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * </ul>
456e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
457e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setValue(Object obj) {
458e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (obj == null) {
459e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
460e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Short) {
461e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(((Short) obj).shortValue() & 0x0ffff);
462e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof String) {
463e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((String) obj);
464e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof int[]) {
465e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((int[]) obj);
466e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof long[]) {
467e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((long[]) obj);
468e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Rational) {
469e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((Rational) obj);
470e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Rational[]) {
471e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((Rational[]) obj);
472e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof byte[]) {
473e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue((byte[]) obj);
474e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Integer) {
475e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(((Integer) obj).intValue());
476e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Long) {
477e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(((Long) obj).longValue());
478e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Byte) {
479e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(((Byte) obj).byteValue());
480e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Short[]) {
481e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            // Nulls in this array are treated as zeroes.
482e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            Short[] arr = (Short[]) obj;
483e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            int[] fin = new int[arr.length];
484e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            for (int i = 0; i < arr.length; i++) {
485e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                fin[i] = (arr[i] == null) ? 0 : arr[i].shortValue() & 0x0ffff;
486e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
487e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(fin);
488e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Integer[]) {
489e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            // Nulls in this array are treated as zeroes.
490e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            Integer[] arr = (Integer[]) obj;
491e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            int[] fin = new int[arr.length];
492e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            for (int i = 0; i < arr.length; i++) {
493e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                fin[i] = (arr[i] == null) ? 0 : arr[i].intValue();
494e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
495e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(fin);
496e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Long[]) {
497e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            // Nulls in this array are treated as zeroes.
498e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            Long[] arr = (Long[]) obj;
499e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            long[] fin = new long[arr.length];
500e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            for (int i = 0; i < arr.length; i++) {
501e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                fin[i] = (arr[i] == null) ? 0 : arr[i].longValue();
502e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
503e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(fin);
504e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (obj instanceof Byte[]) {
505e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            // Nulls in this array are treated as zeroes.
506e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            Byte[] arr = (Byte[]) obj;
507e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            byte[] fin = new byte[arr.length];
508e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            for (int i = 0; i < arr.length; i++) {
509e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                fin[i] = (arr[i] == null) ? 0 : arr[i].byteValue();
510e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
511e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(fin);
512e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else {
513e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
514e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
515e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
516e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
517e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
518e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets a timestamp to this tag. The method converts the timestamp with the
519e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * format of "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}. This
520e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * method will fail if the data type is not {@link #TYPE_ASCII} or the
521e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * component count of this tag is not 20 or undefined.
522e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
523e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param time the number of milliseconds since Jan. 1, 1970 GMT
524e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return true on success
525e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
526e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean setTimeValue(long time) {
527e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe
528e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        synchronized (TIME_FORMAT) {
529e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return setValue(TIME_FORMAT.format(new Date(time)));
530e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
531e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
532e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
533e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
534e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a String. This method should be used for tags of type
535e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_ASCII}.
536e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
537e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the value as a String, or null if the tag's value does not exist
538e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         or cannot be converted to a String.
539e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
540e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public String getValueAsString() {
541e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue == null) {
542e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return null;
543e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof String) {
544e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return (String) mValue;
545e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof byte[]) {
546e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return new String((byte[]) mValue, US_ASCII);
547e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
548e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return null;
549e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
550e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
551e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
552e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a String. This method should be used for tags of type
553e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_ASCII}.
554e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
555e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the String to return if the tag's value does not
556e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            exist or cannot be converted to a String.
557e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a String, or the defaultValue.
558e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
559e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public String getValueAsString(String defaultValue) {
560e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        String s = getValueAsString();
561e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (s == null) {
562e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return defaultValue;
563e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
564e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return s;
565e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
566e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
567e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
568e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a byte array. This method should be used for tags of
569e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
570e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
571e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the value as a byte array, or null if the tag's value does not
572e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         exist or cannot be converted to a byte array.
573e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
574e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public byte[] getValueAsBytes() {
575e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue instanceof byte[]) {
576e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return (byte[]) mValue;
577e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
578e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return null;
579e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
580e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
581e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
582e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a byte. If there are more than 1 bytes in this value,
583e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * gets the first byte. This method should be used for tags of type
584e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
585e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
586e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the byte to return if tag's value does not exist or
587e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            cannot be converted to a byte.
588e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a byte, or the defaultValue.
589e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
590e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public byte getValueAsByte(byte defaultValue) {
591e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        byte[] b = getValueAsBytes();
592e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (b == null || b.length < 1) {
593e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return defaultValue;
594e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
595e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return b[0];
596e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
597e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
598e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
599e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as an array of Rationals. This method should be used for
600e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * tags of type {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
601e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
602e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the value as as an array of Rationals, or null if the tag's value
603e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         does not exist or cannot be converted to an array of Rationals.
604e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
605e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public Rational[] getValueAsRationals() {
606e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue instanceof Rational[]) {
607e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return (Rational[]) mValue;
608e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
609e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return null;
610e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
611e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
612e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
613e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a Rational. If there are more than 1 Rationals in this
614e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * value, gets the first one. This method should be used for tags of type
615e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
616e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
617e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the Rational to return if tag's value does not exist
618e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            or cannot be converted to a Rational.
619e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a Rational, or the defaultValue.
620e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
621e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public Rational getValueAsRational(Rational defaultValue) {
622e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        Rational[] r = getValueAsRationals();
623e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (r == null || r.length < 1) {
624e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return defaultValue;
625e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
626e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return r[0];
627e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
628e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
629e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
630e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as a Rational. If there are more than 1 Rationals in this
631e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * value, gets the first one. This method should be used for tags of type
632e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
633e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
634e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the numerator of the Rational to return if tag's
635e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            value does not exist or cannot be converted to a Rational (the
636e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            denominator will be 1).
637e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a Rational, or the defaultValue.
638e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
639e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public Rational getValueAsRational(long defaultValue) {
640e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        Rational defaultVal = new Rational(defaultValue, 1);
641e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return getValueAsRational(defaultVal);
642e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
643e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
644e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
645e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as an array of ints. This method should be used for tags
646e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * of type {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
647e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
648e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the value as as an array of ints, or null if the tag's value does
649e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         not exist or cannot be converted to an array of ints.
650e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
651e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public int[] getValueAsInts() {
652e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue == null) {
653e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return null;
654e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof long[]) {
655e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            long[] val = (long[]) mValue;
656e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            int[] arr = new int[val.length];
657e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            for (int i = 0; i < val.length; i++) {
658e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                arr[i] = (int) val[i]; // Truncates
659e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
660e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return arr;
661e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
662e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return null;
663e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
664e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
665e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
666e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as an int. If there are more than 1 ints in this value,
667e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * gets the first one. This method should be used for tags of type
668e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNSIGNED_SHORT}, {@link #TYPE_UNSIGNED_LONG}.
669e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
670e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the int to return if tag's value does not exist or
671e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            cannot be converted to an int.
672e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a int, or the defaultValue.
673e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
674e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public int getValueAsInt(int defaultValue) {
675e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        int[] i = getValueAsInts();
676e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (i == null || i.length < 1) {
677e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return defaultValue;
678e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
679e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return i[0];
680e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
681e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
682e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
683e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value as an array of longs. This method should be used for tags
684e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * of type {@link #TYPE_UNSIGNED_LONG}.
685e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
686e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the value as as an array of longs, or null if the tag's value
687e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         does not exist or cannot be converted to an array of longs.
688e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
689e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public long[] getValueAsLongs() {
690e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue instanceof long[]) {
691e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return (long[]) mValue;
692e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
693e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return null;
694e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
695e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
696e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
697e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value or null if none exists. If there are more than 1 longs in
698e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * this value, gets the first one. This method should be used for tags of
699e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * type {@link #TYPE_UNSIGNED_LONG}.
700e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
701e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue the long to return if tag's value does not exist or
702e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            cannot be converted to a long.
703e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a long, or the defaultValue.
704e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
705e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public long getValueAsLong(long defaultValue) {
706e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        long[] l = getValueAsLongs();
707e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (l == null || l.length < 1) {
708e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return defaultValue;
709e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
710e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return l[0];
711e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
712e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
713e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
714e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the tag's value or null if none exists.
715e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
716e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public Object getValue() {
717e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mValue;
718e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
719e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
720e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
721e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets a long representation of the value.
722e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
723e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param defaultValue value to return if there is no value or value is a
724e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            rational with a denominator of 0.
725e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @return the tag's value as a long, or defaultValue if no representation
726e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *         exists.
727e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
728e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public long forceGetValueAsLong(long defaultValue) {
729e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        long[] l = getValueAsLongs();
730e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (l != null && l.length >= 1) {
731e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return l[0];
732e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
733e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        byte[] b = getValueAsBytes();
734e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (b != null && b.length >= 1) {
735e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return b[0];
736e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
737e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        Rational[] r = getValueAsRationals();
738e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (r != null && r.length >= 1 && r[0].getDenominator() != 0) {
739e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return (long) r[0].toDouble();
740e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
741e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return defaultValue;
742e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
743e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
744e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
745e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets a string representation of the value.
746e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
747e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public String forceGetValueAsString() {
748e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue == null) {
749e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return "";
750e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof byte[]) {
751e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (mDataType == TYPE_ASCII) {
752e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return new String((byte[]) mValue, US_ASCII);
753e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            } else {
754e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return Arrays.toString((byte[]) mValue);
755e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
756e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof long[]) {
757e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (((long[]) mValue).length == 1) {
758e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return String.valueOf(((long[]) mValue)[0]);
759e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            } else {
760e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return Arrays.toString((long[]) mValue);
761e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
762e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof Object[]) {
763e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (((Object[]) mValue).length == 1) {
764e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                Object val = ((Object[]) mValue)[0];
765e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                if (val == null) {
766e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return "";
767e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                } else {
768e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return val.toString();
769e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                }
770e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            } else {
771e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return Arrays.toString((Object[]) mValue);
772e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
773e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else {
774e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return mValue.toString();
775e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
776e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
777e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
778e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
779e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the value for type {@link #TYPE_ASCII}, {@link #TYPE_LONG},
780e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNDEFINED}, {@link #TYPE_UNSIGNED_BYTE},
781e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_UNSIGNED_SHORT}. For
782e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}, call
783e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * {@link #getRational(int)} instead.
784e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
785e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @exception IllegalArgumentException if the data type is
786e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
787e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
788e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected long getValueAt(int index) {
789e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mValue instanceof long[]) {
790e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return ((long[]) mValue)[index];
791e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        } else if (mValue instanceof byte[]) {
792e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return ((byte[]) mValue)[index];
793e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
794e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        throw new IllegalArgumentException("Cannot get integer value from "
795e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                + convertTypeToString(mDataType));
796e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
797e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
798e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
799e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the {@link #TYPE_ASCII} data.
800e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
801e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @exception IllegalArgumentException If the type is NOT
802e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *                {@link #TYPE_ASCII}.
803e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
804e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected String getString() {
805e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mDataType != TYPE_ASCII) {
806e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            throw new IllegalArgumentException("Cannot get ASCII value from "
807e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    + convertTypeToString(mDataType));
808e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
809e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return new String((byte[]) mValue, US_ASCII);
810e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
811e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
812e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /*
813e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Get the converted ascii byte. Used by ExifOutputStream.
814e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
815e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected byte[] getStringByte() {
816e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return (byte[]) mValue;
817e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
818e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
819e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
820e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data.
821e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
822e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @exception IllegalArgumentException If the type is NOT
823e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *                {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL}.
824e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
825e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected Rational getRational(int index) {
826e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) {
827e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            throw new IllegalArgumentException("Cannot get RATIONAL value from "
828e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    + convertTypeToString(mDataType));
829e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
830e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return ((Rational[]) mValue)[index];
831e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
832e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
833e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
834e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Equivalent to getBytes(buffer, 0, buffer.length).
835e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
836e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void getBytes(byte[] buf) {
837e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        getBytes(buf, 0, buf.length);
838e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
839e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
840e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
841e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
842e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *
843e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param buf the byte array in which to store the bytes read.
844e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param offset the initial position in buffer to store the bytes.
845e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @param length the maximum number of bytes to store in buffer. If length >
846e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *            component count, only the valid bytes will be stored.
847e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * @exception IllegalArgumentException If the type is NOT
848e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     *                {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE}.
849e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
850e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void getBytes(byte[] buf, int offset, int length) {
851e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) {
852e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            throw new IllegalArgumentException("Cannot get BYTE value from "
853e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    + convertTypeToString(mDataType));
854e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
855e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        System.arraycopy(mValue, 0, buf, offset,
856e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                (length > mComponentCountActual) ? mComponentCountActual : length);
857e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
858e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
859e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
860e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Gets the offset of this tag. This is only valid if this data size > 4 and
861e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * contains an offset to the location of the actual value.
862e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
863e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected int getOffset() {
864e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mOffset;
865e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
866e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
867e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    /**
868e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     * Sets the offset of this tag.
869e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor     */
870e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void setOffset(int offset) {
871e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mOffset = offset;
872e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
873e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
874e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected void setHasDefinedCount(boolean d) {
875e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        mHasDefinedDefaultComponentCount = d;
876e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
877e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
878e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    protected boolean hasDefinedCount() {
879e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return mHasDefinedDefaultComponentCount;
880e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
881e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
882e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkBadComponentCount(int count) {
883e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (mHasDefinedDefaultComponentCount && (mComponentCountActual != count)) {
884e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return true;
885e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
886e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
887e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
888e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
889e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private static String convertTypeToString(short type) {
890e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        switch (type) {
891e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_UNSIGNED_BYTE:
892e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "UNSIGNED_BYTE";
893e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_ASCII:
894e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "ASCII";
895e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_UNSIGNED_SHORT:
896e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "UNSIGNED_SHORT";
897e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_UNSIGNED_LONG:
898e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "UNSIGNED_LONG";
899e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_UNSIGNED_RATIONAL:
900e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "UNSIGNED_RATIONAL";
901e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_UNDEFINED:
902e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "UNDEFINED";
903e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_LONG:
904e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "LONG";
905e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            case TYPE_RATIONAL:
906e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "RATIONAL";
907e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            default:
908e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return "";
909e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
910e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
911e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
912e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkOverflowForUnsignedShort(int[] value) {
913e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (int v : value) {
914e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (v > UNSIGNED_SHORT_MAX || v < 0) {
915e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return true;
916e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
917e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
918e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
919e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
920e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
921e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkOverflowForUnsignedLong(long[] value) {
922e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (long v : value) {
923e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (v < 0 || v > UNSIGNED_LONG_MAX) {
924e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return true;
925e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
926e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
927e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
928e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
929e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
930e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkOverflowForUnsignedLong(int[] value) {
931e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (int v : value) {
932e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (v < 0) {
933e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return true;
934e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
935e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
936e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
937e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
938e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
939e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkOverflowForUnsignedRational(Rational[] value) {
940e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (Rational v : value) {
941e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (v.getNumerator() < 0 || v.getDenominator() < 0
942e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || v.getNumerator() > UNSIGNED_LONG_MAX
943e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || v.getDenominator() > UNSIGNED_LONG_MAX) {
944e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return true;
945e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
946e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
947e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
948e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
949e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
950e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    private boolean checkOverflowForRational(Rational[] value) {
951e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        for (Rational v : value) {
952e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (v.getNumerator() < LONG_MIN || v.getDenominator() < LONG_MIN
953e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || v.getNumerator() > LONG_MAX
954e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || v.getDenominator() > LONG_MAX) {
955e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return true;
956e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
957e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
958e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
959e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
960e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
961e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    @Override
962e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public boolean equals(Object obj) {
963e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (obj == null) {
964e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            return false;
965e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
966e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        if (obj instanceof ExifTag) {
967e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            ExifTag tag = (ExifTag) obj;
968e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (tag.mTagId != this.mTagId
969e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || tag.mComponentCountActual != this.mComponentCountActual
970e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    || tag.mDataType != this.mDataType) {
971e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return false;
972e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
973e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            if (mValue != null) {
974e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                if (tag.mValue == null) {
975e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return false;
976e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                } else if (mValue instanceof long[]) {
977e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    if (!(tag.mValue instanceof long[])) {
978e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                        return false;
979e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    }
980e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
981e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                } else if (mValue instanceof Rational[]) {
982e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    if (!(tag.mValue instanceof Rational[])) {
983e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                        return false;
984e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    }
985e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
986e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                } else if (mValue instanceof byte[]) {
987e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    if (!(tag.mValue instanceof byte[])) {
988e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                        return false;
989e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    }
990e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
991e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                } else {
992e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                    return mValue.equals(tag.mValue);
993e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                }
994e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            } else {
995e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                return tag.mValue == null;
996e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor            }
997e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        }
998e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return false;
999e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
1000e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
1001e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    @Override
1002e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    public String toString() {
1003e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor        return String.format("tag id: %04X\n", mTagId) + "ifd id: " + mIfd + "\ntype: "
1004e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                + convertTypeToString(mDataType) + "\ncount: " + mComponentCountActual
1005e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor                + "\noffset: " + mOffset + "\nvalue: " + forceGetValueAsString() + "\n";
1006e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor    }
1007e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor
1008e8a0d786fba1960818cb3da938cdbf2b2b11b340Tom Taylor}
1009