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.text.SimpleDateFormat;
22 import java.util.Arrays;
23 import java.util.Date;
26 * This class stores information of an EXIF tag.
32 public class ExifTag {
34 public static final short TAG_IMAGE_WIDTH = 0x100;
36 * The height of the image.
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;
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;
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;
162 // Interoperability tag
163 public static final short TAG_INTEROPERABILITY_INDEX = 1;
166 * Constants for {@link #TAG_ORIENTATION}
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;
180 * Constants for {@link #TAG_Y_CB_CR_POSITIONING}
182 public static interface YCbCrPositioning {
183 public static final short CENTERED = 1;
184 public static final short CO_SITED = 2;
188 * Constants for {@link #TAG_COMPRESSION}
190 public static interface Compression {
191 public static final short UNCOMPRESSION = 1;
192 public static final short JPEG = 6;
196 * Constants for {@link #TAG_RESOLUTION_UNIT}
198 public static interface ResolutionUnit {
199 public static final short INCHES = 2;
200 public static final short CENTIMETERS = 3;
204 * Constants for {@link #TAG_PHOTOMETRIC_INTERPRETATION}
206 public static interface PhotometricInterpretation {
207 public static final short RGB = 2;
208 public static final short YCBCR = 6;
212 * Constants for {@link #TAG_PLANAR_CONFIGURATION}
214 public static interface PlanarConfiguration {
215 public static final short CHUNKY = 1;
216 public static final short PLANAR = 2;
220 * Constants for {@link #TAG_EXPOSURE_PROGRAM}
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;
235 * Constants for {@link #TAG_METERING_MODE}
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;
249 * Constants for {@link #TAG_FLASH} As the definition in Jeita EXIF 2.2 standard, we can
250 * treat this constant as bitwise flag.
254 * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED | MODE_AUTO_MODE
256 public static interface Flash {
258 public static final short DID_NOT_FIRED = 0;
259 public static final short FIRED = 1;
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;
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;
270 public static final short FUNCTION_PRESENT = 0 << 5;
271 public static final short FUNCTION_NO_FUNCTION = 1 << 5;
273 public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6;
274 public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6;
278 * Constants for {@link #TAG_COLOR_SPACE}
280 public static interface ColorSpace {
281 public static final short SRGB = 1;
282 public static final short UNCALIBRATED = (short) 0xFFFF;
286 * Constants for {@link #TAG_EXPOSURE_MODE}
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;
295 * Constants for {@link #TAG_WHITE_BALANCE}
297 public static interface WhiteBalance {
298 public static final short AUTO = 0;
299 public static final short MANUAL = 1;
303 * Constants for {@link #TAG_SCENE_CAPTURE_TYPE}
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;
313 * Constants for {@link #TAG_COMPONENTS_CONFIGURATION}
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;
326 * Constants for {@link #TAG_LIGHT_SOURCE}
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;
353 * Constants for {@link #TAG_SENSING_METHOD}
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;
366 * Constants for {@link #TAG_FILE_SOURCE}
368 public static interface FileSource {
369 public static final short DSC = 3;
373 * Constants for {@link #TAG_SCENE_TYPE}
375 public static interface SceneType {
376 public static final short DIRECT_PHOTOGRAPHED = 1;
380 * Constants for {@link #TAG_GAIN_CONTROL}
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;
391 * Constants for {@link #TAG_CONTRAST}
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;
400 * Constants for {@link #TAG_SATURATION}
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;
409 * Constants for {@link #TAG_SHARPNESS}
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;
418 * Constants for {@link #TAG_SUBJECT_DISTANCE}
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;
428 * Constants for {@link #TAG_GPS_LATITUDE_REF}, {@link #TAG_GPS_DEST_LATITUDE_REF}
430 public static interface GpsLatitudeRef {
431 public static final String NORTH = "N";
432 public static final String SOUTH = "S";
436 * Constants for {@link #TAG_GPS_LONGITUDE_REF}, {@link #TAG_GPS_DEST_LONGITUDE_REF}
438 public static interface GpsLongitudeRef {
439 public static final String EAST = "E";
440 public static final String WEST = "W";
444 * Constants for {@link #TAG_GPS_ALTITUDE_REF}
446 public static interface GpsAltitudeRef {
447 public static final short SEA_LEVEL = 0;
448 public static final short SEA_LEVEL_NEGATIVE = 1;
452 * Constants for {@link #TAG_GPS_STATUS}
454 public static interface GpsStatus {
455 public static final String IN_PROGRESS = "A";
456 public static final String INTEROPERABILITY = "V";
460 * Constants for {@link #TAG_GPS_MEASURE_MODE}
462 public static interface GpsMeasureMode {
463 public static final String MODE_2_DIMENSIONAL = "2";
464 public static final String MODE_3_DIMENSIONAL = "3";
468 * Constants for {@link #TAG_GPS_SPEED_REF}, {@link #TAG_GPS_DEST_DISTANCE_REF}
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";
477 * Constants for {@link #TAG_GPS_TRACK_REF}, {@link #TAG_GPS_IMG_DIRECTION_REF},
478 * {@link #TAG_GPS_DEST_BEARING_REF}
480 public static interface GpsTrackRef {
481 public static final String TRUE_DIRECTION = "T";
482 public static final String MAGNETIC_DIRECTION = "M";
486 * Constants for {@link #TAG_GPS_DIFFERENTIAL}
488 public static interface GpsDifferential {
489 public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0;
490 public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1;
494 * The BYTE type in the EXIF standard. An 8-bit unsigned integer.
496 public static final short TYPE_UNSIGNED_BYTE = 1;
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.
501 public static final short TYPE_ASCII = 2;
503 * The SHORT type in the EXIF standard. A 16-bit (2-byte) unsigned integer
505 public static final short TYPE_UNSIGNED_SHORT = 3;
507 * The LONG type in the EXIF standard. A 32-bit (4-byte) unsigned integer
509 public static final short TYPE_UNSIGNED_LONG = 4;
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.
514 public static final short TYPE_UNSIGNED_RATIONAL = 5;
516 * The UNDEFINED type in the EXIF standard. An 8-bit byte that can take any value
517 * depending on the field definition.
519 public static final short TYPE_UNDEFINED = 7;
521 * The SLONG type in the EXIF standard. A 32-bit (4-byte) signed integer
522 * (2's complement notation).
524 public static final short TYPE_LONG = 9;
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.
529 public static final short TYPE_RATIONAL = 10;
531 private static final int TYPE_TO_SIZE_MAP[] = new int[11];
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;
544 * Gets the element size of the given data type.
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
555 public static int getElementSize(short type) {
556 return TYPE_TO_SIZE_MAP[type];
559 private static volatile SparseArray<Integer> sTagInfo = null;
560 private static volatile SparseArray<Integer> sInteroperTagInfo = null;
561 private static final int SIZE_UNDEFINED = 0;
563 private static SparseArray<Integer> getTagInfo() {
564 if (sTagInfo == null) {
565 synchronized(ExifTag.class) {
566 if (sTagInfo == null) {
567 sTagInfo = new SparseArray<Integer>();
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);
586 return sInteroperTagInfo;
589 private static void initTagInfo() {
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
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);
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);
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);
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;
844 static private short getTypeFromInfo(int info) {
845 return (short) ((info >> 16) & 0xff);
848 static private int getComponentCountFromInfo(int info) {
849 return info & 0xffff;
852 static private int getIfdIdFromInfo(int info) {
853 return (info >> 24) & 0xff;
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;
863 static int getIfdIdFromTagId(short tagId) {
864 Integer info = getTagInfo().get(tagId);
866 throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
868 return getIfdIdFromInfo(info);
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.
876 static public ExifTag buildTag(short tagId) {
877 Integer info = getTagInfo().get(tagId);
879 throw new IllegalArgumentException("Unknown Tag ID: " + tagId);
881 return new ExifTag(tagId, getTypeFromInfo(info),
882 getComponentCountFromInfo(info),
883 getIfdIdFromInfo(info));
887 * Create a tag related to thumbnail with given ID.
888 * @exception IllegalArgumentException If the ID is invalid.
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);
895 return new ExifTag(tagId, getTypeFromInfo(info),
896 getComponentCountFromInfo(info),
901 * Create a tag related to interoperability with given ID.
902 * @exception IllegalArgumentException If the ID is invalid.
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);
909 return new ExifTag(tagId, getTypeFromInfo(info),
910 getComponentCountFromInfo(info),
911 IfdId.TYPE_IFD_INTEROPERABILITY);
914 ExifTag(short tagId, short type, int componentCount, int ifd) {
917 mComponentCount = componentCount;
918 mComponentCountDefined = getComponentCountDefined(tagId, ifd);
923 * Returns the ID of the IFD this tag belongs to.
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
931 public int getIfd() {
936 * Gets the ID of this tag.
938 public short getTagId() {
943 * Gets the data type of this tag
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
954 public short getDataType() {
959 * Gets the total data size in bytes of the value of this tag.
961 public int getDataSize() {
962 return getComponentCount() * getElementSize(getDataType());
966 * Gets the component count of this tag.
968 public int getComponentCount() {
969 return mComponentCount;
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.
978 public boolean hasValue() {
979 return mValue != null;
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.
986 public int getOffset() {
991 * Sets the offset of this tag.
993 void setOffset(int offset) {
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
1006 private void throwTypeNotMatchedException(String className)
1007 throws IllegalArgumentException {
1008 throw new IllegalArgumentException("Tag " + mTagId + ": expect type " +
1009 convertTypeToString(mDataType) + " but got " + className);
1012 private static String convertTypeToString(short type) {
1014 case TYPE_UNSIGNED_BYTE:
1015 return "UNSIGNED_BYTE";
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:
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;
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");
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");
1060 private void checkOverflowForUnsignedLong(int[] value) {
1061 for (int v: value) {
1063 throw new IllegalArgumentException(
1064 "Tag " + mTagId+ ": Value" + v +
1065 " is illegal for type UNSIGNED_LONG");
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");
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");
1095 * Sets integer values into this tag.
1096 * @exception IllegalArgumentException for the following situation:
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>
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");
1111 if (mDataType == TYPE_UNSIGNED_SHORT) {
1112 checkOverflowForUnsignedShort(value);
1113 } else if (mDataType == TYPE_UNSIGNED_LONG) {
1114 checkOverflowForUnsignedLong(value);
1117 long[] data = new long[value.length];
1118 for (int i = 0; i < value.length; i++) {
1122 mComponentCount = value.length;
1126 * Sets integer values into this tag.
1127 * @exception IllegalArgumentException For the following situation:
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>
1135 public void setValue(int value) {
1136 checkComponentCountOrThrow(1);
1137 setValue(new int[] {value});
1141 * Sets long values into this tag.
1142 * @exception IllegalArgumentException For the following situation:
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>
1150 public void setValue(long[] value) {
1151 checkComponentCountOrThrow(value.length);
1152 if (mDataType != TYPE_UNSIGNED_LONG) {
1153 throwTypeNotMatchedException("long");
1155 checkOverflowForUnsignedLong(value);
1157 mComponentCount = value.length;
1161 * Sets long values into this tag.
1162 * @exception IllegalArgumentException For the following situation:
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>
1169 public void setValue(long value) {
1170 setValue(new long[] {value});
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
1179 public void setValue(String value) {
1180 checkComponentCountOrThrow(value.length() + 1);
1181 if (mDataType != TYPE_ASCII) {
1182 throwTypeNotMatchedException("String");
1184 mComponentCount = value.length() + 1;
1189 * Sets Rational values into this tag.
1190 * @exception IllegalArgumentException For the following situation:
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>
1199 public void setValue(Rational[] value) {
1200 if (mDataType == TYPE_UNSIGNED_RATIONAL) {
1201 checkOverflowForUnsignedRational(value);
1202 } else if (mDataType == TYPE_RATIONAL) {
1203 checkOverflowForRational(value);
1205 throwTypeNotMatchedException("Rational");
1207 checkComponentCountOrThrow(value.length);
1209 mComponentCount = value.length;
1213 * Sets Rational values into this tag.
1214 * @exception IllegalArgumentException For the following situation:
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>
1222 public void setValue(Rational value) {
1223 setValue(new Rational[] {value});
1227 * Sets byte values into this tag.
1228 * @exception IllegalArgumentException For the following situation:
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>
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");
1240 mValue = new byte[length];
1241 System.arraycopy(value, offset, mValue, 0, length);
1242 mComponentCount = length;
1246 * Equivalent to setValue(value, 0, value.length).
1248 public void setValue(byte[] value) {
1249 setValue(value, 0, value.length);
1252 private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy:MM:dd kk:mm:ss");
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)}.
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
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)));
1270 * Gets the {@link #TYPE_UNSIGNED_SHORT} data.
1271 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_SHORT}.
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));
1278 return (int) (((long[]) mValue) [index]);
1282 * Gets the {@link #TYPE_LONG} data.
1283 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_LONG}.
1285 public int getLong(int index) {
1286 if (mDataType != TYPE_LONG) {
1287 throw new IllegalArgumentException("Cannot get LONG value from "
1288 + convertTypeToString(mDataType));
1290 return (int) (((long[]) mValue) [index]);
1294 * Gets the {@link #TYPE_UNSIGNED_LONG} data.
1295 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNSIGNED_LONG}.
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));
1302 return ((long[]) mValue) [index];
1306 * Gets the {@link #TYPE_ASCII} data.
1307 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_ASCII}.
1309 public String getString() {
1310 if (mDataType != TYPE_ASCII) {
1311 throw new IllegalArgumentException("Cannot get ASCII value from "
1312 + convertTypeToString(mDataType));
1314 return (String) mValue;
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}.
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));
1327 return ((Rational[]) mValue) [index];
1331 * Equivalent to getBytes(buffer, 0, buffer.length).
1333 public void getBytes(byte[] buf) {
1334 getBytes(buf, 0, buf.length);
1338 * Gets the {@link #TYPE_UNDEFINED} or {@link #TYPE_UNSIGNED_BYTE} data.
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.
1345 * @exception IllegalArgumentException If the type is NOT {@link #TYPE_UNDEFINED} or
1346 * {@link #TYPE_UNSIGNED_BYTE}.
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));
1353 System.arraycopy(mValue, 0, buf, offset,
1354 (length > mComponentCount) ? mComponentCount : length);
1357 private String undefinedTypeValueToString() {
1358 StringBuilder sbuilder = new StringBuilder();
1360 case TAG_COMPONENTS_CONFIGURATION:
1361 case TAG_FILE_SOURCE:
1362 case TAG_SCENE_TYPE:
1363 byte buf[] = (byte[]) mValue;
1364 for(int i = 0, n = getComponentCount(); i < n; i++) {
1365 if(i != 0) sbuilder.append(" ");
1366 sbuilder.append(buf[i]);
1370 sbuilder.append(new String((byte[]) mValue));
1372 return sbuilder.toString();
1376 * Returns a string representation of the value of this tag.
1378 String valueToString() {
1379 StringBuilder sbuilder = new StringBuilder();
1380 switch (getDataType()) {
1381 case ExifTag.TYPE_UNDEFINED:
1382 sbuilder.append(undefinedTypeValueToString());
1384 case ExifTag.TYPE_UNSIGNED_BYTE:
1385 byte buf[] = (byte[]) mValue;
1386 for(int i = 0, n = getComponentCount(); i < n; i++) {
1387 if(i != 0) sbuilder.append(" ");
1388 sbuilder.append(buf[i]);
1391 case ExifTag.TYPE_ASCII:
1392 String s = getString();
1393 for (int i = 0, n = s.length(); i < n; i++) {
1394 int code = s.codePointAt(i);
1395 if (code == 0) continue;
1396 if (code > 31 && code < 127) {
1397 sbuilder.append((char) code);
1399 sbuilder.append('.');
1403 case ExifTag.TYPE_UNSIGNED_LONG:
1404 for(int i = 0, n = getComponentCount(); i < n; i++) {
1405 if(i != 0) sbuilder.append(" ");
1406 sbuilder.append(getUnsignedLong(i));
1409 case ExifTag.TYPE_RATIONAL:
1410 case ExifTag.TYPE_UNSIGNED_RATIONAL:
1411 for(int i = 0, n = getComponentCount(); i < n; i++) {
1412 Rational r = getRational(i);
1413 if(i != 0) sbuilder.append(" ");
1414 sbuilder.append(r.getNominator()).append("/").append(r.getDenominator());
1417 case ExifTag.TYPE_UNSIGNED_SHORT:
1418 for(int i = 0, n = getComponentCount(); i < n; i++) {
1419 if(i != 0) sbuilder.append(" ");
1420 sbuilder.append(getUnsignedShort(i));
1423 case ExifTag.TYPE_LONG:
1424 for(int i = 0, n = getComponentCount(); i < n; i++) {
1425 if(i != 0) sbuilder.append(" ");
1426 sbuilder.append(getLong(i));
1430 return sbuilder.toString();
1434 * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1435 * {@link #TAG_GPS_IFD}, {@link #TAG_JPEG_INTERCHANGE_FORMAT},
1436 * {@link #TAG_STRIP_OFFSETS}, {@link #TAG_INTEROPERABILITY_IFD}
1438 static boolean isOffsetTag(short tagId) {
1439 return tagId == TAG_EXIF_IFD
1440 || tagId == TAG_GPS_IFD
1441 || tagId == TAG_JPEG_INTERCHANGE_FORMAT
1442 || tagId == TAG_STRIP_OFFSETS
1443 || tagId == TAG_INTEROPERABILITY_IFD;
1447 * Returns true if the ID is one of the following: {@link #TAG_EXIF_IFD},
1448 * {@link #TAG_GPS_IFD}, {@link #TAG_INTEROPERABILITY_IFD}
1450 static boolean isSubIfdOffsetTag(short tagId) {
1451 return tagId == TAG_EXIF_IFD
1452 || tagId == TAG_GPS_IFD
1453 || tagId == TAG_INTEROPERABILITY_IFD;
1456 public boolean equals(Object obj) {
1457 if (obj instanceof ExifTag) {
1458 ExifTag tag = (ExifTag) obj;
1459 if (mValue != null) {
1460 if (mValue instanceof long[]) {
1461 if (!(tag.mValue instanceof long[])) return false;
1462 return Arrays.equals((long[]) mValue, (long[]) tag.mValue);
1463 } else if (mValue instanceof Rational[]) {
1464 if (!(tag.mValue instanceof Rational[])) return false;
1465 return Arrays.equals((Rational[]) mValue, (Rational[]) tag.mValue);
1466 } else if (mValue instanceof byte[]) {
1467 if (!(tag.mValue instanceof byte[])) return false;
1468 return Arrays.equals((byte[]) mValue, (byte[]) tag.mValue);
1470 return mValue.equals(tag.mValue);
1473 return tag.mValue == null;