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
17package com.android.gallery3d.exif;
18
19import android.util.SparseArray;
20
21import java.text.SimpleDateFormat;
22import java.util.Arrays;
23import 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 */
32public 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    /**
1358     * Returns a string representation of the value of this tag.
1359     */
1360    public String valueToString() {
1361        StringBuilder sbuilder = new StringBuilder();
1362        switch (getDataType()) {
1363            case ExifTag.TYPE_UNDEFINED:
1364            case ExifTag.TYPE_UNSIGNED_BYTE:
1365                byte buf[] = new byte[getComponentCount()];
1366                getBytes(buf);
1367                for(int i = 0, n = getComponentCount(); i < n; i++) {
1368                    if(i != 0) sbuilder.append(" ");
1369                    sbuilder.append(String.format("%02x", buf[i]));
1370                }
1371                break;
1372            case ExifTag.TYPE_ASCII:
1373                sbuilder.append(getString());
1374                break;
1375            case ExifTag.TYPE_UNSIGNED_LONG:
1376                for(int i = 0, n = getComponentCount(); i < n; i++) {
1377                    if(i != 0) sbuilder.append(" ");
1378                    sbuilder.append(getUnsignedLong(i));
1379                }
1380                break;
1381            case ExifTag.TYPE_RATIONAL:
1382            case ExifTag.TYPE_UNSIGNED_RATIONAL:
1383                for(int i = 0, n = getComponentCount(); i < n; i++) {
1384                    Rational r = getRational(i);
1385                    if(i != 0) sbuilder.append(" ");
1386                    sbuilder.append(r.getNominator()).append("/").append(r.getDenominator());
1387                }
1388                break;
1389            case ExifTag.TYPE_UNSIGNED_SHORT:
1390                for(int i = 0, n = getComponentCount(); i < n; i++) {
1391                    if(i != 0) sbuilder.append(" ");
1392                    sbuilder.append(getUnsignedShort(i));
1393                }
1394                break;
1395            case ExifTag.TYPE_LONG:
1396                for(int i = 0, n = getComponentCount(); i < n; i++) {
1397                    if(i != 0) sbuilder.append(" ");
1398                    sbuilder.append(getLong(i));
1399                }
1400                break;
1401        }
1402        return sbuilder.toString();
1403    }
1404
1405    /**
1406     * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1407     * {@link #TAG_GPS_IFD}, {@link #TAG_JPEG_INTERCHANGE_FORMAT},
1408     * {@link #TAG_STRIP_OFFSETS}, {@link #TAG_INTEROPERABILITY_IFD}
1409     */
1410    static boolean isOffsetTag(short tagId) {
1411        return tagId == TAG_EXIF_IFD
1412                || tagId == TAG_GPS_IFD
1413                || tagId == TAG_JPEG_INTERCHANGE_FORMAT
1414                || tagId == TAG_STRIP_OFFSETS
1415                || tagId == TAG_INTEROPERABILITY_IFD;
1416    }
1417
1418    @Override
1419    public boolean equals(Object obj) {
1420        if (obj instanceof ExifTag) {
1421            ExifTag tag = (ExifTag) obj;
1422            if (mValue != null) {
1423                if (mValue instanceof long[]) {
1424                    if (!(tag.mValue instanceof long[])) return false;
1425                    return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
1426                } else if (mValue instanceof Rational[]) {
1427                    if (!(tag.mValue instanceof Rational[])) return false;
1428                    return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
1429                } else if (mValue instanceof byte[]) {
1430                    if (!(tag.mValue instanceof byte[])) return false;
1431                    return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
1432                } else {
1433                    return mValue.equals(tag.mValue);
1434                }
1435            } else {
1436                return tag.mValue == null;
1437            }
1438        }
1439        return false;
1440    }
1441}
1442