2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.exif;
19 import android.util.SparseArray;
21 import java.nio.charset.Charset;
22 import java.text.SimpleDateFormat;
23 import java.util.Arrays;
24 import java.util.Date;
27 * This class stores information of an EXIF tag.
33 public class ExifTag {
35 public static final short TAG_IMAGE_WIDTH = 0x100;
37 * The height of the image.
39 public static final short TAG_IMAGE_LENGTH = 0x101;
40 public static final short TAG_BITS_PER_SAMPLE = 0x102;
41 public static final short TAG_COMPRESSION = 0x103;
42 public static final short TAG_PHOTOMETRIC_INTERPRETATION = 0x106;
43 public static final short TAG_IMAGE_DESCRIPTION = 0x10E;
44 public static final short TAG_MAKE = 0x10F;
45 public static final short TAG_MODEL = 0x110;
46 public static final short TAG_STRIP_OFFSETS = 0x111;
47 public static final short TAG_ORIENTATION = 0x112;
48 public static final short TAG_SAMPLES_PER_PIXEL = 0x115;
49 public static final short TAG_ROWS_PER_STRIP = 0x116;
50 public static final short TAG_STRIP_BYTE_COUNTS = 0x117;
51 public static final short TAG_X_RESOLUTION = 0x11A;
52 public static final short TAG_Y_RESOLUTION = 0x11B;
53 public static final short TAG_PLANAR_CONFIGURATION = 0x11C;
54 public static final short TAG_RESOLUTION_UNIT = 0x128;
55 public static final short TAG_TRANSFER_FUNCTION = 0x12D;
56 public static final short TAG_SOFTWARE = 0x131;
57 public static final short TAG_DATE_TIME = 0x132;
58 public static final short TAG_ARTIST = 0x13B;
59 public static final short TAG_WHITE_POINT = 0x13E;
60 public static final short TAG_PRIMARY_CHROMATICITIES = 0x13F;
61 public static final short TAG_JPEG_INTERCHANGE_FORMAT = 0x201;
62 public static final short TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x202;
63 public static final short TAG_Y_CB_CR_COEFFICIENTS = 0x211;
64 public static final short TAG_Y_CB_CR_SUB_SAMPLING = 0x212;
65 public static final short TAG_Y_CB_CR_POSITIONING = 0x213;
66 public static final short TAG_REFERENCE_BLACK_WHITE = 0x214;
67 public static final short TAG_COPYRIGHT = (short) 0x8298;
68 public static final short TAG_EXIF_IFD = (short) 0x8769;
69 public static final short TAG_GPS_IFD = (short) 0x8825;
72 public static final short TAG_EXPOSURE_TIME = (short) 0x829A;
73 public static final short TAG_F_NUMBER = (short) 0x829D;
74 public static final short TAG_EXPOSURE_PROGRAM = (short) 0x8822;
75 public static final short TAG_SPECTRAL_SENSITIVITY = (short) 0x8824;
76 public static final short TAG_ISO_SPEED_RATINGS = (short) 0x8827;
77 public static final short TAG_OECF = (short) 0x8828;
78 public static final short TAG_EXIF_VERSION = (short) 0x9000;
79 public static final short TAG_DATE_TIME_ORIGINAL = (short) 0x9003;
80 public static final short TAG_DATE_TIME_DIGITIZED = (short) 0x9004;
81 public static final short TAG_COMPONENTS_CONFIGURATION = (short) 0x9101;
82 public static final short TAG_COMPRESSED_BITS_PER_PIXEL = (short) 0x9102;
83 public static final short TAG_SHUTTER_SPEED_VALUE = (short) 0x9201;
84 public static final short TAG_APERTURE_VALUE = (short) 0x9202;
85 public static final short TAG_BRIGHTNESS_VALUE = (short) 0x9203;
86 public static final short TAG_EXPOSURE_BIAS_VALUE = (short) 0x9204;
87 public static final short TAG_MAX_APERTURE_VALUE = (short) 0x9205;
88 public static final short TAG_SUBJECT_DISTANCE = (short) 0x9206;
89 public static final short TAG_METERING_MODE = (short) 0x9207;
90 public static final short TAG_LIGHT_SOURCE = (short) 0x9208;
91 public static final short TAG_FLASH = (short) 0x9209;
92 public static final short TAG_FOCAL_LENGTH = (short) 0x920A;
93 public static final short TAG_SUBJECT_AREA = (short) 0x9214;
94 public static final short TAG_MAKER_NOTE = (short) 0x927C;
95 public static final short TAG_USER_COMMENT = (short) 0x9286;
96 public static final short TAG_SUB_SEC_TIME = (short) 0x9290;
97 public static final short TAG_SUB_SEC_TIME_ORIGINAL = (short) 0x9291;
98 public static final short TAG_SUB_SEC_TIME_DIGITIZED = (short) 0x9292;
99 public static final short TAG_FLASHPIX_VERSION = (short) 0xA000;
100 public static final short TAG_COLOR_SPACE = (short) 0xA001;
101 public static final short TAG_PIXEL_X_DIMENSION = (short) 0xA002;
102 public static final short TAG_PIXEL_Y_DIMENSION = (short) 0xA003;
103 public static final short TAG_RELATED_SOUND_FILE = (short) 0xA004;
104 public static final short TAG_INTEROPERABILITY_IFD = (short) 0xA005;
105 public static final short TAG_FLASH_ENERGY = (short) 0xA20B;
106 public static final short TAG_SPATIAL_FREQUENCY_RESPONSE = (short) 0xA20C;
107 public static final short TAG_FOCAL_PLANE_X_RESOLUTION = (short) 0xA20E;
108 public static final short TAG_FOCAL_PLANE_Y_RESOLUTION = (short) 0xA20F;
109 public static final short TAG_FOCAL_PLANE_RESOLUTION_UNIT = (short) 0xA210;
110 public static final short TAG_SUBJECT_LOCATION = (short) 0xA214;
111 public static final short TAG_EXPOSURE_INDEX = (short) 0xA215;
112 public static final short TAG_SENSING_METHOD = (short) 0xA217;
113 public static final short TAG_FILE_SOURCE = (short) 0xA300;
114 public static final short TAG_SCENE_TYPE = (short) 0xA301;
115 public static final short TAG_CFA_PATTERN = (short) 0xA302;
116 public static final short TAG_CUSTOM_RENDERED = (short) 0xA401;
117 public static final short TAG_EXPOSURE_MODE = (short) 0xA402;
118 public static final short TAG_WHITE_BALANCE = (short) 0xA403;
119 public static final short TAG_DIGITAL_ZOOM_RATIO = (short) 0xA404;
120 public static final short TAG_FOCAL_LENGTH_IN_35_MM_FILE = (short) 0xA405;
121 public static final short TAG_SCENE_CAPTURE_TYPE = (short) 0xA406;
122 public static final short TAG_GAIN_CONTROL = (short) 0xA407;
123 public static final short TAG_CONTRAST = (short) 0xA408;
124 public static final short TAG_SATURATION = (short) 0xA409;
125 public static final short TAG_SHARPNESS = (short) 0xA40A;
126 public static final short TAG_DEVICE_SETTING_DESCRIPTION = (short) 0xA40B;
127 public static final short TAG_SUBJECT_DISTANCE_RANGE = (short) 0xA40C;
128 public static final short TAG_IMAGE_UNIQUE_ID = (short) 0xA420;
131 public static final short TAG_GPS_VERSION_ID = 0;
132 public static final short TAG_GPS_LATITUDE_REF = 1;
133 public static final short TAG_GPS_LATITUDE = 2;
134 public static final short TAG_GPS_LONGITUDE_REF = 3;
135 public static final short TAG_GPS_LONGITUDE = 4;
136 public static final short TAG_GPS_ALTITUDE_REF = 5;
137 public static final short TAG_GPS_ALTITUDE = 6;
138 public static final short TAG_GPS_TIME_STAMP = 7;
139 public static final short TAG_GPS_SATTELLITES = 8;
140 public static final short TAG_GPS_STATUS = 9;
141 public static final short TAG_GPS_MEASURE_MODE = 10;
142 public static final short TAG_GPS_DOP = 11;
143 public static final short TAG_GPS_SPEED_REF = 12;
144 public static final short TAG_GPS_SPEED = 13;
145 public static final short TAG_GPS_TRACK_REF = 14;
146 public static final short TAG_GPS_TRACK = 15;
147 public static final short TAG_GPS_IMG_DIRECTION_REF = 16;
148 public static final short TAG_GPS_IMG_DIRECTION = 17;
149 public static final short TAG_GPS_MAP_DATUM = 18;
150 public static final short TAG_GPS_DEST_LATITUDE_REF = 19;
151 public static final short TAG_GPS_DEST_LATITUDE = 20;
152 public static final short TAG_GPS_DEST_LONGITUDE_REF = 21;
153 public static final short TAG_GPS_DEST_LONGITUDE = 22;
154 public static final short TAG_GPS_DEST_BEARING_REF = 23;
155 public static final short TAG_GPS_DEST_BEARING = 24;
156 public static final short TAG_GPS_DEST_DISTANCE_REF = 25;
157 public static final short TAG_GPS_DEST_DISTANCE = 26;
158 public static final short TAG_GPS_PROCESSING_METHOD = 27;
159 public static final short TAG_GPS_AREA_INFORMATION = 28;
160 public static final short TAG_GPS_DATE_STAMP = 29;
161 public static final short TAG_GPS_DIFFERENTIAL = 30;
163 // Interoperability tag
164 public static final short TAG_INTEROPERABILITY_INDEX = 1;
167 * Constants for {@link #TAG_ORIENTATION}
169 public static interface Orientation {
170 public static final short TOP_LEFT = 1;
171 public static final short TOP_RIGHT = 2;
172 public static final short BOTTOM_LEFT = 3;
173 public static final short BOTTOM_RIGHT = 4;
174 public static final short LEFT_TOP = 5;
175 public static final short RIGHT_TOP = 6;
176 public static final short LEFT_BOTTOM = 7;
177 public static final short RIGHT_BOTTOM = 8;
181 * Constants for {@link #TAG_Y_CB_CR_POSITIONING}
183 public static interface YCbCrPositioning {
184 public static final short CENTERED = 1;
185 public static final short CO_SITED = 2;
189 * Constants for {@link #TAG_COMPRESSION}
191 public static interface Compression {
192 public static final short UNCOMPRESSION = 1;
193 public static final short JPEG = 6;
197 * Constants for {@link #TAG_RESOLUTION_UNIT}
199 public static interface ResolutionUnit {
200 public static final short INCHES = 2;
201 public static final short CENTIMETERS = 3;
205 * Constants for {@link #TAG_PHOTOMETRIC_INTERPRETATION}
207 public static interface PhotometricInterpretation {
208 public static final short RGB = 2;
209 public static final short YCBCR = 6;
213 * Constants for {@link #TAG_PLANAR_CONFIGURATION}
215 public static interface PlanarConfiguration {
216 public static final short CHUNKY = 1;
217 public static final short PLANAR = 2;
221 * Constants for {@link #TAG_EXPOSURE_PROGRAM}
223 public static interface ExposureProgram {
224 public static final short NOT_DEFINED = 0;
225 public static final short MANUAL = 1;
226 public static final short NORMAL_PROGRAM = 2;
227 public static final short APERTURE_PRIORITY = 3;
228 public static final short SHUTTER_PRIORITY = 4;
229 public static final short CREATIVE_PROGRAM = 5;
230 public static final short ACTION_PROGRAM = 6;
231 public static final short PROTRAIT_MODE = 7;
232 public static final short LANDSCAPE_MODE = 8;
236 * Constants for {@link #TAG_METERING_MODE}
238 public static interface MeteringMode {
239 public static final short UNKNOWN = 0;
240 public static final short AVERAGE = 1;
241 public static final short CENTER_WEIGHTED_AVERAGE = 2;
242 public static final short SPOT = 3;
243 public static final short MULTISPOT = 4;
244 public static final short PATTERN = 5;
245 public static final short PARTAIL = 6;
246 public static final short OTHER = 255;
250 * Constants for {@link #TAG_FLASH} As the definition in Jeita EXIF 2.2 standard, we can
251 * treat this constant as bitwise flag.
255 * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED | MODE_AUTO_MODE
257 public static interface Flash {
259 public static final short DID_NOT_FIRED = 0;
260 public static final short FIRED = 1;
262 public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1;
263 public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1;
264 public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1;
266 public static final short MODE_UNKNOWN = 0 << 3;
267 public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3;
268 public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3;
269 public static final short MODE_AUTO_MODE = 3 << 3;
271 public static final short FUNCTION_PRESENT = 0 << 5;
272 public static final short FUNCTION_NO_FUNCTION = 1 << 5;
274 public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
275 public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
279 * Constants for {@link #TAG_COLOR_SPACE}
281 public static interface ColorSpace {
282 public static final short SRGB = 1;
283 public static final short UNCALIBRATED = (short) 0xFFFF;
287 * Constants for {@link #TAG_EXPOSURE_MODE}
289 public static interface ExposureMode {
290 public static final short AUTO_EXPOSURE = 0;
291 public static final short MANUAL_EXPOSURE = 1;
292 public static final short AUTO_BRACKET = 2;
296 * Constants for {@link #TAG_WHITE_BALANCE}
298 public static interface WhiteBalance {
299 public static final short AUTO = 0;
300 public static final short MANUAL = 1;
304 * Constants for {@link #TAG_SCENE_CAPTURE_TYPE}
306 public static interface SceneCapture {
307 public static final short STANDARD = 0;
308 public static final short LANDSCAPE = 1;
309 public static final short PROTRAIT = 2;
310 public static final short NIGHT_SCENE = 3;
314 * Constants for {@link #TAG_COMPONENTS_CONFIGURATION}
316 public static interface ComponentsConfiguration {
317 public static final short NOT_EXIST = 0;
318 public static final short Y = 1;
319 public static final short CB = 2;
320 public static final short CR = 3;
321 public static final short R = 4;
322 public static final short G = 5;
323 public static final short B = 6;
327 * Constants for {@link #TAG_LIGHT_SOURCE}
329 public static interface LightSource {
330 public static final short UNKNOWN = 0;
331 public static final short DAYLIGHT = 1;
332 public static final short FLUORESCENT = 2;
333 public static final short TUNGSTEN = 3;
334 public static final short FLASH = 4;
335 public static final short FINE_WEATHER = 9;
336 public static final short CLOUDY_WEATHER = 10;
337 public static final short SHADE = 11;
338 public static final short DAYLIGHT_FLUORESCENT = 12;
339 public static final short DAY_WHITE_FLUORESCENT = 13;
340 public static final short COOL_WHITE_FLUORESCENT = 14;
341 public static final short WHITE_FLUORESCENT = 15;
342 public static final short STANDARD_LIGHT_A = 17;
343 public static final short STANDARD_LIGHT_B = 18;
344 public static final short STANDARD_LIGHT_C = 19;
345 public static final short D55 = 20;
346 public static final short D65 = 21;
347 public static final short D75 = 22;
348 public static final short D50 = 23;
349 public static final short ISO_STUDIO_TUNGSTEN = 24;
350 public static final short OTHER = 255;
354 * Constants for {@link #TAG_SENSING_METHOD}
356 public static interface SensingMethod {
357 public static final short NOT_DEFINED = 1;
358 public static final short ONE_CHIP_COLOR = 2;
359 public static final short TWO_CHIP_COLOR = 3;
360 public static final short THREE_CHIP_COLOR = 4;
361 public static final short COLOR_SEQUENTIAL_AREA = 5;
362 public static final short TRILINEAR = 7;
363 public static final short COLOR_SEQUENTIAL_LINEAR = 8;
367 * Constants for {@link #TAG_FILE_SOURCE}
369 public static interface FileSource {
370 public static final short DSC = 3;
374 * Constants for {@link #TAG_SCENE_TYPE}
376 public static interface SceneType {
377 public static final short DIRECT_PHOTOGRAPHED = 1;
381 * Constants for {@link #TAG_GAIN_CONTROL}
383 public static interface GainControl {
384 public static final short NONE = 0;
385 public static final short LOW_UP = 1;
386 public static final short HIGH_UP = 2;
387 public static final short LOW_DOWN = 3;
388 public static final short HIGH_DOWN = 4;
392 * Constants for {@link #TAG_CONTRAST}
394 public static interface Contrast {
395 public static final short NORMAL = 0;
396 public static final short SOFT = 1;
397 public static final short HARD = 2;
401 * Constants for {@link #TAG_SATURATION}
403 public static interface Saturation {
404 public static final short NORMAL = 0;
405 public static final short LOW = 1;
406 public static final short HIGH = 2;
410 * Constants for {@link #TAG_SHARPNESS}
412 public static interface Sharpness {
413 public static final short NORMAL = 0;
414 public static final short SOFT = 1;
415 public static final short HARD = 2;
419 * Constants for {@link #TAG_SUBJECT_DISTANCE}
421 public static interface SubjectDistance {
422 public static final short UNKNOWN = 0;
423 public static final short MACRO = 1;
424 public static final short CLOSE_VIEW = 2;
425 public static final short DISTANT_VIEW = 3;
429 * Constants for {@link #TAG_GPS_LATITUDE_REF}, {@link #TAG_GPS_DEST_LATITUDE_REF}
431 public static interface GpsLatitudeRef {
432 public static final String NORTH = "N";
433 public static final String SOUTH = "S";
437 * Constants for {@link #TAG_GPS_LONGITUDE_REF}, {@link #TAG_GPS_DEST_LONGITUDE_REF}
439 public static interface GpsLongitudeRef {
440 public static final String EAST = "E";
441 public static final String WEST = "W";
445 * Constants for {@link #TAG_GPS_ALTITUDE_REF}
447 public static interface GpsAltitudeRef {
448 public static final short SEA_LEVEL = 0;
449 public static final short SEA_LEVEL_NEGATIVE = 1;
453 * Constants for {@link #TAG_GPS_STATUS}
455 public static interface GpsStatus {
456 public static final String IN_PROGRESS = "A";
457 public static final String INTEROPERABILITY = "V";
461 * Constants for {@link #TAG_GPS_MEASURE_MODE}
463 public static interface GpsMeasureMode {
464 public static final String MODE_2_DIMENSIONAL = "2";
465 public static final String MODE_3_DIMENSIONAL = "3";
469 * Constants for {@link #TAG_GPS_SPEED_REF}, {@link #TAG_GPS_DEST_DISTANCE_REF}
471 public static interface GpsSpeedRef {
472 public static final String KILOMETERS = "K";
473 public static final String MILES = "M";
474 public static final String KNOTS = "N";
478 * Constants for {@link #TAG_GPS_TRACK_REF}, {@link #TAG_GPS_IMG_DIRECTION_REF},
479 * {@link #TAG_GPS_DEST_BEARING_REF}
481 public static interface GpsTrackRef {
482 public static final String TRUE_DIRECTION = "T";
483 public static final String MAGNETIC_DIRECTION = "M";
487 * Constants for {@link #TAG_GPS_DIFFERENTIAL}
489 public static interface GpsDifferential {
490 public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
491 public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
495 * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
497 public static final short TYPE_UNSIGNED_BYTE = 1;
499 * The ASCII type in the EXIF standard. An 8-bit byte containing one 7-bit ASCII code.
500 * The final byte is terminated with NULL.
502 public static final short TYPE_ASCII = 2;
504 * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
506 public static final short TYPE_UNSIGNED_SHORT = 3;
508 * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
510 public static final short TYPE_UNSIGNED_LONG = 4;
512 * The RATIONAL type of EXIF standard. It consists of two LONGs. The first one is the numerator
513 * and the second one expresses the denominator.
515 public static final short TYPE_UNSIGNED_RATIONAL = 5;
517 * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any value
518 * depending on the field definition.
520 public static final short TYPE_UNDEFINED = 7;
522 * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
523 * (2's complement notation).
525 public static final short TYPE_LONG = 9;
527 * The SRATIONAL type of EXIF standard. It consists of two SLONGs. The first one is the
528 * numerator and the second one is the denominator.
530 public static final short TYPE_RATIONAL = 10;
532 private static final int TYPE_TO_SIZE_MAP[] = new int[11];
534 TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_BYTE] = 1;
535 TYPE_TO_SIZE_MAP[TYPE_ASCII] = 1;
536 TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_SHORT] = 2;
537 TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_LONG] = 4;
538 TYPE_TO_SIZE_MAP[TYPE_UNSIGNED_RATIONAL] = 8;
539 TYPE_TO_SIZE_MAP[TYPE_UNDEFINED] = 1;
540 TYPE_TO_SIZE_MAP[TYPE_LONG] = 4;
541 TYPE_TO_SIZE_MAP[TYPE_RATIONAL] = 8;
545 * Gets the element size of the given data type.
549 * @see #TYPE_RATIONAL
550 * @see #TYPE_UNDEFINED
551 * @see #TYPE_UNSIGNED_BYTE
552 * @see #TYPE_UNSIGNED_LONG
553 * @see #TYPE_UNSIGNED_RATIONAL
554 * @see #TYPE_UNSIGNED_SHORT
556 public static int getElementSize(short type) {
557 return TYPE_TO_SIZE_MAP[type];
560 private static volatile SparseArray<Integer> sTagInfo = null;
561 private static volatile SparseArray<Integer> sInteroperTagInfo = null;
562 private static final int SIZE_UNDEFINED = 0;
564 private static SparseArray<Integer> getTagInfo() {
565 if (sTagInfo == null) {
566 synchronized(ExifTag.class) {
567 if (sTagInfo == null) {
568 sTagInfo = new SparseArray<Integer>();
576 private static SparseArray<Integer> getInteroperTagInfo() {
577 if (sInteroperTagInfo == null) {
578 synchronized(ExifTag.class) {
579 if (sInteroperTagInfo == null) {
580 sInteroperTagInfo = new SparseArray<Integer>();
581 sInteroperTagInfo.put(TAG_INTEROPERABILITY_INDEX,
582 (IfdId.TYPE_IFD_INTEROPERABILITY << 24)
583 | TYPE_ASCII << 16 | SIZE_UNDEFINED);
587 return sInteroperTagInfo;
590 private static void initTagInfo() {
592 * We put tag information in a 4-bytes integer. The first byte is the
593 * IFD of the tag, and the second byte is the default data type. The
594 * last two byte are a short value indicating the component count of this
597 sTagInfo.put(TAG_MAKE,
598 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
599 sTagInfo.put(TAG_IMAGE_WIDTH,
600 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
601 sTagInfo.put(TAG_IMAGE_LENGTH,
602 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
603 sTagInfo.put(TAG_BITS_PER_SAMPLE,
604 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3);
605 sTagInfo.put(TAG_COMPRESSION,
606 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
607 sTagInfo.put(TAG_PHOTOMETRIC_INTERPRETATION,
608 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
609 sTagInfo.put(TAG_ORIENTATION, (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
610 sTagInfo.put(TAG_SAMPLES_PER_PIXEL,
611 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
612 sTagInfo.put(TAG_PLANAR_CONFIGURATION,
613 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
614 sTagInfo.put(TAG_Y_CB_CR_SUB_SAMPLING,
615 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 2);
616 sTagInfo.put(TAG_Y_CB_CR_POSITIONING,
617 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
618 sTagInfo.put(TAG_X_RESOLUTION,
619 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
620 sTagInfo.put(TAG_Y_RESOLUTION,
621 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
622 sTagInfo.put(TAG_RESOLUTION_UNIT,
623 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
624 sTagInfo.put(TAG_STRIP_OFFSETS,
625 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED);
626 sTagInfo.put(TAG_ROWS_PER_STRIP,
627 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
628 sTagInfo.put(TAG_STRIP_BYTE_COUNTS,
629 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | SIZE_UNDEFINED);
630 sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT,
631 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
632 sTagInfo.put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
633 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
634 sTagInfo.put(TAG_TRANSFER_FUNCTION,
635 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_SHORT << 16 | 3 * 256);
636 sTagInfo.put(TAG_WHITE_POINT,
637 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 2);
638 sTagInfo.put(TAG_PRIMARY_CHROMATICITIES,
639 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6);
640 sTagInfo.put(TAG_Y_CB_CR_COEFFICIENTS,
641 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3);
642 sTagInfo.put(TAG_REFERENCE_BLACK_WHITE,
643 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 6);
644 sTagInfo.put(TAG_DATE_TIME,
645 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | 20);
646 sTagInfo.put(TAG_IMAGE_DESCRIPTION,
647 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
648 sTagInfo.put(TAG_MAKE,
649 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
650 sTagInfo.put(TAG_MODEL,
651 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
652 sTagInfo.put(TAG_SOFTWARE,
653 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
654 sTagInfo.put(TAG_ARTIST,
655 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
656 sTagInfo.put(TAG_COPYRIGHT,
657 (IfdId.TYPE_IFD_0 << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
658 sTagInfo.put(TAG_EXIF_IFD,
659 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
660 sTagInfo.put(TAG_GPS_IFD,
661 (IfdId.TYPE_IFD_0 << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
664 sTagInfo.put(TAG_EXIF_VERSION,
665 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
666 sTagInfo.put(TAG_FLASHPIX_VERSION,
667 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
668 sTagInfo.put(TAG_COLOR_SPACE,
669 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
670 sTagInfo.put(TAG_COMPONENTS_CONFIGURATION,
671 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 4);
672 sTagInfo.put(TAG_COMPRESSED_BITS_PER_PIXEL,
673 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
674 sTagInfo.put(TAG_PIXEL_X_DIMENSION,
675 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
676 sTagInfo.put(TAG_PIXEL_Y_DIMENSION,
677 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_LONG << 16 | 1);
678 sTagInfo.put(TAG_MAKER_NOTE,
679 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
680 sTagInfo.put(TAG_USER_COMMENT,
681 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
682 sTagInfo.put(TAG_RELATED_SOUND_FILE,
683 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 13);
684 sTagInfo.put(TAG_DATE_TIME_ORIGINAL,
685 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20);
686 sTagInfo.put(TAG_DATE_TIME_DIGITIZED,
687 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 20);
688 sTagInfo.put(TAG_SUB_SEC_TIME,
689 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
690 sTagInfo.put(TAG_SUB_SEC_TIME_ORIGINAL,
691 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
692 sTagInfo.put(TAG_SUB_SEC_TIME_DIGITIZED,
693 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
694 sTagInfo.put(TAG_IMAGE_UNIQUE_ID,
695 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | 33);
696 sTagInfo.put(TAG_EXPOSURE_TIME,
697 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
698 sTagInfo.put(TAG_F_NUMBER,
699 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
700 sTagInfo.put(TAG_EXPOSURE_PROGRAM,
701 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
702 sTagInfo.put(TAG_SPECTRAL_SENSITIVITY,
703 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
704 sTagInfo.put(TAG_ISO_SPEED_RATINGS,
705 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED);
706 sTagInfo.put(TAG_OECF,
707 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
708 sTagInfo.put(TAG_SHUTTER_SPEED_VALUE,
709 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
710 sTagInfo.put(TAG_APERTURE_VALUE,
711 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
712 sTagInfo.put(TAG_BRIGHTNESS_VALUE,
713 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
714 sTagInfo.put(TAG_EXPOSURE_BIAS_VALUE,
715 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_RATIONAL << 16 | 1);
716 sTagInfo.put(TAG_MAX_APERTURE_VALUE,
717 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
718 sTagInfo.put(TAG_SUBJECT_DISTANCE,
719 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
720 sTagInfo.put(TAG_METERING_MODE,
721 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
722 sTagInfo.put(TAG_LIGHT_SOURCE,
723 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
724 sTagInfo.put(TAG_FLASH,
725 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
726 sTagInfo.put(TAG_FOCAL_LENGTH,
727 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
728 sTagInfo.put(TAG_SUBJECT_AREA,
729 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | SIZE_UNDEFINED);
730 sTagInfo.put(TAG_FLASH_ENERGY,
731 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
732 sTagInfo.put(TAG_SPATIAL_FREQUENCY_RESPONSE,
733 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
734 sTagInfo.put(TAG_FOCAL_PLANE_X_RESOLUTION,
735 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
736 sTagInfo.put(TAG_FOCAL_PLANE_Y_RESOLUTION,
737 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
738 sTagInfo.put(TAG_FOCAL_PLANE_RESOLUTION_UNIT,
739 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
740 sTagInfo.put(TAG_SUBJECT_LOCATION,
741 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 2);
742 sTagInfo.put(TAG_EXPOSURE_INDEX,
743 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
744 sTagInfo.put(TAG_SENSING_METHOD,
745 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
746 sTagInfo.put(TAG_FILE_SOURCE,
747 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1);
748 sTagInfo.put(TAG_SCENE_TYPE,
749 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | 1);
750 sTagInfo.put(TAG_CFA_PATTERN,
751 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
752 sTagInfo.put(TAG_CUSTOM_RENDERED,
753 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
754 sTagInfo.put(TAG_EXPOSURE_MODE,
755 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
756 sTagInfo.put(TAG_WHITE_BALANCE,
757 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
758 sTagInfo.put(TAG_DIGITAL_ZOOM_RATIO,
759 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
760 sTagInfo.put(TAG_FOCAL_LENGTH_IN_35_MM_FILE,
761 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
762 sTagInfo.put(TAG_SCENE_CAPTURE_TYPE,
763 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
764 sTagInfo.put(TAG_GAIN_CONTROL,
765 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
766 sTagInfo.put(TAG_CONTRAST,
767 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
768 sTagInfo.put(TAG_SATURATION,
769 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
770 sTagInfo.put(TAG_SHARPNESS,
771 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
772 sTagInfo.put(TAG_DEVICE_SETTING_DESCRIPTION,
773 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
774 sTagInfo.put(TAG_SUBJECT_DISTANCE_RANGE,
775 (IfdId.TYPE_IFD_EXIF << 24) | TYPE_UNSIGNED_SHORT << 16 | 1);
777 sTagInfo.put(TAG_GPS_VERSION_ID,
778 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 4);
779 sTagInfo.put(TAG_GPS_LATITUDE_REF,
780 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
781 sTagInfo.put(TAG_GPS_LONGITUDE_REF,
782 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
783 sTagInfo.put(TAG_GPS_LATITUDE,
784 (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3);
785 sTagInfo.put(TAG_GPS_LONGITUDE,
786 (IfdId.TYPE_IFD_GPS << 24) | TYPE_RATIONAL << 16 | 3);
787 sTagInfo.put(TAG_GPS_ALTITUDE_REF,
788 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_BYTE << 16 | 1);
789 sTagInfo.put(TAG_GPS_ALTITUDE,
790 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
791 sTagInfo.put(TAG_GPS_TIME_STAMP,
792 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 3);
793 sTagInfo.put(TAG_GPS_SATTELLITES,
794 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
795 sTagInfo.put(TAG_GPS_STATUS,
796 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
797 sTagInfo.put(TAG_GPS_MEASURE_MODE,
798 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
799 sTagInfo.put(TAG_GPS_DOP,
800 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
801 sTagInfo.put(TAG_GPS_SPEED_REF,
802 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
803 sTagInfo.put(TAG_GPS_SPEED,
804 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
805 sTagInfo.put(TAG_GPS_TRACK_REF,
806 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
807 sTagInfo.put(TAG_GPS_TRACK,
808 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
809 sTagInfo.put(TAG_GPS_IMG_DIRECTION_REF,
810 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
811 sTagInfo.put(TAG_GPS_IMG_DIRECTION,
812 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
813 sTagInfo.put(TAG_GPS_MAP_DATUM,
814 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | SIZE_UNDEFINED);
815 sTagInfo.put(TAG_GPS_DEST_LATITUDE_REF,
816 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
817 sTagInfo.put(TAG_GPS_DEST_LATITUDE,
818 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
819 sTagInfo.put(TAG_GPS_DEST_BEARING_REF,
820 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
821 sTagInfo.put(TAG_GPS_DEST_BEARING,
822 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
823 sTagInfo.put(TAG_GPS_DEST_DISTANCE_REF,
824 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 2);
825 sTagInfo.put(TAG_GPS_DEST_DISTANCE,
826 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_RATIONAL << 16 | 1);
827 sTagInfo.put(TAG_GPS_PROCESSING_METHOD,
828 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
829 sTagInfo.put(TAG_GPS_AREA_INFORMATION,
830 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNDEFINED << 16 | SIZE_UNDEFINED);
831 sTagInfo.put(TAG_GPS_DATE_STAMP,
832 (IfdId.TYPE_IFD_GPS << 24) | TYPE_ASCII << 16 | 11);
833 sTagInfo.put(TAG_GPS_DIFFERENTIAL,
834 (IfdId.TYPE_IFD_GPS << 24) | TYPE_UNSIGNED_SHORT << 16 | 11);
837 private static Charset US_ASCII = Charset.forName("US-ASCII");
838 private final short mTagId;
839 private final short mDataType;
840 private final int mIfd;
841 private final boolean mComponentCountDefined;
842 private int mComponentCount;
843 private Object mValue;
846 static private short getTypeFromInfo(int info) {
847 return (short) ((info >> 16) & 0xff);
850 static private int getComponentCountFromInfo(int info) {
851 return info & 0xffff;
854 static private int getIfdIdFromInfo(int info) {
855 return (info >> 24) & 0xff;
858 static private boolean getComponentCountDefined(short tagId, int ifd) {
859 Integer info = (ifd == IfdId.TYPE_IFD_INTEROPERABILITY) ?
860 getInteroperTagInfo().get(tagId) : getTagInfo().get(tagId);
861 if (info == null) return false;
862 return getComponentCountFromInfo(info) != SIZE_UNDEFINED;
865 static int getIfdIdFromTagId(short tagId) {
866 Integer info = getTagInfo().get(tagId);
868 throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
870 return getIfdIdFromInfo(info);
874 * Create a tag with given ID. For tags related to interoperability and thumbnail, call
875 * {@link #buildInteroperabilityTag(short)} and {@link #buildThumbnailTag(short)} respectively.
876 * @exception IllegalArgumentException If the ID is invalid.
878 static public ExifTag buildTag(short tagId) {
879 Integer info = getTagInfo().get(tagId);
881 throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
883 return new ExifTag(tagId, getTypeFromInfo(info),
884 getComponentCountFromInfo(info),
885 getIfdIdFromInfo(info));
889 * Create a tag related to thumbnail with given ID.
890 * @exception IllegalArgumentException If the ID is invalid.
892 static public ExifTag buildThumbnailTag(short tagId) {
893 Integer info = getTagInfo().get(tagId);
894 if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_0) {
895 throw new IllegalArgumentException("Unknown Thumnail Tag ID: " + tagId);
897 return new ExifTag(tagId, getTypeFromInfo(info),
898 getComponentCountFromInfo(info),
903 * Create a tag related to interoperability with given ID.
904 * @exception IllegalArgumentException If the ID is invalid.
906 static public ExifTag buildInteroperabilityTag(short tagId) {
907 Integer info = getInteroperTagInfo().get(tagId);
908 if (info == null || getIfdIdFromInfo(info) != IfdId.TYPE_IFD_INTEROPERABILITY) {
909 throw new RuntimeException("Unknown Interoperability Tag ID: " + tagId);
911 return new ExifTag(tagId, getTypeFromInfo(info),
912 getComponentCountFromInfo(info),
913 IfdId.TYPE_IFD_INTEROPERABILITY);
916 static boolean isValidType(short type) {
917 return type == TYPE_UNSIGNED_BYTE || type == TYPE_ASCII ||
918 type == TYPE_UNSIGNED_SHORT || type == TYPE_UNSIGNED_LONG ||
919 type == TYPE_UNSIGNED_RATIONAL || type == TYPE_UNDEFINED ||
920 type == TYPE_LONG || type == TYPE_RATIONAL;
923 ExifTag(short tagId, short type, int componentCount, int ifd) {
926 mComponentCount = componentCount;
927 mComponentCountDefined = getComponentCountDefined(tagId, ifd);
932 * Returns the ID of the IFD this tag belongs to.
934 * @see IfdId#TYPE_IFD_0
935 * @see IfdId#TYPE_IFD_1
936 * @see IfdId#TYPE_IFD_EXIF
937 * @see IfdId#TYPE_IFD_GPS
938 * @see IfdId#TYPE_IFD_INTEROPERABILITY
940 public int getIfd() {
945 * Gets the ID of this tag.
947 public short getTagId() {
952 * Gets the data type of this tag
956 * @see #TYPE_RATIONAL
957 * @see #TYPE_UNDEFINED
958 * @see #TYPE_UNSIGNED_BYTE
959 * @see #TYPE_UNSIGNED_LONG
960 * @see #TYPE_UNSIGNED_RATIONAL
961 * @see #TYPE_UNSIGNED_SHORT
963 public short getDataType() {
968 * Gets the total data size in bytes of the value of this tag.
970 public int getDataSize() {
971 return getComponentCount() * getElementSize(getDataType());
975 * Gets the component count of this tag.
977 public int getComponentCount() {
978 return mComponentCount;
982 * Sets the component count of this tag.
983 * Call this function before setValue() if the length of value does not
984 * match the component count.
986 public void setComponentCount(int count) {
987 mComponentCount = count;
991 * Returns true if this ExifTag contains value; otherwise, this tag will contain an offset value
992 * that links to the area where the actual value is located.
996 public boolean hasValue() {
997 return mValue != null;
1001 * Gets the offset of this tag. This is only valid if this data size > 4 and contains an offset
1002 * to the location of the actual value.
1004 public int getOffset() {
1009 * Sets the offset of this tag.
1011 void setOffset(int offset) {
1015 private void checkComponentCountOrThrow(int count)
1016 throws IllegalArgumentException {
1017 if (mComponentCountDefined && (mComponentCount != count)) {
1018 throw new IllegalArgumentException("Tag " + mTagId + ": Required "
1019 + mComponentCount + " components but was given " + count
1024 private void throwTypeNotMatchedException(String className)
1025 throws IllegalArgumentException {
1026 throw new IllegalArgumentException("Tag " + mTagId + ": expect type " +
1027 convertTypeToString(mDataType) + " but got " + className);
1030 private static String convertTypeToString(short type) {
1032 case TYPE_UNSIGNED_BYTE:
1033 return "UNSIGNED_BYTE";
1036 case TYPE_UNSIGNED_SHORT:
1037 return "UNSIGNED_SHORT";
1038 case TYPE_UNSIGNED_LONG:
1039 return "UNSIGNED_LONG";
1040 case TYPE_UNSIGNED_RATIONAL:
1041 return "UNSIGNED_RATIONAL";
1042 case TYPE_UNDEFINED:
1053 private static final int UNSIGNED_SHORT_MAX = 65535;
1054 private static final long UNSIGNED_LONG_MAX = 4294967295L;
1055 private static final long LONG_MAX = Integer.MAX_VALUE;
1056 private static final long LONG_MIN = Integer.MIN_VALUE;
1058 private void checkOverflowForUnsignedShort(int[] value) {
1059 for (int v : value) {
1060 if (v > UNSIGNED_SHORT_MAX || v < 0) {
1061 throw new IllegalArgumentException(
1062 "Tag " + mTagId+ ": Value" + v +
1063 " is illegal for type UNSIGNED_SHORT");
1068 private void checkOverflowForUnsignedLong(long[] value) {
1069 for (long v: value) {
1070 if (v < 0 || v > UNSIGNED_LONG_MAX) {
1071 throw new IllegalArgumentException(
1072 "Tag " + mTagId+ ": Value" + v +
1073 " is illegal for type UNSIGNED_LONG");
1078 private void checkOverflowForUnsignedLong(int[] value) {
1079 for (int v: value) {
1081 throw new IllegalArgumentException(
1082 "Tag " + mTagId+ ": Value" + v +
1083 " is illegal for type UNSIGNED_LONG");
1088 private void checkOverflowForUnsignedRational(Rational[] value) {
1089 for (Rational v: value) {
1090 if (v.getNominator() < 0 || v.getDenominator() < 0
1091 || v.getNominator() > UNSIGNED_LONG_MAX
1092 || v.getDenominator() > UNSIGNED_LONG_MAX) {
1093 throw new IllegalArgumentException(
1094 "Tag " + mTagId+ ": Value" + v +
1095 " is illegal for type UNSIGNED_RATIONAL");
1100 private void checkOverflowForRational(Rational[] value) {
1101 for (Rational v: value) {
1102 if (v.getNominator() < LONG_MIN || v.getDenominator() < LONG_MIN
1103 || v.getNominator() > LONG_MAX
1104 || v.getDenominator() > LONG_MAX) {
1105 throw new IllegalArgumentException(
1106 "Tag " + mTagId+ ": Value" + v +
1107 " is illegal for type RATIONAL");
1113 * Sets integer values into this tag.
1114 * @exception IllegalArgumentException for the following situation:
1116 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
1117 * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
1118 * <li>The value overflows. </li>
1119 * <li>The value.length does NOT match the definition of component count in
1120 * EXIF standard.</li>
1123 public void setValue(int[] value) {
1124 checkComponentCountOrThrow(value.length);
1125 if (mDataType != TYPE_UNSIGNED_SHORT && mDataType != TYPE_LONG &&
1126 mDataType != TYPE_UNSIGNED_LONG) {
1127 throwTypeNotMatchedException("int");
1129 if (mDataType == TYPE_UNSIGNED_SHORT) {
1130 checkOverflowForUnsignedShort(value);
1131 } else if (mDataType == TYPE_UNSIGNED_LONG) {
1132 checkOverflowForUnsignedLong(value);
1135 long[] data = new long[value.length];
1136 for (int i = 0; i < value.length; i++) {
1140 mComponentCount = value.length;
1144 * Sets integer values into this tag.
1145 * @exception IllegalArgumentException For the following situation:
1147 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_SHORT},
1148 * {@link #TYPE_UNSIGNED_LONG}, or {@link #TYPE_LONG}.</li>
1149 * <li>The value overflows.</li>
1150 * <li>The component count in the definition of EXIF standard is not 1.</li>
1153 public void setValue(int value) {
1154 checkComponentCountOrThrow(1);
1155 setValue(new int[] {value});
1159 * Sets long values into this tag.
1160 * @exception IllegalArgumentException For the following situation:
1162 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
1163 * <li>The value overflows. </li>
1164 * <li>The value.length does NOT match the definition of component count in
1165 * EXIF standard.</li>
1168 public void setValue(long[] value) {
1169 checkComponentCountOrThrow(value.length);
1170 if (mDataType != TYPE_UNSIGNED_LONG) {
1171 throwTypeNotMatchedException("long");
1173 checkOverflowForUnsignedLong(value);
1175 mComponentCount = value.length;
1179 * Sets long values into this tag.
1180 * @exception IllegalArgumentException For the following situation:
1182 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_LONG}.</li>
1183 * <li>The value overflows. </li>
1184 * <li>The component count in the definition of EXIF standard is not 1.</li>
1187 public void setValue(long value) {
1188 setValue(new long[] {value});
1192 * Sets a string value into this tag. The value is treated as an ASCII string where we only
1193 * preserve the lower byte of each character. The length of the string should be equal
1194 * to either (component count -1) or (component count). A "0" byte will be appeneded while
1195 * written to the EXIF file. If the length equals (component count), the final byte will be
1196 * replaced by a "0" byte.
1198 * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII}
1199 * or the length of the string is not equal to (component count -1) and (component count)
1201 public void setValue(String value) {
1202 if (mDataType != TYPE_ASCII) {
1203 throwTypeNotMatchedException("String");
1206 byte[] buf = new byte[value.length()];
1207 for (int i = 0, n = value.length(); i < n; i++) {
1208 buf[i] = (byte) value.charAt(i);
1211 int count = buf.length;
1212 if (mComponentCountDefined) {
1213 if (mComponentCount != count && mComponentCount != count + 1) {
1214 throw new IllegalArgumentException("Tag " + mTagId + ": Required "
1215 + mComponentCount + " or " + (mComponentCount + 1)
1216 + " components but was given " + count
1220 mComponentCount = buf[count - 1] == 0 ? count : count + 1;
1226 * Sets Rational values into this tag.
1227 * @exception IllegalArgumentException For the following situation:
1229 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or
1230 * {@link #TYPE_RATIONAL} .</li>
1231 * <li>The value overflows. </li>
1232 * <li>The value.length does NOT match the definition of component count in
1233 * EXIF standard.</li>
1236 public void setValue(Rational[] value) {
1237 if (mDataType == TYPE_UNSIGNED_RATIONAL) {
1238 checkOverflowForUnsignedRational(value);
1239 } else if (mDataType == TYPE_RATIONAL) {
1240 checkOverflowForRational(value);
1242 throwTypeNotMatchedException("Rational");
1244 checkComponentCountOrThrow(value.length);
1246 mComponentCount = value.length;
1250 * Sets Rational values into this tag.
1251 * @exception IllegalArgumentException For the following situation:
1253 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_RATIONAL} or
1254 * {@link #TYPE_RATIONAL} .</li>
1255 * <li>The value overflows. </li>
1256 * <li>The component count in the definition of EXIF standard is not 1.</li>
1259 public void setValue(Rational value) {
1260 setValue(new Rational[] {value});
1264 * Sets byte values into this tag.
1265 * @exception IllegalArgumentException For the following situation:
1267 * <li>The component type of this tag is not {@link #TYPE_UNSIGNED_BYTE} or
1268 * {@link #TYPE_UNDEFINED} .</li>
1269 * <li>The length does NOT match the definition of component count in EXIF standard.</li>
1272 public void setValue(byte[] value, int offset, int length) {
1273 checkComponentCountOrThrow(length);
1274 if (mDataType != TYPE_UNSIGNED_BYTE && mDataType != TYPE_UNDEFINED) {
1275 throwTypeNotMatchedException("byte");
1277 mValue = new byte[length];
1278 System.arraycopy(value, offset, mValue, 0, length);
1279 mComponentCount = length;
1283 * Equivalent to setValue(value, 0, value.length).
1285 public void setValue(byte[] value) {
1286 setValue(value, 0, value.length);
1289 private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
1292 * Sets a timestamp to this tag. The method converts the timestamp with the format of
1293 * "yyyy:MM:dd kk:mm:ss" and calls {@link #setValue(String)}.
1295 * @param time the number of milliseconds since Jan. 1, 1970 GMT
1296 * @exception IllegalArgumentException If the data type is not {@link #TYPE_ASCII}
1297 * or the component count of this tag is not 20 or undefined
1299 public void setTimeValue(long time) {
1300 // synchronized on TIME_FORMAT as SimpleDateFormat is not thread safe
1301 synchronized (TIME_FORMAT) {
1302 setValue(TIME_FORMAT.format(new Date(time)));
1307 * Gets the {@link #TYPE_UNSIGNED_SHORT} data.
1308 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_SHORT}.
1310 public int getUnsignedShort(int index) {
1311 if (mDataType != TYPE_UNSIGNED_SHORT) {
1312 throw new IllegalArgumentException("Cannot get UNSIGNED_SHORT value from "
1313 + convertTypeToString(mDataType));
1315 return (int) (((long[]) mValue) [index]);
1319 * Gets the {@link #TYPE_LONG} data.
1320 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_LONG}.
1322 public int getLong(int index) {
1323 if (mDataType != TYPE_LONG) {
1324 throw new IllegalArgumentException("Cannot get LONG value from "
1325 + convertTypeToString(mDataType));
1327 return (int) (((long[]) mValue) [index]);
1331 * Gets the {@link #TYPE_UNSIGNED_LONG} data.
1332 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_LONG}.
1334 public long getUnsignedLong(int index) {
1335 if (mDataType != TYPE_UNSIGNED_LONG) {
1336 throw new IllegalArgumentException("Cannot get UNSIGNED LONG value from "
1337 + convertTypeToString(mDataType));
1339 return ((long[]) mValue) [index];
1343 * Gets the {@link #TYPE_ASCII} data.
1344 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_ASCII}.
1346 public String getString() {
1347 if (mDataType != TYPE_ASCII) {
1348 throw new IllegalArgumentException("Cannot get ASCII value from "
1349 + convertTypeToString(mDataType));
1351 return new String((byte[]) mValue, US_ASCII);
1355 * Get the converted ascii byte. Used by ExifOutputStream.
1357 byte[] getStringByte() {
1358 return (byte[]) mValue;
1362 * Gets the {@link #TYPE_RATIONAL} or {@link #TYPE_UNSIGNED_RATIONAL} data.
1363 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_RATIONAL} or
1364 * {@link #TYPE_UNSIGNED_RATIONAL}.
1366 public Rational getRational(int index) {
1367 if ((mDataType != TYPE_RATIONAL) && (mDataType != TYPE_UNSIGNED_RATIONAL)) {
1368 throw new IllegalArgumentException("Cannot get RATIONAL value from "
1369 + convertTypeToString(mDataType));
1371 return ((Rational[]) mValue) [index];
1375 * Equivalent to getBytes(buffer, 0, buffer.length).
1377 public void getBytes(byte[] buf) {
1378 getBytes(buf, 0, buf.length);
1382 * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
1384 * @param buf the byte array in which to store the bytes read.
1385 * @param offset the initial position in buffer to store the bytes.
1386 * @param length the maximum number of bytes to store in buffer. If length > component count,
1387 * only the valid bytes will be stored.
1389 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNDEFINED} or
1390 * {@link #TYPE_UNSIGNED_BYTE}.
1392 public void getBytes(byte[] buf, int offset, int length) {
1393 if ((mDataType != TYPE_UNDEFINED) && (mDataType != TYPE_UNSIGNED_BYTE)) {
1394 throw new IllegalArgumentException("Cannot get BYTE value from "
1395 + convertTypeToString(mDataType));
1397 System.arraycopy(mValue, 0, buf, offset,
1398 (length > mComponentCount) ? mComponentCount : length);
1402 * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1403 * {@link #TAG_GPS_IFD}, {@link #TAG_JPEG_INTERCHANGE_FORMAT},
1404 * {@link #TAG_STRIP_OFFSETS}, {@link #TAG_INTEROPERABILITY_IFD}
1406 static boolean isOffsetTag(short tagId) {
1407 return tagId == TAG_EXIF_IFD
1408 || tagId == TAG_GPS_IFD
1409 || tagId == TAG_JPEG_INTERCHANGE_FORMAT
1410 || tagId == TAG_STRIP_OFFSETS
1411 || tagId == TAG_INTEROPERABILITY_IFD;
1415 * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1416 * {@link #TAG_GPS_IFD}, {@link #TAG_INTEROPERABILITY_IFD}
1418 static boolean isSubIfdOffsetTag(short tagId) {
1419 return tagId == TAG_EXIF_IFD
1420 || tagId == TAG_GPS_IFD
1421 || tagId == TAG_INTEROPERABILITY_IFD;
1424 public boolean equals(Object obj) {
1425 if (obj instanceof ExifTag) {
1426 ExifTag tag = (ExifTag) obj;
1427 if (mValue != null) {
1428 if (mValue instanceof long[]) {
1429 if (!(tag.mValue instanceof long[])) return false;
1430 return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
1431 } else if (mValue instanceof Rational[]) {
1432 if (!(tag.mValue instanceof Rational[])) return false;
1433 return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
1434 } else if (mValue instanceof byte[]) {
1435 if (!(tag.mValue instanceof byte[])) return false;
1436 return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
1438 return mValue.equals(tag.mValue);
1441 return tag.mValue == null;