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