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