1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.exif; 18 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapFactory; 21 import android.util.SparseIntArray; 22 import com.android.camera.debug.Log; 23 24 import java.io.BufferedInputStream; 25 import java.io.ByteArrayInputStream; 26 import java.io.ByteArrayOutputStream; 27 import java.io.Closeable; 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.io.FileNotFoundException; 31 import java.io.FileOutputStream; 32 import java.io.IOException; 33 import java.io.InputStream; 34 import java.io.OutputStream; 35 import java.io.RandomAccessFile; 36 import java.nio.ByteBuffer; 37 import java.nio.ByteOrder; 38 import java.nio.channels.FileChannel.MapMode; 39 import java.text.DateFormat; 40 import java.text.SimpleDateFormat; 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.Calendar; 44 import java.util.Collection; 45 import java.util.HashSet; 46 import java.util.List; 47 import java.util.TimeZone; 48 49 /** 50 * This class provides methods and constants for reading and writing jpeg file 51 * metadata. It contains a collection of ExifTags, and a collection of 52 * definitions for creating valid ExifTags. The collection of ExifTags can be 53 * updated by: reading new ones from a file, deleting or adding existing ones, 54 * or building new ExifTags from a tag definition. These ExifTags can be written 55 * to a valid jpeg image as exif metadata. 56 * <p> 57 * Each ExifTag has a tag ID (TID) and is stored in a specific image file 58 * directory (IFD) as specified by the exif standard. A tag definition can be 59 * looked up with a constant that is a combination of TID and IFD. This 60 * definition has information about the type, number of components, and valid 61 * IFDs for a tag. 62 * 63 * @see ExifTag 64 */ 65 public class ExifInterface { 66 public static final int TAG_NULL = -1; 67 public static final int IFD_NULL = -1; 68 public static final int DEFINITION_NULL = 0; 69 70 /** 71 * Tag constants for Jeita EXIF 2.2 72 */ 73 public static final String EXIF_VERSION = "0220"; 74 75 // IFD 0 76 public static final int TAG_IMAGE_WIDTH = 77 defineTag(IfdId.TYPE_IFD_0, (short) 0x0100); 78 public static final int TAG_IMAGE_LENGTH = 79 defineTag(IfdId.TYPE_IFD_0, (short) 0x0101); // Image height 80 public static final int TAG_BITS_PER_SAMPLE = 81 defineTag(IfdId.TYPE_IFD_0, (short) 0x0102); 82 public static final int TAG_COMPRESSION = 83 defineTag(IfdId.TYPE_IFD_0, (short) 0x0103); 84 public static final int TAG_PHOTOMETRIC_INTERPRETATION = 85 defineTag(IfdId.TYPE_IFD_0, (short) 0x0106); 86 public static final int TAG_IMAGE_DESCRIPTION = 87 defineTag(IfdId.TYPE_IFD_0, (short) 0x010E); 88 public static final int TAG_MAKE = 89 defineTag(IfdId.TYPE_IFD_0, (short) 0x010F); 90 public static final int TAG_MODEL = 91 defineTag(IfdId.TYPE_IFD_0, (short) 0x0110); 92 public static final int TAG_STRIP_OFFSETS = 93 defineTag(IfdId.TYPE_IFD_0, (short) 0x0111); 94 public static final int TAG_ORIENTATION = 95 defineTag(IfdId.TYPE_IFD_0, (short) 0x0112); 96 public static final int TAG_SAMPLES_PER_PIXEL = 97 defineTag(IfdId.TYPE_IFD_0, (short) 0x0115); 98 public static final int TAG_ROWS_PER_STRIP = 99 defineTag(IfdId.TYPE_IFD_0, (short) 0x0116); 100 public static final int TAG_STRIP_BYTE_COUNTS = 101 defineTag(IfdId.TYPE_IFD_0, (short) 0x0117); 102 public static final int TAG_X_RESOLUTION = 103 defineTag(IfdId.TYPE_IFD_0, (short) 0x011A); 104 public static final int TAG_Y_RESOLUTION = 105 defineTag(IfdId.TYPE_IFD_0, (short) 0x011B); 106 public static final int TAG_PLANAR_CONFIGURATION = 107 defineTag(IfdId.TYPE_IFD_0, (short) 0x011C); 108 public static final int TAG_RESOLUTION_UNIT = 109 defineTag(IfdId.TYPE_IFD_0, (short) 0x0128); 110 public static final int TAG_TRANSFER_FUNCTION = 111 defineTag(IfdId.TYPE_IFD_0, (short) 0x012D); 112 public static final int TAG_SOFTWARE = 113 defineTag(IfdId.TYPE_IFD_0, (short) 0x0131); 114 public static final int TAG_DATE_TIME = 115 defineTag(IfdId.TYPE_IFD_0, (short) 0x0132); 116 public static final int TAG_ARTIST = 117 defineTag(IfdId.TYPE_IFD_0, (short) 0x013B); 118 public static final int TAG_WHITE_POINT = 119 defineTag(IfdId.TYPE_IFD_0, (short) 0x013E); 120 public static final int TAG_PRIMARY_CHROMATICITIES = 121 defineTag(IfdId.TYPE_IFD_0, (short) 0x013F); 122 public static final int TAG_Y_CB_CR_COEFFICIENTS = 123 defineTag(IfdId.TYPE_IFD_0, (short) 0x0211); 124 public static final int TAG_Y_CB_CR_SUB_SAMPLING = 125 defineTag(IfdId.TYPE_IFD_0, (short) 0x0212); 126 public static final int TAG_Y_CB_CR_POSITIONING = 127 defineTag(IfdId.TYPE_IFD_0, (short) 0x0213); 128 public static final int TAG_REFERENCE_BLACK_WHITE = 129 defineTag(IfdId.TYPE_IFD_0, (short) 0x0214); 130 public static final int TAG_COPYRIGHT = 131 defineTag(IfdId.TYPE_IFD_0, (short) 0x8298); 132 public static final int TAG_EXIF_IFD = 133 defineTag(IfdId.TYPE_IFD_0, (short) 0x8769); 134 public static final int TAG_GPS_IFD = 135 defineTag(IfdId.TYPE_IFD_0, (short) 0x8825); 136 // IFD 1 137 public static final int TAG_JPEG_INTERCHANGE_FORMAT = 138 defineTag(IfdId.TYPE_IFD_1, (short) 0x0201); 139 public static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 140 defineTag(IfdId.TYPE_IFD_1, (short) 0x0202); 141 // IFD Exif Tags 142 public static final int TAG_EXPOSURE_TIME = 143 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829A); 144 public static final int TAG_F_NUMBER = 145 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x829D); 146 public static final int TAG_EXPOSURE_PROGRAM = 147 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8822); 148 public static final int TAG_SPECTRAL_SENSITIVITY = 149 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8824); 150 public static final int TAG_ISO_SPEED_RATINGS = 151 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8827); 152 public static final int TAG_OECF = 153 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x8828); 154 public static final int TAG_EXIF_VERSION = 155 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9000); 156 public static final int TAG_DATE_TIME_ORIGINAL = 157 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9003); 158 public static final int TAG_DATE_TIME_DIGITIZED = 159 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9004); 160 public static final int TAG_COMPONENTS_CONFIGURATION = 161 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9101); 162 public static final int TAG_COMPRESSED_BITS_PER_PIXEL = 163 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9102); 164 public static final int TAG_SHUTTER_SPEED_VALUE = 165 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9201); 166 public static final int TAG_APERTURE_VALUE = 167 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9202); 168 public static final int TAG_BRIGHTNESS_VALUE = 169 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9203); 170 public static final int TAG_EXPOSURE_BIAS_VALUE = 171 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9204); 172 public static final int TAG_MAX_APERTURE_VALUE = 173 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9205); 174 public static final int TAG_SUBJECT_DISTANCE = 175 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9206); 176 public static final int TAG_METERING_MODE = 177 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9207); 178 public static final int TAG_LIGHT_SOURCE = 179 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9208); 180 public static final int TAG_FLASH = 181 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9209); 182 public static final int TAG_FOCAL_LENGTH = 183 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x920A); 184 public static final int TAG_SUBJECT_AREA = 185 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9214); 186 public static final int TAG_MAKER_NOTE = 187 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x927C); 188 public static final int TAG_USER_COMMENT = 189 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9286); 190 public static final int TAG_SUB_SEC_TIME = 191 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9290); 192 public static final int TAG_SUB_SEC_TIME_ORIGINAL = 193 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9291); 194 public static final int TAG_SUB_SEC_TIME_DIGITIZED = 195 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0x9292); 196 public static final int TAG_FLASHPIX_VERSION = 197 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA000); 198 public static final int TAG_COLOR_SPACE = 199 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA001); 200 public static final int TAG_PIXEL_X_DIMENSION = 201 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA002); 202 public static final int TAG_PIXEL_Y_DIMENSION = 203 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA003); 204 public static final int TAG_RELATED_SOUND_FILE = 205 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA004); 206 public static final int TAG_INTEROPERABILITY_IFD = 207 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA005); 208 public static final int TAG_FLASH_ENERGY = 209 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20B); 210 public static final int TAG_SPATIAL_FREQUENCY_RESPONSE = 211 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20C); 212 public static final int TAG_FOCAL_PLANE_X_RESOLUTION = 213 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20E); 214 public static final int TAG_FOCAL_PLANE_Y_RESOLUTION = 215 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA20F); 216 public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT = 217 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA210); 218 public static final int TAG_SUBJECT_LOCATION = 219 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA214); 220 public static final int TAG_EXPOSURE_INDEX = 221 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA215); 222 public static final int TAG_SENSING_METHOD = 223 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA217); 224 public static final int TAG_FILE_SOURCE = 225 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA300); 226 public static final int TAG_SCENE_TYPE = 227 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA301); 228 public static final int TAG_CFA_PATTERN = 229 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA302); 230 public static final int TAG_CUSTOM_RENDERED = 231 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA401); 232 public static final int TAG_EXPOSURE_MODE = 233 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA402); 234 public static final int TAG_WHITE_BALANCE = 235 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA403); 236 public static final int TAG_DIGITAL_ZOOM_RATIO = 237 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA404); 238 public static final int TAG_FOCAL_LENGTH_IN_35_MM_FILE = 239 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA405); 240 public static final int TAG_SCENE_CAPTURE_TYPE = 241 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA406); 242 public static final int TAG_GAIN_CONTROL = 243 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA407); 244 public static final int TAG_CONTRAST = 245 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA408); 246 public static final int TAG_SATURATION = 247 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA409); 248 public static final int TAG_SHARPNESS = 249 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40A); 250 public static final int TAG_DEVICE_SETTING_DESCRIPTION = 251 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40B); 252 public static final int TAG_SUBJECT_DISTANCE_RANGE = 253 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA40C); 254 public static final int TAG_IMAGE_UNIQUE_ID = 255 defineTag(IfdId.TYPE_IFD_EXIF, (short) 0xA420); 256 // IFD GPS tags 257 public static final int TAG_GPS_VERSION_ID = 258 defineTag(IfdId.TYPE_IFD_GPS, (short) 0); 259 public static final int TAG_GPS_LATITUDE_REF = 260 defineTag(IfdId.TYPE_IFD_GPS, (short) 1); 261 public static final int TAG_GPS_LATITUDE = 262 defineTag(IfdId.TYPE_IFD_GPS, (short) 2); 263 public static final int TAG_GPS_LONGITUDE_REF = 264 defineTag(IfdId.TYPE_IFD_GPS, (short) 3); 265 public static final int TAG_GPS_LONGITUDE = 266 defineTag(IfdId.TYPE_IFD_GPS, (short) 4); 267 public static final int TAG_GPS_ALTITUDE_REF = 268 defineTag(IfdId.TYPE_IFD_GPS, (short) 5); 269 public static final int TAG_GPS_ALTITUDE = 270 defineTag(IfdId.TYPE_IFD_GPS, (short) 6); 271 public static final int TAG_GPS_TIME_STAMP = 272 defineTag(IfdId.TYPE_IFD_GPS, (short) 7); 273 public static final int TAG_GPS_SATTELLITES = 274 defineTag(IfdId.TYPE_IFD_GPS, (short) 8); 275 public static final int TAG_GPS_STATUS = 276 defineTag(IfdId.TYPE_IFD_GPS, (short) 9); 277 public static final int TAG_GPS_MEASURE_MODE = 278 defineTag(IfdId.TYPE_IFD_GPS, (short) 10); 279 public static final int TAG_GPS_DOP = 280 defineTag(IfdId.TYPE_IFD_GPS, (short) 11); 281 public static final int TAG_GPS_SPEED_REF = 282 defineTag(IfdId.TYPE_IFD_GPS, (short) 12); 283 public static final int TAG_GPS_SPEED = 284 defineTag(IfdId.TYPE_IFD_GPS, (short) 13); 285 public static final int TAG_GPS_TRACK_REF = 286 defineTag(IfdId.TYPE_IFD_GPS, (short) 14); 287 public static final int TAG_GPS_TRACK = 288 defineTag(IfdId.TYPE_IFD_GPS, (short) 15); 289 public static final int TAG_GPS_IMG_DIRECTION_REF = 290 defineTag(IfdId.TYPE_IFD_GPS, (short) 16); 291 public static final int TAG_GPS_IMG_DIRECTION = 292 defineTag(IfdId.TYPE_IFD_GPS, (short) 17); 293 public static final int TAG_GPS_MAP_DATUM = 294 defineTag(IfdId.TYPE_IFD_GPS, (short) 18); 295 public static final int TAG_GPS_DEST_LATITUDE_REF = 296 defineTag(IfdId.TYPE_IFD_GPS, (short) 19); 297 public static final int TAG_GPS_DEST_LATITUDE = 298 defineTag(IfdId.TYPE_IFD_GPS, (short) 20); 299 public static final int TAG_GPS_DEST_LONGITUDE_REF = 300 defineTag(IfdId.TYPE_IFD_GPS, (short) 21); 301 public static final int TAG_GPS_DEST_LONGITUDE = 302 defineTag(IfdId.TYPE_IFD_GPS, (short) 22); 303 public static final int TAG_GPS_DEST_BEARING_REF = 304 defineTag(IfdId.TYPE_IFD_GPS, (short) 23); 305 public static final int TAG_GPS_DEST_BEARING = 306 defineTag(IfdId.TYPE_IFD_GPS, (short) 24); 307 public static final int TAG_GPS_DEST_DISTANCE_REF = 308 defineTag(IfdId.TYPE_IFD_GPS, (short) 25); 309 public static final int TAG_GPS_DEST_DISTANCE = 310 defineTag(IfdId.TYPE_IFD_GPS, (short) 26); 311 public static final int TAG_GPS_PROCESSING_METHOD = 312 defineTag(IfdId.TYPE_IFD_GPS, (short) 27); 313 public static final int TAG_GPS_AREA_INFORMATION = 314 defineTag(IfdId.TYPE_IFD_GPS, (short) 28); 315 public static final int TAG_GPS_DATE_STAMP = 316 defineTag(IfdId.TYPE_IFD_GPS, (short) 29); 317 public static final int TAG_GPS_DIFFERENTIAL = 318 defineTag(IfdId.TYPE_IFD_GPS, (short) 30); 319 // IFD Interoperability tags 320 public static final int TAG_INTEROPERABILITY_INDEX = 321 defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 1); 322 private static final Log.Tag TAG = new Log.Tag("ExifInterface"); 323 324 /** 325 * Tags that contain offset markers. These are included in the banned 326 * defines. 327 */ 328 private static HashSet<Short> sOffsetTags = new HashSet<Short>(); 329 static { 330 sOffsetTags.add(getTrueTagKey(TAG_GPS_IFD)); 331 sOffsetTags.add(getTrueTagKey(TAG_EXIF_IFD)); 332 sOffsetTags.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT)); 333 sOffsetTags.add(getTrueTagKey(TAG_INTEROPERABILITY_IFD)); 334 sOffsetTags.add(getTrueTagKey(TAG_STRIP_OFFSETS)); 335 } 336 337 /** 338 * Tags with definitions that cannot be overridden (banned defines). 339 */ 340 protected static HashSet<Short> sBannedDefines = new HashSet<Short>(sOffsetTags); 341 static { 342 sBannedDefines.add(getTrueTagKey(TAG_NULL)); 343 sBannedDefines.add(getTrueTagKey(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH)); 344 sBannedDefines.add(getTrueTagKey(TAG_STRIP_BYTE_COUNTS)); 345 } 346 347 /** 348 * Returns the constant representing a tag with a given TID and default IFD. 349 */ 350 public static int defineTag(int ifdId, short tagId) { 351 return (tagId & 0x0000ffff) | (ifdId << 16); 352 } 353 354 /** 355 * Returns the TID for a tag constant. 356 */ 357 public static short getTrueTagKey(int tag) { 358 // Truncate 359 return (short) tag; 360 } 361 362 /** 363 * Returns the default IFD for a tag constant. 364 */ 365 public static int getTrueIfd(int tag) { 366 return tag >>> 16; 367 } 368 369 /** 370 * Constants for {@link TAG_ORIENTATION}. They can be interpreted as 371 * follows: 372 * <ul> 373 * <li>TOP_LEFT is the normal orientation.</li> 374 * <li>TOP_RIGHT is a left-right mirror.</li> 375 * <li>BOTTOM_LEFT is a 180 degree rotation.</li> 376 * <li>BOTTOM_RIGHT is a top-bottom mirror.</li> 377 * <li>LEFT_TOP is mirrored about the top-left<->bottom-right axis.</li> 378 * <li>RIGHT_TOP is a 90 degree clockwise rotation.</li> 379 * <li>LEFT_BOTTOM is mirrored about the top-right<->bottom-left axis.</li> 380 * <li>RIGHT_BOTTOM is a 270 degree clockwise rotation.</li> 381 * </ul> 382 */ 383 public static interface Orientation { 384 public static final short TOP_LEFT = 1; 385 public static final short TOP_RIGHT = 2; 386 public static final short BOTTOM_LEFT = 3; 387 public static final short BOTTOM_RIGHT = 4; 388 public static final short LEFT_TOP = 5; 389 public static final short RIGHT_TOP = 6; 390 public static final short LEFT_BOTTOM = 7; 391 public static final short RIGHT_BOTTOM = 8; 392 } 393 394 /** 395 * Constants for {@link TAG_Y_CB_CR_POSITIONING} 396 */ 397 public static interface YCbCrPositioning { 398 public static final short CENTERED = 1; 399 public static final short CO_SITED = 2; 400 } 401 402 /** 403 * Constants for {@link TAG_COMPRESSION} 404 */ 405 public static interface Compression { 406 public static final short UNCOMPRESSION = 1; 407 public static final short JPEG = 6; 408 } 409 410 /** 411 * Constants for {@link TAG_RESOLUTION_UNIT} 412 */ 413 public static interface ResolutionUnit { 414 public static final short INCHES = 2; 415 public static final short CENTIMETERS = 3; 416 } 417 418 /** 419 * Constants for {@link TAG_PHOTOMETRIC_INTERPRETATION} 420 */ 421 public static interface PhotometricInterpretation { 422 public static final short RGB = 2; 423 public static final short YCBCR = 6; 424 } 425 426 /** 427 * Constants for {@link TAG_PLANAR_CONFIGURATION} 428 */ 429 public static interface PlanarConfiguration { 430 public static final short CHUNKY = 1; 431 public static final short PLANAR = 2; 432 } 433 434 /** 435 * Constants for {@link TAG_EXPOSURE_PROGRAM} 436 */ 437 public static interface ExposureProgram { 438 public static final short NOT_DEFINED = 0; 439 public static final short MANUAL = 1; 440 public static final short NORMAL_PROGRAM = 2; 441 public static final short APERTURE_PRIORITY = 3; 442 public static final short SHUTTER_PRIORITY = 4; 443 public static final short CREATIVE_PROGRAM = 5; 444 public static final short ACTION_PROGRAM = 6; 445 public static final short PROTRAIT_MODE = 7; 446 public static final short LANDSCAPE_MODE = 8; 447 } 448 449 /** 450 * Constants for {@link TAG_METERING_MODE} 451 */ 452 public static interface MeteringMode { 453 public static final short UNKNOWN = 0; 454 public static final short AVERAGE = 1; 455 public static final short CENTER_WEIGHTED_AVERAGE = 2; 456 public static final short SPOT = 3; 457 public static final short MULTISPOT = 4; 458 public static final short PATTERN = 5; 459 public static final short PARTAIL = 6; 460 public static final short OTHER = 255; 461 } 462 463 /** 464 * Constants for {@link TAG_FLASH} As the definition in Jeita EXIF 2.2 465 * standard, we can treat this constant as bitwise flag. 466 * <p> 467 * e.g. 468 * <p> 469 * short flash = FIRED | RETURN_STROBE_RETURN_LIGHT_DETECTED | 470 * MODE_AUTO_MODE 471 */ 472 public static interface Flash { 473 // LSB 474 public static final short DID_NOT_FIRE = 0; 475 public static final short FIRED = 1; 476 // 1st~2nd bits 477 public static final short RETURN_NO_STROBE_RETURN_DETECTION_FUNCTION = 0 << 1; 478 public static final short RETURN_STROBE_RETURN_LIGHT_NOT_DETECTED = 2 << 1; 479 public static final short RETURN_STROBE_RETURN_LIGHT_DETECTED = 3 << 1; 480 // 3rd~4th bits 481 public static final short MODE_UNKNOWN = 0 << 3; 482 public static final short MODE_COMPULSORY_FLASH_FIRING = 1 << 3; 483 public static final short MODE_COMPULSORY_FLASH_SUPPRESSION = 2 << 3; 484 public static final short MODE_AUTO_MODE = 3 << 3; 485 // 5th bit 486 public static final short FUNCTION_PRESENT = 0 << 5; 487 public static final short FUNCTION_NO_FUNCTION = 1 << 5; 488 // 6th bit 489 public static final short RED_EYE_REDUCTION_NO_OR_UNKNOWN = 0 << 6; 490 public static final short RED_EYE_REDUCTION_SUPPORT = 1 << 6; 491 } 492 493 /** 494 * Constants for {@link TAG_COLOR_SPACE} 495 */ 496 public static interface ColorSpace { 497 public static final short SRGB = 1; 498 public static final short UNCALIBRATED = (short) 0xFFFF; 499 } 500 501 /** 502 * Constants for {@link TAG_EXPOSURE_MODE} 503 */ 504 public static interface ExposureMode { 505 public static final short AUTO_EXPOSURE = 0; 506 public static final short MANUAL_EXPOSURE = 1; 507 public static final short AUTO_BRACKET = 2; 508 } 509 510 /** 511 * Constants for {@link TAG_WHITE_BALANCE} 512 */ 513 public static interface WhiteBalance { 514 public static final short AUTO = 0; 515 public static final short MANUAL = 1; 516 } 517 518 /** 519 * Constants for {@link TAG_SCENE_CAPTURE_TYPE} 520 */ 521 public static interface SceneCapture { 522 public static final short STANDARD = 0; 523 public static final short LANDSCAPE = 1; 524 public static final short PROTRAIT = 2; 525 public static final short NIGHT_SCENE = 3; 526 } 527 528 /** 529 * Constants for {@link TAG_COMPONENTS_CONFIGURATION} 530 */ 531 public static interface ComponentsConfiguration { 532 public static final short NOT_EXIST = 0; 533 public static final short Y = 1; 534 public static final short CB = 2; 535 public static final short CR = 3; 536 public static final short R = 4; 537 public static final short G = 5; 538 public static final short B = 6; 539 } 540 541 /** 542 * Constants for {@link TAG_LIGHT_SOURCE} 543 */ 544 public static interface LightSource { 545 public static final short UNKNOWN = 0; 546 public static final short DAYLIGHT = 1; 547 public static final short FLUORESCENT = 2; 548 public static final short TUNGSTEN = 3; 549 public static final short FLASH = 4; 550 public static final short FINE_WEATHER = 9; 551 public static final short CLOUDY_WEATHER = 10; 552 public static final short SHADE = 11; 553 public static final short DAYLIGHT_FLUORESCENT = 12; 554 public static final short DAY_WHITE_FLUORESCENT = 13; 555 public static final short COOL_WHITE_FLUORESCENT = 14; 556 public static final short WHITE_FLUORESCENT = 15; 557 public static final short STANDARD_LIGHT_A = 17; 558 public static final short STANDARD_LIGHT_B = 18; 559 public static final short STANDARD_LIGHT_C = 19; 560 public static final short D55 = 20; 561 public static final short D65 = 21; 562 public static final short D75 = 22; 563 public static final short D50 = 23; 564 public static final short ISO_STUDIO_TUNGSTEN = 24; 565 public static final short OTHER = 255; 566 } 567 568 /** 569 * Constants for {@link TAG_SENSING_METHOD} 570 */ 571 public static interface SensingMethod { 572 public static final short NOT_DEFINED = 1; 573 public static final short ONE_CHIP_COLOR = 2; 574 public static final short TWO_CHIP_COLOR = 3; 575 public static final short THREE_CHIP_COLOR = 4; 576 public static final short COLOR_SEQUENTIAL_AREA = 5; 577 public static final short TRILINEAR = 7; 578 public static final short COLOR_SEQUENTIAL_LINEAR = 8; 579 } 580 581 /** 582 * Constants for {@link TAG_FILE_SOURCE} 583 */ 584 public static interface FileSource { 585 public static final short DSC = 3; 586 } 587 588 /** 589 * Constants for {@link TAG_SCENE_TYPE} 590 */ 591 public static interface SceneType { 592 public static final short DIRECT_PHOTOGRAPHED = 1; 593 } 594 595 /** 596 * Constants for {@link TAG_GAIN_CONTROL} 597 */ 598 public static interface GainControl { 599 public static final short NONE = 0; 600 public static final short LOW_UP = 1; 601 public static final short HIGH_UP = 2; 602 public static final short LOW_DOWN = 3; 603 public static final short HIGH_DOWN = 4; 604 } 605 606 /** 607 * Constants for {@link TAG_CONTRAST} 608 */ 609 public static interface Contrast { 610 public static final short NORMAL = 0; 611 public static final short SOFT = 1; 612 public static final short HARD = 2; 613 } 614 615 /** 616 * Constants for {@link TAG_SATURATION} 617 */ 618 public static interface Saturation { 619 public static final short NORMAL = 0; 620 public static final short LOW = 1; 621 public static final short HIGH = 2; 622 } 623 624 /** 625 * Constants for {@link TAG_SHARPNESS} 626 */ 627 public static interface Sharpness { 628 public static final short NORMAL = 0; 629 public static final short SOFT = 1; 630 public static final short HARD = 2; 631 } 632 633 /** 634 * Constants for {@link TAG_SUBJECT_DISTANCE} 635 */ 636 public static interface SubjectDistance { 637 public static final short UNKNOWN = 0; 638 public static final short MACRO = 1; 639 public static final short CLOSE_VIEW = 2; 640 public static final short DISTANT_VIEW = 3; 641 } 642 643 /** 644 * Constants for {@link TAG_GPS_LATITUDE_REF}, 645 * {@link TAG_GPS_DEST_LATITUDE_REF} 646 */ 647 public static interface GpsLatitudeRef { 648 public static final String NORTH = "N"; 649 public static final String SOUTH = "S"; 650 } 651 652 /** 653 * Constants for {@link TAG_GPS_LONGITUDE_REF}, 654 * {@link TAG_GPS_DEST_LONGITUDE_REF} 655 */ 656 public static interface GpsLongitudeRef { 657 public static final String EAST = "E"; 658 public static final String WEST = "W"; 659 } 660 661 /** 662 * Constants for {@link TAG_GPS_ALTITUDE_REF} 663 */ 664 public static interface GpsAltitudeRef { 665 public static final short SEA_LEVEL = 0; 666 public static final short SEA_LEVEL_NEGATIVE = 1; 667 } 668 669 /** 670 * Constants for {@link TAG_GPS_STATUS} 671 */ 672 public static interface GpsStatus { 673 public static final String IN_PROGRESS = "A"; 674 public static final String INTEROPERABILITY = "V"; 675 } 676 677 /** 678 * Constants for {@link TAG_GPS_MEASURE_MODE} 679 */ 680 public static interface GpsMeasureMode { 681 public static final String MODE_2_DIMENSIONAL = "2"; 682 public static final String MODE_3_DIMENSIONAL = "3"; 683 } 684 685 /** 686 * Constants for {@link TAG_GPS_SPEED_REF}, 687 * {@link TAG_GPS_DEST_DISTANCE_REF} 688 */ 689 public static interface GpsSpeedRef { 690 public static final String KILOMETERS = "K"; 691 public static final String MILES = "M"; 692 public static final String KNOTS = "N"; 693 } 694 695 /** 696 * Constants for {@link TAG_GPS_TRACK_REF}, 697 * {@link TAG_GPS_IMG_DIRECTION_REF}, {@link TAG_GPS_DEST_BEARING_REF} 698 */ 699 public static interface GpsTrackRef { 700 public static final String TRUE_DIRECTION = "T"; 701 public static final String MAGNETIC_DIRECTION = "M"; 702 } 703 704 /** 705 * Constants for {@link TAG_GPS_DIFFERENTIAL} 706 */ 707 public static interface GpsDifferential { 708 public static final short WITHOUT_DIFFERENTIAL_CORRECTION = 0; 709 public static final short DIFFERENTIAL_CORRECTION_APPLIED = 1; 710 } 711 712 private static final String NULL_ARGUMENT_STRING = "Argument is null"; 713 private ExifData mData = new ExifData(DEFAULT_BYTE_ORDER); 714 public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN; 715 716 public ExifInterface() { 717 mGPSDateStampFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 718 } 719 720 /** 721 * Reads the exif tags from a byte array, clearing this ExifInterface 722 * object's existing exif tags. 723 * 724 * @param jpeg a byte array containing a jpeg compressed image. 725 * @throws IOException 726 */ 727 public void readExif(byte[] jpeg) throws IOException { 728 readExif(new ByteArrayInputStream(jpeg)); 729 } 730 731 /** 732 * Reads the exif tags from an InputStream, clearing this ExifInterface 733 * object's existing exif tags. 734 * 735 * @param inStream an InputStream containing a jpeg compressed image. 736 * @throws IOException 737 */ 738 public void readExif(InputStream inStream) throws IOException { 739 if (inStream == null) { 740 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 741 } 742 ExifData d = null; 743 try { 744 d = new ExifReader(this).read(inStream); 745 } catch (ExifInvalidFormatException e) { 746 throw new IOException("Invalid exif format : " + e); 747 } 748 mData = d; 749 } 750 751 /** 752 * Reads the exif tags from a file, clearing this ExifInterface object's 753 * existing exif tags. 754 * 755 * @param inFileName a string representing the filepath to jpeg file. 756 * @throws FileNotFoundException 757 * @throws IOException 758 */ 759 public void readExif(String inFileName) throws FileNotFoundException, IOException { 760 if (inFileName == null) { 761 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 762 } 763 InputStream is = null; 764 765 is = new BufferedInputStream(new FileInputStream(inFileName)); 766 readExif(is); 767 768 is.close(); 769 } 770 771 /** 772 * Sets the exif tags, clearing this ExifInterface object's existing exif 773 * tags. 774 * 775 * @param tags a collection of exif tags to set. 776 */ 777 public void setExif(Collection<ExifTag> tags) { 778 clearExif(); 779 setTags(tags); 780 } 781 782 /** 783 * Clears this ExifInterface object's existing exif tags. 784 */ 785 public void clearExif() { 786 mData = new ExifData(DEFAULT_BYTE_ORDER); 787 } 788 789 /** 790 * Writes the tags from this ExifInterface object into a jpeg image, 791 * removing prior exif tags. 792 * 793 * @param jpeg a byte array containing a jpeg compressed image. 794 * @param exifOutStream an OutputStream to which the jpeg image with added 795 * exif tags will be written. 796 * @throws IOException 797 */ 798 public void writeExif(byte[] jpeg, OutputStream exifOutStream) throws IOException { 799 if (jpeg == null || exifOutStream == null) { 800 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 801 } 802 OutputStream s = getExifWriterStream(exifOutStream); 803 s.write(jpeg, 0, jpeg.length); 804 s.flush(); 805 } 806 807 /** 808 * Writes the tags from this ExifInterface object into a jpeg compressed 809 * bitmap, removing prior exif tags. 810 * 811 * @param bmap a bitmap to compress and write exif into. 812 * @param exifOutStream the OutputStream to which the jpeg image with added 813 * exif tags will be written. 814 * @throws IOException 815 */ 816 public void writeExif(Bitmap bmap, OutputStream exifOutStream) throws IOException { 817 if (bmap == null || exifOutStream == null) { 818 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 819 } 820 OutputStream s = getExifWriterStream(exifOutStream); 821 bmap.compress(Bitmap.CompressFormat.JPEG, 90, s); 822 s.flush(); 823 } 824 825 /** 826 * Writes the tags from this ExifInterface object into a jpeg stream, 827 * removing prior exif tags. 828 * 829 * @param jpegStream an InputStream containing a jpeg compressed image. 830 * @param exifOutStream an OutputStream to which the jpeg image with added 831 * exif tags will be written. 832 * @throws IOException 833 */ 834 public void writeExif(InputStream jpegStream, OutputStream exifOutStream) throws IOException { 835 if (jpegStream == null || exifOutStream == null) { 836 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 837 } 838 OutputStream s = getExifWriterStream(exifOutStream); 839 doExifStreamIO(jpegStream, s); 840 s.flush(); 841 } 842 843 /** 844 * Writes the tags from this ExifInterface object into a jpeg image, 845 * removing prior exif tags. 846 * 847 * @param jpeg a byte array containing a jpeg compressed image. 848 * @param exifOutFileName a String containing the filepath to which the jpeg 849 * image with added exif tags will be written. 850 * @throws FileNotFoundException 851 * @throws IOException 852 */ 853 public void writeExif(byte[] jpeg, String exifOutFileName) throws FileNotFoundException, 854 IOException { 855 if (jpeg == null || exifOutFileName == null) { 856 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 857 } 858 OutputStream s = null; 859 s = getExifWriterStream(exifOutFileName); 860 s.write(jpeg, 0, jpeg.length); 861 s.flush(); 862 s.close(); 863 } 864 865 /** 866 * Writes the tags from this ExifInterface object into a jpeg compressed 867 * bitmap, removing prior exif tags. 868 * 869 * @param bmap a bitmap to compress and write exif into. 870 * @param exifOutFileName a String containing the filepath to which the jpeg 871 * image with added exif tags will be written. 872 * @throws FileNotFoundException 873 * @throws IOException 874 */ 875 public void writeExif(Bitmap bmap, String exifOutFileName) throws FileNotFoundException, 876 IOException { 877 if (bmap == null || exifOutFileName == null) { 878 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 879 } 880 OutputStream s = null; 881 882 s = getExifWriterStream(exifOutFileName); 883 bmap.compress(Bitmap.CompressFormat.JPEG, 90, s); 884 s.flush(); 885 s.close(); 886 } 887 888 /** 889 * Writes the tags from this ExifInterface object into a jpeg stream, 890 * removing prior exif tags. 891 * 892 * @param jpegStream an InputStream containing a jpeg compressed image. 893 * @param exifOutFileName a String containing the filepath to which the jpeg 894 * image with added exif tags will be written. 895 * @throws FileNotFoundException 896 * @throws IOException 897 */ 898 public void writeExif(InputStream jpegStream, String exifOutFileName) 899 throws FileNotFoundException, IOException { 900 if (jpegStream == null || exifOutFileName == null) { 901 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 902 } 903 OutputStream s = null; 904 905 s = getExifWriterStream(exifOutFileName); 906 doExifStreamIO(jpegStream, s); 907 s.flush(); 908 909 s.close(); 910 } 911 912 /** 913 * Writes the tags from this ExifInterface object into a jpeg file, removing 914 * prior exif tags. 915 * 916 * @param jpegFileName a String containing the filepath for a jpeg file. 917 * @param exifOutFileName a String containing the filepath to which the jpeg 918 * image with added exif tags will be written. 919 * @throws FileNotFoundException 920 * @throws IOException 921 */ 922 public void writeExif(String jpegFileName, String exifOutFileName) 923 throws FileNotFoundException, IOException { 924 if (jpegFileName == null || exifOutFileName == null) { 925 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 926 } 927 InputStream is = null; 928 929 is = new FileInputStream(jpegFileName); 930 writeExif(is, exifOutFileName); 931 932 is.close(); 933 } 934 935 /** 936 * Wraps an OutputStream object with an ExifOutputStream. Exif tags in this 937 * ExifInterface object will be added to a jpeg image written to this 938 * stream, removing prior exif tags. Other methods of this ExifInterface 939 * object should not be called until the returned OutputStream has been 940 * closed. 941 * 942 * @param outStream an OutputStream to wrap. 943 * @return an OutputStream that wraps the outStream parameter, and adds exif 944 * metadata. A jpeg image should be written to this stream. 945 */ 946 public OutputStream getExifWriterStream(OutputStream outStream) { 947 if (outStream == null) { 948 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 949 } 950 ExifOutputStream eos = new ExifOutputStream(outStream, this); 951 eos.setExifData(mData); 952 return eos; 953 } 954 955 /** 956 * Returns an OutputStream object that writes to a file. Exif tags in this 957 * ExifInterface object will be added to a jpeg image written to this 958 * stream, removing prior exif tags. Other methods of this ExifInterface 959 * object should not be called until the returned OutputStream has been 960 * closed. 961 * 962 * @param exifOutFileName an String containing a filepath for a jpeg file. 963 * @return an OutputStream that writes to the exifOutFileName file, and adds 964 * exif metadata. A jpeg image should be written to this stream. 965 * @throws FileNotFoundException 966 */ 967 public OutputStream getExifWriterStream(String exifOutFileName) throws FileNotFoundException { 968 if (exifOutFileName == null) { 969 throw new IllegalArgumentException(NULL_ARGUMENT_STRING); 970 } 971 OutputStream out = null; 972 try { 973 out = new FileOutputStream(exifOutFileName); 974 } catch (FileNotFoundException e) { 975 closeSilently(out); 976 throw e; 977 } 978 return getExifWriterStream(out); 979 } 980 981 /** 982 * Attempts to do an in-place rewrite the exif metadata in a file for the 983 * given tags. If tags do not exist or do not have the same size as the 984 * existing exif tags, this method will fail. 985 * 986 * @param filename a String containing a filepath for a jpeg file with exif 987 * tags to rewrite. 988 * @param tags tags that will be written into the jpeg file over existing 989 * tags if possible. 990 * @return true if success, false if could not overwrite. If false, no 991 * changes are made to the file. 992 * @throws FileNotFoundException 993 * @throws IOException 994 */ 995 public boolean rewriteExif(String filename, Collection<ExifTag> tags) 996 throws FileNotFoundException, IOException { 997 RandomAccessFile file = null; 998 InputStream is = null; 999 boolean ret; 1000 try { 1001 File temp = new File(filename); 1002 is = new BufferedInputStream(new FileInputStream(temp)); 1003 1004 // Parse beginning of APP1 in exif to find size of exif header. 1005 ExifParser parser = null; 1006 try { 1007 parser = ExifParser.parse(is, this); 1008 } catch (ExifInvalidFormatException e) { 1009 throw new IOException("Invalid exif format : ", e); 1010 } 1011 long exifSize = parser.getOffsetToExifEndFromSOF(); 1012 1013 // Free up resources 1014 is.close(); 1015 is = null; 1016 1017 // Open file for memory mapping. 1018 file = new RandomAccessFile(temp, "rw"); 1019 long fileLength = file.length(); 1020 if (fileLength < exifSize) { 1021 throw new IOException("Filesize changed during operation"); 1022 } 1023 1024 // Map only exif header into memory. 1025 ByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize); 1026 1027 // Attempt to overwrite tag values without changing lengths (avoids 1028 // file copy). 1029 ret = rewriteExif(buf, tags); 1030 } finally { 1031 closeSilently(is); 1032 } 1033 file.close(); 1034 return ret; 1035 } 1036 1037 /** 1038 * Attempts to do an in-place rewrite the exif metadata in a ByteBuffer for 1039 * the given tags. If tags do not exist or do not have the same size as the 1040 * existing exif tags, this method will fail. 1041 * 1042 * @param buf a ByteBuffer containing a jpeg file with existing exif tags to 1043 * rewrite. 1044 * @param tags tags that will be written into the jpeg ByteBuffer over 1045 * existing tags if possible. 1046 * @return true if success, false if could not overwrite. If false, no 1047 * changes are made to the ByteBuffer. 1048 * @throws IOException 1049 */ 1050 public boolean rewriteExif(ByteBuffer buf, Collection<ExifTag> tags) throws IOException { 1051 ExifModifier mod = null; 1052 try { 1053 mod = new ExifModifier(buf, this); 1054 for (ExifTag t : tags) { 1055 mod.modifyTag(t); 1056 } 1057 return mod.commit(); 1058 } catch (ExifInvalidFormatException e) { 1059 throw new IOException("Invalid exif format : " + e); 1060 } 1061 } 1062 1063 /** 1064 * Attempts to do an in-place rewrite of the exif metadata. If this fails, 1065 * fall back to overwriting file. This preserves tags that are not being 1066 * rewritten. 1067 * 1068 * @param filename a String containing a filepath for a jpeg file. 1069 * @param tags tags that will be written into the jpeg file over existing 1070 * tags if possible. 1071 * @throws FileNotFoundException 1072 * @throws IOException 1073 * @see #rewriteExif 1074 */ 1075 public void forceRewriteExif(String filename, Collection<ExifTag> tags) 1076 throws FileNotFoundException, 1077 IOException { 1078 // Attempt in-place write 1079 if (!rewriteExif(filename, tags)) { 1080 // Fall back to doing a copy 1081 ExifData tempData = mData; 1082 mData = new ExifData(DEFAULT_BYTE_ORDER); 1083 FileInputStream is = null; 1084 ByteArrayOutputStream bytes = null; 1085 try { 1086 is = new FileInputStream(filename); 1087 bytes = new ByteArrayOutputStream(); 1088 doExifStreamIO(is, bytes); 1089 byte[] imageBytes = bytes.toByteArray(); 1090 readExif(imageBytes); 1091 setTags(tags); 1092 writeExif(imageBytes, filename); 1093 } finally { 1094 is.close(); 1095 // Prevent clobbering of mData 1096 mData = tempData; 1097 } 1098 } 1099 } 1100 1101 /** 1102 * Attempts to do an in-place rewrite of the exif metadata using the tags in 1103 * this ExifInterface object. If this fails, fall back to overwriting file. 1104 * This preserves tags that are not being rewritten. 1105 * 1106 * @param filename a String containing a filepath for a jpeg file. 1107 * @throws FileNotFoundException 1108 * @throws IOException 1109 * @see #rewriteExif 1110 */ 1111 public void forceRewriteExif(String filename) throws FileNotFoundException, IOException { 1112 forceRewriteExif(filename, getAllTags()); 1113 } 1114 1115 /** 1116 * Get the exif tags in this ExifInterface object or null if none exist. 1117 * 1118 * @return a List of {@link ExifTag}s. 1119 */ 1120 public List<ExifTag> getAllTags() { 1121 return mData.getAllTags(); 1122 } 1123 1124 /** 1125 * Returns a list of ExifTags that share a TID (which can be obtained by 1126 * calling {@link #getTrueTagKey} on a defined tag constant) or null if none 1127 * exist. 1128 * 1129 * @param tagId a TID as defined in the exif standard (or with 1130 * {@link #defineTag}). 1131 * @return a List of {@link ExifTag}s. 1132 */ 1133 public List<ExifTag> getTagsForTagId(short tagId) { 1134 return mData.getAllTagsForTagId(tagId); 1135 } 1136 1137 /** 1138 * Returns a list of ExifTags that share an IFD (which can be obtained by 1139 * calling {@link #getTrueIFD} on a defined tag constant) or null if none 1140 * exist. 1141 * 1142 * @param ifdId an IFD as defined in the exif standard (or with 1143 * {@link #defineTag}). 1144 * @return a List of {@link ExifTag}s. 1145 */ 1146 public List<ExifTag> getTagsForIfdId(int ifdId) { 1147 return mData.getAllTagsForIfd(ifdId); 1148 } 1149 1150 /** 1151 * Gets an ExifTag for an IFD other than the tag's default. 1152 * 1153 * @see #getTag 1154 */ 1155 public ExifTag getTag(int tagId, int ifdId) { 1156 if (!ExifTag.isValidIfd(ifdId)) { 1157 return null; 1158 } 1159 return mData.getTag(getTrueTagKey(tagId), ifdId); 1160 } 1161 1162 /** 1163 * Returns the ExifTag in that tag's default IFD for a defined tag constant 1164 * or null if none exists. 1165 * 1166 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1167 * @return an {@link ExifTag} or null if none exists. 1168 */ 1169 public ExifTag getTag(int tagId) { 1170 int ifdId = getDefinedTagDefaultIfd(tagId); 1171 return getTag(tagId, ifdId); 1172 } 1173 1174 /** 1175 * Gets a tag value for an IFD other than the tag's default. 1176 * 1177 * @see #getTagValue 1178 */ 1179 public Object getTagValue(int tagId, int ifdId) { 1180 ExifTag t = getTag(tagId, ifdId); 1181 return (t == null) ? null : t.getValue(); 1182 } 1183 1184 /** 1185 * Returns the value of the ExifTag in that tag's default IFD for a defined 1186 * tag constant or null if none exists or the value could not be cast into 1187 * the return type. 1188 * 1189 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1190 * @return the value of the ExifTag or null if none exists. 1191 */ 1192 public Object getTagValue(int tagId) { 1193 int ifdId = getDefinedTagDefaultIfd(tagId); 1194 return getTagValue(tagId, ifdId); 1195 } 1196 1197 /* 1198 * Getter methods that are similar to getTagValue. Null is returned if the 1199 * tag value cannot be cast into the return type. 1200 */ 1201 1202 /** 1203 * @see #getTagValue 1204 */ 1205 public String getTagStringValue(int tagId, int ifdId) { 1206 ExifTag t = getTag(tagId, ifdId); 1207 if (t == null) { 1208 return null; 1209 } 1210 return t.getValueAsString(); 1211 } 1212 1213 /** 1214 * @see #getTagValue 1215 */ 1216 public String getTagStringValue(int tagId) { 1217 int ifdId = getDefinedTagDefaultIfd(tagId); 1218 return getTagStringValue(tagId, ifdId); 1219 } 1220 1221 /** 1222 * @see #getTagValue 1223 */ 1224 public Long getTagLongValue(int tagId, int ifdId) { 1225 long[] l = getTagLongValues(tagId, ifdId); 1226 if (l == null || l.length <= 0) { 1227 return null; 1228 } 1229 return new Long(l[0]); 1230 } 1231 1232 /** 1233 * @see #getTagValue 1234 */ 1235 public Long getTagLongValue(int tagId) { 1236 int ifdId = getDefinedTagDefaultIfd(tagId); 1237 return getTagLongValue(tagId, ifdId); 1238 } 1239 1240 /** 1241 * @see #getTagValue 1242 */ 1243 public Integer getTagIntValue(int tagId, int ifdId) { 1244 int[] l = getTagIntValues(tagId, ifdId); 1245 if (l == null || l.length <= 0) { 1246 return null; 1247 } 1248 return new Integer(l[0]); 1249 } 1250 1251 /** 1252 * @see #getTagValue 1253 */ 1254 public Integer getTagIntValue(int tagId) { 1255 int ifdId = getDefinedTagDefaultIfd(tagId); 1256 return getTagIntValue(tagId, ifdId); 1257 } 1258 1259 /** 1260 * @see #getTagValue 1261 */ 1262 public Byte getTagByteValue(int tagId, int ifdId) { 1263 byte[] l = getTagByteValues(tagId, ifdId); 1264 if (l == null || l.length <= 0) { 1265 return null; 1266 } 1267 return new Byte(l[0]); 1268 } 1269 1270 /** 1271 * @see #getTagValue 1272 */ 1273 public Byte getTagByteValue(int tagId) { 1274 int ifdId = getDefinedTagDefaultIfd(tagId); 1275 return getTagByteValue(tagId, ifdId); 1276 } 1277 1278 /** 1279 * @see #getTagValue 1280 */ 1281 public Rational getTagRationalValue(int tagId, int ifdId) { 1282 Rational[] l = getTagRationalValues(tagId, ifdId); 1283 if (l == null || l.length == 0) { 1284 return null; 1285 } 1286 return new Rational(l[0]); 1287 } 1288 1289 /** 1290 * @see #getTagValue 1291 */ 1292 public Rational getTagRationalValue(int tagId) { 1293 int ifdId = getDefinedTagDefaultIfd(tagId); 1294 return getTagRationalValue(tagId, ifdId); 1295 } 1296 1297 /** 1298 * @see #getTagValue 1299 */ 1300 public long[] getTagLongValues(int tagId, int ifdId) { 1301 ExifTag t = getTag(tagId, ifdId); 1302 if (t == null) { 1303 return null; 1304 } 1305 return t.getValueAsLongs(); 1306 } 1307 1308 /** 1309 * @see #getTagValue 1310 */ 1311 public long[] getTagLongValues(int tagId) { 1312 int ifdId = getDefinedTagDefaultIfd(tagId); 1313 return getTagLongValues(tagId, ifdId); 1314 } 1315 1316 /** 1317 * @see #getTagValue 1318 */ 1319 public int[] getTagIntValues(int tagId, int ifdId) { 1320 ExifTag t = getTag(tagId, ifdId); 1321 if (t == null) { 1322 return null; 1323 } 1324 return t.getValueAsInts(); 1325 } 1326 1327 /** 1328 * @see #getTagValue 1329 */ 1330 public int[] getTagIntValues(int tagId) { 1331 int ifdId = getDefinedTagDefaultIfd(tagId); 1332 return getTagIntValues(tagId, ifdId); 1333 } 1334 1335 /** 1336 * @see #getTagValue 1337 */ 1338 public byte[] getTagByteValues(int tagId, int ifdId) { 1339 ExifTag t = getTag(tagId, ifdId); 1340 if (t == null) { 1341 return null; 1342 } 1343 return t.getValueAsBytes(); 1344 } 1345 1346 /** 1347 * @see #getTagValue 1348 */ 1349 public byte[] getTagByteValues(int tagId) { 1350 int ifdId = getDefinedTagDefaultIfd(tagId); 1351 return getTagByteValues(tagId, ifdId); 1352 } 1353 1354 /** 1355 * @see #getTagValue 1356 */ 1357 public Rational[] getTagRationalValues(int tagId, int ifdId) { 1358 ExifTag t = getTag(tagId, ifdId); 1359 if (t == null) { 1360 return null; 1361 } 1362 return t.getValueAsRationals(); 1363 } 1364 1365 /** 1366 * @see #getTagValue 1367 */ 1368 public Rational[] getTagRationalValues(int tagId) { 1369 int ifdId = getDefinedTagDefaultIfd(tagId); 1370 return getTagRationalValues(tagId, ifdId); 1371 } 1372 1373 /** 1374 * Checks whether a tag has a defined number of elements. 1375 * 1376 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1377 * @return true if the tag has a defined number of elements. 1378 */ 1379 public boolean isTagCountDefined(int tagId) { 1380 int info = getTagInfo().get(tagId); 1381 // No value in info can be zero, as all tags have a non-zero type 1382 if (info == 0) { 1383 return false; 1384 } 1385 return getComponentCountFromInfo(info) != ExifTag.SIZE_UNDEFINED; 1386 } 1387 1388 /** 1389 * Gets the defined number of elements for a tag. 1390 * 1391 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1392 * @return the number of elements or {@link ExifTag#SIZE_UNDEFINED} if the 1393 * tag or the number of elements is not defined. 1394 */ 1395 public int getDefinedTagCount(int tagId) { 1396 int info = getTagInfo().get(tagId); 1397 if (info == 0) { 1398 return ExifTag.SIZE_UNDEFINED; 1399 } 1400 return getComponentCountFromInfo(info); 1401 } 1402 1403 /** 1404 * Gets the number of elements for an ExifTag in a given IFD. 1405 * 1406 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1407 * @param ifdId the IFD containing the ExifTag to check. 1408 * @return the number of elements in the ExifTag, if the tag's size is 1409 * undefined this will return the actual number of elements that is 1410 * in the ExifTag's value. 1411 */ 1412 public int getActualTagCount(int tagId, int ifdId) { 1413 ExifTag t = getTag(tagId, ifdId); 1414 if (t == null) { 1415 return 0; 1416 } 1417 return t.getComponentCount(); 1418 } 1419 1420 /** 1421 * Gets the default IFD for a tag. 1422 * 1423 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1424 * @return the default IFD for a tag definition or {@link #IFD_NULL} if no 1425 * definition exists. 1426 */ 1427 public int getDefinedTagDefaultIfd(int tagId) { 1428 int info = getTagInfo().get(tagId); 1429 if (info == DEFINITION_NULL) { 1430 return IFD_NULL; 1431 } 1432 return getTrueIfd(tagId); 1433 } 1434 1435 /** 1436 * Gets the defined type for a tag. 1437 * 1438 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1439 * @return the type. 1440 * @see ExifTag#getDataType() 1441 */ 1442 public short getDefinedTagType(int tagId) { 1443 int info = getTagInfo().get(tagId); 1444 if (info == 0) { 1445 return -1; 1446 } 1447 return getTypeFromInfo(info); 1448 } 1449 1450 /** 1451 * Returns true if tag TID is one of the following: {@link TAG_EXIF_IFD}, 1452 * {@link TAG_GPS_IFD}, {@link TAG_JPEG_INTERCHANGE_FORMAT}, 1453 * {@link TAG_STRIP_OFFSETS}, {@link TAG_INTEROPERABILITY_IFD} 1454 * <p> 1455 * Note: defining tags with these TID's is disallowed. 1456 * 1457 * @param tag a tag's TID (can be obtained from a defined tag constant with 1458 * {@link #getTrueTagKey}). 1459 * @return true if the TID is that of an offset tag. 1460 */ 1461 protected static boolean isOffsetTag(short tag) { 1462 return sOffsetTags.contains(tag); 1463 } 1464 1465 /** 1466 * Creates a tag for a defined tag constant in a given IFD if that IFD is 1467 * allowed for the tag. This method will fail anytime the appropriate 1468 * {@link ExifTag#setValue} for this tag's datatype would fail. 1469 * 1470 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1471 * @param ifdId the IFD that the tag should be in. 1472 * @param val the value of the tag to set. 1473 * @return an ExifTag object or null if one could not be constructed. 1474 * @see #buildTag 1475 */ 1476 public ExifTag buildTag(int tagId, int ifdId, Object val) { 1477 int info = getTagInfo().get(tagId); 1478 if (info == 0 || val == null) { 1479 return null; 1480 } 1481 short type = getTypeFromInfo(info); 1482 int definedCount = getComponentCountFromInfo(info); 1483 boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED); 1484 if (!ExifInterface.isIfdAllowed(info, ifdId)) { 1485 return null; 1486 } 1487 ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount); 1488 if (!t.setValue(val)) { 1489 return null; 1490 } 1491 return t; 1492 } 1493 1494 /** 1495 * Creates a tag for a defined tag constant in the tag's default IFD. 1496 * 1497 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1498 * @param val the tag's value. 1499 * @return an ExifTag object. 1500 */ 1501 public ExifTag buildTag(int tagId, Object val) { 1502 int ifdId = getTrueIfd(tagId); 1503 return buildTag(tagId, ifdId, val); 1504 } 1505 1506 protected ExifTag buildUninitializedTag(int tagId) { 1507 int info = getTagInfo().get(tagId); 1508 if (info == 0) { 1509 return null; 1510 } 1511 short type = getTypeFromInfo(info); 1512 int definedCount = getComponentCountFromInfo(info); 1513 boolean hasDefinedCount = (definedCount != ExifTag.SIZE_UNDEFINED); 1514 int ifdId = getTrueIfd(tagId); 1515 ExifTag t = new ExifTag(getTrueTagKey(tagId), type, definedCount, ifdId, hasDefinedCount); 1516 return t; 1517 } 1518 1519 /** 1520 * Sets the value of an ExifTag if it exists in the given IFD. The value 1521 * must be the correct type and length for that ExifTag. 1522 * 1523 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1524 * @param ifdId the IFD that the ExifTag is in. 1525 * @param val the value to set. 1526 * @return true if success, false if the ExifTag doesn't exist or the value 1527 * is the wrong type/length. 1528 * @see #setTagValue 1529 */ 1530 public boolean setTagValue(int tagId, int ifdId, Object val) { 1531 ExifTag t = getTag(tagId, ifdId); 1532 if (t == null) { 1533 return false; 1534 } 1535 return t.setValue(val); 1536 } 1537 1538 /** 1539 * Sets the value of an ExifTag if it exists it's default IFD. The value 1540 * must be the correct type and length for that ExifTag. 1541 * 1542 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1543 * @param val the value to set. 1544 * @return true if success, false if the ExifTag doesn't exist or the value 1545 * is the wrong type/length. 1546 */ 1547 public boolean setTagValue(int tagId, Object val) { 1548 int ifdId = getDefinedTagDefaultIfd(tagId); 1549 return setTagValue(tagId, ifdId, val); 1550 } 1551 1552 /** 1553 * Puts an ExifTag into this ExifInterface object's tags, removing a 1554 * previous ExifTag with the same TID and IFD. The IFD it is put into will 1555 * be the one the tag was created with in {@link #buildTag}. 1556 * 1557 * @param tag an ExifTag to put into this ExifInterface's tags. 1558 * @return the previous ExifTag with the same TID and IFD or null if none 1559 * exists. 1560 */ 1561 public ExifTag setTag(ExifTag tag) { 1562 return mData.addTag(tag); 1563 } 1564 1565 /** 1566 * Puts a collection of ExifTags into this ExifInterface objects's tags. Any 1567 * previous ExifTags with the same TID and IFDs will be removed. 1568 * 1569 * @param tags a Collection of ExifTags. 1570 * @see #setTag 1571 */ 1572 public void setTags(Collection<ExifTag> tags) { 1573 for (ExifTag t : tags) { 1574 setTag(t); 1575 } 1576 } 1577 1578 /** 1579 * Removes the ExifTag for a tag constant from the given IFD. 1580 * 1581 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1582 * @param ifdId the IFD of the ExifTag to remove. 1583 */ 1584 public void deleteTag(int tagId, int ifdId) { 1585 mData.removeTag(getTrueTagKey(tagId), ifdId); 1586 } 1587 1588 /** 1589 * Removes the ExifTag for a tag constant from that tag's default IFD. 1590 * 1591 * @param tagId a tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1592 */ 1593 public void deleteTag(int tagId) { 1594 int ifdId = getDefinedTagDefaultIfd(tagId); 1595 deleteTag(tagId, ifdId); 1596 } 1597 1598 /** 1599 * Creates a new tag definition in this ExifInterface object for a given TID 1600 * and default IFD. Creating a definition with the same TID and default IFD 1601 * as a previous definition will override it. 1602 * 1603 * @param tagId the TID for the tag. 1604 * @param defaultIfd the default IFD for the tag. 1605 * @param tagType the type of the tag (see {@link ExifTag#getDataType()}). 1606 * @param defaultComponentCount the number of elements of this tag's type in 1607 * the tags value. 1608 * @param allowedIfds the IFD's this tag is allowed to be put in. 1609 * @return the defined tag constant (e.g. {@link #TAG_IMAGE_WIDTH}) or 1610 * {@link #TAG_NULL} if the definition could not be made. 1611 */ 1612 public int setTagDefinition(short tagId, int defaultIfd, short tagType, 1613 short defaultComponentCount, int[] allowedIfds) { 1614 if (sBannedDefines.contains(tagId)) { 1615 return TAG_NULL; 1616 } 1617 if (ExifTag.isValidType(tagType) && ExifTag.isValidIfd(defaultIfd)) { 1618 int tagDef = defineTag(defaultIfd, tagId); 1619 if (tagDef == TAG_NULL) { 1620 return TAG_NULL; 1621 } 1622 int[] otherDefs = getTagDefinitionsForTagId(tagId); 1623 SparseIntArray infos = getTagInfo(); 1624 // Make sure defaultIfd is in allowedIfds 1625 boolean defaultCheck = false; 1626 for (int i : allowedIfds) { 1627 if (defaultIfd == i) { 1628 defaultCheck = true; 1629 } 1630 if (!ExifTag.isValidIfd(i)) { 1631 return TAG_NULL; 1632 } 1633 } 1634 if (!defaultCheck) { 1635 return TAG_NULL; 1636 } 1637 1638 int ifdFlags = getFlagsFromAllowedIfds(allowedIfds); 1639 // Make sure no identical tags can exist in allowedIfds 1640 if (otherDefs != null) { 1641 for (int def : otherDefs) { 1642 int tagInfo = infos.get(def); 1643 int allowedFlags = getAllowedIfdFlagsFromInfo(tagInfo); 1644 if ((ifdFlags & allowedFlags) != 0) { 1645 return TAG_NULL; 1646 } 1647 } 1648 } 1649 getTagInfo().put(tagDef, ifdFlags << 24 | (tagType << 16) | defaultComponentCount); 1650 return tagDef; 1651 } 1652 return TAG_NULL; 1653 } 1654 1655 protected int getTagDefinition(short tagId, int defaultIfd) { 1656 return getTagInfo().get(defineTag(defaultIfd, tagId)); 1657 } 1658 1659 protected int[] getTagDefinitionsForTagId(short tagId) { 1660 int[] ifds = IfdData.getIfds(); 1661 int[] defs = new int[ifds.length]; 1662 int counter = 0; 1663 SparseIntArray infos = getTagInfo(); 1664 for (int i : ifds) { 1665 int def = defineTag(i, tagId); 1666 if (infos.get(def) != DEFINITION_NULL) { 1667 defs[counter++] = def; 1668 } 1669 } 1670 if (counter == 0) { 1671 return null; 1672 } 1673 1674 return Arrays.copyOfRange(defs, 0, counter); 1675 } 1676 1677 protected int getTagDefinitionForTag(ExifTag tag) { 1678 short type = tag.getDataType(); 1679 int count = tag.getComponentCount(); 1680 int ifd = tag.getIfd(); 1681 return getTagDefinitionForTag(tag.getTagId(), type, count, ifd); 1682 } 1683 1684 protected int getTagDefinitionForTag(short tagId, short type, int count, int ifd) { 1685 int[] defs = getTagDefinitionsForTagId(tagId); 1686 if (defs == null) { 1687 return TAG_NULL; 1688 } 1689 SparseIntArray infos = getTagInfo(); 1690 int ret = TAG_NULL; 1691 for (int i : defs) { 1692 int info = infos.get(i); 1693 short def_type = getTypeFromInfo(info); 1694 int def_count = getComponentCountFromInfo(info); 1695 int[] def_ifds = getAllowedIfdsFromInfo(info); 1696 boolean valid_ifd = false; 1697 for (int j : def_ifds) { 1698 if (j == ifd) { 1699 valid_ifd = true; 1700 break; 1701 } 1702 } 1703 if (valid_ifd && type == def_type 1704 && (count == def_count || def_count == ExifTag.SIZE_UNDEFINED)) { 1705 ret = i; 1706 break; 1707 } 1708 } 1709 return ret; 1710 } 1711 1712 /** 1713 * Removes a tag definition for given defined tag constant. 1714 * 1715 * @param tagId a defined tag constant, e.g. {@link #TAG_IMAGE_WIDTH}. 1716 */ 1717 public void removeTagDefinition(int tagId) { 1718 getTagInfo().delete(tagId); 1719 } 1720 1721 /** 1722 * Resets tag definitions to the default ones. 1723 */ 1724 public void resetTagDefinitions() { 1725 mTagInfo = null; 1726 } 1727 1728 /** 1729 * Returns the thumbnail from IFD1 as a bitmap, or null if none exists. 1730 * 1731 * @return the thumbnail as a bitmap. 1732 */ 1733 public Bitmap getThumbnailBitmap() { 1734 if (mData.hasCompressedThumbnail()) { 1735 byte[] thumb = mData.getCompressedThumbnail(); 1736 return BitmapFactory.decodeByteArray(thumb, 0, thumb.length); 1737 } else if (mData.hasUncompressedStrip()) { 1738 // TODO: implement uncompressed 1739 } 1740 return null; 1741 } 1742 1743 /** 1744 * Returns the thumbnail from IFD1 as a byte array, or null if none exists. 1745 * The bytes may either be an uncompressed strip as specified in the exif 1746 * standard or a jpeg compressed image. 1747 * 1748 * @return the thumbnail as a byte array. 1749 */ 1750 public byte[] getThumbnailBytes() { 1751 if (mData.hasCompressedThumbnail()) { 1752 return mData.getCompressedThumbnail(); 1753 } else if (mData.hasUncompressedStrip()) { 1754 // TODO: implement this 1755 } 1756 return null; 1757 } 1758 1759 /** 1760 * Returns the thumbnail if it is jpeg compressed, or null if none exists. 1761 * 1762 * @return the thumbnail as a byte array. 1763 */ 1764 public byte[] getThumbnail() { 1765 return mData.getCompressedThumbnail(); 1766 } 1767 1768 /** 1769 * Check if thumbnail is compressed. 1770 * 1771 * @return true if the thumbnail is compressed. 1772 */ 1773 public boolean isThumbnailCompressed() { 1774 return mData.hasCompressedThumbnail(); 1775 } 1776 1777 /** 1778 * Check if thumbnail exists. 1779 * 1780 * @return true if a compressed thumbnail exists. 1781 */ 1782 public boolean hasThumbnail() { 1783 // TODO: add back in uncompressed strip 1784 return mData.hasCompressedThumbnail(); 1785 } 1786 1787 // TODO: uncompressed thumbnail setters 1788 1789 /** 1790 * Sets the thumbnail to be a jpeg compressed image. Clears any prior 1791 * thumbnail. 1792 * 1793 * @param thumb a byte array containing a jpeg compressed image. 1794 * @return true if the thumbnail was set. 1795 */ 1796 public boolean setCompressedThumbnail(byte[] thumb) { 1797 mData.clearThumbnailAndStrips(); 1798 mData.setCompressedThumbnail(thumb); 1799 return true; 1800 } 1801 1802 /** 1803 * Sets the thumbnail to be a jpeg compressed bitmap. Clears any prior 1804 * thumbnail. 1805 * 1806 * @param thumb a bitmap to compress to a jpeg thumbnail. 1807 * @return true if the thumbnail was set. 1808 */ 1809 public boolean setCompressedThumbnail(Bitmap thumb) { 1810 ByteArrayOutputStream thumbnail = new ByteArrayOutputStream(); 1811 if (!thumb.compress(Bitmap.CompressFormat.JPEG, 90, thumbnail)) { 1812 return false; 1813 } 1814 return setCompressedThumbnail(thumbnail.toByteArray()); 1815 } 1816 1817 /** 1818 * Clears the compressed thumbnail if it exists. 1819 */ 1820 public void removeCompressedThumbnail() { 1821 mData.setCompressedThumbnail(null); 1822 } 1823 1824 // Convenience methods: 1825 1826 /** 1827 * Decodes the user comment tag into string as specified in the EXIF 1828 * standard. Returns null if decoding failed. 1829 */ 1830 public String getUserComment() { 1831 return mData.getUserComment(); 1832 } 1833 1834 /** 1835 * Returns the Orientation ExifTag value for a given number of degrees. 1836 * 1837 * @param degrees the amount an image is rotated in degrees. 1838 */ 1839 public static short getOrientationValueForRotation(int degrees) { 1840 degrees %= 360; 1841 if (degrees < 0) { 1842 degrees += 360; 1843 } 1844 if (degrees < 90) { 1845 return Orientation.TOP_LEFT; // 0 degrees 1846 } else if (degrees < 180) { 1847 return Orientation.RIGHT_TOP; // 90 degrees cw 1848 } else if (degrees < 270) { 1849 return Orientation.BOTTOM_LEFT; // 180 degrees 1850 } else { 1851 return Orientation.RIGHT_BOTTOM; // 270 degrees cw 1852 } 1853 } 1854 1855 /** 1856 * Returns the rotation degrees corresponding to an ExifTag Orientation 1857 * value. 1858 * 1859 * @param orientation the ExifTag Orientation value. 1860 */ 1861 public static int getRotationForOrientationValue(short orientation) { 1862 switch (orientation) { 1863 case Orientation.TOP_LEFT: 1864 return 0; 1865 case Orientation.RIGHT_TOP: 1866 return 90; 1867 case Orientation.BOTTOM_LEFT: 1868 return 180; 1869 case Orientation.RIGHT_BOTTOM: 1870 return 270; 1871 default: 1872 return 0; 1873 } 1874 } 1875 1876 /** 1877 * Gets the double representation of the GPS latitude or longitude 1878 * coordinate. 1879 * 1880 * @param coordinate an array of 3 Rationals representing the degrees, 1881 * minutes, and seconds of the GPS location as defined in the 1882 * exif specification. 1883 * @param reference a GPS reference reperesented by a String containing "N", 1884 * "S", "E", or "W". 1885 * @return the GPS coordinate represented as degrees + minutes/60 + 1886 * seconds/3600 1887 */ 1888 public static double convertLatOrLongToDouble(Rational[] coordinate, String reference) { 1889 try { 1890 double degrees = coordinate[0].toDouble(); 1891 double minutes = coordinate[1].toDouble(); 1892 double seconds = coordinate[2].toDouble(); 1893 double result = degrees + minutes / 60.0 + seconds / 3600.0; 1894 if ((reference.equals("S") || reference.equals("W"))) { 1895 return -result; 1896 } 1897 return result; 1898 } catch (ArrayIndexOutOfBoundsException e) { 1899 throw new IllegalArgumentException(); 1900 } 1901 } 1902 1903 /** 1904 * Gets the GPS latitude and longitude as a pair of doubles from this 1905 * ExifInterface object's tags, or null if the necessary tags do not exist. 1906 * 1907 * @return an array of 2 doubles containing the latitude, and longitude 1908 * respectively. 1909 * @see #convertLatOrLongToDouble 1910 */ 1911 public double[] getLatLongAsDoubles() { 1912 Rational[] latitude = getTagRationalValues(TAG_GPS_LATITUDE); 1913 String latitudeRef = getTagStringValue(TAG_GPS_LATITUDE_REF); 1914 Rational[] longitude = getTagRationalValues(TAG_GPS_LONGITUDE); 1915 String longitudeRef = getTagStringValue(TAG_GPS_LONGITUDE_REF); 1916 if (latitude == null || longitude == null || latitudeRef == null || longitudeRef == null 1917 || latitude.length < 3 || longitude.length < 3) { 1918 return null; 1919 } 1920 double[] latLon = new double[2]; 1921 latLon[0] = convertLatOrLongToDouble(latitude, latitudeRef); 1922 latLon[1] = convertLatOrLongToDouble(longitude, longitudeRef); 1923 return latLon; 1924 } 1925 1926 private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd"; 1927 private static final String DATETIME_FORMAT_STR = "yyyy:MM:dd kk:mm:ss"; 1928 private final DateFormat mDateTimeStampFormat = new SimpleDateFormat(DATETIME_FORMAT_STR); 1929 private final DateFormat mGPSDateStampFormat = new SimpleDateFormat(GPS_DATE_FORMAT_STR); 1930 private final Calendar mGPSTimeStampCalendar = Calendar 1931 .getInstance(TimeZone.getTimeZone("UTC")); 1932 1933 /** 1934 * Creates, formats, and sets the DateTimeStamp tag for one of: 1935 * {@link #TAG_DATE_TIME}, {@link #TAG_DATE_TIME_DIGITIZED}, 1936 * {@link #TAG_DATE_TIME_ORIGINAL}. 1937 * 1938 * @param tagId one of the DateTimeStamp tags. 1939 * @param timestamp a timestamp to format, in ms. 1940 * @param timezone a TimeZone object. 1941 * @return true if success, false if the tag could not be set. 1942 */ 1943 public boolean addDateTimeStampTag(int tagId, long timestamp, TimeZone timezone) { 1944 if (tagId == TAG_DATE_TIME || tagId == TAG_DATE_TIME_DIGITIZED 1945 || tagId == TAG_DATE_TIME_ORIGINAL) { 1946 mDateTimeStampFormat.setTimeZone(timezone); 1947 ExifTag t = buildTag(tagId, mDateTimeStampFormat.format(timestamp)); 1948 if (t == null) { 1949 return false; 1950 } 1951 setTag(t); 1952 } else { 1953 return false; 1954 } 1955 return true; 1956 } 1957 1958 /** 1959 * Creates and sets all to the GPS tags for a give latitude and longitude. 1960 * 1961 * @param latitude a GPS latitude coordinate. 1962 * @param longitude a GPS longitude coordinate. 1963 * @return true if success, false if they could not be created or set. 1964 */ 1965 public boolean addGpsTags(double latitude, double longitude) { 1966 ExifTag latTag = buildTag(TAG_GPS_LATITUDE, toExifLatLong(latitude)); 1967 ExifTag longTag = buildTag(TAG_GPS_LONGITUDE, toExifLatLong(longitude)); 1968 ExifTag latRefTag = buildTag(TAG_GPS_LATITUDE_REF, 1969 latitude >= 0 ? ExifInterface.GpsLatitudeRef.NORTH 1970 : ExifInterface.GpsLatitudeRef.SOUTH); 1971 ExifTag longRefTag = buildTag(TAG_GPS_LONGITUDE_REF, 1972 longitude >= 0 ? ExifInterface.GpsLongitudeRef.EAST 1973 : ExifInterface.GpsLongitudeRef.WEST); 1974 if (latTag == null || longTag == null || latRefTag == null || longRefTag == null) { 1975 return false; 1976 } 1977 setTag(latTag); 1978 setTag(longTag); 1979 setTag(latRefTag); 1980 setTag(longRefTag); 1981 return true; 1982 } 1983 1984 /** 1985 * Creates and sets the GPS timestamp tag. 1986 * 1987 * @param timestamp a GPS timestamp. 1988 * @return true if success, false if could not be created or set. 1989 */ 1990 public boolean addGpsDateTimeStampTag(long timestamp) { 1991 ExifTag t = buildTag(TAG_GPS_DATE_STAMP, mGPSDateStampFormat.format(timestamp)); 1992 if (t == null) { 1993 return false; 1994 } 1995 setTag(t); 1996 mGPSTimeStampCalendar.setTimeInMillis(timestamp); 1997 t = buildTag(TAG_GPS_TIME_STAMP, new Rational[] { 1998 new Rational(mGPSTimeStampCalendar.get(Calendar.HOUR_OF_DAY), 1), 1999 new Rational(mGPSTimeStampCalendar.get(Calendar.MINUTE), 1), 2000 new Rational(mGPSTimeStampCalendar.get(Calendar.SECOND), 1) 2001 }); 2002 if (t == null) { 2003 return false; 2004 } 2005 setTag(t); 2006 return true; 2007 } 2008 2009 private static Rational[] toExifLatLong(double value) { 2010 // convert to the format dd/1 mm/1 ssss/100 2011 value = Math.abs(value); 2012 int degrees = (int) value; 2013 value = (value - degrees) * 60; 2014 int minutes = (int) value; 2015 value = (value - minutes) * 6000; 2016 int seconds = (int) value; 2017 return new Rational[] { 2018 new Rational(degrees, 1), new Rational(minutes, 1), new Rational(seconds, 100) 2019 }; 2020 } 2021 2022 private void doExifStreamIO(InputStream is, OutputStream os) throws IOException { 2023 byte[] buf = new byte[1024]; 2024 int ret = is.read(buf, 0, 1024); 2025 while (ret != -1) { 2026 os.write(buf, 0, ret); 2027 ret = is.read(buf, 0, 1024); 2028 } 2029 } 2030 2031 protected static void closeSilently(Closeable c) { 2032 if (c != null) { 2033 try { 2034 c.close(); 2035 } catch (Throwable e) { 2036 // ignored 2037 } 2038 } 2039 } 2040 2041 private SparseIntArray mTagInfo = null; 2042 2043 protected SparseIntArray getTagInfo() { 2044 if (mTagInfo == null) { 2045 mTagInfo = new SparseIntArray(); 2046 initTagInfo(); 2047 } 2048 return mTagInfo; 2049 } 2050 2051 private void initTagInfo() { 2052 /** 2053 * We put tag information in a 4-bytes integer. The first byte a bitmask 2054 * representing the allowed IFDs of the tag, the second byte is the data 2055 * type, and the last two byte are a short value indicating the default 2056 * component count of this tag. 2057 */ 2058 // IFD0 tags 2059 int[] ifdAllowedIfds = { 2060 IfdId.TYPE_IFD_0, IfdId.TYPE_IFD_1 2061 }; 2062 int ifdFlags = getFlagsFromAllowedIfds(ifdAllowedIfds) << 24; 2063 mTagInfo.put(ExifInterface.TAG_MAKE, 2064 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2065 mTagInfo.put(ExifInterface.TAG_IMAGE_WIDTH, 2066 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2067 mTagInfo.put(ExifInterface.TAG_IMAGE_LENGTH, 2068 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2069 mTagInfo.put(ExifInterface.TAG_BITS_PER_SAMPLE, 2070 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3); 2071 mTagInfo.put(ExifInterface.TAG_COMPRESSION, 2072 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2073 mTagInfo.put(ExifInterface.TAG_PHOTOMETRIC_INTERPRETATION, 2074 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2075 mTagInfo.put(ExifInterface.TAG_ORIENTATION, ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 2076 | 1); 2077 mTagInfo.put(ExifInterface.TAG_SAMPLES_PER_PIXEL, 2078 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2079 mTagInfo.put(ExifInterface.TAG_PLANAR_CONFIGURATION, 2080 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2081 mTagInfo.put(ExifInterface.TAG_Y_CB_CR_SUB_SAMPLING, 2082 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2); 2083 mTagInfo.put(ExifInterface.TAG_Y_CB_CR_POSITIONING, 2084 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2085 mTagInfo.put(ExifInterface.TAG_X_RESOLUTION, 2086 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2087 mTagInfo.put(ExifInterface.TAG_Y_RESOLUTION, 2088 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2089 mTagInfo.put(ExifInterface.TAG_RESOLUTION_UNIT, 2090 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2091 mTagInfo.put(ExifInterface.TAG_STRIP_OFFSETS, 2092 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED); 2093 mTagInfo.put(ExifInterface.TAG_ROWS_PER_STRIP, 2094 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2095 mTagInfo.put(ExifInterface.TAG_STRIP_BYTE_COUNTS, 2096 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | ExifTag.SIZE_UNDEFINED); 2097 mTagInfo.put(ExifInterface.TAG_TRANSFER_FUNCTION, 2098 ifdFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 3 * 256); 2099 mTagInfo.put(ExifInterface.TAG_WHITE_POINT, 2100 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 2); 2101 mTagInfo.put(ExifInterface.TAG_PRIMARY_CHROMATICITIES, 2102 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6); 2103 mTagInfo.put(ExifInterface.TAG_Y_CB_CR_COEFFICIENTS, 2104 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3); 2105 mTagInfo.put(ExifInterface.TAG_REFERENCE_BLACK_WHITE, 2106 ifdFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 6); 2107 mTagInfo.put(ExifInterface.TAG_DATE_TIME, 2108 ifdFlags | ExifTag.TYPE_ASCII << 16 | 20); 2109 mTagInfo.put(ExifInterface.TAG_IMAGE_DESCRIPTION, 2110 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2111 mTagInfo.put(ExifInterface.TAG_MAKE, 2112 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2113 mTagInfo.put(ExifInterface.TAG_MODEL, 2114 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2115 mTagInfo.put(ExifInterface.TAG_SOFTWARE, 2116 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2117 mTagInfo.put(ExifInterface.TAG_ARTIST, 2118 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2119 mTagInfo.put(ExifInterface.TAG_COPYRIGHT, 2120 ifdFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2121 mTagInfo.put(ExifInterface.TAG_EXIF_IFD, 2122 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2123 mTagInfo.put(ExifInterface.TAG_GPS_IFD, 2124 ifdFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2125 // IFD1 tags 2126 int[] ifd1AllowedIfds = { 2127 IfdId.TYPE_IFD_1 2128 }; 2129 int ifdFlags1 = getFlagsFromAllowedIfds(ifd1AllowedIfds) << 24; 2130 mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 2131 ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2132 mTagInfo.put(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 2133 ifdFlags1 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2134 // Exif tags 2135 int[] exifAllowedIfds = { 2136 IfdId.TYPE_IFD_EXIF 2137 }; 2138 int exifFlags = getFlagsFromAllowedIfds(exifAllowedIfds) << 24; 2139 mTagInfo.put(ExifInterface.TAG_EXIF_VERSION, 2140 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4); 2141 mTagInfo.put(ExifInterface.TAG_FLASHPIX_VERSION, 2142 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4); 2143 mTagInfo.put(ExifInterface.TAG_COLOR_SPACE, 2144 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2145 mTagInfo.put(ExifInterface.TAG_COMPONENTS_CONFIGURATION, 2146 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 4); 2147 mTagInfo.put(ExifInterface.TAG_COMPRESSED_BITS_PER_PIXEL, 2148 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2149 mTagInfo.put(ExifInterface.TAG_PIXEL_X_DIMENSION, 2150 exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2151 mTagInfo.put(ExifInterface.TAG_PIXEL_Y_DIMENSION, 2152 exifFlags | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2153 mTagInfo.put(ExifInterface.TAG_MAKER_NOTE, 2154 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2155 mTagInfo.put(ExifInterface.TAG_USER_COMMENT, 2156 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2157 mTagInfo.put(ExifInterface.TAG_RELATED_SOUND_FILE, 2158 exifFlags | ExifTag.TYPE_ASCII << 16 | 13); 2159 mTagInfo.put(ExifInterface.TAG_DATE_TIME_ORIGINAL, 2160 exifFlags | ExifTag.TYPE_ASCII << 16 | 20); 2161 mTagInfo.put(ExifInterface.TAG_DATE_TIME_DIGITIZED, 2162 exifFlags | ExifTag.TYPE_ASCII << 16 | 20); 2163 mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME, 2164 exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2165 mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_ORIGINAL, 2166 exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2167 mTagInfo.put(ExifInterface.TAG_SUB_SEC_TIME_DIGITIZED, 2168 exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2169 mTagInfo.put(ExifInterface.TAG_IMAGE_UNIQUE_ID, 2170 exifFlags | ExifTag.TYPE_ASCII << 16 | 33); 2171 mTagInfo.put(ExifInterface.TAG_EXPOSURE_TIME, 2172 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2173 mTagInfo.put(ExifInterface.TAG_F_NUMBER, 2174 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2175 mTagInfo.put(ExifInterface.TAG_EXPOSURE_PROGRAM, 2176 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2177 mTagInfo.put(ExifInterface.TAG_SPECTRAL_SENSITIVITY, 2178 exifFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2179 mTagInfo.put(ExifInterface.TAG_ISO_SPEED_RATINGS, 2180 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED); 2181 mTagInfo.put(ExifInterface.TAG_OECF, 2182 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2183 mTagInfo.put(ExifInterface.TAG_SHUTTER_SPEED_VALUE, 2184 exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1); 2185 mTagInfo.put(ExifInterface.TAG_APERTURE_VALUE, 2186 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2187 mTagInfo.put(ExifInterface.TAG_BRIGHTNESS_VALUE, 2188 exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1); 2189 mTagInfo.put(ExifInterface.TAG_EXPOSURE_BIAS_VALUE, 2190 exifFlags | ExifTag.TYPE_RATIONAL << 16 | 1); 2191 mTagInfo.put(ExifInterface.TAG_MAX_APERTURE_VALUE, 2192 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2193 mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE, 2194 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2195 mTagInfo.put(ExifInterface.TAG_METERING_MODE, 2196 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2197 mTagInfo.put(ExifInterface.TAG_LIGHT_SOURCE, 2198 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2199 mTagInfo.put(ExifInterface.TAG_FLASH, 2200 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2201 mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH, 2202 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2203 mTagInfo.put(ExifInterface.TAG_SUBJECT_AREA, 2204 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | ExifTag.SIZE_UNDEFINED); 2205 mTagInfo.put(ExifInterface.TAG_FLASH_ENERGY, 2206 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2207 mTagInfo.put(ExifInterface.TAG_SPATIAL_FREQUENCY_RESPONSE, 2208 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2209 mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION, 2210 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2211 mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION, 2212 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2213 mTagInfo.put(ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT, 2214 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2215 mTagInfo.put(ExifInterface.TAG_SUBJECT_LOCATION, 2216 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 2); 2217 mTagInfo.put(ExifInterface.TAG_EXPOSURE_INDEX, 2218 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2219 mTagInfo.put(ExifInterface.TAG_SENSING_METHOD, 2220 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2221 mTagInfo.put(ExifInterface.TAG_FILE_SOURCE, 2222 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1); 2223 mTagInfo.put(ExifInterface.TAG_SCENE_TYPE, 2224 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | 1); 2225 mTagInfo.put(ExifInterface.TAG_CFA_PATTERN, 2226 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2227 mTagInfo.put(ExifInterface.TAG_CUSTOM_RENDERED, 2228 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2229 mTagInfo.put(ExifInterface.TAG_EXPOSURE_MODE, 2230 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2231 mTagInfo.put(ExifInterface.TAG_WHITE_BALANCE, 2232 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2233 mTagInfo.put(ExifInterface.TAG_DIGITAL_ZOOM_RATIO, 2234 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2235 mTagInfo.put(ExifInterface.TAG_FOCAL_LENGTH_IN_35_MM_FILE, 2236 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2237 mTagInfo.put(ExifInterface.TAG_SCENE_CAPTURE_TYPE, 2238 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2239 mTagInfo.put(ExifInterface.TAG_GAIN_CONTROL, 2240 exifFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2241 mTagInfo.put(ExifInterface.TAG_CONTRAST, 2242 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2243 mTagInfo.put(ExifInterface.TAG_SATURATION, 2244 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2245 mTagInfo.put(ExifInterface.TAG_SHARPNESS, 2246 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2247 mTagInfo.put(ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION, 2248 exifFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2249 mTagInfo.put(ExifInterface.TAG_SUBJECT_DISTANCE_RANGE, 2250 exifFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 1); 2251 mTagInfo.put(ExifInterface.TAG_INTEROPERABILITY_IFD, exifFlags 2252 | ExifTag.TYPE_UNSIGNED_LONG << 16 | 1); 2253 // GPS tag 2254 int[] gpsAllowedIfds = { 2255 IfdId.TYPE_IFD_GPS 2256 }; 2257 int gpsFlags = getFlagsFromAllowedIfds(gpsAllowedIfds) << 24; 2258 mTagInfo.put(ExifInterface.TAG_GPS_VERSION_ID, 2259 gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 4); 2260 mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE_REF, 2261 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2262 mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE_REF, 2263 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2264 mTagInfo.put(ExifInterface.TAG_GPS_LATITUDE, 2265 gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3); 2266 mTagInfo.put(ExifInterface.TAG_GPS_LONGITUDE, 2267 gpsFlags | ExifTag.TYPE_RATIONAL << 16 | 3); 2268 mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE_REF, 2269 gpsFlags | ExifTag.TYPE_UNSIGNED_BYTE << 16 | 1); 2270 mTagInfo.put(ExifInterface.TAG_GPS_ALTITUDE, 2271 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2272 mTagInfo.put(ExifInterface.TAG_GPS_TIME_STAMP, 2273 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 3); 2274 mTagInfo.put(ExifInterface.TAG_GPS_SATTELLITES, 2275 gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2276 mTagInfo.put(ExifInterface.TAG_GPS_STATUS, 2277 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2278 mTagInfo.put(ExifInterface.TAG_GPS_MEASURE_MODE, 2279 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2280 mTagInfo.put(ExifInterface.TAG_GPS_DOP, 2281 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2282 mTagInfo.put(ExifInterface.TAG_GPS_SPEED_REF, 2283 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2284 mTagInfo.put(ExifInterface.TAG_GPS_SPEED, 2285 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2286 mTagInfo.put(ExifInterface.TAG_GPS_TRACK_REF, 2287 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2288 mTagInfo.put(ExifInterface.TAG_GPS_TRACK, 2289 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2290 mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION_REF, 2291 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2292 mTagInfo.put(ExifInterface.TAG_GPS_IMG_DIRECTION, 2293 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2294 mTagInfo.put(ExifInterface.TAG_GPS_MAP_DATUM, 2295 gpsFlags | ExifTag.TYPE_ASCII << 16 | ExifTag.SIZE_UNDEFINED); 2296 mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE_REF, 2297 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2298 mTagInfo.put(ExifInterface.TAG_GPS_DEST_LATITUDE, 2299 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2300 mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING_REF, 2301 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2302 mTagInfo.put(ExifInterface.TAG_GPS_DEST_BEARING, 2303 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2304 mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE_REF, 2305 gpsFlags | ExifTag.TYPE_ASCII << 16 | 2); 2306 mTagInfo.put(ExifInterface.TAG_GPS_DEST_DISTANCE, 2307 gpsFlags | ExifTag.TYPE_UNSIGNED_RATIONAL << 16 | 1); 2308 mTagInfo.put(ExifInterface.TAG_GPS_PROCESSING_METHOD, 2309 gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2310 mTagInfo.put(ExifInterface.TAG_GPS_AREA_INFORMATION, 2311 gpsFlags | ExifTag.TYPE_UNDEFINED << 16 | ExifTag.SIZE_UNDEFINED); 2312 mTagInfo.put(ExifInterface.TAG_GPS_DATE_STAMP, 2313 gpsFlags | ExifTag.TYPE_ASCII << 16 | 11); 2314 mTagInfo.put(ExifInterface.TAG_GPS_DIFFERENTIAL, 2315 gpsFlags | ExifTag.TYPE_UNSIGNED_SHORT << 16 | 11); 2316 // Interoperability tag 2317 int[] interopAllowedIfds = { 2318 IfdId.TYPE_IFD_INTEROPERABILITY 2319 }; 2320 int interopFlags = getFlagsFromAllowedIfds(interopAllowedIfds) << 24; 2321 mTagInfo.put(TAG_INTEROPERABILITY_INDEX, interopFlags | ExifTag.TYPE_ASCII << 16 2322 | ExifTag.SIZE_UNDEFINED); 2323 } 2324 2325 protected static int getAllowedIfdFlagsFromInfo(int info) { 2326 return info >>> 24; 2327 } 2328 2329 protected static int[] getAllowedIfdsFromInfo(int info) { 2330 int ifdFlags = getAllowedIfdFlagsFromInfo(info); 2331 int[] ifds = IfdData.getIfds(); 2332 ArrayList<Integer> l = new ArrayList<Integer>(); 2333 for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { 2334 int flag = (ifdFlags >> i) & 1; 2335 if (flag == 1) { 2336 l.add(ifds[i]); 2337 } 2338 } 2339 if (l.size() <= 0) { 2340 return null; 2341 } 2342 int[] ret = new int[l.size()]; 2343 int j = 0; 2344 for (int i : l) { 2345 ret[j++] = i; 2346 } 2347 return ret; 2348 } 2349 2350 protected static boolean isIfdAllowed(int info, int ifd) { 2351 int[] ifds = IfdData.getIfds(); 2352 int ifdFlags = getAllowedIfdFlagsFromInfo(info); 2353 for (int i = 0; i < ifds.length; i++) { 2354 if (ifd == ifds[i] && ((ifdFlags >> i) & 1) == 1) { 2355 return true; 2356 } 2357 } 2358 return false; 2359 } 2360 2361 protected static int getFlagsFromAllowedIfds(int[] allowedIfds) { 2362 if (allowedIfds == null || allowedIfds.length == 0) { 2363 return 0; 2364 } 2365 int flags = 0; 2366 int[] ifds = IfdData.getIfds(); 2367 for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) { 2368 for (int j : allowedIfds) { 2369 if (ifds[i] == j) { 2370 flags |= 1 << i; 2371 break; 2372 } 2373 } 2374 } 2375 return flags; 2376 } 2377 2378 protected static short getTypeFromInfo(int info) { 2379 return (short) ((info >> 16) & 0x0ff); 2380 } 2381 2382 protected static int getComponentCountFromInfo(int info) { 2383 return info & 0x0ffff; 2384 } 2385 2386 } 2387