• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       */
getElementSize(short type)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  
getTagInfo()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  
getInteroperTagInfo()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  
initTagInfo()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  
getTypeFromInfo(int info)844      static private short getTypeFromInfo(int info) {
845          return (short) ((info >> 16) & 0xff);
846      }
847  
getComponentCountFromInfo(int info)848      static private int getComponentCountFromInfo(int info) {
849          return info & 0xffff;
850      }
851  
getIfdIdFromInfo(int info)852      static private int getIfdIdFromInfo(int info) {
853          return (info >> 24) & 0xff;
854      }
855  
getComponentCountDefined(short tagId, int ifd)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  
getIfdIdFromTagId(short tagId)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       */
buildTag(short tagId)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       */
buildThumbnailTag(short tagId)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       */
buildInteroperabilityTag(short tagId)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  
ExifTag(short tagId, short type, int componentCount, int ifd)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       */
getIfd()931      public int getIfd() {
932          return mIfd;
933      }
934  
935      /**
936       * Gets the ID of this tag.
937       */
getTagId()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       */
getDataType()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       */
getDataSize()961      public int getDataSize() {
962          return getComponentCount() * getElementSize(getDataType());
963      }
964  
965      /**
966       * Gets the component count of this tag.
967       */
getComponentCount()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       */
hasValue()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       */
getOffset()986      public int getOffset() {
987          return mOffset;
988      }
989  
990      /**
991       * Sets the offset of this tag.
992       */
setOffset(int offset)993      void setOffset(int offset) {
994          mOffset = offset;
995      }
996  
checkComponentCountOrThrow(int count)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  
throwTypeNotMatchedException(String className)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  
convertTypeToString(short type)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  
checkOverflowForUnsignedShort(int[] value)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  
checkOverflowForUnsignedLong(long[] value)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  
checkOverflowForUnsignedLong(int[] value)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  
checkOverflowForUnsignedRational(Rational[] value)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  
checkOverflowForRational(Rational[] value)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       */
setValue(int[] value)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       */
setValue(int value)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       */
setValue(long[] value)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       */
setValue(long value)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       */
setValue(String value)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       */
setValue(Rational[] value)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       * */
setValue(Rational value)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       * */
setValue(byte[] value, int offset, int length)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       */
setValue(byte[] value)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       */
setTimeValue(long time)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       */
getUnsignedShort(int index)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       */
getLong(int index)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       */
getUnsignedLong(int index)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       */
getString()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       */
getRational(int index)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       */
getBytes(byte[] buf)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       */
getBytes(byte[] buf, int offset, int length)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       */
valueToString()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       */
isOffsetTag(short tagId)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
equals(Object obj)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