OSDN Git Service

am 10f975a6: Merge "Add proxy launcher" into gb-ub-photos-arches
[android-x86/packages-apps-Gallery2.git] / gallerycommon / src / com / android / gallery3d / exif / ExifTag.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.gallery3d.exif;
18
19 import android.util.SparseArray;
20
21 import java.text.SimpleDateFormat;
22 import java.util.Arrays;
23 import java.util.Date;
24
25 /**
26  * This class stores information of an EXIF tag.
27  * @see ExifParser
28  * @see ExifReader
29  * @see IfdData
30  * @see ExifData
31  */
32 public class ExifTag {
33     // Tiff Tags
34     public static final short TAG_IMAGE_WIDTH = 0x100;
35     /*
36      * The height of the image.
37      */
38     public static final short TAG_IMAGE_LENGTH = 0x101;
39     public static final short TAG_BITS_PER_SAMPLE = 0x102;
40     public static final short TAG_COMPRESSION = 0x103;
41     public static final short TAG_PHOTOMETRIC_INTERPRETATION = 0x106;
42     public static final short TAG_IMAGE_DESCRIPTION = 0x10E;
43     public static final short TAG_MAKE = 0x10F;
44     public static final short TAG_MODEL = 0x110;
45     public static final short TAG_STRIP_OFFSETS = 0x111;
46     public static final short TAG_ORIENTATION = 0x112;
47     public static final short TAG_SAMPLES_PER_PIXEL = 0x115;
48     public static final short TAG_ROWS_PER_STRIP = 0x116;
49     public static final short TAG_STRIP_BYTE_COUNTS = 0x117;
50     public static final short TAG_X_RESOLUTION = 0x11A;
51     public static final short TAG_Y_RESOLUTION = 0x11B;
52     public static final short TAG_PLANAR_CONFIGURATION = 0x11C;
53     public static final short TAG_RESOLUTION_UNIT = 0x128;
54     public static final short TAG_TRANSFER_FUNCTION = 0x12D;
55     public static final short TAG_SOFTWARE = 0x131;
56     public static final short TAG_DATE_TIME = 0x132;
57     public static final short TAG_ARTIST = 0x13B;
58     public static final short TAG_WHITE_POINT = 0x13E;
59     public static final short TAG_PRIMARY_CHROMATICITIES = 0x13F;
60     public static final short TAG_JPEG_INTERCHANGE_FORMAT = 0x201;
61     public static final short TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x202;
62     public static final short TAG_Y_CB_CR_COEFFICIENTS = 0x211;
63     public static final short TAG_Y_CB_CR_SUB_SAMPLING = 0x212;
64     public static final short TAG_Y_CB_CR_POSITIONING = 0x213;
65     public static final short TAG_REFERENCE_BLACK_WHITE = 0x214;
66     public static final short TAG_COPYRIGHT = (short) 0x8298;
67     public static final short TAG_EXIF_IFD = (short) 0x8769;
68     public static final short TAG_GPS_IFD = (short) 0x8825;
69
70     // Exif Tags
71     public static final short TAG_EXPOSURE_TIME = (short) 0x829A;
72     public static final short TAG_F_NUMBER = (short) 0x829D;
73     public static final short TAG_EXPOSURE_PROGRAM = (short) 0x8822;
74     public static final short TAG_SPECTRAL_SENSITIVITY = (short) 0x8824;
75     public static final short TAG_ISO_SPEED_RATINGS = (short) 0x8827;
76     public static final short TAG_OECF = (short) 0x8828;
77     public static final short TAG_EXIF_VERSION = (short) 0x9000;
78     public static final short TAG_DATE_TIME_ORIGINAL = (short) 0x9003;
79     public static final short TAG_DATE_TIME_DIGITIZED = (short) 0x9004;
80     public static final short TAG_COMPONENTS_CONFIGURATION = (short) 0x9101;
81     public static final short TAG_COMPRESSED_BITS_PER_PIXEL = (short) 0x9102;
82     public static final short TAG_SHUTTER_SPEED_VALUE = (short) 0x9201;
83     public static final short TAG_APERTURE_VALUE = (short) 0x9202;
84     public static final short TAG_BRIGHTNESS_VALUE = (short) 0x9203;
85     public static final short TAG_EXPOSURE_BIAS_VALUE = (short) 0x9204;
86     public static final short TAG_MAX_APERTURE_VALUE = (short) 0x9205;
87     public static final short TAG_SUBJECT_DISTANCE = (short) 0x9206;
88     public static final short TAG_METERING_MODE = (short) 0x9207;
89     public static final short TAG_LIGHT_SOURCE = (short) 0x9208;
90     public static final short TAG_FLASH = (short) 0x9209;
91     public static final short TAG_FOCAL_LENGTH = (short) 0x920A;
92     public static final short TAG_SUBJECT_AREA = (short) 0x9214;
93     public static final short TAG_MAKER_NOTE = (short) 0x927C;
94     public static final short TAG_USER_COMMENT = (short) 0x9286;
95     public static final short TAG_SUB_SEC_TIME = (short) 0x9290;
96     public static final short TAG_SUB_SEC_TIME_ORIGINAL = (short) 0x9291;
97     public static final short TAG_SUB_SEC_TIME_DIGITIZED = (short) 0x9292;
98     public static final short TAG_FLASHPIX_VERSION = (short) 0xA000;
99     public static final short TAG_COLOR_SPACE = (short) 0xA001;
100     public static final short TAG_PIXEL_X_DIMENSION = (short) 0xA002;
101     public static final short TAG_PIXEL_Y_DIMENSION = (short) 0xA003;
102     public static final short TAG_RELATED_SOUND_FILE = (short) 0xA004;
103     public static final short TAG_INTEROPERABILITY_IFD = (short) 0xA005;
104     public static final short TAG_FLASH_ENERGY = (short) 0xA20B;
105     public static final short TAG_SPATIAL_FREQUENCY_RESPONSE = (short) 0xA20C;
106     public static final short TAG_FOCAL_PLANE_X_RESOLUTION = (short) 0xA20E;
107     public static final short TAG_FOCAL_PLANE_Y_RESOLUTION = (short) 0xA20F;
108     public static final short TAG_FOCAL_PLANE_RESOLUTION_UNIT = (short) 0xA210;
109     public static final short TAG_SUBJECT_LOCATION = (short) 0xA214;
110     public static final short TAG_EXPOSURE_INDEX = (short) 0xA215;
111     public static final short TAG_SENSING_METHOD = (short) 0xA217;
112     public static final short TAG_FILE_SOURCE = (short) 0xA300;
113     public static final short TAG_SCENE_TYPE = (short) 0xA301;
114     public static final short TAG_CFA_PATTERN = (short) 0xA302;
115     public static final short TAG_CUSTOM_RENDERED = (short) 0xA401;
116     public static final short TAG_EXPOSURE_MODE = (short) 0xA402;
117     public static final short TAG_WHITE_BALANCE = (short) 0xA403;
118     public static final short TAG_DIGITAL_ZOOM_RATIO = (short) 0xA404;
119     public static final short TAG_FOCAL_LENGTH_IN_35_MM_FILE = (short) 0xA405;
120     public static final short TAG_SCENE_CAPTURE_TYPE = (short) 0xA406;
121     public static final short TAG_GAIN_CONTROL = (short) 0xA407;
122     public static final short TAG_CONTRAST = (short) 0xA408;
123     public static final short TAG_SATURATION = (short) 0xA409;
124     public static final short TAG_SHARPNESS = (short) 0xA40A;
125     public static final short TAG_DEVICE_SETTING_DESCRIPTION = (short) 0xA40B;
126     public static final short TAG_SUBJECT_DISTANCE_RANGE = (short) 0xA40C;
127     public static final short TAG_IMAGE_UNIQUE_ID = (short) 0xA420;
128
129     // GPS tags
130     public static final short TAG_GPS_VERSION_ID = 0;
131     public static final short TAG_GPS_LATITUDE_REF = 1;
132     public static final short TAG_GPS_LATITUDE = 2;
133     public static final short TAG_GPS_LONGITUDE_REF = 3;
134     public static final short TAG_GPS_LONGITUDE = 4;
135     public static final short TAG_GPS_ALTITUDE_REF = 5;
136     public static final short TAG_GPS_ALTITUDE = 6;
137     public static final short TAG_GPS_TIME_STAMP = 7;
138     public static final short TAG_GPS_SATTELLITES = 8;
139     public static final short TAG_GPS_STATUS = 9;
140     public static final short TAG_GPS_MEASURE_MODE = 10;
141     public static final short TAG_GPS_DOP = 11;
142     public static final short TAG_GPS_SPEED_REF = 12;
143     public static final short TAG_GPS_SPEED = 13;
144     public static final short TAG_GPS_TRACK_REF = 14;
145     public static final short TAG_GPS_TRACK = 15;
146     public static final short TAG_GPS_IMG_DIRECTION_REF = 16;
147     public static final short TAG_GPS_IMG_DIRECTION = 17;
148     public static final short TAG_GPS_MAP_DATUM = 18;
149     public static final short TAG_GPS_DEST_LATITUDE_REF = 19;
150     public static final short TAG_GPS_DEST_LATITUDE = 20;
151     public static final short TAG_GPS_DEST_LONGITUDE_REF = 21;
152     public static final short TAG_GPS_DEST_LONGITUDE = 22;
153     public static final short TAG_GPS_DEST_BEARING_REF = 23;
154     public static final short TAG_GPS_DEST_BEARING = 24;
155     public static final short TAG_GPS_DEST_DISTANCE_REF = 25;
156     public static final short TAG_GPS_DEST_DISTANCE = 26;
157     public static final short TAG_GPS_PROCESSING_METHOD = 27;
158     public static final short TAG_GPS_AREA_INFORMATION = 28;
159     public static final short TAG_GPS_DATA_STAMP = 29;
160     public static final short TAG_GPS_DIFFERENTIAL = 30;
161
162     // Interoperability tag
163     public static final short TAG_INTEROPERABILITY_INDEX = 1;
164
165     /**
166      * Constants for {@link #TAG_ORIENTATION}
167      */
168     public static interface Orientation {
169         public static final short TOP_LEFT = 1;
170         public static final short TOP_RIGHT = 2;
171         public static final short BOTTOM_LEFT = 3;
172         public static final short BOTTOM_RIGHT = 4;
173         public static final short LEFT_TOP = 5;
174         public static final short RIGHT_TOP = 6;
175         public static final short LEFT_BOTTOM = 7;
176         public static final short RIGHT_BOTTOM = 8;
177     }
178
179     /**
180      * Constants for {@link #TAG_Y_CB_CR_POSITIONING}
181      */
182     public static interface YCbCrPositioning {
183         public static final short CENTERED = 1;
184         public static final short CO_SITED = 2;
185     }
186
187     /**
188      * Constants for {@link #TAG_COMPRESSION}
189      */
190     public static interface Compression {
191         public static final short UNCOMPRESSION = 1;
192         public static final short JPEG = 6;
193     }
194
195     /**
196      * Constants for {@link #TAG_RESOLUTION_UNIT}
197      */
198     public static interface ResolutionUnit {
199         public static final short INCHES = 2;
200         public static final short CENTIMETERS = 3;
201     }
202
203     /**
204      * Constants for {@link #TAG_PHOTOMETRIC_INTERPRETATION}
205      */
206     public static interface PhotometricInterpretation {
207         public static final short RGB = 2;
208         public static final short YCBCR = 6;
209     }
210
211     /**
212      * Constants for {@link #TAG_PLANAR_CONFIGURATION}
213      */
214     public static interface PlanarConfiguration {
215         public static final short CHUNKY = 1;
216         public static final short PLANAR = 2;
217     }
218
219     /**
220      * Constants for {@link #TAG_EXPOSURE_PROGRAM}
221      */
222     public static interface ExposureProgram {
223         public static final short NOT_DEFINED = 0;
224         public static final short MANUAL = 1;
225         public static final short NORMAL_PROGRAM = 2;
226         public static final short APERTURE_PRIORITY = 3;
227         public static final short SHUTTER_PRIORITY = 4;
228         public static final short CREATIVE_PROGRAM = 5;
229         public static final short ACTION_PROGRAM = 6;
230         public static final short PROTRAIT_MODE = 7;
231         public static final short LANDSCAPE_MODE = 8;
232     }
233
234     /**
235      * Constants for {@link #TAG_METERING_MODE}
236      */
237     public static interface MeteringMode {
238         public static final short UNKNOWN = 0;
239         public static final short AVERAGE = 1;
240         public static final short CENTER_WEIGHTED_AVERAGE = 2;
241         public static final short SPOT = 3;
242         public static final short MULTISPOT = 4;
243         public static final short PATTERN = 5;
244         public static final short PARTAIL = 6;
245         public static final short OTHER = 255;
246     }
247
248     /**
249      * Constants for {@link #TAG_FLASH} As the definition in Jeita EXIF 2.2 standard, we can
250      * treat this constant as bitwise flag.
251      * <p>
252      * e.g.
253      * <p>
254      * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED | MODE_AUTO_MODE
255      */
256     public static interface Flash {
257         // LSB
258         public static final short DID_NOT_FIRED = 0;
259         public static final short FIRED = 1;
260         // 1st~2nd bits
261         public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1;
262         public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1;
263         public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1;
264         // 3rd~4th bits
265         public static final short MODE_UNKNOWN = 0 << 3;
266         public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3;
267         public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3;
268         public static final short MODE_AUTO_MODE = 3 << 3;
269         // 5th bit
270         public static final short FUNCTION_PRESENT = 0 << 5;
271         public static final short FUNCTION_NO_FUNCTION = 1 << 5;
272         // 6th bit
273         public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
274         public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
275     }
276
277     /**
278      * Constants for {@link #TAG_COLOR_SPACE}
279      */
280     public static interface ColorSpace {
281         public static final short SRGB = 1;
282         public static final short UNCALIBRATED = (short) 0xFFFF;
283     }
284
285     /**
286      * Constants for {@link #TAG_EXPOSURE_MODE}
287      */
288     public static interface ExposureMode {
289         public static final short AUTO_EXPOSURE = 0;
290         public static final short MANUAL_EXPOSURE = 1;
291         public static final short AUTO_BRACKET = 2;
292     }
293
294     /**
295      * Constants for {@link #TAG_WHITE_BALANCE}
296      */
297     public static interface WhiteBalance {
298         public static final short AUTO = 0;
299         public static final short MANUAL = 1;
300     }
301
302     /**
303      * Constants for {@link #TAG_SCENE_CAPTURE_TYPE}
304      */
305     public static interface SceneCapture {
306         public static final short STANDARD = 0;
307         public static final short LANDSCAPE = 1;
308         public static final short PROTRAIT = 2;
309         public static final short NIGHT_SCENE = 3;
310     }
311
312     /**
313      * Constants for {@link #TAG_COMPONENTS_CONFIGURATION}
314      */
315     public static interface ComponentsConfiguration {
316         public static final short NOT_EXIST = 0;
317         public static final short Y = 1;
318         public static final short CB = 2;
319         public static final short CR = 3;
320         public static final short R = 4;
321         public static final short G = 5;
322         public static final short B = 6;
323     }
324
325     /**
326      * Constants for {@link #TAG_LIGHT_SOURCE}
327      */
328     public static interface LightSource {
329         public static final short UNKNOWN = 0;
330         public static final short DAYLIGHT = 1;
331         public static final short FLUORESCENT = 2;
332         public static final short TUNGSTEN = 3;
333         public static final short FLASH = 4;
334         public static final short FINE_WEATHER = 9;
335         public static final short CLOUDY_WEATHER = 10;
336         public static final short SHADE = 11;
337         public static final short DAYLIGHT_FLUORESCENT = 12;
338         public static final short DAY_WHITE_FLUORESCENT = 13;
339         public static final short COOL_WHITE_FLUORESCENT = 14;
340         public static final short WHITE_FLUORESCENT = 15;
341         public static final short STANDARD_LIGHT_A = 17;
342         public static final short STANDARD_LIGHT_B = 18;
343         public static final short STANDARD_LIGHT_C = 19;
344         public static final short D55 = 20;
345         public static final short D65 = 21;
346         public static final short D75 = 22;
347         public static final short D50 = 23;
348         public static final short ISO_STUDIO_TUNGSTEN = 24;
349         public static final short OTHER = 255;
350     }
351
352     /**
353      * Constants for {@link #TAG_SENSING_METHOD}
354      */
355     public static interface SensingMethod {
356         public static final short NOT_DEFINED = 1;
357         public static final short ONE_CHIP_COLOR = 2;
358         public static final short TWO_CHIP_COLOR = 3;
359         public static final short THREE_CHIP_COLOR = 4;
360         public static final short COLOR_SEQUENTIAL_AREA = 5;
361         public static final short TRILINEAR = 7;
362         public static final short COLOR_SEQUENTIAL_LINEAR = 8;
363     }
364
365     /**
366      * Constants for {@link #TAG_FILE_SOURCE}
367      */
368     public static interface FileSource {
369         public static final short DSC = 3;
370     }
371
372     /**
373      * Constants for {@link #TAG_SCENE_TYPE}
374      */
375     public static interface SceneType {
376         public static final short DIRECT_PHOTOGRAPHED = 1;
377     }
378
379     /**
380      * Constants for {@link #TAG_GAIN_CONTROL}
381      */
382     public static interface GainControl {
383         public static final short NONE = 0;
384         public static final short LOW_UP = 1;
385         public static final short HIGH_UP = 2;
386         public static final short LOW_DOWN = 3;
387         public static final short HIGH_DOWN = 4;
388     }
389
390     /**
391      * Constants for {@link #TAG_CONTRAST}
392      */
393     public static interface Contrast {
394         public static final short NORMAL = 0;
395         public static final short SOFT = 1;
396         public static final short HARD = 2;
397     }
398
399     /**
400      * Constants for {@link #TAG_SATURATION}
401      */
402     public static interface Saturation {
403         public static final short NORMAL = 0;
404         public static final short LOW = 1;
405         public static final short HIGH = 2;
406     }
407
408     /**
409      * Constants for {@link #TAG_SHARPNESS}
410      */
411     public static interface Sharpness {
412         public static final short NORMAL = 0;
413         public static final short SOFT = 1;
414         public static final short HARD = 2;
415     }
416
417     /**
418      * Constants for {@link #TAG_SUBJECT_DISTANCE}
419      */
420     public static interface SubjectDistance {
421         public static final short UNKNOWN = 0;
422         public static final short MACRO = 1;
423         public static final short CLOSE_VIEW = 2;
424         public static final short DISTANT_VIEW = 3;
425     }
426
427     /**
428      * Constants for {@link #TAG_GPS_LATITUDE_REF}, {@link #TAG_GPS_DEST_LATITUDE_REF}
429      */
430     public static interface GpsLatitudeRef {
431         public static final String NORTH = "N";
432         public static final String SOUTH = "S";
433     }
434
435     /**
436      * Constants for {@link #TAG_GPS_LONGITUDE_REF}, {@link #TAG_GPS_DEST_LONGITUDE_REF}
437      */
438     public static interface GpsLongitudeRef {
439         public static final String EAST = "E";
440         public static final String WEST = "W";
441     }
442
443     /**
444      * Constants for {@link #TAG_GPS_ALTITUDE_REF}
445      */
446     public static interface GpsAltitudeRef {
447         public static final short SEA_LEVEL = 0;
448         public static final short SEA_LEVEL_NEGATIVE = 1;
449     }
450
451     /**
452      * Constants for {@link #TAG_GPS_STATUS}
453      */
454     public static interface GpsStatus {
455         public static final String IN_PROGRESS = "A";
456         public static final String INTEROPERABILITY = "V";
457     }
458
459     /**
460      * Constants for {@link #TAG_GPS_MEASURE_MODE}
461      */
462     public static interface GpsMeasureMode {
463         public static final String MODE_2_DIMENSIONAL = "2";
464         public static final String MODE_3_DIMENSIONAL = "3";
465     }
466
467     /**
468      * Constants for {@link #TAG_GPS_SPEED_REF}, {@link #TAG_GPS_DEST_DISTANCE_REF}
469      */
470     public static interface GpsSpeedRef {
471         public static final String KILOMETERS = "K";
472         public static final String MILES = "M";
473         public static final String KNOTS = "N";
474     }
475
476     /**
477      * Constants for {@link #TAG_GPS_TRACK_REF}, {@link #TAG_GPS_IMG_DIRECTION_REF},
478      * {@link #TAG_GPS_DEST_BEARING_REF}
479      */
480     public static interface GpsTrackRef {
481         public static final String TRUE_DIRECTION = "T";
482         public static final String MAGNETIC_DIRECTION = "M";
483     }
484
485     /**
486      * Constants for {@link #TAG_GPS_DIFFERENTIAL}
487      */
488     public static interface GpsDifferential {
489         public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
490         public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
491     }
492
493     /**
494      * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
495      */
496     public static final short TYPE_UNSIGNED_BYTE = 1;
497     /**
498      * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit ASCII code.
499      * The final byte is terminated with NULL.
500      */
501     public static final short TYPE_ASCII = 2;
502     /**
503      * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
504      */
505     public static final short TYPE_UNSIGNED_SHORT = 3;
506     /**
507      * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
508      */
509     public static final short TYPE_UNSIGNED_LONG = 4;
510     /**
511      * The RATIONAL type of EXIF standard. It consists of two LONGs. The first one is the numerator
512      * and the second one expresses the denominator.
513      */
514     public static final short TYPE_UNSIGNED_RATIONAL = 5;
515     /**
516      * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any value
517      * depending on the field definition.
518      */
519     public static final short TYPE_UNDEFINED = 7;
520     /**
521      * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
522      * (2's complement notation).
523      */
524     public static final short TYPE_LONG = 9;
525     /**
526      * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first one is the
527      * numerator and the second one is the denominator.
528      */
529     public static final short TYPE_RATIONAL = 10;
530
531     private static final int TYPE_TO_SIZE_MAP[] = new int[11];
532     static {
533         TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1;
534         TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1;
535         TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2;
536         TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4;
537         TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8;
538         TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1;
539         TYPE_TO_SIZE_MAP[TYPE_LONG] = 4;
540         TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8;
541     }
542
543     /**
544      * Gets the element size of the given data type.
545      *
546      * @see #TYPE_ASCII
547      * @see #TYPE_LONG
548      * @see #TYPE_RATIONAL
549      * @see #TYPE_UNDEFINED
550      * @see #TYPE_UNSIGNED_BYTE
551      * @see #TYPE_UNSIGNED_LONG
552      * @see #TYPE_UNSIGNED_RATIONAL
553      * @see #TYPE_UNSIGNED_SHORT
554      */
555     public static int getElementSize(short type) {
556         return TYPE_TO_SIZE_MAP[type];
557     }
558
559     private static volatile SparseArray<Integer> sTagInfo = null;
560     private static volatile SparseArray<Integer> sInteroperTagInfo = null;
561     private static final int SIZE_UNDEFINED = 0;
562
563     private static SparseArray<Integer> getTagInfo() {
564         if (sTagInfo == null) {
565             synchronized(ExifTag.class) {
566                 if (sTagInfo == null) {
567                     sTagInfo = new SparseArray<Integer>();
568                     initTagInfo();
569                 }
570             }
571         }
572         return sTagInfo;
573     }
574
575     private static SparseArray<Integer> getInteroperTagInfo() {
576         if (sInteroperTagInfo == null) {
577             synchronized(ExifTag.class) {
578                 if (sInteroperTagInfo == null) {
579                     sInteroperTagInfo = new SparseArray<Integer>();
580                     sInteroperTagInfo.put(TAG_INTEROPERABILITY_INDEX,
581                             (IfdId.TYPE_IFD_INTEROPERABILITY << 24)
582                             | TYPE_ASCII << 16 | SIZE_UNDEFINED);
583                 }
584             }
585         }
586         return sInteroperTagInfo;
587     }
588
589     private static void initTagInfo() {
590         /**
591          * We put tag information in a 4-bytes integer. The first byte is the
592          * IFD of the tag, and the second byte is the default data type. The
593          * last two byte are a short value indicating the component count of this
594          * tag.
595          */
596         sTagInfo.put(TAG_MAKE,
597                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
598         sTagInfo.put(TAG_IMAGE_WIDTH,
599                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
600         sTagInfo.put(TAG_IMAGE_LENGTH,
601                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
602         sTagInfo.put(TAG_BITS_PER_SAMPLE,
603                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3);
604         sTagInfo.put(TAG_COMPRESSION,
605                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
606         sTagInfo.put(TAG_PHOTOMETRIC_INTERPRETATION,
607                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
608         sTagInfo.put(TAG_ORIENTATION, (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
609         sTagInfo.put(TAG_SAMPLES_PER_PIXEL,
610                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
611         sTagInfo.put(TAG_PLANAR_CONFIGURATION,
612                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
613         sTagInfo.put(TAG_Y_CB_CR_SUB_SAMPLING,
614                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 2);
615         sTagInfo.put(TAG_Y_CB_CR_POSITIONING,
616                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
617         sTagInfo.put(TAG_X_RESOLUTION,
618                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
619         sTagInfo.put(TAG_Y_RESOLUTION,
620                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
621         sTagInfo.put(TAG_RESOLUTION_UNIT,
622                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
623         sTagInfo.put(TAG_STRIP_OFFSETS,
624                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED);
625         sTagInfo.put(TAG_ROWS_PER_STRIP,
626                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
627         sTagInfo.put(TAG_STRIP_BYTE_COUNTS,
628                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED);
629         sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT,
630                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
631         sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
632                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
633         sTagInfo.put(TAG_TRANSFER_FUNCTION,
634                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3 * 256);
635         sTagInfo.put(TAG_WHITE_POINT,
636                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 2);
637         sTagInfo.put(TAG_PRIMARY_CHROMATICITIES,
638                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6);
639         sTagInfo.put(TAG_Y_CB_CR_COEFFICIENTS,
640                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3);
641         sTagInfo.put(TAG_REFERENCE_BLACK_WHITE,
642                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6);
643         sTagInfo.put(TAG_DATE_TIME,
644                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | 20);
645         sTagInfo.put(TAG_IMAGE_DESCRIPTION,
646                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
647         sTagInfo.put(TAG_MAKE,
648                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
649         sTagInfo.put(TAG_MODEL,
650                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
651         sTagInfo.put(TAG_SOFTWARE,
652                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
653         sTagInfo.put(TAG_ARTIST,
654                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
655         sTagInfo.put(TAG_COPYRIGHT,
656                 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
657         sTagInfo.put(TAG_EXIF_IFD,
658                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
659         sTagInfo.put(TAG_GPS_IFD,
660                 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
661
662         // EXIF TAG
663         sTagInfo.put(TAG_EXIF_VERSION,
664                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
665         sTagInfo.put(TAG_FLASHPIX_VERSION,
666                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
667         sTagInfo.put(TAG_COLOR_SPACE,
668                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
669         sTagInfo.put(TAG_COMPONENTS_CONFIGURATION,
670                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
671         sTagInfo.put(TAG_COMPRESSED_BITS_PER_PIXEL,
672                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
673         sTagInfo.put(TAG_PIXEL_X_DIMENSION,
674                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
675         sTagInfo.put(TAG_PIXEL_Y_DIMENSION,
676                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
677         sTagInfo.put(TAG_MAKER_NOTE,
678                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
679         sTagInfo.put(TAG_USER_COMMENT,
680                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
681         sTagInfo.put(TAG_RELATED_SOUND_FILE,
682                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 13);
683         sTagInfo.put(TAG_DATE_TIME_ORIGINAL,
684                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20);
685         sTagInfo.put(TAG_DATE_TIME_DIGITIZED,
686                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20);
687         sTagInfo.put(TAG_SUB_SEC_TIME,
688                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
689         sTagInfo.put(TAG_SUB_SEC_TIME_ORIGINAL,
690                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
691         sTagInfo.put(TAG_SUB_SEC_TIME_DIGITIZED,
692                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
693         sTagInfo.put(TAG_IMAGE_UNIQUE_ID,
694                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 33);
695         sTagInfo.put(TAG_EXPOSURE_TIME,
696                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
697         sTagInfo.put(TAG_F_NUMBER,
698                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
699         sTagInfo.put(TAG_EXPOSURE_PROGRAM,
700                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
701         sTagInfo.put(TAG_SPECTRAL_SENSITIVITY,
702                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
703         sTagInfo.put(TAG_ISO_SPEED_RATINGS,
704                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED);
705         sTagInfo.put(TAG_OECF,
706                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
707         sTagInfo.put(TAG_SHUTTER_SPEED_VALUE,
708                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
709         sTagInfo.put(TAG_APERTURE_VALUE,
710                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
711         sTagInfo.put(TAG_BRIGHTNESS_VALUE,
712                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
713         sTagInfo.put(TAG_EXPOSURE_BIAS_VALUE,
714                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
715         sTagInfo.put(TAG_MAX_APERTURE_VALUE,
716                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
717         sTagInfo.put(TAG_SUBJECT_DISTANCE,
718                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
719         sTagInfo.put(TAG_METERING_MODE,
720                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
721         sTagInfo.put(TAG_LIGHT_SOURCE,
722                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
723         sTagInfo.put(TAG_FLASH,
724                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
725         sTagInfo.put(TAG_FOCAL_LENGTH,
726                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
727         sTagInfo.put(TAG_SUBJECT_AREA,
728                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED);
729         sTagInfo.put(TAG_FLASH_ENERGY,
730                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
731         sTagInfo.put(TAG_SPATIAL_FREQUENCY_RESPONSE,
732                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
733         sTagInfo.put(TAG_FOCAL_PLANE_X_RESOLUTION,
734                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
735         sTagInfo.put(TAG_FOCAL_PLANE_Y_RESOLUTION,
736                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
737         sTagInfo.put(TAG_FOCAL_PLANE_RESOLUTION_UNIT,
738                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
739         sTagInfo.put(TAG_SUBJECT_LOCATION,
740                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 2);
741         sTagInfo.put(TAG_EXPOSURE_INDEX,
742                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
743         sTagInfo.put(TAG_SENSING_METHOD,
744                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
745         sTagInfo.put(TAG_FILE_SOURCE,
746                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1);
747         sTagInfo.put(TAG_SCENE_TYPE,
748                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1);
749         sTagInfo.put(TAG_CFA_PATTERN,
750                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
751         sTagInfo.put(TAG_CUSTOM_RENDERED,
752                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
753         sTagInfo.put(TAG_EXPOSURE_MODE,
754                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
755         sTagInfo.put(TAG_WHITE_BALANCE,
756                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
757         sTagInfo.put(TAG_DIGITAL_ZOOM_RATIO,
758                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
759         sTagInfo.put(TAG_FOCAL_LENGTH_IN_35_MM_FILE,
760                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
761         sTagInfo.put(TAG_SCENE_CAPTURE_TYPE,
762                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
763         sTagInfo.put(TAG_GAIN_CONTROL,
764                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
765         sTagInfo.put(TAG_CONTRAST,
766                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
767         sTagInfo.put(TAG_SATURATION,
768                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
769         sTagInfo.put(TAG_SHARPNESS,
770                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
771         sTagInfo.put(TAG_DEVICE_SETTING_DESCRIPTION,
772                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
773         sTagInfo.put(TAG_SUBJECT_DISTANCE_RANGE,
774                 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
775         // GPS tag
776         sTagInfo.put(TAG_GPS_VERSION_ID,
777                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 4);
778         sTagInfo.put(TAG_GPS_LATITUDE_REF,
779                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
780         sTagInfo.put(TAG_GPS_LONGITUDE_REF,
781                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
782         sTagInfo.put(TAG_GPS_LATITUDE,
783                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3);
784         sTagInfo.put(TAG_GPS_LONGITUDE,
785                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3);
786         sTagInfo.put(TAG_GPS_ALTITUDE_REF,
787                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 1);
788         sTagInfo.put(TAG_GPS_ALTITUDE,
789                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
790         sTagInfo.put(TAG_GPS_TIME_STAMP,
791                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3);
792         sTagInfo.put(TAG_GPS_SATTELLITES,
793                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
794         sTagInfo.put(TAG_GPS_STATUS,
795                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
796         sTagInfo.put(TAG_GPS_MEASURE_MODE,
797                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
798         sTagInfo.put(TAG_GPS_DOP,
799                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
800         sTagInfo.put(TAG_GPS_SPEED_REF,
801                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
802         sTagInfo.put(TAG_GPS_SPEED,
803                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
804         sTagInfo.put(TAG_GPS_TRACK_REF,
805                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
806         sTagInfo.put(TAG_GPS_TRACK,
807                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
808         sTagInfo.put(TAG_GPS_IMG_DIRECTION_REF,
809                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
810         sTagInfo.put(TAG_GPS_IMG_DIRECTION,
811                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
812         sTagInfo.put(TAG_GPS_MAP_DATUM,
813                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
814         sTagInfo.put(TAG_GPS_DEST_LATITUDE_REF,
815                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
816         sTagInfo.put(TAG_GPS_DEST_LATITUDE,
817                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
818         sTagInfo.put(TAG_GPS_DEST_BEARING_REF,
819                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
820         sTagInfo.put(TAG_GPS_DEST_BEARING,
821                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
822         sTagInfo.put(TAG_GPS_DEST_DISTANCE_REF,
823                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
824         sTagInfo.put(TAG_GPS_DEST_DISTANCE,
825                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
826         sTagInfo.put(TAG_GPS_PROCESSING_METHOD,
827                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
828         sTagInfo.put(TAG_GPS_AREA_INFORMATION,
829                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
830         sTagInfo.put(TAG_GPS_DATA_STAMP,
831                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 11);
832         sTagInfo.put(TAG_GPS_DIFFERENTIAL,
833                 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_SHORT << 16 | 11);
834     }
835
836     private final short mTagId;
837     private final short mDataType;
838     private final int mIfd;
839     private final boolean mComponentCountDefined;
840     private int mComponentCount;
841     private Object mValue;
842     private int mOffset;
843
844     static private short getTypeFromInfo(int info) {
845         return (short) ((info >> 16) & 0xff);
846     }
847
848     static private int getComponentCountFromInfo(int info) {
849         return info & 0xffff;
850     }
851
852     static private int getIfdIdFromInfo(int info) {
853         return (info >> 24) & 0xff;
854     }
855
856     static private boolean getComponentCountDefined(short tagId, int ifd) {
857         Integer info = (ifd == IfdId.TYPE_IFD_INTEROPERABILITY) ?
858                 getInteroperTagInfo().get(tagId) : getTagInfo().get(tagId);
859         if (info == null) return false;
860         return getComponentCountFromInfo(info) != SIZE_UNDEFINED;
861     }
862
863     static int getIfdIdFromTagId(short tagId) {
864         Integer info = getTagInfo().get(tagId);
865         if (info == null) {
866             throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
867         }
868         return getIfdIdFromInfo(info);
869     }
870
871     /**
872      * Create a tag with given ID. For tags related to interoperability and thumbnail, call
873      * {@link #buildInteroperabilityTag(short)} and {@link #buildThumbnailTag(short)} respectively.
874      * @exception IllegalArgumentException If the ID is invalid.
875      */
876     static public ExifTag buildTag(short tagId) {
877         Integer info = getTagInfo().get(tagId);
878         if (info == null) {
879             throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
880         }
881         return new ExifTag(tagId, getTypeFromInfo(info),
882                 getComponentCountFromInfo(info),
883                 getIfdIdFromInfo(info));
884     }
885
886     /**
887      * Create a tag related to thumbnail with given ID.
888      * @exception IllegalArgumentException If the ID is invalid.
889      */
890     static public ExifTag buildThumbnailTag(short tagId) {
891         Integer info = getTagInfo().get(tagId);
892         if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_0) {
893             throw new IllegalArgumentException("Unknown Thumnail Tag ID: " + tagId);
894         }
895         return new ExifTag(tagId, getTypeFromInfo(info),
896                 getComponentCountFromInfo(info),
897                 IfdId.TYPE_IFD_1);
898     }
899
900     /**
901      * Create a tag related to interoperability with given ID.
902      * @exception IllegalArgumentException If the ID is invalid.
903      */
904     static public ExifTag buildInteroperabilityTag(short tagId) {
905         Integer info = getInteroperTagInfo().get(tagId);
906         if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_INTEROPERABILITY) {
907             throw new RuntimeException("Unknown Interoperability Tag ID: " + tagId);
908         }
909         return new ExifTag(tagId, getTypeFromInfo(info),
910                 getComponentCountFromInfo(info),
911                 IfdId.TYPE_IFD_INTEROPERABILITY);
912     }
913
914     ExifTag(short tagId, short type, int componentCount, int ifd) {
915         mTagId = tagId;
916         mDataType = type;
917         mComponentCount = componentCount;
918         mComponentCountDefined = getComponentCountDefined(tagId, ifd);
919         mIfd = ifd;
920     }
921
922     /**
923      * Returns the ID of the IFD this tag belongs to.
924      *
925      * @see IfdId#TYPE_IFD_0
926      * @see IfdId#TYPE_IFD_1
927      * @see IfdId#TYPE_IFD_EXIF
928      * @see IfdId#TYPE_IFD_GPS
929      * @see IfdId#TYPE_IFD_INTEROPERABILITY
930      */
931     public int getIfd() {
932         return mIfd;
933     }
934
935     /**
936      * Gets the ID of this tag.
937      */
938     public short getTagId() {
939         return mTagId;
940     }
941
942     /**
943      * Gets the data type of this tag
944      *
945      * @see #TYPE_ASCII
946      * @see #TYPE_LONG
947      * @see #TYPE_RATIONAL
948      * @see #TYPE_UNDEFINED
949      * @see #TYPE_UNSIGNED_BYTE
950      * @see #TYPE_UNSIGNED_LONG
951      * @see #TYPE_UNSIGNED_RATIONAL
952      * @see #TYPE_UNSIGNED_SHORT
953      */
954     public short getDataType() {
955         return mDataType;
956     }
957
958     /**
959      * Gets the total data size in bytes of the value of this tag.
960      */
961     public int getDataSize() {
962         return getComponentCount() * getElementSize(getDataType());
963     }
964
965     /**
966      * Gets the component count of this tag.
967      */
968     public int getComponentCount() {
969         return mComponentCount;
970     }
971
972     /**
973      * Returns true if this ExifTag contains value; otherwise, this tag will contain an offset value
974      * that links to the area where the actual value is located.
975      *
976      * @see #getOffset()
977      */
978     public boolean hasValue() {
979         return mValue != null;
980     }
981
982     /**
983      * Gets the offset of this tag. This is only valid if this data size > 4 and contains an offset
984      * to the location of the actual value.
985      */
986     public int getOffset() {
987         return mOffset;
988     }
989
990     /**
991      * Sets the offset of this tag.
992      */
993     void setOffset(int offset) {
994         mOffset = offset;
995     }
996
997     private void checkComponentCountOrThrow(int count)
998             throws IllegalArgumentException {
999         if (mComponentCountDefined && (mComponentCount != count)) {
1000             throw new IllegalArgumentException("Tag " + mTagId + ": Required "
1001                     + mComponentCount + " components but was given " + count
1002                     + " component(s)");
1003         }
1004     }
1005
1006     private void throwTypeNotMatchedException(String className)
1007             throws IllegalArgumentException {
1008         throw new IllegalArgumentException("Tag " + mTagId + ": expect type " +
1009                 convertTypeToString(mDataType) + " but got " + className);
1010     }
1011
1012     private static String convertTypeToString(short type) {
1013         switch (type) {
1014             case TYPE_UNSIGNED_BYTE:
1015                 return "UNSIGNED_BYTE";
1016             case TYPE_ASCII:
1017                 return "ASCII";
1018             case TYPE_UNSIGNED_SHORT:
1019                 return "UNSIGNED_SHORT";
1020             case TYPE_UNSIGNED_LONG:
1021                 return "UNSIGNED_LONG";
1022             case TYPE_UNSIGNED_RATIONAL:
1023                 return "UNSIGNED_RATIONAL";
1024             case TYPE_UNDEFINED:
1025                 return "UNDEFINED";
1026             case TYPE_LONG:
1027                 return "LONG";
1028             case TYPE_RATIONAL:
1029                 return "RATIONAL";
1030             default:
1031                 return "";
1032         }
1033     }
1034
1035     private static final int UNSIGNED_SHORT_MAX = 65535;
1036     private static final long UNSIGNED_LONG_MAX = 4294967295L;
1037     private static final long LONG_MAX = Integer.MAX_VALUE;
1038     private static final long LONG_MIN = Integer.MIN_VALUE;
1039
1040     private void checkOverflowForUnsignedShort(int[] value) {
1041         for (int v : value) {
1042             if (v > UNSIGNED_SHORT_MAX || v < 0) {
1043                 throw new IllegalArgumentException(
1044                         "Tag " + mTagId+ ": Value" + v +
1045                         " is illegal for type UNSIGNED_SHORT");
1046             }
1047         }
1048     }
1049
1050     private void checkOverflowForUnsignedLong(long[] value) {
1051         for (long v: value) {
1052             if (v < 0 || v > UNSIGNED_LONG_MAX) {
1053                 throw new IllegalArgumentException(
1054                         "Tag " + mTagId+ ": Value" + v +
1055                         " is illegal for type UNSIGNED_LONG");
1056             }
1057         }
1058     }
1059
1060     private void checkOverflowForUnsignedLong(int[] value) {
1061         for (int v: value) {
1062             if (v < 0) {
1063                 throw new IllegalArgumentException(
1064                         "Tag " + mTagId+ ": Value" + v +
1065                         " is illegal for type UNSIGNED_LONG");
1066             }
1067         }
1068     }
1069
1070     private void checkOverflowForUnsignedRational(Rational[] value) {
1071         for (Rational v: value) {
1072             if (v.getNominator() < 0 || v.getDenominator() < 0
1073                     || v.getNominator() > UNSIGNED_LONG_MAX
1074                     || v.getDenominator() > UNSIGNED_LONG_MAX) {
1075                 throw new IllegalArgumentException(
1076                         "Tag " + mTagId+ ": Value" + v +
1077                         " is illegal for type UNSIGNED_RATIONAL");
1078             }
1079         }
1080     }
1081
1082     private void checkOverflowForRational(Rational[] value) {
1083         for (Rational v: value) {
1084             if (v.getNominator() < LONG_MIN || v.getDenominator() < LONG_MIN
1085                     || v.getNominator() > LONG_MAX
1086                     || v.getDenominator() > LONG_MAX) {
1087                 throw new IllegalArgumentException(
1088                         "Tag " + mTagId+ ": Value" + v +
1089                         " is illegal for type RATIONAL");
1090             }
1091         }
1092     }
1093
1094     /**
1095      * Sets integer values into this tag.
1096      * @exception IllegalArgumentException for the following situation:
1097      * <ul>
1098      *     <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
1099      *      {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
1100      *     <li>The value overflows. </li>
1101      *     <li>The value.length does NOT match the definition of component count in
1102      *      EXIF standard.</li>
1103      * </ul>
1104      */
1105     public void setValue(int[] value) {
1106         checkComponentCountOrThrow(value.length);
1107         if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG &&
1108                 mDataType != TYPE_UNSIGNED_LONG) {
1109             throwTypeNotMatchedException("int");
1110         }
1111         if (mDataType == TYPE_UNSIGNED_SHORT) {
1112             checkOverflowForUnsignedShort(value);
1113         } else if (mDataType == TYPE_UNSIGNED_LONG) {
1114             checkOverflowForUnsignedLong(value);
1115         }
1116
1117         long[] data = new long[value.length];
1118         for (int i = 0; i < value.length; i++) {
1119             data[i] = value[i];
1120         }
1121         mValue = data;
1122         mComponentCount = value.length;
1123     }
1124
1125     /**
1126      * Sets integer values into this tag.
1127      * @exception IllegalArgumentException For the following situation:
1128      * <ul>
1129      *     <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
1130      *      {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
1131      *     <li>The value overflows.</li>
1132      *     <li>The component count in the definition of EXIF standard is not 1.</li>
1133      * </ul>
1134      */
1135     public void setValue(int value) {
1136         checkComponentCountOrThrow(1);
1137         setValue(new int[] {value});
1138     }
1139
1140     /**
1141      * Sets long values into this tag.
1142      * @exception IllegalArgumentException For the following situation:
1143      * <ul>
1144      *      <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
1145      *      <li>The value overflows. </li>
1146      *      <li>The value.length does NOT match the definition of component count in
1147      *       EXIF standard.</li>
1148      * </ul>
1149      */
1150     public void setValue(long[] value) {
1151         checkComponentCountOrThrow(value.length);
1152         if (mDataType != TYPE_UNSIGNED_LONG) {
1153             throwTypeNotMatchedException("long");
1154         }
1155         checkOverflowForUnsignedLong(value);
1156         mValue = value;
1157         mComponentCount = value.length;
1158     }
1159
1160     /**
1161      * Sets long values into this tag.
1162      * @exception IllegalArgumentException For the following situation:
1163      * <ul>
1164      *     <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
1165      *     <li>The value overflows. </li>
1166      *     <li>The component count in the definition of EXIF standard is not 1.</li>
1167      * </ul>
1168      */
1169     public void setValue(long value) {
1170         setValue(new long[] {value});
1171     }
1172
1173     /**
1174      * Sets string values into this tag.
1175      * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII}
1176      * or value.length() + 1 does NOT fit the definition of the component count in the
1177      * EXIF standard.
1178      */
1179     public void setValue(String value) {
1180         checkComponentCountOrThrow(value.length() + 1);
1181         if (mDataType != TYPE_ASCII) {
1182             throwTypeNotMatchedException("String");
1183         }
1184         mComponentCount = value.length() + 1;
1185         mValue = value;
1186     }
1187
1188     /**
1189      * Sets Rational values into this tag.
1190      * @exception IllegalArgumentException For the following situation:
1191      * <ul>
1192      *      <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or
1193      *       {@link #TYPE_RATIONAL} .</li>
1194      *      <li>The value overflows. </li>
1195      *      <li>The value.length does NOT match the definition of component count in
1196      *       EXIF standard.</li>
1197      * </ul>
1198      */
1199     public void setValue(Rational[] value) {
1200         if (mDataType == TYPE_UNSIGNED_RATIONAL) {
1201             checkOverflowForUnsignedRational(value);
1202         } else if (mDataType == TYPE_RATIONAL) {
1203             checkOverflowForRational(value);
1204         } else {
1205             throwTypeNotMatchedException("Rational");
1206         }
1207         checkComponentCountOrThrow(value.length);
1208         mValue = value;
1209         mComponentCount = value.length;
1210     }
1211
1212     /**
1213      * Sets Rational values into this tag.
1214      * @exception IllegalArgumentException For the following situation:
1215      * <ul>
1216      *      <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or
1217      *       {@link #TYPE_RATIONAL} .</li>
1218      *      <li>The value overflows. </li>
1219      *      <li>The component count in the definition of EXIF standard is not 1.</li>
1220      * </ul>
1221      * */
1222     public void setValue(Rational value) {
1223         setValue(new Rational[] {value});
1224     }
1225
1226     /**
1227      * Sets byte values into this tag.
1228      * @exception IllegalArgumentException For the following situation:
1229      * <ul>
1230      *      <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
1231      *       {@link #TYPE_UNDEFINED} .</li>
1232      *      <li>The length does NOT match the definition of component count in EXIF standard.</li>
1233      * </ul>
1234      * */
1235     public void setValue(byte[] value, int offset, int length) {
1236         checkComponentCountOrThrow(length);
1237         if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) {
1238             throwTypeNotMatchedException("byte");
1239         }
1240         mValue = new byte[length];
1241         System.arraycopy(value, offset, mValue, 0, length);
1242         mComponentCount = length;
1243     }
1244
1245     /**
1246      * Equivalent to setValue(value, 0, value.length).
1247      */
1248     public void setValue(byte[] value) {
1249         setValue(value, 0, value.length);
1250     }
1251
1252     private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
1253
1254     /**
1255      * Sets a timestamp to this tag. The method converts the timestamp with the format of
1256      * "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}.
1257      *
1258      * @param time the number of milliseconds since Jan. 1, 1970 GMT
1259      * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII}
1260      * or the component count of this tag is not 20 or undefined
1261      */
1262     public void setTimeValue(long time) {
1263         // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe
1264         synchronized (TIME_FORMAT) {
1265             setValue(TIME_FORMAT.format(new Date(time)));
1266         }
1267     }
1268
1269     /**
1270      * Gets the {@link #TYPE_UNSIGNED_SHORT} data.
1271      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_SHORT}.
1272      */
1273     public int getUnsignedShort(int index) {
1274         if (mDataType != TYPE_UNSIGNED_SHORT) {
1275             throw new IllegalArgumentException("Cannot get UNSIGNED_SHORT value from "
1276                     + convertTypeToString(mDataType));
1277         }
1278         return (int) (((long[]) mValue) [index]);
1279     }
1280
1281     /**
1282      * Gets the {@link #TYPE_LONG} data.
1283      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_LONG}.
1284      */
1285     public int getLong(int index) {
1286         if (mDataType != TYPE_LONG) {
1287             throw new IllegalArgumentException("Cannot get LONG value from "
1288                     + convertTypeToString(mDataType));
1289         }
1290         return (int) (((long[]) mValue) [index]);
1291     }
1292
1293     /**
1294      * Gets the {@link #TYPE_UNSIGNED_LONG} data.
1295      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_LONG}.
1296      */
1297     public long getUnsignedLong(int index) {
1298         if (mDataType != TYPE_UNSIGNED_LONG) {
1299             throw new IllegalArgumentException("Cannot get UNSIGNED LONG value from "
1300                     + convertTypeToString(mDataType));
1301         }
1302         return ((long[]) mValue) [index];
1303     }
1304
1305     /**
1306      * Gets the {@link #TYPE_ASCII} data.
1307      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_ASCII}.
1308      */
1309     public String getString() {
1310         if (mDataType != TYPE_ASCII) {
1311             throw new IllegalArgumentException("Cannot get ASCII value from "
1312                     + convertTypeToString(mDataType));
1313         }
1314         return (String) mValue;
1315     }
1316
1317     /**
1318      * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data.
1319      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_RATIONAL} or
1320      * {@link #TYPE_UNSIGNED_RATIONAL}.
1321      */
1322     public Rational getRational(int index) {
1323         if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) {
1324             throw new IllegalArgumentException("Cannot get RATIONAL value from "
1325                     + convertTypeToString(mDataType));
1326         }
1327         return ((Rational[]) mValue) [index];
1328     }
1329
1330     /**
1331      * Equivalent to getBytes(buffer, 0, buffer.length).
1332      */
1333     public void getBytes(byte[] buf) {
1334         getBytes(buf, 0, buf.length);
1335     }
1336
1337     /**
1338      * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
1339      *
1340      * @param buf the byte array in which to store the bytes read.
1341      * @param offset the initial position in buffer to store the bytes.
1342      * @param length the maximum number of bytes to store in buffer. If length > component count,
1343      * only the valid bytes will be stored.
1344      *
1345      * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNDEFINED} or
1346      * {@link #TYPE_UNSIGNED_BYTE}.
1347      */
1348     public void getBytes(byte[] buf, int offset, int length) {
1349         if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) {
1350             throw new IllegalArgumentException("Cannot get BYTE value from "
1351                     + convertTypeToString(mDataType));
1352         }
1353         System.arraycopy(mValue, 0, buf, offset,
1354                 (length > mComponentCount) ? mComponentCount : length);
1355     }
1356
1357     private String undefinedTypeValueToString() {
1358         StringBuilder sbuilder = new StringBuilder();
1359         switch (mTagId) {
1360             case TAG_COMPONENTS_CONFIGURATION:
1361             case TAG_FILE_SOURCE:
1362             case TAG_SCENE_TYPE:
1363                 byte buf[] = (byte[]) mValue;
1364                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1365                     if(i != 0) sbuilder.append(" ");
1366                     sbuilder.append(buf[i]);
1367                 }
1368                 break;
1369             default:
1370                 sbuilder.append(new String((byte[]) mValue));
1371         }
1372         return sbuilder.toString();
1373     }
1374
1375     /**
1376      * Returns a string representation of the value of this tag.
1377      */
1378     String valueToString() {
1379         StringBuilder sbuilder = new StringBuilder();
1380         switch (getDataType()) {
1381             case ExifTag.TYPE_UNDEFINED:
1382                 sbuilder.append(undefinedTypeValueToString());
1383                 break;
1384             case ExifTag.TYPE_UNSIGNED_BYTE:
1385                 byte buf[] = (byte[]) mValue;
1386                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1387                     if(i != 0) sbuilder.append(" ");
1388                     sbuilder.append(buf[i]);
1389                 }
1390                 break;
1391             case ExifTag.TYPE_ASCII:
1392                 String s = getString();
1393                 for (int i = 0, n = s.length(); i < n; i++) {
1394                     int code = s.codePointAt(i);
1395                     if (code == 0) continue;
1396                     if (code > 31 && code < 127) {
1397                         sbuilder.append((char) code);
1398                     } else {
1399                         sbuilder.append('.');
1400                     }
1401                 }
1402                 break;
1403             case ExifTag.TYPE_UNSIGNED_LONG:
1404                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1405                     if(i != 0) sbuilder.append(" ");
1406                     sbuilder.append(getUnsignedLong(i));
1407                 }
1408                 break;
1409             case ExifTag.TYPE_RATIONAL:
1410             case ExifTag.TYPE_UNSIGNED_RATIONAL:
1411                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1412                     Rational r = getRational(i);
1413                     if(i != 0) sbuilder.append(" ");
1414                     sbuilder.append(r.getNominator()).append("/").append(r.getDenominator());
1415                 }
1416                 break;
1417             case ExifTag.TYPE_UNSIGNED_SHORT:
1418                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1419                     if(i != 0) sbuilder.append(" ");
1420                     sbuilder.append(getUnsignedShort(i));
1421                 }
1422                 break;
1423             case ExifTag.TYPE_LONG:
1424                 for(int i = 0, n = getComponentCount(); i < n; i++) {
1425                     if(i != 0) sbuilder.append(" ");
1426                     sbuilder.append(getLong(i));
1427                 }
1428                 break;
1429         }
1430         return sbuilder.toString();
1431     }
1432
1433     /**
1434      * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1435      * {@link #TAG_GPS_IFD}, {@link #TAG_JPEG_INTERCHANGE_FORMAT},
1436      * {@link #TAG_STRIP_OFFSETS}, {@link #TAG_INTEROPERABILITY_IFD}
1437      */
1438     static boolean isOffsetTag(short tagId) {
1439         return tagId == TAG_EXIF_IFD
1440                 || tagId == TAG_GPS_IFD
1441                 || tagId == TAG_JPEG_INTERCHANGE_FORMAT
1442                 || tagId == TAG_STRIP_OFFSETS
1443                 || tagId == TAG_INTEROPERABILITY_IFD;
1444     }
1445
1446     /**
1447      * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1448      * {@link #TAG_GPS_IFD}, {@link #TAG_INTEROPERABILITY_IFD}
1449      */
1450     static boolean isSubIfdOffsetTag(short tagId) {
1451         return tagId == TAG_EXIF_IFD
1452                 || tagId == TAG_GPS_IFD
1453                 || tagId == TAG_INTEROPERABILITY_IFD;
1454     }
1455     @Override
1456     public boolean equals(Object obj) {
1457         if (obj instanceof ExifTag) {
1458             ExifTag tag = (ExifTag) obj;
1459             if (mValue != null) {
1460                 if (mValue instanceof long[]) {
1461                     if (!(tag.mValue instanceof long[])) return false;
1462                     return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
1463                 } else if (mValue instanceof Rational[]) {
1464                     if (!(tag.mValue instanceof Rational[])) return false;
1465                     return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
1466                 } else if (mValue instanceof byte[]) {
1467                     if (!(tag.mValue instanceof byte[])) return false;
1468                     return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
1469                 } else {
1470                     return mValue.equals(tag.mValue);
1471                 }
1472             } else {
1473                 return tag.mValue == null;
1474             }
1475         }
1476         return false;
1477     }
1478 }