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