ExifInterface.java revision ab68451b27e13a861135d8ff147d515a4c4fdff5
19ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt/* 29ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * Copyright (C) 2007 The Android Open Source Project 39ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * 49ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 59ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * you may not use this file except in compliance with the License. 69ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * You may obtain a copy of the License at 79ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * 89ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 99ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * 109ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * Unless required by applicable law or agreed to in writing, software 119ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 129ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * See the License for the specific language governing permissions and 149ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt * limitations under the License. 159ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt */ 169ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt 179ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwaltpackage android.support.media; 189ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwalt 199ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwaltimport android.content.res.AssetManager; 209ba9c58e4a249456794fbfb9989f27bd846d067eRobert Greenwaltimport android.graphics.Bitmap; 21import android.graphics.BitmapFactory; 22import android.location.Location; 23import android.support.annotation.IntDef; 24import android.support.annotation.NonNull; 25import android.util.Log; 26import android.util.Pair; 27 28import java.io.BufferedInputStream; 29import java.io.ByteArrayInputStream; 30import java.io.Closeable; 31import java.io.DataInput; 32import java.io.DataInputStream; 33import java.io.EOFException; 34import java.io.File; 35import java.io.FileInputStream; 36import java.io.FileNotFoundException; 37import java.io.FileOutputStream; 38import java.io.FilterOutputStream; 39import java.io.IOException; 40import java.io.InputStream; 41import java.io.OutputStream; 42import java.lang.annotation.Retention; 43import java.lang.annotation.RetentionPolicy; 44import java.nio.ByteBuffer; 45import java.nio.ByteOrder; 46import java.nio.charset.Charset; 47import java.text.ParsePosition; 48import java.text.SimpleDateFormat; 49import java.util.Arrays; 50import java.util.Date; 51import java.util.HashMap; 52import java.util.HashSet; 53import java.util.List; 54import java.util.Map; 55import java.util.TimeZone; 56import java.util.concurrent.TimeUnit; 57import java.util.regex.Matcher; 58import java.util.regex.Pattern; 59 60/** 61 * This is a class for reading and writing Exif tags in a JPEG file or a RAW image file. 62 * <p> 63 * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW and RAF. 64 * <p> 65 * Attribute mutation is supported for JPEG image files. 66 */ 67public class ExifInterface { 68 private static final String TAG = "ExifInterface"; 69 private static final boolean DEBUG = false; 70 71 // The Exif tag names. See JEITA CP-3451C specifications (Exif 2.3) Section 3-8. 72 // A. Tags related to image data structure 73 /** 74 * <p>The number of columns of image data, equal to the number of pixels per row. In JPEG 75 * compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p> 76 * 77 * <ul> 78 * <li>Tag = 256</li> 79 * <li>Type = Unsigned short or Unsigned long</li> 80 * <li>Count = 1</li> 81 * <li>Default = None</li> 82 * </ul> 83 */ 84 public static final String TAG_IMAGE_WIDTH = "ImageWidth"; 85 /** 86 * <p>The number of rows of image data. In JPEG compressed data, this tag shall not be used 87 * because a JPEG marker is used instead of it.</p> 88 * 89 * <ul> 90 * <li>Tag = 257</li> 91 * <li>Type = Unsigned short or Unsigned long</li> 92 * <li>Count = 1</li> 93 * <li>Default = None</li> 94 * </ul> 95 */ 96 public static final String TAG_IMAGE_LENGTH = "ImageLength"; 97 /** 98 * <p>The number of bits per image component. In this standard each component of the image is 99 * 8 bits, so the value for this tag is 8. See also {@link #TAG_SAMPLES_PER_PIXEL}. In JPEG 100 * compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p> 101 * 102 * <ul> 103 * <li>Tag = 258</li> 104 * <li>Type = Unsigned short</li> 105 * <li>Count = 3</li> 106 * <li>Default = {@link #BITS_PER_SAMPLE_RGB}</li> 107 * </ul> 108 */ 109 public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample"; 110 /** 111 * <p>The compression scheme used for the image data. When a primary image is JPEG compressed, 112 * this designation is not necessary. So, this tag shall not be recorded. When thumbnails use 113 * JPEG compression, this tag value is set to 6.</p> 114 * 115 * <ul> 116 * <li>Tag = 259</li> 117 * <li>Type = Unsigned short</li> 118 * <li>Count = 1</li> 119 * <li>Default = None</li> 120 * </ul> 121 * 122 * @see #DATA_UNCOMPRESSED 123 * @see #DATA_JPEG 124 */ 125 public static final String TAG_COMPRESSION = "Compression"; 126 /** 127 * <p>The pixel composition. In JPEG compressed data, this tag shall not be used because a JPEG 128 * marker is used instead of it.</p> 129 * 130 * <ul> 131 * <li>Tag = 262</li> 132 * <li>Type = SHORT</li> 133 * <li>Count = 1</li> 134 * <li>Default = None</li> 135 * </ul> 136 * 137 * @see #PHOTOMETRIC_INTERPRETATION_RGB 138 * @see #PHOTOMETRIC_INTERPRETATION_YCBCR 139 */ 140 public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation"; 141 /** 142 * <p>The image orientation viewed in terms of rows and columns.</p> 143 * 144 * <ul> 145 * <li>Tag = 274</li> 146 * <li>Type = Unsigned short</li> 147 * <li>Count = 1</li> 148 * <li>Default = {@link #ORIENTATION_NORMAL}</li> 149 * </ul> 150 * 151 * @see #ORIENTATION_UNDEFINED 152 * @see #ORIENTATION_NORMAL 153 * @see #ORIENTATION_FLIP_HORIZONTAL 154 * @see #ORIENTATION_ROTATE_180 155 * @see #ORIENTATION_FLIP_VERTICAL 156 * @see #ORIENTATION_TRANSPOSE 157 * @see #ORIENTATION_ROTATE_90 158 * @see #ORIENTATION_TRANSVERSE 159 * @see #ORIENTATION_ROTATE_270 160 */ 161 public static final String TAG_ORIENTATION = "Orientation"; 162 /** 163 * <p>The number of components per pixel. Since this standard applies to RGB and YCbCr images, 164 * the value set for this tag is 3. In JPEG compressed data, this tag shall not be used because 165 * a JPEG marker is used instead of it.</p> 166 * 167 * <ul> 168 * <li>Tag = 277</li> 169 * <li>Type = Unsigned short</li> 170 * <li>Count = 1</li> 171 * <li>Default = 3</li> 172 * </ul> 173 */ 174 public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel"; 175 /** 176 * <p>Indicates whether pixel components are recorded in chunky or planar format. In JPEG 177 * compressed data, this tag shall not be used because a JPEG marker is used instead of it. 178 * If this field does not exist, the TIFF default, {@link #FORMAT_CHUNKY}, is assumed.</p> 179 * 180 * <ul> 181 * <li>Tag = 284</li> 182 * <li>Type = Unsigned short</li> 183 * <li>Count = 1</li> 184 * </ul> 185 * 186 * @see #FORMAT_CHUNKY 187 * @see #FORMAT_PLANAR 188 */ 189 public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration"; 190 /** 191 * <p>The sampling ratio of chrominance components in relation to the luminance component. 192 * In JPEG compressed data a JPEG marker is used instead of this tag. So, this tag shall not 193 * be recorded.</p> 194 * 195 * <ul> 196 * <li>Tag = 530</li> 197 * <li>Type = Unsigned short</li> 198 * <li>Count = 2</li> 199 * <ul> 200 * <li>[2, 1] = YCbCr4:2:2</li> 201 * <li>[2, 2] = YCbCr4:2:0</li> 202 * <li>Other = reserved</li> 203 * </ul> 204 * </ul> 205 */ 206 public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling"; 207 /** 208 * <p>The position of chrominance components in relation to the luminance component. This field 209 * is designated only for JPEG compressed data or uncompressed YCbCr data. The TIFF default is 210 * {@link #Y_CB_CR_POSITIONING_CENTERED}; but when Y:Cb:Cr = 4:2:2 it is recommended in this 211 * standard that {@link #Y_CB_CR_POSITIONING_CO_SITED} be used to record data, in order to 212 * improve the image quality when viewed on TV systems. When this field does not exist, 213 * the reader shall assume the TIFF default. In the case of Y:Cb:Cr = 4:2:0, the TIFF default 214 * ({@link #Y_CB_CR_POSITIONING_CENTERED}) is recommended. If the Exif/DCF reader does not 215 * have the capability of supporting both kinds of positioning, it shall follow the TIFF 216 * default regardless of the value in this field. It is preferable that readers can support 217 * both centered and co-sited positioning.</p> 218 * 219 * <ul> 220 * <li>Tag = 531</li> 221 * <li>Type = Unsigned short</li> 222 * <li>Count = 1</li> 223 * <li>Default = {@link #Y_CB_CR_POSITIONING_CENTERED}</li> 224 * </ul> 225 * 226 * @see #Y_CB_CR_POSITIONING_CENTERED 227 * @see #Y_CB_CR_POSITIONING_CO_SITED 228 */ 229 public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning"; 230 /** 231 * <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH} 232 * direction. When the image resolution is unknown, 72 [dpi] shall be designated.</p> 233 * 234 * <ul> 235 * <li>Tag = 282</li> 236 * <li>Type = Unsigned rational</li> 237 * <li>Count = 1</li> 238 * <li>Default = 72</li> 239 * </ul> 240 * 241 * @see #TAG_Y_RESOLUTION 242 * @see #TAG_RESOLUTION_UNIT 243 */ 244 public static final String TAG_X_RESOLUTION = "XResolution"; 245 /** 246 * <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH} 247 * direction. The same value as {@link #TAG_X_RESOLUTION} shall be designated.</p> 248 * 249 * <ul> 250 * <li>Tag = 283</li> 251 * <li>Type = Unsigned rational</li> 252 * <li>Count = 1</li> 253 * <li>Default = 72</li> 254 * </ul> 255 * 256 * @see #TAG_X_RESOLUTION 257 * @see #TAG_RESOLUTION_UNIT 258 */ 259 public static final String TAG_Y_RESOLUTION = "YResolution"; 260 /** 261 * <p>The unit for measuring {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. The same 262 * unit is used for both {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. If the image 263 * resolution is unknown, {@link #RESOLUTION_UNIT_INCHES} shall be designated.</p> 264 * 265 * <ul> 266 * <li>Tag = 296</li> 267 * <li>Type = Unsigned short</li> 268 * <li>Count = 1</li> 269 * <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li> 270 * </ul> 271 * 272 * @see #RESOLUTION_UNIT_INCHES 273 * @see #RESOLUTION_UNIT_CENTIMETERS 274 * @see #TAG_X_RESOLUTION 275 * @see #TAG_Y_RESOLUTION 276 */ 277 public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit"; 278 279 // B. Tags related to recording offset 280 /** 281 * <p>For each strip, the byte offset of that strip. It is recommended that this be selected 282 * so the number of strip bytes does not exceed 64 KBytes.In the case of JPEG compressed data, 283 * this designation is not necessary. So, this tag shall not be recorded.</p> 284 * 285 * <ul> 286 * <li>Tag = 273</li> 287 * <li>Type = Unsigned short or Unsigned long</li> 288 * <li>Count = StripsPerImage (for {@link #FORMAT_CHUNKY}) 289 * or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage 290 * (for {@link #FORMAT_PLANAR})</li> 291 * <li>Default = None</li> 292 * </ul> 293 * 294 * <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1) 295 * / {@link #TAG_ROWS_PER_STRIP})</p> 296 * 297 * @see #TAG_ROWS_PER_STRIP 298 * @see #TAG_STRIP_BYTE_COUNTS 299 */ 300 public static final String TAG_STRIP_OFFSETS = "StripOffsets"; 301 /** 302 * <p>The number of rows per strip. This is the number of rows in the image of one strip when 303 * an image is divided into strips. In the case of JPEG compressed data, this designation is 304 * not necessary. So, this tag shall not be recorded.</p> 305 * 306 * <ul> 307 * <li>Tag = 278</li> 308 * <li>Type = Unsigned short or Unsigned long</li> 309 * <li>Count = 1</li> 310 * <li>Default = None</li> 311 * </ul> 312 * 313 * @see #TAG_STRIP_OFFSETS 314 * @see #TAG_STRIP_BYTE_COUNTS 315 */ 316 public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip"; 317 /** 318 * <p>The total number of bytes in each strip. In the case of JPEG compressed data, this 319 * designation is not necessary. So, this tag shall not be recorded.</p> 320 * 321 * <ul> 322 * <li>Tag = 279</li> 323 * <li>Type = Unsigned short or Unsigned long</li> 324 * <li>Count = StripsPerImage (when using {@link #FORMAT_CHUNKY}) 325 * or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage 326 * (when using {@link #FORMAT_PLANAR})</li> 327 * <li>Default = None</li> 328 * </ul> 329 * 330 * <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1) 331 * / {@link #TAG_ROWS_PER_STRIP})</p> 332 */ 333 public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts"; 334 /** 335 * <p>The offset to the start byte (SOI) of JPEG compressed thumbnail data. This shall not be 336 * used for primary image JPEG data.</p> 337 * 338 * <ul> 339 * <li>Tag = 513</li> 340 * <li>Type = Unsigned long</li> 341 * <li>Default = None</li> 342 * </ul> 343 */ 344 public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat"; 345 /** 346 * <p>The number of bytes of JPEG compressed thumbnail data. This is not used for primary image 347 * JPEG data. JPEG thumbnails are not divided but are recorded as a continuous JPEG bitstream 348 * from SOI to EOI. APPn and COM markers should not be recorded. Compressed thumbnails shall be 349 * recorded in no more than 64 KBytes, including all other data to be recorded in APP1.</p> 350 * 351 * <ul> 352 * <li>Tag = 514</li> 353 * <li>Type = Unsigned long</li> 354 * <li>Default = None</li> 355 * </ul> 356 */ 357 public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength"; 358 359 // C. Tags related to Image Data Characteristics 360 /** 361 * <p>A transfer function for the image, described in tabular style. Normally this tag need not 362 * be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p> 363 * 364 * <ul> 365 * <li>Tag = 301</li> 366 * <li>Type = Unsigned short</li> 367 * <li>Count = 3 * 256</li> 368 * <li>Default = None</li> 369 * </ul> 370 */ 371 public static final String TAG_TRANSFER_FUNCTION = "TransferFunction"; 372 /** 373 * <p>The chromaticity of the white point of the image. Normally this tag need not be used, 374 * since color space is specified in {@link #TAG_COLOR_SPACE}.</p> 375 * 376 * <ul> 377 * <li>Tag = 318</li> 378 * <li>Type = Unsigned rational</li> 379 * <li>Count = 2</li> 380 * <li>Default = None</li> 381 * </ul> 382 */ 383 public static final String TAG_WHITE_POINT = "WhitePoint"; 384 /** 385 * <p>The chromaticity of the three primary colors of the image. Normally this tag need not 386 * be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p> 387 * 388 * <ul> 389 * <li>Tag = 319</li> 390 * <li>Type = Unsigned rational</li> 391 * <li>Count = 6</li> 392 * <li>Default = None</li> 393 * </ul> 394 */ 395 public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities"; 396 /** 397 * <p>The matrix coefficients for transformation from RGB to YCbCr image data. About 398 * the default value, please refer to JEITA CP-3451C Spec, Annex D.</p> 399 * 400 * <ul> 401 * <li>Tag = 529</li> 402 * <li>Type = Unsigned rational</li> 403 * <li>Count = 3</li> 404 * </ul> 405 */ 406 public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients"; 407 /** 408 * <p>The reference black point value and reference white point value. No defaults are given 409 * in TIFF, but the values below are given as defaults here. The color space is declared in 410 * a color space information tag, with the default being the value that gives the optimal image 411 * characteristics Interoperability these conditions</p> 412 * 413 * <ul> 414 * <li>Tag = 532</li> 415 * <li>Type = RATIONAL</li> 416 * <li>Count = 6</li> 417 * <li>Default = [0, 255, 0, 255, 0, 255] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION} 418 * is {@link #PHOTOMETRIC_INTERPRETATION_RGB}) 419 * or [0, 255, 0, 128, 0, 128] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION} 420 * is {@link #PHOTOMETRIC_INTERPRETATION_YCBCR})</li> 421 * </ul> 422 */ 423 public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite"; 424 425 // D. Other tags 426 /** 427 * <p>The date and time of image creation. In this standard it is the date and time the file 428 * was changed. The format is "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and 429 * the date and time separated by one blank character ({@code 0x20}). When the date and time 430 * are unknown, all the character spaces except colons (":") should be filled with blank 431 * characters, or else the Interoperability field should be filled with blank characters. 432 * The character string length is 20 Bytes including NULL for termination. When the field is 433 * left blank, it is treated as unknown.</p> 434 * 435 * <ul> 436 * <li>Tag = 306</li> 437 * <li>Type = String</li> 438 * <li>Length = 19</li> 439 * <li>Default = None</li> 440 * </ul> 441 */ 442 public static final String TAG_DATETIME = "DateTime"; 443 /** 444 * <p>An ASCII string giving the title of the image. It is possible to be added a comment 445 * such as "1988 company picnic" or the like. Two-byte character codes cannot be used. When 446 * a 2-byte code is necessary, {@link #TAG_USER_COMMENT} is to be used.</p> 447 * 448 * <ul> 449 * <li>Tag = 270</li> 450 * <li>Type = String</li> 451 * <li>Default = None</li> 452 * </ul> 453 */ 454 public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription"; 455 /** 456 * <p>The manufacturer of the recording equipment. This is the manufacturer of the DSC, 457 * scanner, video digitizer or other equipment that generated the image. When the field is left 458 * blank, it is treated as unknown.</p> 459 * 460 * <ul> 461 * <li>Tag = 271</li> 462 * <li>Type = String</li> 463 * <li>Default = None</li> 464 * </ul> 465 */ 466 public static final String TAG_MAKE = "Make"; 467 /** 468 * <p>The model name or model number of the equipment. This is the model name of number of 469 * the DSC, scanner, video digitizer or other equipment that generated the image. When 470 * the field is left blank, it is treated as unknown.</p> 471 * 472 * <ul> 473 * <li>Tag = 272</li> 474 * <li>Type = String</li> 475 * <li>Default = None</li> 476 * </ul> 477 */ 478 public static final String TAG_MODEL = "Model"; 479 /** 480 * <p>This tag records the name and version of the software or firmware of the camera or image 481 * input device used to generate the image. The detailed format is not specified, but it is 482 * recommended that the example shown below be followed. When the field is left blank, it is 483 * treated as unknown.</p> 484 * 485 * <p>Ex.) "Exif Software Version 1.00a".</p> 486 * 487 * <ul> 488 * <li>Tag = 305</li> 489 * <li>Type = String</li> 490 * <li>Default = None</li> 491 * </ul> 492 */ 493 public static final String TAG_SOFTWARE = "Software"; 494 /** 495 * <p>This tag records the name of the camera owner, photographer or image creator. 496 * The detailed format is not specified, but it is recommended that the information be written 497 * as in the example below for ease of Interoperability. When the field is left blank, it is 498 * treated as unknown.</p> 499 * 500 * <p>Ex.) "Camera owner, John Smith; Photographer, Michael Brown; Image creator, 501 * Ken James"</p> 502 * 503 * <ul> 504 * <li>Tag = 315</li> 505 * <li>Type = String</li> 506 * <li>Default = None</li> 507 * </ul> 508 */ 509 public static final String TAG_ARTIST = "Artist"; 510 /** 511 * <p>Copyright information. In this standard the tag is used to indicate both the photographer 512 * and editor copyrights. It is the copyright notice of the person or organization claiming 513 * rights to the image. The Interoperability copyright statement including date and rights 514 * should be written in this field; e.g., "Copyright, John Smith, 19xx. All rights reserved." 515 * In this standard the field records both the photographer and editor copyrights, with each 516 * recorded in a separate part of the statement. When there is a clear distinction between 517 * the photographer and editor copyrights, these are to be written in the order of photographer 518 * followed by editor copyright, separated by NULL (in this case, since the statement also ends 519 * with a NULL, there are two NULL codes) (see example 1). When only the photographer copyright 520 * is given, it is terminated by one NULL code (see example 2). When only the editor copyright 521 * is given, the photographer copyright part consists of one space followed by a terminating 522 * NULL code, then the editor copyright is given (see example 3). When the field is left blank, 523 * it is treated as unknown.</p> 524 * 525 * <p>Ex. 1) When both the photographer copyright and editor copyright are given. 526 * <ul><li>Photographer copyright + NULL + editor copyright + NULL</li></ul></p> 527 * <p>Ex. 2) When only the photographer copyright is given. 528 * <ul><li>Photographer copyright + NULL</li></ul></p> 529 * <p>Ex. 3) When only the editor copyright is given. 530 * <ul><li>Space ({@code 0x20}) + NULL + editor copyright + NULL</li></ul></p> 531 * 532 * <ul> 533 * <li>Tag = 315</li> 534 * <li>Type = String</li> 535 * <li>Default = None</li> 536 * </ul> 537 */ 538 public static final String TAG_COPYRIGHT = "Copyright"; 539 540 // Exif IFD Attribute Information 541 // A. Tags related to version 542 /** 543 * <p>The version of this standard supported. Nonexistence of this field is taken to mean 544 * nonconformance to the standard. In according with conformance to this standard, this tag 545 * shall be recorded like "0230” as 4-byte ASCII.</p> 546 * 547 * <ul> 548 * <li>Tag = 36864</li> 549 * <li>Type = Undefined</li> 550 * <li>Length = 4</li> 551 * <li>Default = "0230"</li> 552 * </ul> 553 */ 554 public static final String TAG_EXIF_VERSION = "ExifVersion"; 555 /** 556 * <p>The Flashpix format version supported by a FPXR file. If the FPXR function supports 557 * Flashpix format Ver. 1.0, this is indicated similarly to {@link #TAG_EXIF_VERSION} by 558 * recording "0100" as 4-byte ASCII.</p> 559 * 560 * <ul> 561 * <li>Tag = 40960</li> 562 * <li>Type = Undefined</li> 563 * <li>Length = 4</li> 564 * <li>Default = "0100"</li> 565 * </ul> 566 */ 567 public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion"; 568 569 // B. Tags related to image data characteristics 570 /** 571 * <p>The color space information tag is always recorded as the color space specifier. 572 * Normally {@link #COLOR_SPACE_S_RGB} is used to define the color space based on the PC 573 * monitor conditions and environment. If a color space other than {@link #COLOR_SPACE_S_RGB} 574 * is used, {@link #COLOR_SPACE_UNCALIBRATED} is set. Image data recorded as 575 * {@link #COLOR_SPACE_UNCALIBRATED} may be treated as {@link #COLOR_SPACE_S_RGB} when it is 576 * converted to Flashpix.</p> 577 * 578 * <ul> 579 * <li>Tag = 40961</li> 580 * <li>Type = Unsigned short</li> 581 * <li>Count = 1</li> 582 * </ul> 583 * 584 * @see #COLOR_SPACE_S_RGB 585 * @see #COLOR_SPACE_UNCALIBRATED 586 */ 587 public static final String TAG_COLOR_SPACE = "ColorSpace"; 588 /** 589 * <p>Indicates the value of coefficient gamma. The formula of transfer function used for image 590 * reproduction is expressed as follows.</p> 591 * 592 * <p>(Reproduced value) = (Input value) ^ gamma</p> 593 * 594 * <p>Both reproduced value and input value indicate normalized value, whose minimum value is 595 * 0 and maximum value is 1.</p> 596 * 597 * <ul> 598 * <li>Tag = 42240</li> 599 * <li>Type = Unsigned rational</li> 600 * <li>Count = 1</li> 601 * <li>Default = None</li> 602 * </ul> 603 */ 604 public static final String TAG_GAMMA = "Gamma"; 605 606 // C. Tags related to image configuration 607 /** 608 * <p>Information specific to compressed data. When a compressed file is recorded, the valid 609 * width of the meaningful image shall be recorded in this tag, whether or not there is padding 610 * data or a restart marker. This tag shall not exist in an uncompressed file.</p> 611 * 612 * <ul> 613 * <li>Tag = 40962</li> 614 * <li>Type = Unsigned short or Unsigned long</li> 615 * <li>Count = 1</li> 616 * <li>Default = None</li> 617 * </ul> 618 */ 619 public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension"; 620 /** 621 * <p>Information specific to compressed data. When a compressed file is recorded, the valid 622 * height of the meaningful image shall be recorded in this tag, whether or not there is 623 * padding data or a restart marker. This tag shall not exist in an uncompressed file. 624 * Since data padding is unnecessary in the vertical direction, the number of lines recorded 625 * in this valid image height tag will in fact be the same as that recorded in the SOF.</p> 626 * 627 * <ul> 628 * <li>Tag = 40963</li> 629 * <li>Type = Unsigned short or Unsigned long</li> 630 * <li>Count = 1</li> 631 * </ul> 632 */ 633 public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension"; 634 /** 635 * <p>Information specific to compressed data. The channels of each component are arranged 636 * in order from the 1st component to the 4th. For uncompressed data the data arrangement is 637 * given in the {@link #TAG_PHOTOMETRIC_INTERPRETATION}. However, since 638 * {@link #TAG_PHOTOMETRIC_INTERPRETATION} can only express the order of Y, Cb and Cr, this tag 639 * is provided for cases when compressed data uses components other than Y, Cb, and Cr and to 640 * enable support of other sequences.</p> 641 * 642 * <ul> 643 * <li>Tag = 37121</li> 644 * <li>Type = Undefined</li> 645 * <li>Length = 4</li> 646 * <li>Default = 4 5 6 0 (if RGB uncompressed) or 1 2 3 0 (other cases)</li> 647 * <ul> 648 * <li>0 = does not exist</li> 649 * <li>1 = Y</li> 650 * <li>2 = Cb</li> 651 * <li>3 = Cr</li> 652 * <li>4 = R</li> 653 * <li>5 = G</li> 654 * <li>6 = B</li> 655 * <li>other = reserved</li> 656 * </ul> 657 * </ul> 658 */ 659 public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration"; 660 /** 661 * <p>Information specific to compressed data. The compression mode used for a compressed image 662 * is indicated in unit bits per pixel.</p> 663 * 664 * <ul> 665 * <li>Tag = 37122</li> 666 * <li>Type = Unsigned rational</li> 667 * <li>Count = 1</li> 668 * <li>Default = None</li> 669 * </ul> 670 */ 671 public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel"; 672 673 // D. Tags related to user information 674 /** 675 * <p>A tag for manufacturers of Exif/DCF writers to record any desired information. 676 * The contents are up to the manufacturer, but this tag shall not be used for any other than 677 * its intended purpose.</p> 678 * 679 * <ul> 680 * <li>Tag = 37500</li> 681 * <li>Type = Undefined</li> 682 * <li>Default = None</li> 683 * </ul> 684 */ 685 public static final String TAG_MAKER_NOTE = "MakerNote"; 686 /** 687 * <p>A tag for Exif users to write keywords or comments on the image besides those in 688 * {@link #TAG_IMAGE_DESCRIPTION}, and without the character code limitations of it.</p> 689 * 690 * <ul> 691 * <li>Tag = 37510</li> 692 * <li>Type = Undefined</li> 693 * <li>Default = None</li> 694 * </ul> 695 */ 696 public static final String TAG_USER_COMMENT = "UserComment"; 697 698 // E. Tags related to related file information 699 /** 700 * <p>This tag is used to record the name of an audio file related to the image data. The only 701 * relational information recorded here is the Exif audio file name and extension (an ASCII 702 * string consisting of 8 characters + '.' + 3 characters). The path is not recorded.</p> 703 * 704 * <p>When using this tag, audio files shall be recorded in conformance to the Exif audio 705 * format. Writers can also store the data such as Audio within APP2 as Flashpix extension 706 * stream data. Audio files shall be recorded in conformance to the Exif audio format.</p> 707 * 708 * <ul> 709 * <li>Tag = 40964</li> 710 * <li>Type = String</li> 711 * <li>Length = 12</li> 712 * <li>Default = None</li> 713 * </ul> 714 */ 715 public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile"; 716 717 // F. Tags related to date and time 718 /** 719 * <p>The date and time when the original image data was generated. For a DSC the date and time 720 * the picture was taken are recorded. The format is "YYYY:MM:DD HH:MM:SS" with time shown in 721 * 24-hour format, and the date and time separated by one blank character ({@code 0x20}). 722 * When the date and time are unknown, all the character spaces except colons (":") should be 723 * filled with blank characters, or else the Interoperability field should be filled with blank 724 * characters. When the field is left blank, it is treated as unknown.</p> 725 * 726 * <ul> 727 * <li>Tag = 36867</li> 728 * <li>Type = String</li> 729 * <li>Length = 19</li> 730 * <li>Default = None</li> 731 * </ul> 732 */ 733 public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal"; 734 /** 735 * <p>The date and time when the image was stored as digital data. If, for example, an image 736 * was captured by DSC and at the same time the file was recorded, then 737 * {@link #TAG_DATETIME_ORIGINAL} and this tag will have the same contents. The format is 738 * "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and the date and time separated by 739 * one blank character ({@code 0x20}). When the date and time are unknown, all the character 740 * spaces except colons (":")should be filled with blank characters, or else 741 * the Interoperability field should be filled with blank characters. When the field is left 742 * blank, it is treated as unknown.</p> 743 * 744 * <ul> 745 * <li>Tag = 36868</li> 746 * <li>Type = String</li> 747 * <li>Length = 19</li> 748 * <li>Default = None</li> 749 * </ul> 750 */ 751 public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized"; 752 /** 753 * <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME}.</p> 754 * 755 * <ul> 756 * <li>Tag = 37520</li> 757 * <li>Type = String</li> 758 * <li>Default = None</li> 759 * </ul> 760 */ 761 public static final String TAG_SUBSEC_TIME = "SubSecTime"; 762 /** 763 * <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_ORIGINAL}.</p> 764 * 765 * <ul> 766 * <li>Tag = 37521</li> 767 * <li>Type = String</li> 768 * <li>Default = None</li> 769 * </ul> 770 */ 771 public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal"; 772 /** 773 * <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_DIGITIZED}.</p> 774 * 775 * <ul> 776 * <li>Tag = 37522</li> 777 * <li>Type = String</li> 778 * <li>Default = None</li> 779 * </ul> 780 */ 781 public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized"; 782 783 // G. Tags related to picture-taking condition 784 /** 785 * <p>Exposure time, given in seconds.</p> 786 * 787 * <ul> 788 * <li>Tag = 33434</li> 789 * <li>Type = Unsigned rational</li> 790 * <li>Count = 1</li> 791 * <li>Default = None</li> 792 * </ul> 793 */ 794 public static final String TAG_EXPOSURE_TIME = "ExposureTime"; 795 /** 796 * <p>The F number.</p> 797 * 798 * <ul> 799 * <li>Tag = 33437</li> 800 * <li>Type = Unsigned rational</li> 801 * <li>Count = 1</li> 802 * <li>Default = None</li> 803 * </ul> 804 */ 805 public static final String TAG_F_NUMBER = "FNumber"; 806 /** 807 * <p>TThe class of the program used by the camera to set exposure when the picture is taken. 808 * The tag values are as follows.</p> 809 * 810 * <ul> 811 * <li>Tag = 34850</li> 812 * <li>Type = Unsigned short</li> 813 * <li>Count = 1</li> 814 * <li>Default = {@link #EXPOSURE_PROGRAM_NOT_DEFINED}</li> 815 * </ul> 816 * 817 * @see #EXPOSURE_PROGRAM_NOT_DEFINED 818 * @see #EXPOSURE_PROGRAM_MANUAL 819 * @see #EXPOSURE_PROGRAM_NORMAL 820 * @see #EXPOSURE_PROGRAM_APERTURE_PRIORITY 821 * @see #EXPOSURE_PROGRAM_SHUTTER_PRIORITY 822 * @see #EXPOSURE_PROGRAM_CREATIVE 823 * @see #EXPOSURE_PROGRAM_ACTION 824 * @see #EXPOSURE_PROGRAM_PORTRAIT_MODE 825 * @see #EXPOSURE_PROGRAM_LANDSCAPE_MODE 826 */ 827 public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram"; 828 /** 829 * <p>Indicates the spectral sensitivity of each channel of the camera used. The tag value is 830 * an ASCII string compatible with the standard developed by the ASTM Technical committee.</p> 831 * 832 * <ul> 833 * <li>Tag = 34852</li> 834 * <li>Type = String</li> 835 * <li>Default = None</li> 836 * </ul> 837 */ 838 public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity"; 839 /** 840 * @deprecated Use {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} instead. 841 * @see #TAG_PHOTOGRAPHIC_SENSITIVITY 842 */ 843 @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings"; 844 /** 845 * <p>This tag indicates the sensitivity of the camera or input device when the image was shot. 846 * More specifically, it indicates one of the following values that are parameters defined in 847 * ISO 12232: standard output sensitivity (SOS), recommended exposure index (REI), or ISO 848 * speed. Accordingly, if a tag corresponding to a parameter that is designated by 849 * {@link #TAG_SENSITIVITY_TYPE} is recorded, the values of the tag and of this tag are 850 * the same. However, if the value is 65535 or higher, the value of this tag shall be 65535. 851 * When recording this tag, {@link #TAG_SENSITIVITY_TYPE} should also be recorded. In addition, 852 * while “Count = Any”, only 1 count should be used when recording this tag.</p> 853 * 854 * <ul> 855 * <li>Tag = 34855</li> 856 * <li>Type = Unsigned short</li> 857 * <li>Count = Any</li> 858 * <li>Default = None</li> 859 * </ul> 860 */ 861 public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity"; 862 /** 863 * <p>Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524. OECF is 864 * the relationship between the camera optical input and the image values.</p> 865 * 866 * <ul> 867 * <li>Tag = 34856</li> 868 * <li>Type = Undefined</li> 869 * <li>Default = None</li> 870 * </ul> 871 */ 872 public static final String TAG_OECF = "OECF"; 873 /** 874 * <p>This tag indicates which one of the parameters of ISO12232 is 875 * {@link #TAG_PHOTOGRAPHIC_SENSITIVITY}. Although it is an optional tag, it should be recorded 876 * when {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} is recorded.</p> 877 * 878 * <ul> 879 * <li>Tag = 34864</li> 880 * <li>Type = Unsigned short</li> 881 * <li>Count = 1</li> 882 * <li>Default = None</li> 883 * </ul> 884 * 885 * @see #SENSITIVITY_TYPE_UNKNOWN 886 * @see #SENSITIVITY_TYPE_SOS 887 * @see #SENSITIVITY_TYPE_REI 888 * @see #SENSITIVITY_TYPE_ISO_SPEED 889 * @see #SENSITIVITY_TYPE_SOS_AND_REI 890 * @see #SENSITIVITY_TYPE_SOS_AND_ISO 891 * @see #SENSITIVITY_TYPE_REI_AND_ISO 892 * @see #SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO 893 */ 894 public static final String TAG_SENSITIVITY_TYPE = "SensitivityType"; 895 /** 896 * <p>This tag indicates the standard output sensitivity value of a camera or input device 897 * defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and 898 * {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p> 899 * 900 * <ul> 901 * <li>Tag = 34865</li> 902 * <li>Type = Unsigned long</li> 903 * <li>Count = 1</li> 904 * <li>Default = None</li> 905 * </ul> 906 */ 907 public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity"; 908 /** 909 * <p>This tag indicates the recommended exposure index value of a camera or input device 910 * defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and 911 * {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p> 912 * 913 * <ul> 914 * <li>Tag = 34866</li> 915 * <li>Type = Unsigned long</li> 916 * <li>Count = 1</li> 917 * <li>Default = None</li> 918 * </ul> 919 */ 920 public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex"; 921 /** 922 * <p>This tag indicates the ISO speed value of a camera or input device that is defined in 923 * ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and 924 * {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p> 925 * 926 * <ul> 927 * <li>Tag = 34867</li> 928 * <li>Type = Unsigned long</li> 929 * <li>Count = 1</li> 930 * <li>Default = None</li> 931 * </ul> 932 */ 933 public static final String TAG_ISO_SPEED = "ISOSpeed"; 934 /** 935 * <p>This tag indicates the ISO speed latitude yyy value of a camera or input device that is 936 * defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED} 937 * and {@link #TAG_ISO_SPEED_LATITUDE_ZZZ}.</p> 938 * 939 * <ul> 940 * <li>Tag = 34868</li> 941 * <li>Type = Unsigned long</li> 942 * <li>Count = 1</li> 943 * <li>Default = None</li> 944 * </ul> 945 */ 946 public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy"; 947 /** 948 * <p>This tag indicates the ISO speed latitude zzz value of a camera or input device that is 949 * defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED} 950 * and {@link #TAG_ISO_SPEED_LATITUDE_YYY}.</p> 951 * 952 * <ul> 953 * <li>Tag = 34869</li> 954 * <li>Type = Unsigned long</li> 955 * <li>Count = 1</li> 956 * <li>Default = None</li> 957 * </ul> 958 */ 959 public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz"; 960 /** 961 * <p>Shutter speed. The unit is the APEX setting.</p> 962 * 963 * <ul> 964 * <li>Tag = 37377</li> 965 * <li>Type = Signed rational</li> 966 * <li>Count = 1</li> 967 * <li>Default = None</li> 968 * </ul> 969 */ 970 public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue"; 971 /** 972 * <p>The lens aperture. The unit is the APEX value.</p> 973 * 974 * <ul> 975 * <li>Tag = 37378</li> 976 * <li>Type = Unsigned rational</li> 977 * <li>Count = 1</li> 978 * <li>Default = None</li> 979 * </ul> 980 */ 981 public static final String TAG_APERTURE_VALUE = "ApertureValue"; 982 /** 983 * <p>The value of brightness. The unit is the APEX value. Ordinarily it is given in the range 984 * of -99.99 to 99.99. Note that if the numerator of the recorded value is 0xFFFFFFFF, 985 * Unknown shall be indicated.</p> 986 * 987 * <ul> 988 * <li>Tag = 37379</li> 989 * <li>Type = Signed rational</li> 990 * <li>Count = 1</li> 991 * <li>Default = None</li> 992 * </ul> 993 */ 994 public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue"; 995 /** 996 * <p>The exposure bias. The unit is the APEX value. Ordinarily it is given in the range of 997 * -99.99 to 99.99.</p> 998 * 999 * <ul> 1000 * <li>Tag = 37380</li> 1001 * <li>Type = Signed rational</li> 1002 * <li>Count = 1</li> 1003 * <li>Default = None</li> 1004 * </ul> 1005 */ 1006 public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue"; 1007 /** 1008 * <p>The smallest F number of the lens. The unit is the APEX value. Ordinarily it is given 1009 * in the range of 00.00 to 99.99, but it is not limited to this range.</p> 1010 * 1011 * <ul> 1012 * <li>Tag = 37381</li> 1013 * <li>Type = Unsigned rational</li> 1014 * <li>Count = 1</li> 1015 * <li>Default = None</li> 1016 * </ul> 1017 */ 1018 public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue"; 1019 /** 1020 * <p>The distance to the subject, given in meters. Note that if the numerator of the recorded 1021 * value is 0xFFFFFFFF, Infinity shall be indicated; and if the numerator is 0, Distance 1022 * unknown shall be indicated.</p> 1023 * 1024 * <ul> 1025 * <li>Tag = 37382</li> 1026 * <li>Type = Unsigned rational</li> 1027 * <li>Count = 1</li> 1028 * <li>Default = None</li> 1029 * </ul> 1030 */ 1031 public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance"; 1032 /** 1033 * <p>The metering mode.</p> 1034 * 1035 * <ul> 1036 * <li>Tag = 37383</li> 1037 * <li>Type = Unsigned short</li> 1038 * <li>Count = 1</li> 1039 * <li>Default = {@link #METERING_MODE_UNKNOWN}</li> 1040 * </ul> 1041 * 1042 * @see #METERING_MODE_UNKNOWN 1043 * @see #METERING_MODE_AVERAGE 1044 * @see #METERING_MODE_CENTER_WEIGHT_AVERAGE 1045 * @see #METERING_MODE_SPOT 1046 * @see #METERING_MODE_MULTI_SPOT 1047 * @see #METERING_MODE_PATTERN 1048 * @see #METERING_MODE_PARTIAL 1049 * @see #METERING_MODE_OTHER 1050 */ 1051 public static final String TAG_METERING_MODE = "MeteringMode"; 1052 /** 1053 * <p>The kind of light source.</p> 1054 * 1055 * <ul> 1056 * <li>Tag = 37384</li> 1057 * <li>Type = Unsigned short</li> 1058 * <li>Count = 1</li> 1059 * <li>Default = {@link #LIGHT_SOURCE_UNKNOWN}</li> 1060 * </ul> 1061 * 1062 * @see #LIGHT_SOURCE_UNKNOWN 1063 * @see #LIGHT_SOURCE_DAYLIGHT 1064 * @see #LIGHT_SOURCE_FLUORESCENT 1065 * @see #LIGHT_SOURCE_TUNGSTEN 1066 * @see #LIGHT_SOURCE_FLASH 1067 * @see #LIGHT_SOURCE_FINE_WEATHER 1068 * @see #LIGHT_SOURCE_CLOUDY_WEATHER 1069 * @see #LIGHT_SOURCE_SHADE 1070 * @see #LIGHT_SOURCE_DAYLIGHT_FLUORESCENT 1071 * @see #LIGHT_SOURCE_DAY_WHITE_FLUORESCENT 1072 * @see #LIGHT_SOURCE_COOL_WHITE_FLUORESCENT 1073 * @see #LIGHT_SOURCE_WHITE_FLUORESCENT 1074 * @see #LIGHT_SOURCE_WARM_WHITE_FLUORESCENT 1075 * @see #LIGHT_SOURCE_STANDARD_LIGHT_A 1076 * @see #LIGHT_SOURCE_STANDARD_LIGHT_B 1077 * @see #LIGHT_SOURCE_STANDARD_LIGHT_C 1078 * @see #LIGHT_SOURCE_D55 1079 * @see #LIGHT_SOURCE_D65 1080 * @see #LIGHT_SOURCE_D75 1081 * @see #LIGHT_SOURCE_D50 1082 * @see #LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN 1083 * @see #LIGHT_SOURCE_OTHER 1084 */ 1085 public static final String TAG_LIGHT_SOURCE = "LightSource"; 1086 /** 1087 * <p>This tag indicates the status of flash when the image was shot. Bit 0 indicates the flash 1088 * firing status, bits 1 and 2 indicate the flash return status, bits 3 and 4 indicate 1089 * the flash mode, bit 5 indicates whether the flash function is present, and bit 6 indicates 1090 * "red eye" mode.</p> 1091 * 1092 * <ul> 1093 * <li>Tag = 37385</li> 1094 * <li>Type = Unsigned short</li> 1095 * <li>Count = 1</li> 1096 * </ul> 1097 * 1098 * @see #FLAG_FLASH_FIRED 1099 * @see #FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED 1100 * @see #FLAG_FLASH_RETURN_LIGHT_DETECTED 1101 * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING 1102 * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION 1103 * @see #FLAG_FLASH_MODE_AUTO 1104 * @see #FLAG_FLASH_NO_FLASH_FUNCTION 1105 * @see #FLAG_FLASH_RED_EYE_SUPPORTED 1106 */ 1107 public static final String TAG_FLASH = "Flash"; 1108 /** 1109 * <p>This tag indicates the location and area of the main subject in the overall scene.</p> 1110 * 1111 * <ul> 1112 * <li>Tag = 37396</li> 1113 * <li>Type = Unsigned short</li> 1114 * <li>Count = 2 or 3 or 4</li> 1115 * <li>Default = None</li> 1116 * </ul> 1117 * 1118 * <p>The subject location and area are defined by Count values as follows.</p> 1119 * 1120 * <ul> 1121 * <li>Count = 2 Indicates the location of the main subject as coordinates. The first value 1122 * is the X coordinate and the second is the Y coordinate.</li> 1123 * <li>Count = 3 The area of the main subject is given as a circle. The circular area is 1124 * expressed as center coordinates and diameter. The first value is 1125 * the center X coordinate, the second is the center Y coordinate, and 1126 * the third is the diameter.</li> 1127 * <li>Count = 4 The area of the main subject is given as a rectangle. The rectangular 1128 * area is expressed as center coordinates and area dimensions. The first 1129 * value is the center X coordinate, the second is the center Y coordinate, 1130 * the third is the width of the area, and the fourth is the height of 1131 * the area.</li> 1132 * </ul> 1133 * 1134 * <p>Note that the coordinate values, width, and height are expressed in relation to the upper 1135 * left as origin, prior to rotation processing as per {@link #TAG_ORIENTATION}.</p> 1136 */ 1137 public static final String TAG_SUBJECT_AREA = "SubjectArea"; 1138 /** 1139 * <p>The actual focal length of the lens, in mm. Conversion is not made to the focal length 1140 * of a 35mm film camera.</p> 1141 * 1142 * <ul> 1143 * <li>Tag = 37386</li> 1144 * <li>Type = Unsigned rational</li> 1145 * <li>Count = 1</li> 1146 * <li>Default = None</li> 1147 * </ul> 1148 */ 1149 public static final String TAG_FOCAL_LENGTH = "FocalLength"; 1150 /** 1151 * <p>Indicates the strobe energy at the time the image is captured, as measured in Beam Candle 1152 * Power Seconds (BCPS).</p> 1153 * 1154 * <ul> 1155 * <li>Tag = 41483</li> 1156 * <li>Type = Unsigned rational</li> 1157 * <li>Count = 1</li> 1158 * <li>Default = None</li> 1159 * </ul> 1160 */ 1161 public static final String TAG_FLASH_ENERGY = "FlashEnergy"; 1162 /** 1163 * <p>This tag records the camera or input device spatial frequency table and SFR values in 1164 * the direction of image width, image height, and diagonal direction, as specified in 1165 * ISO 12233.</p> 1166 * 1167 * <ul> 1168 * <li>Tag = 41484</li> 1169 * <li>Type = Undefined</li> 1170 * <li>Default = None</li> 1171 * </ul> 1172 */ 1173 public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse"; 1174 /** 1175 * <p>Indicates the number of pixels in the image width (X) direction per 1176 * {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p> 1177 * 1178 * <ul> 1179 * <li>Tag = 41486</li> 1180 * <li>Type = Unsigned rational</li> 1181 * <li>Count = 1</li> 1182 * <li>Default = None</li> 1183 * </ul> 1184 */ 1185 public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution"; 1186 /** 1187 * <p>Indicates the number of pixels in the image height (Y) direction per 1188 * {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p> 1189 * 1190 * <ul> 1191 * <li>Tag = 41487</li> 1192 * <li>Type = Unsigned rational</li> 1193 * <li>Count = 1</li> 1194 * <li>Default = None</li> 1195 * </ul> 1196 */ 1197 public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution"; 1198 /** 1199 * <p>Indicates the unit for measuring {@link #TAG_FOCAL_PLANE_X_RESOLUTION} and 1200 * {@link #TAG_FOCAL_PLANE_Y_RESOLUTION}. This value is the same as 1201 * {@link #TAG_RESOLUTION_UNIT}.</p> 1202 * 1203 * <ul> 1204 * <li>Tag = 41488</li> 1205 * <li>Type = Unsigned short</li> 1206 * <li>Count = 1</li> 1207 * <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li> 1208 * </ul> 1209 * 1210 * @see #TAG_RESOLUTION_UNIT 1211 * @see #RESOLUTION_UNIT_INCHES 1212 * @see #RESOLUTION_UNIT_CENTIMETERS 1213 */ 1214 public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit"; 1215 /** 1216 * <p>Indicates the location of the main subject in the scene. The value of this tag represents 1217 * the pixel at the center of the main subject relative to the left edge, prior to rotation 1218 * processing as per {@link #TAG_ORIENTATION}. The first value indicates the X column number 1219 * and second indicates the Y row number. When a camera records the main subject location, 1220 * it is recommended that {@link #TAG_SUBJECT_AREA} be used instead of this tag.</p> 1221 * 1222 * <ul> 1223 * <li>Tag = 41492</li> 1224 * <li>Type = Unsigned short</li> 1225 * <li>Count = 2</li> 1226 * <li>Default = None</li> 1227 * </ul> 1228 */ 1229 public static final String TAG_SUBJECT_LOCATION = "SubjectLocation"; 1230 /** 1231 * <p>Indicates the exposure index selected on the camera or input device at the time the image 1232 * is captured.</p> 1233 * 1234 * <ul> 1235 * <li>Tag = 41493</li> 1236 * <li>Type = Unsigned rational</li> 1237 * <li>Count = 1</li> 1238 * <li>Default = None</li> 1239 * </ul> 1240 */ 1241 public static final String TAG_EXPOSURE_INDEX = "ExposureIndex"; 1242 /** 1243 * <p>Indicates the image sensor type on the camera or input device.</p> 1244 * 1245 * <ul> 1246 * <li>Tag = 41495</li> 1247 * <li>Type = Unsigned short</li> 1248 * <li>Count = 1</li> 1249 * <li>Default = None</li> 1250 * </ul> 1251 * 1252 * @see #SENSOR_TYPE_NOT_DEFINED 1253 * @see #SENSOR_TYPE_ONE_CHIP 1254 * @see #SENSOR_TYPE_TWO_CHIP 1255 * @see #SENSOR_TYPE_THREE_CHIP 1256 * @see #SENSOR_TYPE_COLOR_SEQUENTIAL 1257 * @see #SENSOR_TYPE_TRILINEAR 1258 * @see #SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR 1259 */ 1260 public static final String TAG_SENSING_METHOD = "SensingMethod"; 1261 /** 1262 * <p>Indicates the image source. If a DSC recorded the image, this tag value always shall 1263 * be set to {@link #FILE_SOURCE_DSC}.</p> 1264 * 1265 * <ul> 1266 * <li>Tag = 41728</li> 1267 * <li>Type = Undefined</li> 1268 * <li>Length = 1</li> 1269 * <li>Default = {@link #FILE_SOURCE_DSC}</li> 1270 * </ul> 1271 * 1272 * @see #FILE_SOURCE_OTHER 1273 * @see #FILE_SOURCE_TRANSPARENT_SCANNER 1274 * @see #FILE_SOURCE_REFLEX_SCANNER 1275 * @see #FILE_SOURCE_DSC 1276 */ 1277 public static final String TAG_FILE_SOURCE = "FileSource"; 1278 /** 1279 * <p>Indicates the type of scene. If a DSC recorded the image, this tag value shall always 1280 * be set to {@link #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED}.</p> 1281 * 1282 * <ul> 1283 * <li>Tag = 41729</li> 1284 * <li>Type = Undefined</li> 1285 * <li>Length = 1</li> 1286 * <li>Default = 1</li> 1287 * </ul> 1288 * 1289 * @see #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED 1290 */ 1291 public static final String TAG_SCENE_TYPE = "SceneType"; 1292 /** 1293 * <p>Indicates the color filter array (CFA) geometric pattern of the image sensor when 1294 * a one-chip color area sensor is used. It does not apply to all sensing methods.</p> 1295 * 1296 * <ul> 1297 * <li>Tag = 41730</li> 1298 * <li>Type = Undefined</li> 1299 * <li>Default = None</li> 1300 * </ul> 1301 * 1302 * @see #TAG_SENSING_METHOD 1303 * @see #SENSOR_TYPE_ONE_CHIP 1304 */ 1305 public static final String TAG_CFA_PATTERN = "CFAPattern"; 1306 /** 1307 * <p>This tag indicates the use of special processing on image data, such as rendering geared 1308 * to output. When special processing is performed, the Exif/DCF reader is expected to disable 1309 * or minimize any further processing.</p> 1310 * 1311 * <ul> 1312 * <li>Tag = 41985</li> 1313 * <li>Type = Unsigned short</li> 1314 * <li>Count = 1</li> 1315 * <li>Default = {@link #RENDERED_PROCESS_NORMAL}</li> 1316 * </ul> 1317 * 1318 * @see #RENDERED_PROCESS_NORMAL 1319 * @see #RENDERED_PROCESS_CUSTOM 1320 */ 1321 public static final String TAG_CUSTOM_RENDERED = "CustomRendered"; 1322 /** 1323 * <p>This tag indicates the exposure mode set when the image was shot. 1324 * In {@link #EXPOSURE_MODE_AUTO_BRACKET}, the camera shoots a series of frames of the same 1325 * scene at different exposure settings.</p> 1326 * 1327 * <ul> 1328 * <li>Tag = 41986</li> 1329 * <li>Type = Unsigned short</li> 1330 * <li>Count = 1</li> 1331 * <li>Default = None</li> 1332 * </ul> 1333 * 1334 * @see #EXPOSURE_MODE_AUTO 1335 * @see #EXPOSURE_MODE_MANUAL 1336 * @see #EXPOSURE_MODE_AUTO_BRACKET 1337 */ 1338 public static final String TAG_EXPOSURE_MODE = "ExposureMode"; 1339 /** 1340 * <p>This tag indicates the white balance mode set when the image was shot.</p> 1341 * 1342 * <ul> 1343 * <li>Tag = 41987</li> 1344 * <li>Type = Unsigned short</li> 1345 * <li>Count = 1</li> 1346 * <li>Default = None</li> 1347 * </ul> 1348 * 1349 * @see #WHITEBALANCE_AUTO 1350 * @see #WHITEBALANCE_MANUAL 1351 */ 1352 public static final String TAG_WHITE_BALANCE = "WhiteBalance"; 1353 /** 1354 * <p>This tag indicates the digital zoom ratio when the image was shot. If the numerator of 1355 * the recorded value is 0, this indicates that digital zoom was not used.</p> 1356 * 1357 * <ul> 1358 * <li>Tag = 41988</li> 1359 * <li>Type = Unsigned rational</li> 1360 * <li>Count = 1</li> 1361 * <li>Default = None</li> 1362 * </ul> 1363 */ 1364 public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio"; 1365 /** 1366 * <p>This tag indicates the equivalent focal length assuming a 35mm film camera, in mm. 1367 * A value of 0 means the focal length is unknown. Note that this tag differs from 1368 * {@link #TAG_FOCAL_LENGTH}.</p> 1369 * 1370 * <ul> 1371 * <li>Tag = 41989</li> 1372 * <li>Type = Unsigned short</li> 1373 * <li>Count = 1</li> 1374 * <li>Default = None</li> 1375 * </ul> 1376 */ 1377 public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm"; 1378 /** 1379 * <p>This tag indicates the type of scene that was shot. It may also be used to record 1380 * the mode in which the image was shot. Note that this differs from 1381 * {@link #TAG_SCENE_TYPE}.</p> 1382 * 1383 * <ul> 1384 * <li>Tag = 41990</li> 1385 * <li>Type = Unsigned short</li> 1386 * <li>Count = 1</li> 1387 * <li>Default = 0</li> 1388 * </ul> 1389 * 1390 * @see #SCENE_CAPTURE_TYPE_STANDARD 1391 * @see #SCENE_CAPTURE_TYPE_LANDSCAPE 1392 * @see #SCENE_CAPTURE_TYPE_PORTRAIT 1393 * @see #SCENE_CAPTURE_TYPE_NIGHT 1394 */ 1395 public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType"; 1396 /** 1397 * <p>This tag indicates the degree of overall image gain adjustment.</p> 1398 * 1399 * <ul> 1400 * <li>Tag = 41991</li> 1401 * <li>Type = Unsigned short</li> 1402 * <li>Count = 1</li> 1403 * <li>Default = None</li> 1404 * </ul> 1405 * 1406 * @see #GAIN_CONTROL_NONE 1407 * @see #GAIN_CONTROL_LOW_GAIN_UP 1408 * @see #GAIN_CONTROL_HIGH_GAIN_UP 1409 * @see #GAIN_CONTROL_LOW_GAIN_DOWN 1410 * @see #GAIN_CONTROL_HIGH_GAIN_DOWN 1411 */ 1412 public static final String TAG_GAIN_CONTROL = "GainControl"; 1413 /** 1414 * <p>This tag indicates the direction of contrast processing applied by the camera when 1415 * the image was shot.</p> 1416 * 1417 * <ul> 1418 * <li>Tag = 41992</li> 1419 * <li>Type = Unsigned short</li> 1420 * <li>Count = 1</li> 1421 * <li>Default = {@link #CONTRAST_NORMAL}</li> 1422 * </ul> 1423 * 1424 * @see #CONTRAST_NORMAL 1425 * @see #CONTRAST_SOFT 1426 * @see #CONTRAST_HARD 1427 */ 1428 public static final String TAG_CONTRAST = "Contrast"; 1429 /** 1430 * <p>This tag indicates the direction of saturation processing applied by the camera when 1431 * the image was shot.</p> 1432 * 1433 * <ul> 1434 * <li>Tag = 41993</li> 1435 * <li>Type = Unsigned short</li> 1436 * <li>Count = 1</li> 1437 * <li>Default = {@link #SATURATION_NORMAL}</li> 1438 * </ul> 1439 * 1440 * @see #SATURATION_NORMAL 1441 * @see #SATURATION_LOW 1442 * @see #SATURATION_HIGH 1443 */ 1444 public static final String TAG_SATURATION = "Saturation"; 1445 /** 1446 * <p>This tag indicates the direction of sharpness processing applied by the camera when 1447 * the image was shot.</p> 1448 * 1449 * <ul> 1450 * <li>Tag = 41994</li> 1451 * <li>Type = Unsigned short</li> 1452 * <li>Count = 1</li> 1453 * <li>Default = {@link #SHARPNESS_NORMAL}</li> 1454 * </ul> 1455 * 1456 * @see #SHARPNESS_NORMAL 1457 * @see #SHARPNESS_SOFT 1458 * @see #SHARPNESS_HARD 1459 */ 1460 public static final String TAG_SHARPNESS = "Sharpness"; 1461 /** 1462 * <p>This tag indicates information on the picture-taking conditions of a particular camera 1463 * model. The tag is used only to indicate the picture-taking conditions in the Exif/DCF 1464 * reader.</p> 1465 * 1466 * <ul> 1467 * <li>Tag = 41995</li> 1468 * <li>Type = Undefined</li> 1469 * <li>Default = None</li> 1470 * </ul> 1471 */ 1472 public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription"; 1473 /** 1474 * <p>This tag indicates the distance to the subject.</p> 1475 * 1476 * <ul> 1477 * <li>Tag = 41996</li> 1478 * <li>Type = Unsigned short</li> 1479 * <li>Count = 1</li> 1480 * <li>Default = None</li> 1481 * </ul> 1482 * 1483 * @see #SUBJECT_DISTANCE_RANGE_UNKNOWN 1484 * @see #SUBJECT_DISTANCE_RANGE_MACRO 1485 * @see #SUBJECT_DISTANCE_RANGE_CLOSE_VIEW 1486 * @see #SUBJECT_DISTANCE_RANGE_DISTANT_VIEW 1487 */ 1488 public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange"; 1489 1490 // H. Other tags 1491 /** 1492 * <p>This tag indicates an identifier assigned uniquely to each image. It is recorded as 1493 * an ASCII string equivalent to hexadecimal notation and 128-bit fixed length.</p> 1494 * 1495 * <ul> 1496 * <li>Tag = 42016</li> 1497 * <li>Type = String</li> 1498 * <li>Length = 32</li> 1499 * <li>Default = None</li> 1500 * </ul> 1501 */ 1502 public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID"; 1503 /** 1504 * <p>This tag records the owner of a camera used in photography as an ASCII string.</p> 1505 * 1506 * <ul> 1507 * <li>Tag = 42032</li> 1508 * <li>Type = String</li> 1509 * <li>Default = None</li> 1510 * </ul> 1511 */ 1512 public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName"; 1513 /** 1514 * <p>This tag records the serial number of the body of the camera that was used in photography 1515 * as an ASCII string.</p> 1516 * 1517 * <ul> 1518 * <li>Tag = 42033</li> 1519 * <li>Type = String</li> 1520 * <li>Default = None</li> 1521 * </ul> 1522 */ 1523 public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber"; 1524 /** 1525 * <p>This tag notes minimum focal length, maximum focal length, minimum F number in the 1526 * minimum focal length, and minimum F number in the maximum focal length, which are 1527 * specification information for the lens that was used in photography. When the minimum 1528 * F number is unknown, the notation is 0/0.</p> 1529 * 1530 * <ul> 1531 * <li>Tag = 42034</li> 1532 * <li>Type = Unsigned rational</li> 1533 * <li>Count = 4</li> 1534 * <li>Default = None</li> 1535 * <ul> 1536 * <li>Value 1 := Minimum focal length (unit: mm)</li> 1537 * <li>Value 2 : = Maximum focal length (unit: mm)</li> 1538 * <li>Value 3 : = Minimum F number in the minimum focal length</li> 1539 * <li>Value 4 : = Minimum F number in the maximum focal length</li> 1540 * </ul> 1541 * </ul> 1542 */ 1543 public static final String TAG_LENS_SPECIFICATION = "LensSpecification"; 1544 /** 1545 * <p>This tag records the lens manufacturer as an ASCII string.</p> 1546 * 1547 * <ul> 1548 * <li>Tag = 42035</li> 1549 * <li>Type = String</li> 1550 * <li>Default = None</li> 1551 * </ul> 1552 */ 1553 public static final String TAG_LENS_MAKE = "LensMake"; 1554 /** 1555 * <p>This tag records the lens’s model name and model number as an ASCII string.</p> 1556 * 1557 * <ul> 1558 * <li>Tag = 42036</li> 1559 * <li>Type = String</li> 1560 * <li>Default = None</li> 1561 * </ul> 1562 */ 1563 public static final String TAG_LENS_MODEL = "LensModel"; 1564 /** 1565 * <p>This tag records the serial number of the interchangeable lens that was used in 1566 * photography as an ASCII string.</p> 1567 * 1568 * <ul> 1569 * <li>Tag = 42037</li> 1570 * <li>Type = String</li> 1571 * <li>Default = None</li> 1572 * </ul> 1573 */ 1574 public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber"; 1575 1576 // GPS Attribute Information 1577 /** 1578 * <p>Indicates the version of GPS Info IFD. The version is given as 2.3.0.0. This tag is 1579 * mandatory when GPS-related tags are present. Note that this tag is written as a different 1580 * byte than {@link #TAG_EXIF_VERSION}.</p> 1581 * 1582 * <ul> 1583 * <li>Tag = 0</li> 1584 * <li>Type = Byte</li> 1585 * <li>Count = 4</li> 1586 * <li>Default = 2.3.0.0</li> 1587 * <ul> 1588 * <li>2300 = Version 2.3</li> 1589 * <li>Other = reserved</li> 1590 * </ul> 1591 * </ul> 1592 */ 1593 public static final String TAG_GPS_VERSION_ID = "GPSVersionID"; 1594 /** 1595 * <p>Indicates whether the latitude is north or south latitude.</p> 1596 * 1597 * <ul> 1598 * <li>Tag = 1</li> 1599 * <li>Type = String</li> 1600 * <li>Length = 1</li> 1601 * <li>Default = None</li> 1602 * </ul> 1603 * 1604 * @see #LATITUDE_NORTH 1605 * @see #LATITUDE_SOUTH 1606 */ 1607 public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef"; 1608 /** 1609 * <p>Indicates the latitude. The latitude is expressed as three RATIONAL values giving 1610 * the degrees, minutes, and seconds, respectively. If latitude is expressed as degrees, 1611 * minutes and seconds, a typical format would be dd/1,mm/1,ss/1. When degrees and minutes are 1612 * used and, for example, fractions of minutes are given up to two decimal places, the format 1613 * would be dd/1,mmmm/100,0/1.</p> 1614 * 1615 * <ul> 1616 * <li>Tag = 2</li> 1617 * <li>Type = Unsigned rational</li> 1618 * <li>Count = 3</li> 1619 * <li>Default = None</li> 1620 * </ul> 1621 */ 1622 public static final String TAG_GPS_LATITUDE = "GPSLatitude"; 1623 /** 1624 * <p>Indicates whether the longitude is east or west longitude.</p> 1625 * 1626 * <ul> 1627 * <li>Tag = 3</li> 1628 * <li>Type = String</li> 1629 * <li>Length = 1</li> 1630 * <li>Default = None</li> 1631 * </ul> 1632 * 1633 * @see #LONGITUDE_EAST 1634 * @see #LONGITUDE_WEST 1635 */ 1636 public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef"; 1637 /** 1638 * <p>Indicates the longitude. The longitude is expressed as three RATIONAL values giving 1639 * the degrees, minutes, and seconds, respectively. If longitude is expressed as degrees, 1640 * minutes and seconds, a typical format would be ddd/1,mm/1,ss/1. When degrees and minutes 1641 * are used and, for example, fractions of minutes are given up to two decimal places, 1642 * the format would be ddd/1,mmmm/100,0/1.</p> 1643 * 1644 * <ul> 1645 * <li>Tag = 4</li> 1646 * <li>Type = Unsigned rational</li> 1647 * <li>Count = 3</li> 1648 * <li>Default = None</li> 1649 * </ul> 1650 */ 1651 public static final String TAG_GPS_LONGITUDE = "GPSLongitude"; 1652 /** 1653 * <p>Indicates the altitude used as the reference altitude. If the reference is sea level 1654 * and the altitude is above sea level, 0 is given. If the altitude is below sea level, 1655 * a value of 1 is given and the altitude is indicated as an absolute value in 1656 * {@link #TAG_GPS_ALTITUDE}.</p> 1657 * 1658 * <ul> 1659 * <li>Tag = 5</li> 1660 * <li>Type = Byte</li> 1661 * <li>Count = 1</li> 1662 * <li>Default = 0</li> 1663 * </ul> 1664 * 1665 * @see #ALTITUDE_ABOVE_SEA_LEVEL 1666 * @see #ALTITUDE_BELOW_SEA_LEVEL 1667 */ 1668 public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef"; 1669 /** 1670 * <p>Indicates the altitude based on the reference in {@link #TAG_GPS_ALTITUDE_REF}. 1671 * The reference unit is meters.</p> 1672 * 1673 * <ul> 1674 * <li>Tag = 6</li> 1675 * <li>Type = Unsigned rational</li> 1676 * <li>Count = 1</li> 1677 * <li>Default = None</li> 1678 * </ul> 1679 */ 1680 public static final String TAG_GPS_ALTITUDE = "GPSAltitude"; 1681 /** 1682 * <p>Indicates the time as UTC (Coordinated Universal Time). TimeStamp is expressed as three 1683 * unsigned rational values giving the hour, minute, and second.</p> 1684 * 1685 * <ul> 1686 * <li>Tag = 7</li> 1687 * <li>Type = Unsigned rational</li> 1688 * <li>Count = 3</li> 1689 * <li>Default = None</li> 1690 * </ul> 1691 */ 1692 public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp"; 1693 /** 1694 * <p>Indicates the GPS satellites used for measurements. This tag may be used to describe 1695 * the number of satellites, their ID number, angle of elevation, azimuth, SNR and other 1696 * information in ASCII notation. The format is not specified. If the GPS receiver is incapable 1697 * of taking measurements, value of the tag shall be set to {@code null}.</p> 1698 * 1699 * <ul> 1700 * <li>Tag = 8</li> 1701 * <li>Type = String</li> 1702 * <li>Default = None</li> 1703 * </ul> 1704 */ 1705 public static final String TAG_GPS_SATELLITES = "GPSSatellites"; 1706 /** 1707 * <p>Indicates the status of the GPS receiver when the image is recorded. 'A' means 1708 * measurement is in progress, and 'V' means the measurement is interrupted.</p> 1709 * 1710 * <ul> 1711 * <li>Tag = 9</li> 1712 * <li>Type = String</li> 1713 * <li>Length = 1</li> 1714 * <li>Default = None</li> 1715 * </ul> 1716 * 1717 * @see #GPS_MEASUREMENT_IN_PROGRESS 1718 * @see #GPS_MEASUREMENT_INTERRUPTED 1719 */ 1720 public static final String TAG_GPS_STATUS = "GPSStatus"; 1721 /** 1722 * <p>Indicates the GPS measurement mode. Originally it was defined for GPS, but it may 1723 * be used for recording a measure mode to record the position information provided from 1724 * a mobile base station or wireless LAN as well as GPS.</p> 1725 * 1726 * <ul> 1727 * <li>Tag = 10</li> 1728 * <li>Type = String</li> 1729 * <li>Length = 1</li> 1730 * <li>Default = None</li> 1731 * </ul> 1732 * 1733 * @see #GPS_MEASUREMENT_2D 1734 * @see #GPS_MEASUREMENT_3D 1735 */ 1736 public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode"; 1737 /** 1738 * <p>Indicates the GPS DOP (data degree of precision). An HDOP value is written during 1739 * two-dimensional measurement, and PDOP during three-dimensional measurement.</p> 1740 * 1741 * <ul> 1742 * <li>Tag = 11</li> 1743 * <li>Type = Unsigned rational</li> 1744 * <li>Count = 1</li> 1745 * <li>Default = None</li> 1746 * </ul> 1747 */ 1748 public static final String TAG_GPS_DOP = "GPSDOP"; 1749 /** 1750 * <p>Indicates the unit used to express the GPS receiver speed of movement.</p> 1751 * 1752 * <ul> 1753 * <li>Tag = 12</li> 1754 * <li>Type = String</li> 1755 * <li>Length = 1</li> 1756 * <li>Default = {@link #GPS_SPEED_KILOMETERS_PER_HOUR}</li> 1757 * </ul> 1758 * 1759 * @see #GPS_SPEED_KILOMETERS_PER_HOUR 1760 * @see #GPS_SPEED_MILES_PER_HOUR 1761 * @see #GPS_SPEED_KNOTS 1762 */ 1763 public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef"; 1764 /** 1765 * <p>Indicates the speed of GPS receiver movement.</p> 1766 * 1767 * <ul> 1768 * <li>Tag = 13</li> 1769 * <li>Type = Unsigned rational</li> 1770 * <li>Count = 1</li> 1771 * <li>Default = None</li> 1772 * </ul> 1773 */ 1774 public static final String TAG_GPS_SPEED = "GPSSpeed"; 1775 /** 1776 * <p>Indicates the reference for giving the direction of GPS receiver movement.</p> 1777 * 1778 * <ul> 1779 * <li>Tag = 14</li> 1780 * <li>Type = String</li> 1781 * <li>Length = 1</li> 1782 * <li>Default = {@link #GPS_DIRECTION_TRUE}</li> 1783 * </ul> 1784 * 1785 * @see #GPS_DIRECTION_TRUE 1786 * @see #GPS_DIRECTION_MAGNETIC 1787 */ 1788 public static final String TAG_GPS_TRACK_REF = "GPSTrackRef"; 1789 /** 1790 * <p>Indicates the direction of GPS receiver movement. 1791 * The range of values is from 0.00 to 359.99.</p> 1792 * 1793 * <ul> 1794 * <li>Tag = 15</li> 1795 * <li>Type = Unsigned rational</li> 1796 * <li>Count = 1</li> 1797 * <li>Default = None</li> 1798 * </ul> 1799 */ 1800 public static final String TAG_GPS_TRACK = "GPSTrack"; 1801 /** 1802 * <p>Indicates the reference for giving the direction of the image when it is captured.</p> 1803 * 1804 * <ul> 1805 * <li>Tag = 16</li> 1806 * <li>Type = String</li> 1807 * <li>Length = 1</li> 1808 * <li>Default = {@link #GPS_DIRECTION_TRUE}</li> 1809 * </ul> 1810 * 1811 * @see #GPS_DIRECTION_TRUE 1812 * @see #GPS_DIRECTION_MAGNETIC 1813 */ 1814 public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef"; 1815 /** 1816 * <p>ndicates the direction of the image when it was captured. 1817 * The range of values is from 0.00 to 359.99.</p> 1818 * 1819 * <ul> 1820 * <li>Tag = 17</li> 1821 * <li>Type = Unsigned rational</li> 1822 * <li>Count = 1</li> 1823 * <li>Default = None</li> 1824 * </ul> 1825 */ 1826 public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection"; 1827 /** 1828 * <p>Indicates the geodetic survey data used by the GPS receiver. If the survey data is 1829 * restricted to Japan,the value of this tag is 'TOKYO' or 'WGS-84'. If a GPS Info tag is 1830 * recorded, it is strongly recommended that this tag be recorded.</p> 1831 * 1832 * <ul> 1833 * <li>Tag = 18</li> 1834 * <li>Type = String</li> 1835 * <li>Default = None</li> 1836 * </ul> 1837 */ 1838 public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum"; 1839 /** 1840 * <p>Indicates whether the latitude of the destination point is north or south latitude.</p> 1841 * 1842 * <ul> 1843 * <li>Tag = 19</li> 1844 * <li>Type = String</li> 1845 * <li>Length = 1</li> 1846 * <li>Default = None</li> 1847 * </ul> 1848 * 1849 * @see #LATITUDE_NORTH 1850 * @see #LATITUDE_SOUTH 1851 */ 1852 public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef"; 1853 /** 1854 * <p>Indicates the latitude of the destination point. The latitude is expressed as three 1855 * unsigned rational values giving the degrees, minutes, and seconds, respectively. 1856 * If latitude is expressed as degrees, minutes and seconds, a typical format would be 1857 * dd/1,mm/1,ss/1. When degrees and minutes are used and, for example, fractions of minutes 1858 * are given up to two decimal places, the format would be dd/1, mmmm/100, 0/1.</p> 1859 * 1860 * <ul> 1861 * <li>Tag = 20</li> 1862 * <li>Type = Unsigned rational</li> 1863 * <li>Count = 3</li> 1864 * <li>Default = None</li> 1865 * </ul> 1866 */ 1867 public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude"; 1868 /** 1869 * <p>Indicates whether the longitude of the destination point is east or west longitude.</p> 1870 * 1871 * <ul> 1872 * <li>Tag = 21</li> 1873 * <li>Type = String</li> 1874 * <li>Length = 1</li> 1875 * <li>Default = None</li> 1876 * </ul> 1877 * 1878 * @see #LONGITUDE_EAST 1879 * @see #LONGITUDE_WEST 1880 */ 1881 public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef"; 1882 /** 1883 * <p>Indicates the longitude of the destination point. The longitude is expressed as three 1884 * unsigned rational values giving the degrees, minutes, and seconds, respectively. 1885 * If longitude is expressed as degrees, minutes and seconds, a typical format would be ddd/1, 1886 * mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are 1887 * given up to two decimal places, the format would be ddd/1, mmmm/100, 0/1.</p> 1888 * 1889 * <ul> 1890 * <li>Tag = 22</li> 1891 * <li>Type = Unsigned rational</li> 1892 * <li>Count = 3</li> 1893 * <li>Default = None</li> 1894 * </ul> 1895 */ 1896 public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude"; 1897 /** 1898 * <p>Indicates the reference used for giving the bearing to the destination point.</p> 1899 * 1900 * <ul> 1901 * <li>Tag = 23</li> 1902 * <li>Type = String</li> 1903 * <li>Length = 1</li> 1904 * <li>Default = {@link #GPS_DIRECTION_TRUE}</li> 1905 * </ul> 1906 * 1907 * @see #GPS_DIRECTION_TRUE 1908 * @see #GPS_DIRECTION_MAGNETIC 1909 */ 1910 public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef"; 1911 /** 1912 * <p>Indicates the bearing to the destination point. 1913 * The range of values is from 0.00 to 359.99.</p> 1914 * 1915 * <ul> 1916 * <li>Tag = 24</li> 1917 * <li>Type = Unsigned rational</li> 1918 * <li>Count = 1</li> 1919 * <li>Default = None</li> 1920 * </ul> 1921 */ 1922 public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing"; 1923 /** 1924 * <p>Indicates the unit used to express the distance to the destination point.</p> 1925 * 1926 * <ul> 1927 * <li>Tag = 25</li> 1928 * <li>Type = String</li> 1929 * <li>Length = 1</li> 1930 * <li>Default = {@link #GPS_DISTANCE_KILOMETERS}</li> 1931 * </ul> 1932 * 1933 * @see #GPS_DISTANCE_KILOMETERS 1934 * @see #GPS_DISTANCE_MILES 1935 * @see #GPS_DISTANCE_NAUTICAL_MILES 1936 */ 1937 public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef"; 1938 /** 1939 * <p>Indicates the distance to the destination point.</p> 1940 * 1941 * <ul> 1942 * <li>Tag = 26</li> 1943 * <li>Type = Unsigned rational</li> 1944 * <li>Count = 1</li> 1945 * <li>Default = None</li> 1946 * </ul> 1947 */ 1948 public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance"; 1949 /** 1950 * <p>A character string recording the name of the method used for location finding. 1951 * The first byte indicates the character code used, and this is followed by the name of 1952 * the method.</p> 1953 * 1954 * <ul> 1955 * <li>Tag = 27</li> 1956 * <li>Type = Undefined</li> 1957 * <li>Default = None</li> 1958 * </ul> 1959 */ 1960 public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod"; 1961 /** 1962 * <p>A character string recording the name of the GPS area. The first byte indicates 1963 * the character code used, and this is followed by the name of the GPS area.</p> 1964 * 1965 * <ul> 1966 * <li>Tag = 28</li> 1967 * <li>Type = Undefined</li> 1968 * <li>Default = None</li> 1969 * </ul> 1970 */ 1971 public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation"; 1972 /** 1973 * <p>A character string recording date and time information relative to UTC (Coordinated 1974 * Universal Time). The format is "YYYY:MM:DD".</p> 1975 * 1976 * <ul> 1977 * <li>Tag = 29</li> 1978 * <li>Type = String</li> 1979 * <li>Length = 10</li> 1980 * <li>Default = None</li> 1981 * </ul> 1982 */ 1983 public static final String TAG_GPS_DATESTAMP = "GPSDateStamp"; 1984 /** 1985 * <p>Indicates whether differential correction is applied to the GPS receiver.</p> 1986 * 1987 * <ul> 1988 * <li>Tag = 30</li> 1989 * <li>Type = Unsigned short</li> 1990 * <li>Count = 1</li> 1991 * <li>Default = None</li> 1992 * </ul> 1993 * 1994 * @see #GPS_MEASUREMENT_NO_DIFFERENTIAL 1995 * @see #GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED 1996 */ 1997 public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential"; 1998 /** 1999 * <p>This tag indicates horizontal positioning errors in meters.</p> 2000 * 2001 * <ul> 2002 * <li>Tag = 31</li> 2003 * <li>Type = Unsigned rational</li> 2004 * <li>Count = 1</li> 2005 * <li>Default = None</li> 2006 * </ul> 2007 */ 2008 public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError"; 2009 2010 // Interoperability IFD Attribute Information 2011 /** 2012 * <p>Indicates the identification of the Interoperability rule.</p> 2013 * 2014 * <ul> 2015 * <li>Tag = 1</li> 2016 * <li>Type = String</li> 2017 * <li>Length = 4</li> 2018 * <li>Default = None</li> 2019 * <ul> 2020 * <li>"R98" = Indicates a file conforming to R98 file specification of Recommended 2021 * Exif Interoperability Rules (Exif R 98) or to DCF basic file stipulated 2022 * by Design Rule for Camera File System.</li> 2023 * <li>"THM" = Indicates a file conforming to DCF thumbnail file stipulated by Design 2024 * rule for Camera File System.</li> 2025 * <li>“R03” = Indicates a file conforming to DCF Option File stipulated by Design rule 2026 * for Camera File System.</li> 2027 * </ul> 2028 * </ul> 2029 */ 2030 public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex"; 2031 2032 /** 2033 * @see #TAG_IMAGE_LENGTH 2034 */ 2035 public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength"; 2036 /** 2037 * @see #TAG_IMAGE_WIDTH 2038 */ 2039 public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth"; 2040 /** Type is int. DNG Specification 1.4.0.0. Section 4 */ 2041 public static final String TAG_DNG_VERSION = "DNGVersion"; 2042 /** Type is int. DNG Specification 1.4.0.0. Section 4 */ 2043 public static final String TAG_DEFAULT_CROP_SIZE = "DefaultCropSize"; 2044 /** Type is undefined. See Olympus MakerNote tags in http://www.exiv2.org/tags-olympus.html. */ 2045 public static final String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage"; 2046 /** Type is int. See Olympus Camera Settings tags in http://www.exiv2.org/tags-olympus.html. */ 2047 public static final String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart"; 2048 /** Type is int. See Olympus Camera Settings tags in http://www.exiv2.org/tags-olympus.html. */ 2049 public static final String TAG_ORF_PREVIEW_IMAGE_LENGTH = "PreviewImageLength"; 2050 /** Type is int. See Olympus Image Processing tags in http://www.exiv2.org/tags-olympus.html. */ 2051 public static final String TAG_ORF_ASPECT_FRAME = "AspectFrame"; 2052 /** 2053 * Type is int. See PanasonicRaw tags in 2054 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2055 */ 2056 public static final String TAG_RW2_SENSOR_BOTTOM_BORDER = "SensorBottomBorder"; 2057 /** 2058 * Type is int. See PanasonicRaw tags in 2059 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2060 */ 2061 public static final String TAG_RW2_SENSOR_LEFT_BORDER = "SensorLeftBorder"; 2062 /** 2063 * Type is int. See PanasonicRaw tags in 2064 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2065 */ 2066 public static final String TAG_RW2_SENSOR_RIGHT_BORDER = "SensorRightBorder"; 2067 /** 2068 * Type is int. See PanasonicRaw tags in 2069 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2070 */ 2071 public static final String TAG_RW2_SENSOR_TOP_BORDER = "SensorTopBorder"; 2072 /** 2073 * Type is int. See PanasonicRaw tags in 2074 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2075 */ 2076 public static final String TAG_RW2_ISO = "ISO"; 2077 /** 2078 * Type is undefined. See PanasonicRaw tags in 2079 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html 2080 */ 2081 public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw"; 2082 /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */ 2083 public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType"; 2084 /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */ 2085 public static final String TAG_SUBFILE_TYPE = "SubfileType"; 2086 2087 /** 2088 * Private tags used for pointing the other IFD offsets. 2089 * The types of the following tags are int. 2090 * See JEITA CP-3451C Section 4.6.3: Exif-specific IFD. 2091 * For SubIFD, see Note 1 of Adobe PageMaker® 6.0 TIFF Technical Notes. 2092 */ 2093 private static final String TAG_EXIF_IFD_POINTER = "ExifIFDPointer"; 2094 private static final String TAG_GPS_INFO_IFD_POINTER = "GPSInfoIFDPointer"; 2095 private static final String TAG_INTEROPERABILITY_IFD_POINTER = "InteroperabilityIFDPointer"; 2096 private static final String TAG_SUB_IFD_POINTER = "SubIFDPointer"; 2097 // Proprietary pointer tags used for ORF files. 2098 // See http://www.exiv2.org/tags-olympus.html 2099 private static final String TAG_ORF_CAMERA_SETTINGS_IFD_POINTER = "CameraSettingsIFDPointer"; 2100 private static final String TAG_ORF_IMAGE_PROCESSING_IFD_POINTER = "ImageProcessingIFDPointer"; 2101 2102 // Private tags used for thumbnail information. 2103 private static final String TAG_HAS_THUMBNAIL = "HasThumbnail"; 2104 private static final String TAG_THUMBNAIL_OFFSET = "ThumbnailOffset"; 2105 private static final String TAG_THUMBNAIL_LENGTH = "ThumbnailLength"; 2106 private static final String TAG_THUMBNAIL_DATA = "ThumbnailData"; 2107 private static final int MAX_THUMBNAIL_SIZE = 512; 2108 2109 // Constants used for the Orientation Exif tag. 2110 public static final int ORIENTATION_UNDEFINED = 0; 2111 public static final int ORIENTATION_NORMAL = 1; 2112 /** 2113 * Indicates the image is left right reversed mirror. 2114 */ 2115 public static final int ORIENTATION_FLIP_HORIZONTAL = 2; 2116 /** 2117 * Indicates the image is rotated by 180 degree clockwise. 2118 */ 2119 public static final int ORIENTATION_ROTATE_180 = 3; 2120 /** 2121 * Indicates the image is upside down mirror, it can also be represented by flip 2122 * horizontally firstly and rotate 180 degree clockwise. 2123 */ 2124 public static final int ORIENTATION_FLIP_VERTICAL = 4; 2125 /** 2126 * Indicates the image is flipped about top-left <--> bottom-right axis, it can also be 2127 * represented by flip horizontally firstly and rotate 270 degree clockwise. 2128 */ 2129 public static final int ORIENTATION_TRANSPOSE = 5; 2130 /** 2131 * Indicates the image is rotated by 90 degree clockwise. 2132 */ 2133 public static final int ORIENTATION_ROTATE_90 = 6; 2134 /** 2135 * Indicates the image is flipped about top-right <--> bottom-left axis, it can also be 2136 * represented by flip horizontally firstly and rotate 90 degree clockwise. 2137 */ 2138 public static final int ORIENTATION_TRANSVERSE = 7; 2139 /** 2140 * Indicates the image is rotated by 270 degree clockwise. 2141 */ 2142 public static final int ORIENTATION_ROTATE_270 = 8; 2143 private static final List<Integer> ROTATION_ORDER = Arrays.asList(ORIENTATION_NORMAL, 2144 ORIENTATION_ROTATE_90, ORIENTATION_ROTATE_180, ORIENTATION_ROTATE_270); 2145 private static final List<Integer> FLIPPED_ROTATION_ORDER = Arrays.asList( 2146 ORIENTATION_FLIP_HORIZONTAL, ORIENTATION_TRANSVERSE, ORIENTATION_FLIP_VERTICAL, 2147 ORIENTATION_TRANSPOSE); 2148 2149 /** 2150 * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Chunky format. 2151 */ 2152 public static final short FORMAT_CHUNKY = 1; 2153 /** 2154 * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Planar format. 2155 */ 2156 public static final short FORMAT_PLANAR = 2; 2157 2158 /** 2159 * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Centered positioning. 2160 */ 2161 public static final short Y_CB_CR_POSITIONING_CENTERED = 1; 2162 /** 2163 * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Co-sited positioning. 2164 */ 2165 public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; 2166 2167 /** 2168 * The contant used to denote resolution unit as inches. 2169 */ 2170 public static final short RESOLUTION_UNIT_INCHES = 2; 2171 /** 2172 * The contant used to denote resolution unit as centimeters. 2173 */ 2174 public static final short RESOLUTION_UNIT_CENTIMETERS = 3; 2175 2176 /** 2177 * The contant used by {@link #TAG_COLOR_SPACE} to denote sRGB color space. 2178 */ 2179 public static final int COLOR_SPACE_S_RGB = 1; 2180 /** 2181 * The contant used by {@link #TAG_COLOR_SPACE} to denote Uncalibrated. 2182 */ 2183 public static final int COLOR_SPACE_UNCALIBRATED = 65535; 2184 2185 /** 2186 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is not defined. 2187 */ 2188 public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; 2189 /** 2190 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Manual. 2191 */ 2192 public static final short EXPOSURE_PROGRAM_MANUAL = 1; 2193 /** 2194 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Normal. 2195 */ 2196 public static final short EXPOSURE_PROGRAM_NORMAL = 2; 2197 /** 2198 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is 2199 * Aperture priority. 2200 */ 2201 public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; 2202 /** 2203 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is 2204 * Shutter priority. 2205 */ 2206 public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; 2207 /** 2208 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Creative 2209 * program (biased toward depth of field). 2210 */ 2211 public static final short EXPOSURE_PROGRAM_CREATIVE = 5; 2212 /** 2213 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Action 2214 * program (biased toward fast shutter speed). 2215 */ 2216 public static final short EXPOSURE_PROGRAM_ACTION = 6; 2217 /** 2218 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Portrait mode 2219 * (for closeup photos with the background out of focus). 2220 */ 2221 public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; 2222 /** 2223 * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Landscape 2224 * mode (for landscape photos with the background in focus). 2225 */ 2226 public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; 2227 2228 /** 2229 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is unknown. 2230 */ 2231 public static final short SENSITIVITY_TYPE_UNKNOWN = 0; 2232 /** 2233 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard 2234 * output sensitivity (SOS). 2235 */ 2236 public static final short SENSITIVITY_TYPE_SOS = 1; 2237 /** 2238 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended 2239 * exposure index (REI). 2240 */ 2241 public static final short SENSITIVITY_TYPE_REI = 2; 2242 /** 2243 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is ISO speed. 2244 */ 2245 public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; 2246 /** 2247 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard 2248 * output sensitivity (SOS) and recommended exposure index (REI). 2249 */ 2250 public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; 2251 /** 2252 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard 2253 * output sensitivity (SOS) and ISO speed. 2254 */ 2255 public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; 2256 /** 2257 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended 2258 * exposure index (REI) and ISO speed. 2259 */ 2260 public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; 2261 /** 2262 * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard 2263 * output sensitivity (SOS) and recommended exposure index (REI) and ISO speed. 2264 */ 2265 public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; 2266 2267 /** 2268 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is unknown. 2269 */ 2270 public static final short METERING_MODE_UNKNOWN = 0; 2271 /** 2272 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Average. 2273 */ 2274 public static final short METERING_MODE_AVERAGE = 1; 2275 /** 2276 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is 2277 * CenterWeightedAverage. 2278 */ 2279 public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; 2280 /** 2281 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Spot. 2282 */ 2283 public static final short METERING_MODE_SPOT = 3; 2284 /** 2285 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is MultiSpot. 2286 */ 2287 public static final short METERING_MODE_MULTI_SPOT = 4; 2288 /** 2289 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Pattern. 2290 */ 2291 public static final short METERING_MODE_PATTERN = 5; 2292 /** 2293 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Partial. 2294 */ 2295 public static final short METERING_MODE_PARTIAL = 6; 2296 /** 2297 * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is other. 2298 */ 2299 public static final short METERING_MODE_OTHER = 255; 2300 2301 /** 2302 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is unknown. 2303 */ 2304 public static final short LIGHT_SOURCE_UNKNOWN = 0; 2305 /** 2306 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight. 2307 */ 2308 public static final short LIGHT_SOURCE_DAYLIGHT = 1; 2309 /** 2310 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fluorescent. 2311 */ 2312 public static final short LIGHT_SOURCE_FLUORESCENT = 2; 2313 /** 2314 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Tungsten 2315 * (incandescent light). 2316 */ 2317 public static final short LIGHT_SOURCE_TUNGSTEN = 3; 2318 /** 2319 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Flash. 2320 */ 2321 public static final short LIGHT_SOURCE_FLASH = 4; 2322 /** 2323 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fine weather. 2324 */ 2325 public static final short LIGHT_SOURCE_FINE_WEATHER = 9; 2326 /** 2327 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cloudy weather. 2328 */ 2329 public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; 2330 /** 2331 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Shade. 2332 */ 2333 public static final short LIGHT_SOURCE_SHADE = 11; 2334 /** 2335 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight fluorescent 2336 * (D 5700 - 7100K). 2337 */ 2338 public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; 2339 /** 2340 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Day white fluorescent 2341 * (N 4600 - 5500K). 2342 */ 2343 public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; 2344 /** 2345 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cool white 2346 * fluorescent (W 3800 - 4500K). 2347 */ 2348 public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; 2349 /** 2350 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is White fluorescent 2351 * (WW 3250 - 3800K). 2352 */ 2353 public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; 2354 /** 2355 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Warm white 2356 * fluorescent (L 2600 - 3250K). 2357 */ 2358 public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; 2359 /** 2360 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light A. 2361 */ 2362 public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; 2363 /** 2364 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light B. 2365 */ 2366 public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; 2367 /** 2368 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light C. 2369 */ 2370 public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; 2371 /** 2372 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D55. 2373 */ 2374 public static final short LIGHT_SOURCE_D55 = 20; 2375 /** 2376 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D65. 2377 */ 2378 public static final short LIGHT_SOURCE_D65 = 21; 2379 /** 2380 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D75. 2381 */ 2382 public static final short LIGHT_SOURCE_D75 = 22; 2383 /** 2384 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D50. 2385 */ 2386 public static final short LIGHT_SOURCE_D50 = 23; 2387 /** 2388 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is ISO studio tungsten. 2389 */ 2390 public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; 2391 /** 2392 * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is other. 2393 */ 2394 public static final short LIGHT_SOURCE_OTHER = 255; 2395 2396 /** 2397 * The flag used by {@link #TAG_FLASH} to indicate whether the flash is fired. 2398 */ 2399 public static final short FLAG_FLASH_FIRED = 0b0000_0001; 2400 /** 2401 * The flag used by {@link #TAG_FLASH} to indicate strobe return light is not detected. 2402 */ 2403 public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 0b0000_0100; 2404 /** 2405 * The flag used by {@link #TAG_FLASH} to indicate strobe return light is detected. 2406 */ 2407 public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 0b0000_0110; 2408 /** 2409 * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash 2410 * firing. 2411 * 2412 * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION 2413 * @see #FLAG_FLASH_MODE_AUTO 2414 */ 2415 public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 0b0000_1000; 2416 /** 2417 * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash 2418 * suppression. 2419 * 2420 * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING 2421 * @see #FLAG_FLASH_MODE_AUTO 2422 */ 2423 public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 0b0001_0000; 2424 /** 2425 * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Auto. 2426 * 2427 * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING 2428 * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION 2429 */ 2430 public static final short FLAG_FLASH_MODE_AUTO = 0b0001_1000; 2431 /** 2432 * The flag used by {@link #TAG_FLASH} to indicate no flash function is present. 2433 */ 2434 public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 0b0010_0000; 2435 /** 2436 * The flag used by {@link #TAG_FLASH} to indicate red-eye reduction is supported. 2437 */ 2438 public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 0b0100_0000; 2439 2440 /** 2441 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is not 2442 * defined. 2443 */ 2444 public static final short SENSOR_TYPE_NOT_DEFINED = 1; 2445 /** 2446 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is One-chip 2447 * color area sensor. 2448 */ 2449 public static final short SENSOR_TYPE_ONE_CHIP = 2; 2450 /** 2451 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Two-chip 2452 * color area sensor. 2453 */ 2454 public static final short SENSOR_TYPE_TWO_CHIP = 3; 2455 /** 2456 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Three-chip 2457 * color area sensor. 2458 */ 2459 public static final short SENSOR_TYPE_THREE_CHIP = 4; 2460 /** 2461 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color 2462 * sequential area sensor. 2463 */ 2464 public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; 2465 /** 2466 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Trilinear 2467 * sensor. 2468 */ 2469 public static final short SENSOR_TYPE_TRILINEAR = 7; 2470 /** 2471 * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color 2472 * sequential linear sensor. 2473 */ 2474 public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; 2475 2476 /** 2477 * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is other. 2478 */ 2479 public static final short FILE_SOURCE_OTHER = 0; 2480 /** 2481 * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of transparent 2482 * type. 2483 */ 2484 public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; 2485 /** 2486 * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of reflex type. 2487 */ 2488 public static final short FILE_SOURCE_REFLEX_SCANNER = 2; 2489 /** 2490 * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is DSC. 2491 */ 2492 public static final short FILE_SOURCE_DSC = 3; 2493 2494 /** 2495 * The contant used by {@link #TAG_SCENE_TYPE} to denote the scene is directly photographed. 2496 */ 2497 public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; 2498 2499 /** 2500 * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote no special processing is used. 2501 */ 2502 public static final short RENDERED_PROCESS_NORMAL = 0; 2503 /** 2504 * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote special processing is used. 2505 */ 2506 public static final short RENDERED_PROCESS_CUSTOM = 1; 2507 2508 /** 2509 * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto. 2510 */ 2511 public static final short EXPOSURE_MODE_AUTO = 0; 2512 /** 2513 * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Manual. 2514 */ 2515 public static final short EXPOSURE_MODE_MANUAL = 1; 2516 /** 2517 * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto bracket. 2518 */ 2519 public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; 2520 2521 /** 2522 * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto. 2523 * 2524 * @deprecated Use {@link #WHITE_BALANCE_AUTO} instead. 2525 */ 2526 @Deprecated public static final int WHITEBALANCE_AUTO = 0; 2527 /** 2528 * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual. 2529 * 2530 * @deprecated Use {@link #WHITE_BALANCE_MANUAL} instead. 2531 */ 2532 @Deprecated public static final int WHITEBALANCE_MANUAL = 1; 2533 /** 2534 * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto. 2535 */ 2536 public static final short WHITE_BALANCE_AUTO = 0; 2537 /** 2538 * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual. 2539 */ 2540 public static final short WHITE_BALANCE_MANUAL = 1; 2541 2542 /** 2543 * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is 2544 * Standard. 2545 */ 2546 public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; 2547 /** 2548 * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is 2549 * Landscape. 2550 */ 2551 public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; 2552 /** 2553 * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is 2554 * Portrait. 2555 */ 2556 public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; 2557 /** 2558 * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is Night 2559 * scene. 2560 */ 2561 public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; 2562 2563 /** 2564 * The contant used by {@link #TAG_GAIN_CONTROL} to denote none gain adjustment. 2565 */ 2566 public static final short GAIN_CONTROL_NONE = 0; 2567 /** 2568 * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain up. 2569 */ 2570 public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; 2571 /** 2572 * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain up. 2573 */ 2574 public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; 2575 /** 2576 * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain down. 2577 */ 2578 public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; 2579 /** 2580 * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain down. 2581 */ 2582 public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; 2583 2584 /** 2585 * The contant used by {@link #TAG_CONTRAST} to denote normal contrast. 2586 */ 2587 public static final short CONTRAST_NORMAL = 0; 2588 /** 2589 * The contant used by {@link #TAG_CONTRAST} to denote soft contrast. 2590 */ 2591 public static final short CONTRAST_SOFT = 1; 2592 /** 2593 * The contant used by {@link #TAG_CONTRAST} to denote hard contrast. 2594 */ 2595 public static final short CONTRAST_HARD = 2; 2596 2597 /** 2598 * The contant used by {@link #TAG_SATURATION} to denote normal saturation. 2599 */ 2600 public static final short SATURATION_NORMAL = 0; 2601 /** 2602 * The contant used by {@link #TAG_SATURATION} to denote low saturation. 2603 */ 2604 public static final short SATURATION_LOW = 0; 2605 /** 2606 * The contant used by {@link #TAG_SHARPNESS} to denote high saturation. 2607 */ 2608 public static final short SATURATION_HIGH = 0; 2609 2610 /** 2611 * The contant used by {@link #TAG_SHARPNESS} to denote normal sharpness. 2612 */ 2613 public static final short SHARPNESS_NORMAL = 0; 2614 /** 2615 * The contant used by {@link #TAG_SHARPNESS} to denote soft sharpness. 2616 */ 2617 public static final short SHARPNESS_SOFT = 1; 2618 /** 2619 * The contant used by {@link #TAG_SHARPNESS} to denote hard sharpness. 2620 */ 2621 public static final short SHARPNESS_HARD = 2; 2622 2623 /** 2624 * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range 2625 * is unknown. 2626 */ 2627 public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; 2628 /** 2629 * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range 2630 * is Macro. 2631 */ 2632 public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; 2633 /** 2634 * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range 2635 * is Close view. 2636 */ 2637 public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; 2638 /** 2639 * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range 2640 * is Distant view. 2641 */ 2642 public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; 2643 2644 /** 2645 * The contant used by GPS latitude-related tags to denote the latitude is North latitude. 2646 * 2647 * @see #TAG_GPS_LATITUDE_REF 2648 * @see #TAG_GPS_DEST_LATITUDE_REF 2649 */ 2650 public static final String LATITUDE_NORTH = "N"; 2651 /** 2652 * The contant used by GPS latitude-related tags to denote the latitude is South latitude. 2653 * 2654 * @see #TAG_GPS_LATITUDE_REF 2655 * @see #TAG_GPS_DEST_LATITUDE_REF 2656 */ 2657 public static final String LATITUDE_SOUTH = "S"; 2658 2659 /** 2660 * The contant used by GPS longitude-related tags to denote the longitude is East longitude. 2661 * 2662 * @see #TAG_GPS_LONGITUDE_REF 2663 * @see #TAG_GPS_DEST_LONGITUDE_REF 2664 */ 2665 public static final String LONGITUDE_EAST = "E"; 2666 /** 2667 * The contant used by GPS longitude-related tags to denote the longitude is West longitude. 2668 * 2669 * @see #TAG_GPS_LONGITUDE_REF 2670 * @see #TAG_GPS_DEST_LONGITUDE_REF 2671 */ 2672 public static final String LONGITUDE_WEST = "W"; 2673 2674 /** 2675 * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is above sea level. 2676 */ 2677 public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; 2678 /** 2679 * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is below sea level. 2680 */ 2681 public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; 2682 2683 /** 2684 * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is in progress. 2685 */ 2686 public static final String GPS_MEASUREMENT_IN_PROGRESS = "A"; 2687 /** 2688 * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is interrupted. 2689 */ 2690 public static final String GPS_MEASUREMENT_INTERRUPTED = "V"; 2691 2692 /** 2693 * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 2-dimensional. 2694 */ 2695 public static final String GPS_MEASUREMENT_2D = "2"; 2696 /** 2697 * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 3-dimensional. 2698 */ 2699 public static final String GPS_MEASUREMENT_3D = "3"; 2700 2701 /** 2702 * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is kilometers per 2703 * hour. 2704 */ 2705 public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K"; 2706 /** 2707 * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is miles per hour. 2708 */ 2709 public static final String GPS_SPEED_MILES_PER_HOUR = "M"; 2710 /** 2711 * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is knots. 2712 */ 2713 public static final String GPS_SPEED_KNOTS = "N"; 2714 2715 /** 2716 * The contant used by GPS attributes to denote the direction is true direction. 2717 */ 2718 public static final String GPS_DIRECTION_TRUE = "T"; 2719 /** 2720 * The contant used by GPS attributes to denote the direction is magnetic direction. 2721 */ 2722 public static final String GPS_DIRECTION_MAGNETIC = "M"; 2723 2724 /** 2725 * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is 2726 * kilometers. 2727 */ 2728 public static final String GPS_DISTANCE_KILOMETERS = "K"; 2729 /** 2730 * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is miles. 2731 */ 2732 public static final String GPS_DISTANCE_MILES = "M"; 2733 /** 2734 * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is 2735 * nautical miles. 2736 */ 2737 public static final String GPS_DISTANCE_NAUTICAL_MILES = "N"; 2738 2739 /** 2740 * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote no differential correction is 2741 * applied. 2742 */ 2743 public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; 2744 /** 2745 * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote differential correction is 2746 * applied. 2747 */ 2748 public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; 2749 2750 /** 2751 * The constant used by {@link #TAG_COMPRESSION} to denote the image is not compressed. 2752 */ 2753 public static final int DATA_UNCOMPRESSED = 1; 2754 /** 2755 * The constant used by {@link #TAG_COMPRESSION} to denote the image is huffman compressed. 2756 */ 2757 public static final int DATA_HUFFMAN_COMPRESSED = 2; 2758 /** 2759 * The constant used by {@link #TAG_COMPRESSION} to denote the image is JPEG. 2760 */ 2761 public static final int DATA_JPEG = 6; 2762 /** 2763 * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0. 2764 * Section 3, Compression 2765 */ 2766 public static final int DATA_JPEG_COMPRESSED = 7; 2767 /** 2768 * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0. 2769 * Section 3, Compression 2770 */ 2771 public static final int DATA_DEFLATE_ZIP = 8; 2772 /** 2773 * The constant used by {@link #TAG_COMPRESSION} to denote the image is pack-bits compressed. 2774 */ 2775 public static final int DATA_PACK_BITS_COMPRESSED = 32773; 2776 /** 2777 * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0. 2778 * Section 3, Compression 2779 */ 2780 public static final int DATA_LOSSY_JPEG = 34892; 2781 2782 /** 2783 * The constant used by {@link #TAG_BITS_PER_SAMPLE}. 2784 * See JEITA CP-3451C Spec Section 6, Differences from Palette Color Images 2785 */ 2786 public static final int[] BITS_PER_SAMPLE_RGB = new int[] { 8, 8, 8 }; 2787 /** 2788 * The constant used by {@link #TAG_BITS_PER_SAMPLE}. 2789 * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images 2790 */ 2791 public static final int[] BITS_PER_SAMPLE_GREYSCALE_1 = new int[] { 4 }; 2792 /** 2793 * The constant used by {@link #TAG_BITS_PER_SAMPLE}. 2794 * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images 2795 */ 2796 public static final int[] BITS_PER_SAMPLE_GREYSCALE_2 = new int[] { 8 }; 2797 2798 /** 2799 * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}. 2800 */ 2801 public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; 2802 /** 2803 * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}. 2804 */ 2805 public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; 2806 /** 2807 * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}. 2808 */ 2809 public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; 2810 /** 2811 * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}. 2812 */ 2813 public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; 2814 2815 /** 2816 * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8. 2817 */ 2818 public static final int ORIGINAL_RESOLUTION_IMAGE = 0; 2819 /** 2820 * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8. 2821 */ 2822 public static final int REDUCED_RESOLUTION_IMAGE = 1; 2823 2824 // Maximum size for checking file type signature (see image_type_recognition_lite.cc) 2825 private static final int SIGNATURE_CHECK_SIZE = 5000; 2826 2827 static final byte[] JPEG_SIGNATURE = new byte[] {(byte) 0xff, (byte) 0xd8, (byte) 0xff}; 2828 private static final String RAF_SIGNATURE = "FUJIFILMCCD-RAW"; 2829 private static final int RAF_OFFSET_TO_JPEG_IMAGE_OFFSET = 84; 2830 private static final int RAF_INFO_SIZE = 160; 2831 private static final int RAF_JPEG_LENGTH_VALUE_SIZE = 4; 2832 2833 // See http://fileformats.archiveteam.org/wiki/Olympus_ORF 2834 private static final short ORF_SIGNATURE_1 = 0x4f52; 2835 private static final short ORF_SIGNATURE_2 = 0x5352; 2836 // There are two formats for Olympus Makernote Headers. Each has different identifiers and 2837 // offsets to the actual data. 2838 // See http://www.exiv2.org/makernote.html#R1 2839 private static final byte[] ORF_MAKER_NOTE_HEADER_1 = new byte[] {(byte) 0x4f, (byte) 0x4c, 2840 (byte) 0x59, (byte) 0x4d, (byte) 0x50, (byte) 0x00}; // "OLYMP\0" 2841 private static final byte[] ORF_MAKER_NOTE_HEADER_2 = new byte[] {(byte) 0x4f, (byte) 0x4c, 2842 (byte) 0x59, (byte) 0x4d, (byte) 0x50, (byte) 0x55, (byte) 0x53, (byte) 0x00, 2843 (byte) 0x49, (byte) 0x49}; // "OLYMPUS\0II" 2844 private static final int ORF_MAKER_NOTE_HEADER_1_SIZE = 8; 2845 private static final int ORF_MAKER_NOTE_HEADER_2_SIZE = 12; 2846 2847 // See http://fileformats.archiveteam.org/wiki/RW2 2848 private static final short RW2_SIGNATURE = 0x0055; 2849 2850 // See http://fileformats.archiveteam.org/wiki/Pentax_PEF 2851 private static final String PEF_SIGNATURE = "PENTAX"; 2852 // See http://www.exiv2.org/makernote.html#R11 2853 private static final int PEF_MAKER_NOTE_SKIP_SIZE = 6; 2854 2855 private static SimpleDateFormat sFormatter; 2856 2857 // See Exchangeable image file format for digital still cameras: Exif version 2.2. 2858 // The following values are for parsing EXIF data area. There are tag groups in EXIF data area. 2859 // They are called "Image File Directory". They have multiple data formats to cover various 2860 // image metadata from GPS longitude to camera model name. 2861 2862 // Types of Exif byte alignments (see JEITA CP-3451C Section 4.5.2) 2863 static final short BYTE_ALIGN_II = 0x4949; // II: Intel order 2864 static final short BYTE_ALIGN_MM = 0x4d4d; // MM: Motorola order 2865 2866 // TIFF Header Fixed Constant (see JEITA CP-3451C Section 4.5.2) 2867 static final byte START_CODE = 0x2a; // 42 2868 private static final int IFD_OFFSET = 8; 2869 2870 // Formats for the value in IFD entry (See TIFF 6.0 Section 2, "Image File Directory".) 2871 private static final int IFD_FORMAT_BYTE = 1; 2872 private static final int IFD_FORMAT_STRING = 2; 2873 private static final int IFD_FORMAT_USHORT = 3; 2874 private static final int IFD_FORMAT_ULONG = 4; 2875 private static final int IFD_FORMAT_URATIONAL = 5; 2876 private static final int IFD_FORMAT_SBYTE = 6; 2877 private static final int IFD_FORMAT_UNDEFINED = 7; 2878 private static final int IFD_FORMAT_SSHORT = 8; 2879 private static final int IFD_FORMAT_SLONG = 9; 2880 private static final int IFD_FORMAT_SRATIONAL = 10; 2881 private static final int IFD_FORMAT_SINGLE = 11; 2882 private static final int IFD_FORMAT_DOUBLE = 12; 2883 // Format indicating a new IFD entry (See Adobe PageMaker® 6.0 TIFF Technical Notes, "New Tag") 2884 private static final int IFD_FORMAT_IFD = 13; 2885 // Names for the data formats for debugging purpose. 2886 static final String[] IFD_FORMAT_NAMES = new String[] { 2887 "", "BYTE", "STRING", "USHORT", "ULONG", "URATIONAL", "SBYTE", "UNDEFINED", "SSHORT", 2888 "SLONG", "SRATIONAL", "SINGLE", "DOUBLE" 2889 }; 2890 // Sizes of the components of each IFD value format 2891 static final int[] IFD_FORMAT_BYTES_PER_FORMAT = new int[] { 2892 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1 2893 }; 2894 private static final byte[] EXIF_ASCII_PREFIX = new byte[] { 2895 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 2896 }; 2897 2898 // A class for indicating EXIF rational type. 2899 private static class Rational { 2900 public final long numerator; 2901 public final long denominator; 2902 2903 private Rational(double value) { 2904 this((long) (value * 10000), 10000); 2905 } 2906 2907 private Rational(long numerator, long denominator) { 2908 // Handle erroneous case 2909 if (denominator == 0) { 2910 this.numerator = 0; 2911 this.denominator = 1; 2912 return; 2913 } 2914 this.numerator = numerator; 2915 this.denominator = denominator; 2916 } 2917 2918 @Override 2919 public String toString() { 2920 return numerator + "/" + denominator; 2921 } 2922 2923 public double calculate() { 2924 return (double) numerator / denominator; 2925 } 2926 } 2927 2928 // A class for indicating EXIF attribute. 2929 private static class ExifAttribute { 2930 public final int format; 2931 public final int numberOfComponents; 2932 public final byte[] bytes; 2933 2934 private ExifAttribute(int format, int numberOfComponents, byte[] bytes) { 2935 this.format = format; 2936 this.numberOfComponents = numberOfComponents; 2937 this.bytes = bytes; 2938 } 2939 2940 public static ExifAttribute createUShort(int[] values, ByteOrder byteOrder) { 2941 final ByteBuffer buffer = ByteBuffer.wrap( 2942 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_USHORT] * values.length]); 2943 buffer.order(byteOrder); 2944 for (int value : values) { 2945 buffer.putShort((short) value); 2946 } 2947 return new ExifAttribute(IFD_FORMAT_USHORT, values.length, buffer.array()); 2948 } 2949 2950 public static ExifAttribute createUShort(int value, ByteOrder byteOrder) { 2951 return createUShort(new int[] {value}, byteOrder); 2952 } 2953 2954 public static ExifAttribute createULong(long[] values, ByteOrder byteOrder) { 2955 final ByteBuffer buffer = ByteBuffer.wrap( 2956 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_ULONG] * values.length]); 2957 buffer.order(byteOrder); 2958 for (long value : values) { 2959 buffer.putInt((int) value); 2960 } 2961 return new ExifAttribute(IFD_FORMAT_ULONG, values.length, buffer.array()); 2962 } 2963 2964 public static ExifAttribute createULong(long value, ByteOrder byteOrder) { 2965 return createULong(new long[] {value}, byteOrder); 2966 } 2967 2968 public static ExifAttribute createSLong(int[] values, ByteOrder byteOrder) { 2969 final ByteBuffer buffer = ByteBuffer.wrap( 2970 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_SLONG] * values.length]); 2971 buffer.order(byteOrder); 2972 for (int value : values) { 2973 buffer.putInt(value); 2974 } 2975 return new ExifAttribute(IFD_FORMAT_SLONG, values.length, buffer.array()); 2976 } 2977 2978 public static ExifAttribute createSLong(int value, ByteOrder byteOrder) { 2979 return createSLong(new int[] {value}, byteOrder); 2980 } 2981 2982 public static ExifAttribute createByte(String value) { 2983 // Exception for GPSAltitudeRef tag 2984 if (value.length() == 1 && value.charAt(0) >= '0' && value.charAt(0) <= '1') { 2985 final byte[] bytes = new byte[] { (byte) (value.charAt(0) - '0') }; 2986 return new ExifAttribute(IFD_FORMAT_BYTE, bytes.length, bytes); 2987 } 2988 final byte[] ascii = value.getBytes(ASCII); 2989 return new ExifAttribute(IFD_FORMAT_BYTE, ascii.length, ascii); 2990 } 2991 2992 public static ExifAttribute createString(String value) { 2993 final byte[] ascii = (value + '\0').getBytes(ASCII); 2994 return new ExifAttribute(IFD_FORMAT_STRING, ascii.length, ascii); 2995 } 2996 2997 public static ExifAttribute createURational(Rational[] values, ByteOrder byteOrder) { 2998 final ByteBuffer buffer = ByteBuffer.wrap( 2999 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_URATIONAL] * values.length]); 3000 buffer.order(byteOrder); 3001 for (Rational value : values) { 3002 buffer.putInt((int) value.numerator); 3003 buffer.putInt((int) value.denominator); 3004 } 3005 return new ExifAttribute(IFD_FORMAT_URATIONAL, values.length, buffer.array()); 3006 } 3007 3008 public static ExifAttribute createURational(Rational value, ByteOrder byteOrder) { 3009 return createURational(new Rational[] {value}, byteOrder); 3010 } 3011 3012 public static ExifAttribute createSRational(Rational[] values, ByteOrder byteOrder) { 3013 final ByteBuffer buffer = ByteBuffer.wrap( 3014 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_SRATIONAL] * values.length]); 3015 buffer.order(byteOrder); 3016 for (Rational value : values) { 3017 buffer.putInt((int) value.numerator); 3018 buffer.putInt((int) value.denominator); 3019 } 3020 return new ExifAttribute(IFD_FORMAT_SRATIONAL, values.length, buffer.array()); 3021 } 3022 3023 public static ExifAttribute createSRational(Rational value, ByteOrder byteOrder) { 3024 return createSRational(new Rational[] {value}, byteOrder); 3025 } 3026 3027 public static ExifAttribute createDouble(double[] values, ByteOrder byteOrder) { 3028 final ByteBuffer buffer = ByteBuffer.wrap( 3029 new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_DOUBLE] * values.length]); 3030 buffer.order(byteOrder); 3031 for (double value : values) { 3032 buffer.putDouble(value); 3033 } 3034 return new ExifAttribute(IFD_FORMAT_DOUBLE, values.length, buffer.array()); 3035 } 3036 3037 public static ExifAttribute createDouble(double value, ByteOrder byteOrder) { 3038 return createDouble(new double[] {value}, byteOrder); 3039 } 3040 3041 @Override 3042 public String toString() { 3043 return "(" + IFD_FORMAT_NAMES[format] + ", data length:" + bytes.length + ")"; 3044 } 3045 3046 private Object getValue(ByteOrder byteOrder) { 3047 ByteOrderedDataInputStream inputStream = null; 3048 try { 3049 inputStream = new ByteOrderedDataInputStream(bytes); 3050 inputStream.setByteOrder(byteOrder); 3051 switch (format) { 3052 case IFD_FORMAT_BYTE: 3053 case IFD_FORMAT_SBYTE: { 3054 // Exception for GPSAltitudeRef tag 3055 if (bytes.length == 1 && bytes[0] >= 0 && bytes[0] <= 1) { 3056 return new String(new char[] { (char) (bytes[0] + '0') }); 3057 } 3058 return new String(bytes, ASCII); 3059 } 3060 case IFD_FORMAT_UNDEFINED: 3061 case IFD_FORMAT_STRING: { 3062 int index = 0; 3063 if (numberOfComponents >= EXIF_ASCII_PREFIX.length) { 3064 boolean same = true; 3065 for (int i = 0; i < EXIF_ASCII_PREFIX.length; ++i) { 3066 if (bytes[i] != EXIF_ASCII_PREFIX[i]) { 3067 same = false; 3068 break; 3069 } 3070 } 3071 if (same) { 3072 index = EXIF_ASCII_PREFIX.length; 3073 } 3074 } 3075 3076 StringBuilder stringBuilder = new StringBuilder(); 3077 while (index < numberOfComponents) { 3078 int ch = bytes[index]; 3079 if (ch == 0) { 3080 break; 3081 } 3082 if (ch >= 32) { 3083 stringBuilder.append((char) ch); 3084 } else { 3085 stringBuilder.append('?'); 3086 } 3087 ++index; 3088 } 3089 return stringBuilder.toString(); 3090 } 3091 case IFD_FORMAT_USHORT: { 3092 final int[] values = new int[numberOfComponents]; 3093 for (int i = 0; i < numberOfComponents; ++i) { 3094 values[i] = inputStream.readUnsignedShort(); 3095 } 3096 return values; 3097 } 3098 case IFD_FORMAT_ULONG: { 3099 final long[] values = new long[numberOfComponents]; 3100 for (int i = 0; i < numberOfComponents; ++i) { 3101 values[i] = inputStream.readUnsignedInt(); 3102 } 3103 return values; 3104 } 3105 case IFD_FORMAT_URATIONAL: { 3106 final Rational[] values = new Rational[numberOfComponents]; 3107 for (int i = 0; i < numberOfComponents; ++i) { 3108 final long numerator = inputStream.readUnsignedInt(); 3109 final long denominator = inputStream.readUnsignedInt(); 3110 values[i] = new Rational(numerator, denominator); 3111 } 3112 return values; 3113 } 3114 case IFD_FORMAT_SSHORT: { 3115 final int[] values = new int[numberOfComponents]; 3116 for (int i = 0; i < numberOfComponents; ++i) { 3117 values[i] = inputStream.readShort(); 3118 } 3119 return values; 3120 } 3121 case IFD_FORMAT_SLONG: { 3122 final int[] values = new int[numberOfComponents]; 3123 for (int i = 0; i < numberOfComponents; ++i) { 3124 values[i] = inputStream.readInt(); 3125 } 3126 return values; 3127 } 3128 case IFD_FORMAT_SRATIONAL: { 3129 final Rational[] values = new Rational[numberOfComponents]; 3130 for (int i = 0; i < numberOfComponents; ++i) { 3131 final long numerator = inputStream.readInt(); 3132 final long denominator = inputStream.readInt(); 3133 values[i] = new Rational(numerator, denominator); 3134 } 3135 return values; 3136 } 3137 case IFD_FORMAT_SINGLE: { 3138 final double[] values = new double[numberOfComponents]; 3139 for (int i = 0; i < numberOfComponents; ++i) { 3140 values[i] = inputStream.readFloat(); 3141 } 3142 return values; 3143 } 3144 case IFD_FORMAT_DOUBLE: { 3145 final double[] values = new double[numberOfComponents]; 3146 for (int i = 0; i < numberOfComponents; ++i) { 3147 values[i] = inputStream.readDouble(); 3148 } 3149 return values; 3150 } 3151 default: 3152 return null; 3153 } 3154 } catch (IOException e) { 3155 Log.w(TAG, "IOException occurred during reading a value", e); 3156 return null; 3157 } finally { 3158 if (inputStream != null) { 3159 try { 3160 inputStream.close(); 3161 } catch (IOException e) { 3162 Log.e(TAG, "IOException occurred while closing InputStream", e); 3163 } 3164 } 3165 } 3166 } 3167 3168 public double getDoubleValue(ByteOrder byteOrder) { 3169 Object value = getValue(byteOrder); 3170 if (value == null) { 3171 throw new NumberFormatException("NULL can't be converted to a double value"); 3172 } 3173 if (value instanceof String) { 3174 return Double.parseDouble((String) value); 3175 } 3176 if (value instanceof long[]) { 3177 long[] array = (long[]) value; 3178 if (array.length == 1) { 3179 return array[0]; 3180 } 3181 throw new NumberFormatException("There are more than one component"); 3182 } 3183 if (value instanceof int[]) { 3184 int[] array = (int[]) value; 3185 if (array.length == 1) { 3186 return array[0]; 3187 } 3188 throw new NumberFormatException("There are more than one component"); 3189 } 3190 if (value instanceof double[]) { 3191 double[] array = (double[]) value; 3192 if (array.length == 1) { 3193 return array[0]; 3194 } 3195 throw new NumberFormatException("There are more than one component"); 3196 } 3197 if (value instanceof Rational[]) { 3198 Rational[] array = (Rational[]) value; 3199 if (array.length == 1) { 3200 return array[0].calculate(); 3201 } 3202 throw new NumberFormatException("There are more than one component"); 3203 } 3204 throw new NumberFormatException("Couldn't find a double value"); 3205 } 3206 3207 public int getIntValue(ByteOrder byteOrder) { 3208 Object value = getValue(byteOrder); 3209 if (value == null) { 3210 throw new NumberFormatException("NULL can't be converted to a integer value"); 3211 } 3212 if (value instanceof String) { 3213 return Integer.parseInt((String) value); 3214 } 3215 if (value instanceof long[]) { 3216 long[] array = (long[]) value; 3217 if (array.length == 1) { 3218 return (int) array[0]; 3219 } 3220 throw new NumberFormatException("There are more than one component"); 3221 } 3222 if (value instanceof int[]) { 3223 int[] array = (int[]) value; 3224 if (array.length == 1) { 3225 return array[0]; 3226 } 3227 throw new NumberFormatException("There are more than one component"); 3228 } 3229 throw new NumberFormatException("Couldn't find a integer value"); 3230 } 3231 3232 public String getStringValue(ByteOrder byteOrder) { 3233 Object value = getValue(byteOrder); 3234 if (value == null) { 3235 return null; 3236 } 3237 if (value instanceof String) { 3238 return (String) value; 3239 } 3240 3241 final StringBuilder stringBuilder = new StringBuilder(); 3242 if (value instanceof long[]) { 3243 long[] array = (long[]) value; 3244 for (int i = 0; i < array.length; ++i) { 3245 stringBuilder.append(array[i]); 3246 if (i + 1 != array.length) { 3247 stringBuilder.append(","); 3248 } 3249 } 3250 return stringBuilder.toString(); 3251 } 3252 if (value instanceof int[]) { 3253 int[] array = (int[]) value; 3254 for (int i = 0; i < array.length; ++i) { 3255 stringBuilder.append(array[i]); 3256 if (i + 1 != array.length) { 3257 stringBuilder.append(","); 3258 } 3259 } 3260 return stringBuilder.toString(); 3261 } 3262 if (value instanceof double[]) { 3263 double[] array = (double[]) value; 3264 for (int i = 0; i < array.length; ++i) { 3265 stringBuilder.append(array[i]); 3266 if (i + 1 != array.length) { 3267 stringBuilder.append(","); 3268 } 3269 } 3270 return stringBuilder.toString(); 3271 } 3272 if (value instanceof Rational[]) { 3273 Rational[] array = (Rational[]) value; 3274 for (int i = 0; i < array.length; ++i) { 3275 stringBuilder.append(array[i].numerator); 3276 stringBuilder.append('/'); 3277 stringBuilder.append(array[i].denominator); 3278 if (i + 1 != array.length) { 3279 stringBuilder.append(","); 3280 } 3281 } 3282 return stringBuilder.toString(); 3283 } 3284 return null; 3285 } 3286 3287 public int size() { 3288 return IFD_FORMAT_BYTES_PER_FORMAT[format] * numberOfComponents; 3289 } 3290 } 3291 3292 // A class for indicating EXIF tag. 3293 static class ExifTag { 3294 public final int number; 3295 public final String name; 3296 public final int primaryFormat; 3297 public final int secondaryFormat; 3298 3299 private ExifTag(String name, int number, int format) { 3300 this.name = name; 3301 this.number = number; 3302 this.primaryFormat = format; 3303 this.secondaryFormat = -1; 3304 } 3305 3306 private ExifTag(String name, int number, int primaryFormat, int secondaryFormat) { 3307 this.name = name; 3308 this.number = number; 3309 this.primaryFormat = primaryFormat; 3310 this.secondaryFormat = secondaryFormat; 3311 } 3312 3313 private boolean isFormatCompatible(int format) { 3314 if (primaryFormat == IFD_FORMAT_UNDEFINED || format == IFD_FORMAT_UNDEFINED) { 3315 return true; 3316 } else if (primaryFormat == format || secondaryFormat == format) { 3317 return true; 3318 } else if ((primaryFormat == IFD_FORMAT_ULONG || secondaryFormat == IFD_FORMAT_ULONG) 3319 && format == IFD_FORMAT_USHORT) { 3320 return true; 3321 } else if ((primaryFormat == IFD_FORMAT_SLONG || secondaryFormat == IFD_FORMAT_SLONG) 3322 && format == IFD_FORMAT_SSHORT) { 3323 return true; 3324 } else if ((primaryFormat == IFD_FORMAT_DOUBLE || secondaryFormat == IFD_FORMAT_DOUBLE) 3325 && format == IFD_FORMAT_SINGLE) { 3326 return true; 3327 } 3328 return false; 3329 } 3330 } 3331 3332 // Primary image IFD TIFF tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels) 3333 private static final ExifTag[] IFD_TIFF_TAGS = new ExifTag[] { 3334 // For below two, see TIFF 6.0 Spec Section 3: Bilevel Images. 3335 new ExifTag(TAG_NEW_SUBFILE_TYPE, 254, IFD_FORMAT_ULONG), 3336 new ExifTag(TAG_SUBFILE_TYPE, 255, IFD_FORMAT_ULONG), 3337 new ExifTag(TAG_IMAGE_WIDTH, 256, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3338 new ExifTag(TAG_IMAGE_LENGTH, 257, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3339 new ExifTag(TAG_BITS_PER_SAMPLE, 258, IFD_FORMAT_USHORT), 3340 new ExifTag(TAG_COMPRESSION, 259, IFD_FORMAT_USHORT), 3341 new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262, IFD_FORMAT_USHORT), 3342 new ExifTag(TAG_IMAGE_DESCRIPTION, 270, IFD_FORMAT_STRING), 3343 new ExifTag(TAG_MAKE, 271, IFD_FORMAT_STRING), 3344 new ExifTag(TAG_MODEL, 272, IFD_FORMAT_STRING), 3345 new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3346 new ExifTag(TAG_ORIENTATION, 274, IFD_FORMAT_USHORT), 3347 new ExifTag(TAG_SAMPLES_PER_PIXEL, 277, IFD_FORMAT_USHORT), 3348 new ExifTag(TAG_ROWS_PER_STRIP, 278, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3349 new ExifTag(TAG_STRIP_BYTE_COUNTS, 279, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3350 new ExifTag(TAG_X_RESOLUTION, 282, IFD_FORMAT_URATIONAL), 3351 new ExifTag(TAG_Y_RESOLUTION, 283, IFD_FORMAT_URATIONAL), 3352 new ExifTag(TAG_PLANAR_CONFIGURATION, 284, IFD_FORMAT_USHORT), 3353 new ExifTag(TAG_RESOLUTION_UNIT, 296, IFD_FORMAT_USHORT), 3354 new ExifTag(TAG_TRANSFER_FUNCTION, 301, IFD_FORMAT_USHORT), 3355 new ExifTag(TAG_SOFTWARE, 305, IFD_FORMAT_STRING), 3356 new ExifTag(TAG_DATETIME, 306, IFD_FORMAT_STRING), 3357 new ExifTag(TAG_ARTIST, 315, IFD_FORMAT_STRING), 3358 new ExifTag(TAG_WHITE_POINT, 318, IFD_FORMAT_URATIONAL), 3359 new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319, IFD_FORMAT_URATIONAL), 3360 // See Adobe PageMaker® 6.0 TIFF Technical Notes, Note 1. 3361 new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG), 3362 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG), 3363 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG), 3364 new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529, IFD_FORMAT_URATIONAL), 3365 new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530, IFD_FORMAT_USHORT), 3366 new ExifTag(TAG_Y_CB_CR_POSITIONING, 531, IFD_FORMAT_USHORT), 3367 new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532, IFD_FORMAT_URATIONAL), 3368 new ExifTag(TAG_COPYRIGHT, 33432, IFD_FORMAT_STRING), 3369 new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG), 3370 new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG), 3371 // RW2 file tags 3372 // See http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html) 3373 new ExifTag(TAG_RW2_SENSOR_TOP_BORDER, 4, IFD_FORMAT_ULONG), 3374 new ExifTag(TAG_RW2_SENSOR_LEFT_BORDER, 5, IFD_FORMAT_ULONG), 3375 new ExifTag(TAG_RW2_SENSOR_BOTTOM_BORDER, 6, IFD_FORMAT_ULONG), 3376 new ExifTag(TAG_RW2_SENSOR_RIGHT_BORDER, 7, IFD_FORMAT_ULONG), 3377 new ExifTag(TAG_RW2_ISO, 23, IFD_FORMAT_USHORT), 3378 new ExifTag(TAG_RW2_JPG_FROM_RAW, 46, IFD_FORMAT_UNDEFINED) 3379 }; 3380 3381 // Primary image IFD Exif Private tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels) 3382 private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] { 3383 new ExifTag(TAG_EXPOSURE_TIME, 33434, IFD_FORMAT_URATIONAL), 3384 new ExifTag(TAG_F_NUMBER, 33437, IFD_FORMAT_URATIONAL), 3385 new ExifTag(TAG_EXPOSURE_PROGRAM, 34850, IFD_FORMAT_USHORT), 3386 new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852, IFD_FORMAT_STRING), 3387 new ExifTag(TAG_PHOTOGRAPHIC_SENSITIVITY, 34855, IFD_FORMAT_USHORT), 3388 new ExifTag(TAG_OECF, 34856, IFD_FORMAT_UNDEFINED), 3389 new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING), 3390 new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING), 3391 new ExifTag(TAG_DATETIME_DIGITIZED, 36868, IFD_FORMAT_STRING), 3392 new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121, IFD_FORMAT_UNDEFINED), 3393 new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122, IFD_FORMAT_URATIONAL), 3394 new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377, IFD_FORMAT_SRATIONAL), 3395 new ExifTag(TAG_APERTURE_VALUE, 37378, IFD_FORMAT_URATIONAL), 3396 new ExifTag(TAG_BRIGHTNESS_VALUE, 37379, IFD_FORMAT_SRATIONAL), 3397 new ExifTag(TAG_EXPOSURE_BIAS_VALUE, 37380, IFD_FORMAT_SRATIONAL), 3398 new ExifTag(TAG_MAX_APERTURE_VALUE, 37381, IFD_FORMAT_URATIONAL), 3399 new ExifTag(TAG_SUBJECT_DISTANCE, 37382, IFD_FORMAT_URATIONAL), 3400 new ExifTag(TAG_METERING_MODE, 37383, IFD_FORMAT_USHORT), 3401 new ExifTag(TAG_LIGHT_SOURCE, 37384, IFD_FORMAT_USHORT), 3402 new ExifTag(TAG_FLASH, 37385, IFD_FORMAT_USHORT), 3403 new ExifTag(TAG_FOCAL_LENGTH, 37386, IFD_FORMAT_URATIONAL), 3404 new ExifTag(TAG_SUBJECT_AREA, 37396, IFD_FORMAT_USHORT), 3405 new ExifTag(TAG_MAKER_NOTE, 37500, IFD_FORMAT_UNDEFINED), 3406 new ExifTag(TAG_USER_COMMENT, 37510, IFD_FORMAT_UNDEFINED), 3407 new ExifTag(TAG_SUBSEC_TIME, 37520, IFD_FORMAT_STRING), 3408 new ExifTag(TAG_SUBSEC_TIME_ORIGINAL, 37521, IFD_FORMAT_STRING), 3409 new ExifTag(TAG_SUBSEC_TIME_DIGITIZED, 37522, IFD_FORMAT_STRING), 3410 new ExifTag(TAG_FLASHPIX_VERSION, 40960, IFD_FORMAT_UNDEFINED), 3411 new ExifTag(TAG_COLOR_SPACE, 40961, IFD_FORMAT_USHORT), 3412 new ExifTag(TAG_PIXEL_X_DIMENSION, 40962, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3413 new ExifTag(TAG_PIXEL_Y_DIMENSION, 40963, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3414 new ExifTag(TAG_RELATED_SOUND_FILE, 40964, IFD_FORMAT_STRING), 3415 new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965, IFD_FORMAT_ULONG), 3416 new ExifTag(TAG_FLASH_ENERGY, 41483, IFD_FORMAT_URATIONAL), 3417 new ExifTag(TAG_SPATIAL_FREQUENCY_RESPONSE, 41484, IFD_FORMAT_UNDEFINED), 3418 new ExifTag(TAG_FOCAL_PLANE_X_RESOLUTION, 41486, IFD_FORMAT_URATIONAL), 3419 new ExifTag(TAG_FOCAL_PLANE_Y_RESOLUTION, 41487, IFD_FORMAT_URATIONAL), 3420 new ExifTag(TAG_FOCAL_PLANE_RESOLUTION_UNIT, 41488, IFD_FORMAT_USHORT), 3421 new ExifTag(TAG_SUBJECT_LOCATION, 41492, IFD_FORMAT_USHORT), 3422 new ExifTag(TAG_EXPOSURE_INDEX, 41493, IFD_FORMAT_URATIONAL), 3423 new ExifTag(TAG_SENSING_METHOD, 41495, IFD_FORMAT_USHORT), 3424 new ExifTag(TAG_FILE_SOURCE, 41728, IFD_FORMAT_UNDEFINED), 3425 new ExifTag(TAG_SCENE_TYPE, 41729, IFD_FORMAT_UNDEFINED), 3426 new ExifTag(TAG_CFA_PATTERN, 41730, IFD_FORMAT_UNDEFINED), 3427 new ExifTag(TAG_CUSTOM_RENDERED, 41985, IFD_FORMAT_USHORT), 3428 new ExifTag(TAG_EXPOSURE_MODE, 41986, IFD_FORMAT_USHORT), 3429 new ExifTag(TAG_WHITE_BALANCE, 41987, IFD_FORMAT_USHORT), 3430 new ExifTag(TAG_DIGITAL_ZOOM_RATIO, 41988, IFD_FORMAT_URATIONAL), 3431 new ExifTag(TAG_FOCAL_LENGTH_IN_35MM_FILM, 41989, IFD_FORMAT_USHORT), 3432 new ExifTag(TAG_SCENE_CAPTURE_TYPE, 41990, IFD_FORMAT_USHORT), 3433 new ExifTag(TAG_GAIN_CONTROL, 41991, IFD_FORMAT_USHORT), 3434 new ExifTag(TAG_CONTRAST, 41992, IFD_FORMAT_USHORT), 3435 new ExifTag(TAG_SATURATION, 41993, IFD_FORMAT_USHORT), 3436 new ExifTag(TAG_SHARPNESS, 41994, IFD_FORMAT_USHORT), 3437 new ExifTag(TAG_DEVICE_SETTING_DESCRIPTION, 41995, IFD_FORMAT_UNDEFINED), 3438 new ExifTag(TAG_SUBJECT_DISTANCE_RANGE, 41996, IFD_FORMAT_USHORT), 3439 new ExifTag(TAG_IMAGE_UNIQUE_ID, 42016, IFD_FORMAT_STRING), 3440 new ExifTag(TAG_DNG_VERSION, 50706, IFD_FORMAT_BYTE), 3441 new ExifTag(TAG_DEFAULT_CROP_SIZE, 50720, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG) 3442 }; 3443 3444 // Primary image IFD GPS Info tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels) 3445 private static final ExifTag[] IFD_GPS_TAGS = new ExifTag[] { 3446 new ExifTag(TAG_GPS_VERSION_ID, 0, IFD_FORMAT_BYTE), 3447 new ExifTag(TAG_GPS_LATITUDE_REF, 1, IFD_FORMAT_STRING), 3448 new ExifTag(TAG_GPS_LATITUDE, 2, IFD_FORMAT_URATIONAL), 3449 new ExifTag(TAG_GPS_LONGITUDE_REF, 3, IFD_FORMAT_STRING), 3450 new ExifTag(TAG_GPS_LONGITUDE, 4, IFD_FORMAT_URATIONAL), 3451 new ExifTag(TAG_GPS_ALTITUDE_REF, 5, IFD_FORMAT_BYTE), 3452 new ExifTag(TAG_GPS_ALTITUDE, 6, IFD_FORMAT_URATIONAL), 3453 new ExifTag(TAG_GPS_TIMESTAMP, 7, IFD_FORMAT_URATIONAL), 3454 new ExifTag(TAG_GPS_SATELLITES, 8, IFD_FORMAT_STRING), 3455 new ExifTag(TAG_GPS_STATUS, 9, IFD_FORMAT_STRING), 3456 new ExifTag(TAG_GPS_MEASURE_MODE, 10, IFD_FORMAT_STRING), 3457 new ExifTag(TAG_GPS_DOP, 11, IFD_FORMAT_URATIONAL), 3458 new ExifTag(TAG_GPS_SPEED_REF, 12, IFD_FORMAT_STRING), 3459 new ExifTag(TAG_GPS_SPEED, 13, IFD_FORMAT_URATIONAL), 3460 new ExifTag(TAG_GPS_TRACK_REF, 14, IFD_FORMAT_STRING), 3461 new ExifTag(TAG_GPS_TRACK, 15, IFD_FORMAT_URATIONAL), 3462 new ExifTag(TAG_GPS_IMG_DIRECTION_REF, 16, IFD_FORMAT_STRING), 3463 new ExifTag(TAG_GPS_IMG_DIRECTION, 17, IFD_FORMAT_URATIONAL), 3464 new ExifTag(TAG_GPS_MAP_DATUM, 18, IFD_FORMAT_STRING), 3465 new ExifTag(TAG_GPS_DEST_LATITUDE_REF, 19, IFD_FORMAT_STRING), 3466 new ExifTag(TAG_GPS_DEST_LATITUDE, 20, IFD_FORMAT_URATIONAL), 3467 new ExifTag(TAG_GPS_DEST_LONGITUDE_REF, 21, IFD_FORMAT_STRING), 3468 new ExifTag(TAG_GPS_DEST_LONGITUDE, 22, IFD_FORMAT_URATIONAL), 3469 new ExifTag(TAG_GPS_DEST_BEARING_REF, 23, IFD_FORMAT_STRING), 3470 new ExifTag(TAG_GPS_DEST_BEARING, 24, IFD_FORMAT_URATIONAL), 3471 new ExifTag(TAG_GPS_DEST_DISTANCE_REF, 25, IFD_FORMAT_STRING), 3472 new ExifTag(TAG_GPS_DEST_DISTANCE, 26, IFD_FORMAT_URATIONAL), 3473 new ExifTag(TAG_GPS_PROCESSING_METHOD, 27, IFD_FORMAT_UNDEFINED), 3474 new ExifTag(TAG_GPS_AREA_INFORMATION, 28, IFD_FORMAT_UNDEFINED), 3475 new ExifTag(TAG_GPS_DATESTAMP, 29, IFD_FORMAT_STRING), 3476 new ExifTag(TAG_GPS_DIFFERENTIAL, 30, IFD_FORMAT_USHORT) 3477 }; 3478 // Primary image IFD Interoperability tag (See JEITA CP-3451C Section 4.6.8 Tag Support Levels) 3479 private static final ExifTag[] IFD_INTEROPERABILITY_TAGS = new ExifTag[] { 3480 new ExifTag(TAG_INTEROPERABILITY_INDEX, 1, IFD_FORMAT_STRING) 3481 }; 3482 // IFD Thumbnail tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels) 3483 private static final ExifTag[] IFD_THUMBNAIL_TAGS = new ExifTag[] { 3484 // For below two, see TIFF 6.0 Spec Section 3: Bilevel Images. 3485 new ExifTag(TAG_NEW_SUBFILE_TYPE, 254, IFD_FORMAT_ULONG), 3486 new ExifTag(TAG_SUBFILE_TYPE, 255, IFD_FORMAT_ULONG), 3487 new ExifTag(TAG_THUMBNAIL_IMAGE_WIDTH, 256, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3488 new ExifTag(TAG_THUMBNAIL_IMAGE_LENGTH, 257, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3489 new ExifTag(TAG_BITS_PER_SAMPLE, 258, IFD_FORMAT_USHORT), 3490 new ExifTag(TAG_COMPRESSION, 259, IFD_FORMAT_USHORT), 3491 new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262, IFD_FORMAT_USHORT), 3492 new ExifTag(TAG_IMAGE_DESCRIPTION, 270, IFD_FORMAT_STRING), 3493 new ExifTag(TAG_MAKE, 271, IFD_FORMAT_STRING), 3494 new ExifTag(TAG_MODEL, 272, IFD_FORMAT_STRING), 3495 new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3496 new ExifTag(TAG_ORIENTATION, 274, IFD_FORMAT_USHORT), 3497 new ExifTag(TAG_SAMPLES_PER_PIXEL, 277, IFD_FORMAT_USHORT), 3498 new ExifTag(TAG_ROWS_PER_STRIP, 278, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3499 new ExifTag(TAG_STRIP_BYTE_COUNTS, 279, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG), 3500 new ExifTag(TAG_X_RESOLUTION, 282, IFD_FORMAT_URATIONAL), 3501 new ExifTag(TAG_Y_RESOLUTION, 283, IFD_FORMAT_URATIONAL), 3502 new ExifTag(TAG_PLANAR_CONFIGURATION, 284, IFD_FORMAT_USHORT), 3503 new ExifTag(TAG_RESOLUTION_UNIT, 296, IFD_FORMAT_USHORT), 3504 new ExifTag(TAG_TRANSFER_FUNCTION, 301, IFD_FORMAT_USHORT), 3505 new ExifTag(TAG_SOFTWARE, 305, IFD_FORMAT_STRING), 3506 new ExifTag(TAG_DATETIME, 306, IFD_FORMAT_STRING), 3507 new ExifTag(TAG_ARTIST, 315, IFD_FORMAT_STRING), 3508 new ExifTag(TAG_WHITE_POINT, 318, IFD_FORMAT_URATIONAL), 3509 new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319, IFD_FORMAT_URATIONAL), 3510 // See Adobe PageMaker® 6.0 TIFF Technical Notes, Note 1. 3511 new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG), 3512 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG), 3513 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG), 3514 new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529, IFD_FORMAT_URATIONAL), 3515 new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530, IFD_FORMAT_USHORT), 3516 new ExifTag(TAG_Y_CB_CR_POSITIONING, 531, IFD_FORMAT_USHORT), 3517 new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532, IFD_FORMAT_URATIONAL), 3518 new ExifTag(TAG_COPYRIGHT, 33432, IFD_FORMAT_STRING), 3519 new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG), 3520 new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG), 3521 new ExifTag(TAG_DNG_VERSION, 50706, IFD_FORMAT_BYTE), 3522 new ExifTag(TAG_DEFAULT_CROP_SIZE, 50720, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG) 3523 }; 3524 3525 // RAF file tag (See piex.cc line 372) 3526 private static final ExifTag TAG_RAF_IMAGE_SIZE = 3527 new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT); 3528 3529 // ORF file tags (See http://www.exiv2.org/tags-olympus.html) 3530 private static final ExifTag[] ORF_MAKER_NOTE_TAGS = new ExifTag[] { 3531 new ExifTag(TAG_ORF_THUMBNAIL_IMAGE, 256, IFD_FORMAT_UNDEFINED), 3532 new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_ULONG), 3533 new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_ULONG) 3534 }; 3535 private static final ExifTag[] ORF_CAMERA_SETTINGS_TAGS = new ExifTag[] { 3536 new ExifTag(TAG_ORF_PREVIEW_IMAGE_START, 257, IFD_FORMAT_ULONG), 3537 new ExifTag(TAG_ORF_PREVIEW_IMAGE_LENGTH, 258, IFD_FORMAT_ULONG) 3538 }; 3539 private static final ExifTag[] ORF_IMAGE_PROCESSING_TAGS = new ExifTag[] { 3540 new ExifTag(TAG_ORF_ASPECT_FRAME, 4371, IFD_FORMAT_USHORT) 3541 }; 3542 // PEF file tag (See http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html) 3543 private static final ExifTag[] PEF_TAGS = new ExifTag[] { 3544 new ExifTag(TAG_COLOR_SPACE, 55, IFD_FORMAT_USHORT) 3545 }; 3546 3547 // See JEITA CP-3451C Section 4.6.3: Exif-specific IFD. 3548 // The following values are used for indicating pointers to the other Image File Directories. 3549 3550 // Indices of Exif Ifd tag groups 3551 /** @hide */ 3552 @Retention(RetentionPolicy.SOURCE) 3553 @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY, 3554 IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE, 3555 IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF}) 3556 public @interface IfdType {} 3557 3558 static final int IFD_TYPE_PRIMARY = 0; 3559 private static final int IFD_TYPE_EXIF = 1; 3560 private static final int IFD_TYPE_GPS = 2; 3561 private static final int IFD_TYPE_INTEROPERABILITY = 3; 3562 static final int IFD_TYPE_THUMBNAIL = 4; 3563 static final int IFD_TYPE_PREVIEW = 5; 3564 private static final int IFD_TYPE_ORF_MAKER_NOTE = 6; 3565 private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7; 3566 private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8; 3567 private static final int IFD_TYPE_PEF = 9; 3568 3569 // List of Exif tag groups 3570 static final ExifTag[][] EXIF_TAGS = new ExifTag[][] { 3571 IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS, 3572 IFD_THUMBNAIL_TAGS, IFD_TIFF_TAGS, ORF_MAKER_NOTE_TAGS, ORF_CAMERA_SETTINGS_TAGS, 3573 ORF_IMAGE_PROCESSING_TAGS, PEF_TAGS 3574 }; 3575 // List of tags for pointing to the other image file directory offset. 3576 private static final ExifTag[] EXIF_POINTER_TAGS = new ExifTag[] { 3577 new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG), 3578 new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG), 3579 new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG), 3580 new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965, IFD_FORMAT_ULONG), 3581 new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE), 3582 new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE) 3583 }; 3584 3585 // Tags for indicating the thumbnail offset and length 3586 private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG = 3587 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG); 3588 private static final ExifTag JPEG_INTERCHANGE_FORMAT_LENGTH_TAG = 3589 new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG); 3590 3591 // Mappings from tag number to tag name and each item represents one IFD tag group. 3592 @SuppressWarnings("unchecked") 3593 private static final HashMap<Integer, ExifTag>[] sExifTagMapsForReading = 3594 new HashMap[EXIF_TAGS.length]; 3595 // Mappings from tag name to tag number and each item represents one IFD tag group. 3596 @SuppressWarnings("unchecked") 3597 private static final HashMap<String, ExifTag>[] sExifTagMapsForWriting = 3598 new HashMap[EXIF_TAGS.length]; 3599 private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList( 3600 TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE, 3601 TAG_GPS_TIMESTAMP)); 3602 // Mappings from tag number to IFD type for pointer tags. 3603 @SuppressWarnings("unchecked") 3604 private static final HashMap<Integer, Integer> sExifPointerTagMap = new HashMap(); 3605 3606 // See JPEG File Interchange Format Version 1.02. 3607 // The following values are defined for handling JPEG streams. In this implementation, we are 3608 // not only getting information from EXIF but also from some JPEG special segments such as 3609 // MARKER_COM for user comment and MARKER_SOFx for image width and height. 3610 3611 private static final Charset ASCII = Charset.forName("US-ASCII"); 3612 // Identifier for EXIF APP1 segment in JPEG 3613 static final byte[] IDENTIFIER_EXIF_APP1 = "Exif\0\0".getBytes(ASCII); 3614 // JPEG segment markers, that each marker consumes two bytes beginning with 0xff and ending with 3615 // the indicator. There is no SOF4, SOF8, SOF16 markers in JPEG and SOFx markers indicates start 3616 // of frame(baseline DCT) and the image size info exists in its beginning part. 3617 static final byte MARKER = (byte) 0xff; 3618 private static final byte MARKER_SOI = (byte) 0xd8; 3619 private static final byte MARKER_SOF0 = (byte) 0xc0; 3620 private static final byte MARKER_SOF1 = (byte) 0xc1; 3621 private static final byte MARKER_SOF2 = (byte) 0xc2; 3622 private static final byte MARKER_SOF3 = (byte) 0xc3; 3623 private static final byte MARKER_SOF5 = (byte) 0xc5; 3624 private static final byte MARKER_SOF6 = (byte) 0xc6; 3625 private static final byte MARKER_SOF7 = (byte) 0xc7; 3626 private static final byte MARKER_SOF9 = (byte) 0xc9; 3627 private static final byte MARKER_SOF10 = (byte) 0xca; 3628 private static final byte MARKER_SOF11 = (byte) 0xcb; 3629 private static final byte MARKER_SOF13 = (byte) 0xcd; 3630 private static final byte MARKER_SOF14 = (byte) 0xce; 3631 private static final byte MARKER_SOF15 = (byte) 0xcf; 3632 private static final byte MARKER_SOS = (byte) 0xda; 3633 static final byte MARKER_APP1 = (byte) 0xe1; 3634 private static final byte MARKER_COM = (byte) 0xfe; 3635 static final byte MARKER_EOI = (byte) 0xd9; 3636 3637 // Supported Image File Types 3638 private static final int IMAGE_TYPE_UNKNOWN = 0; 3639 private static final int IMAGE_TYPE_ARW = 1; 3640 private static final int IMAGE_TYPE_CR2 = 2; 3641 private static final int IMAGE_TYPE_DNG = 3; 3642 private static final int IMAGE_TYPE_JPEG = 4; 3643 private static final int IMAGE_TYPE_NEF = 5; 3644 private static final int IMAGE_TYPE_NRW = 6; 3645 private static final int IMAGE_TYPE_ORF = 7; 3646 private static final int IMAGE_TYPE_PEF = 8; 3647 private static final int IMAGE_TYPE_RAF = 9; 3648 private static final int IMAGE_TYPE_RW2 = 10; 3649 private static final int IMAGE_TYPE_SRW = 11; 3650 3651 static { 3652 sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); 3653 sFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); 3654 3655 // Build up the hash tables to look up Exif tags for reading Exif tags. 3656 for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { 3657 sExifTagMapsForReading[ifdType] = new HashMap<>(); 3658 sExifTagMapsForWriting[ifdType] = new HashMap<>(); 3659 for (ExifTag tag : EXIF_TAGS[ifdType]) { 3660 sExifTagMapsForReading[ifdType].put(tag.number, tag); 3661 sExifTagMapsForWriting[ifdType].put(tag.name, tag); 3662 } 3663 } 3664 3665 // Build up the hash table to look up Exif pointer tags. 3666 sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330 3667 sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665 3668 sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853 3669 sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965 3670 sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224 3671 sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256 3672 } 3673 3674 private final String mFilename; 3675 private final AssetManager.AssetInputStream mAssetInputStream; 3676 private int mMimeType; 3677 @SuppressWarnings("unchecked") 3678 private final HashMap<String, ExifAttribute>[] mAttributes = new HashMap[EXIF_TAGS.length]; 3679 private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN; 3680 private boolean mHasThumbnail; 3681 // The following values used for indicating a thumbnail position. 3682 private int mThumbnailOffset; 3683 private int mThumbnailLength; 3684 private byte[] mThumbnailBytes; 3685 private int mThumbnailCompression; 3686 private int mExifOffset; 3687 private int mOrfMakerNoteOffset; 3688 private int mOrfThumbnailOffset; 3689 private int mOrfThumbnailLength; 3690 private int mRw2JpgFromRawOffset; 3691 private boolean mIsSupportedFile; 3692 3693 // Pattern to check non zero timestamp 3694 private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*"); 3695 // Pattern to check gps timestamp 3696 private static final Pattern sGpsTimestampPattern = 3697 Pattern.compile("^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$"); 3698 3699 /** 3700 * Reads Exif tags from the specified image file. 3701 */ 3702 public ExifInterface(String filename) throws IOException { 3703 if (filename == null) { 3704 throw new IllegalArgumentException("filename cannot be null"); 3705 } 3706 FileInputStream in = null; 3707 mAssetInputStream = null; 3708 mFilename = filename; 3709 try { 3710 in = new FileInputStream(filename); 3711 loadAttributes(in); 3712 } finally { 3713 closeQuietly(in); 3714 } 3715 } 3716 3717 /** 3718 * Reads Exif tags from the specified image input stream. Attribute mutation is not supported 3719 * for input streams. The given input stream will proceed its current position. Developers 3720 * should close the input stream after use. This constructor is not intended to be used with 3721 * an input stream that performs any networking operations. 3722 */ 3723 public ExifInterface(InputStream inputStream) throws IOException { 3724 if (inputStream == null) { 3725 throw new IllegalArgumentException("inputStream cannot be null"); 3726 } 3727 mFilename = null; 3728 if (inputStream instanceof AssetManager.AssetInputStream) { 3729 mAssetInputStream = (AssetManager.AssetInputStream) inputStream; 3730 } else { 3731 mAssetInputStream = null; 3732 } 3733 loadAttributes(inputStream); 3734 } 3735 3736 /** 3737 * Returns the EXIF attribute of the specified tag or {@code null} if there is no such tag in 3738 * the image file. 3739 * 3740 * @param tag the name of the tag. 3741 */ 3742 private ExifAttribute getExifAttribute(String tag) { 3743 if (TAG_ISO_SPEED_RATINGS.equals(tag)) { 3744 if (DEBUG) { 3745 Log.d(TAG, "getExifAttribute: Replacing TAG_ISO_SPEED_RATINGS with " 3746 + "TAG_PHOTOGRAPHIC_SENSITIVITY."); 3747 } 3748 tag = TAG_PHOTOGRAPHIC_SENSITIVITY; 3749 } 3750 // Retrieves all tag groups. The value from primary image tag group has a higher priority 3751 // than the value from the thumbnail tag group if there are more than one candidates. 3752 for (int i = 0; i < EXIF_TAGS.length; ++i) { 3753 ExifAttribute value = mAttributes[i].get(tag); 3754 if (value != null) { 3755 return value; 3756 } 3757 } 3758 return null; 3759 } 3760 3761 /** 3762 * Returns the value of the specified tag or {@code null} if there 3763 * is no such tag in the image file. 3764 * 3765 * @param tag the name of the tag. 3766 */ 3767 public String getAttribute(String tag) { 3768 ExifAttribute attribute = getExifAttribute(tag); 3769 if (attribute != null) { 3770 if (!sTagSetForCompatibility.contains(tag)) { 3771 return attribute.getStringValue(mExifByteOrder); 3772 } 3773 if (tag.equals(TAG_GPS_TIMESTAMP)) { 3774 // Convert the rational values to the custom formats for backwards compatibility. 3775 if (attribute.format != IFD_FORMAT_URATIONAL 3776 && attribute.format != IFD_FORMAT_SRATIONAL) { 3777 Log.w(TAG, "GPS Timestamp format is not rational. format=" + attribute.format); 3778 return null; 3779 } 3780 Rational[] array = (Rational[]) attribute.getValue(mExifByteOrder); 3781 if (array == null || array.length != 3) { 3782 Log.w(TAG, "Invalid GPS Timestamp array. array=" + Arrays.toString(array)); 3783 return null; 3784 } 3785 return String.format("%02d:%02d:%02d", 3786 (int) ((float) array[0].numerator / array[0].denominator), 3787 (int) ((float) array[1].numerator / array[1].denominator), 3788 (int) ((float) array[2].numerator / array[2].denominator)); 3789 } 3790 try { 3791 return Double.toString(attribute.getDoubleValue(mExifByteOrder)); 3792 } catch (NumberFormatException e) { 3793 return null; 3794 } 3795 } 3796 return null; 3797 } 3798 3799 /** 3800 * Returns the integer value of the specified tag. If there is no such tag 3801 * in the image file or the value cannot be parsed as integer, return 3802 * <var>defaultValue</var>. 3803 * 3804 * @param tag the name of the tag. 3805 * @param defaultValue the value to return if the tag is not available. 3806 */ 3807 public int getAttributeInt(String tag, int defaultValue) { 3808 ExifAttribute exifAttribute = getExifAttribute(tag); 3809 if (exifAttribute == null) { 3810 return defaultValue; 3811 } 3812 3813 try { 3814 return exifAttribute.getIntValue(mExifByteOrder); 3815 } catch (NumberFormatException e) { 3816 return defaultValue; 3817 } 3818 } 3819 3820 /** 3821 * Returns the double value of the tag that is specified as rational or contains a 3822 * double-formatted value. If there is no such tag in the image file or the value cannot be 3823 * parsed as double, return <var>defaultValue</var>. 3824 * 3825 * @param tag the name of the tag. 3826 * @param defaultValue the value to return if the tag is not available. 3827 */ 3828 public double getAttributeDouble(String tag, double defaultValue) { 3829 ExifAttribute exifAttribute = getExifAttribute(tag); 3830 if (exifAttribute == null) { 3831 return defaultValue; 3832 } 3833 3834 try { 3835 return exifAttribute.getDoubleValue(mExifByteOrder); 3836 } catch (NumberFormatException e) { 3837 return defaultValue; 3838 } 3839 } 3840 3841 /** 3842 * Sets the value of the specified tag. 3843 * 3844 * @param tag the name of the tag. 3845 * @param value the value of the tag. 3846 */ 3847 public void setAttribute(String tag, String value) { 3848 if (TAG_ISO_SPEED_RATINGS.equals(tag)) { 3849 if (DEBUG) { 3850 Log.d(TAG, "setAttribute: Replacing TAG_ISO_SPEED_RATINGS with " 3851 + "TAG_PHOTOGRAPHIC_SENSITIVITY."); 3852 } 3853 tag = TAG_PHOTOGRAPHIC_SENSITIVITY; 3854 } 3855 // Convert the given value to rational values for backwards compatibility. 3856 if (value != null && sTagSetForCompatibility.contains(tag)) { 3857 if (tag.equals(TAG_GPS_TIMESTAMP)) { 3858 Matcher m = sGpsTimestampPattern.matcher(value); 3859 if (!m.find()) { 3860 Log.w(TAG, "Invalid value for " + tag + " : " + value); 3861 return; 3862 } 3863 value = Integer.parseInt(m.group(1)) + "/1," + Integer.parseInt(m.group(2)) + "/1," 3864 + Integer.parseInt(m.group(3)) + "/1"; 3865 } else { 3866 try { 3867 double doubleValue = Double.parseDouble(value); 3868 value = new Rational(doubleValue).toString(); 3869 } catch (NumberFormatException e) { 3870 Log.w(TAG, "Invalid value for " + tag + " : " + value); 3871 return; 3872 } 3873 } 3874 } 3875 3876 for (int i = 0 ; i < EXIF_TAGS.length; ++i) { 3877 if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) { 3878 continue; 3879 } 3880 final ExifTag exifTag = sExifTagMapsForWriting[i].get(tag); 3881 if (exifTag != null) { 3882 if (value == null) { 3883 mAttributes[i].remove(tag); 3884 continue; 3885 } 3886 Pair<Integer, Integer> guess = guessDataFormat(value); 3887 int dataFormat; 3888 if (exifTag.primaryFormat == guess.first || exifTag.primaryFormat == guess.second) { 3889 dataFormat = exifTag.primaryFormat; 3890 } else if (exifTag.secondaryFormat != -1 && (exifTag.secondaryFormat == guess.first 3891 || exifTag.secondaryFormat == guess.second)) { 3892 dataFormat = exifTag.secondaryFormat; 3893 } else if (exifTag.primaryFormat == IFD_FORMAT_BYTE 3894 || exifTag.primaryFormat == IFD_FORMAT_UNDEFINED 3895 || exifTag.primaryFormat == IFD_FORMAT_STRING) { 3896 dataFormat = exifTag.primaryFormat; 3897 } else { 3898 Log.w(TAG, "Given tag (" + tag + ") value didn't match with one of expected " 3899 + "formats: " + IFD_FORMAT_NAMES[exifTag.primaryFormat] 3900 + (exifTag.secondaryFormat == -1 ? "" : ", " 3901 + IFD_FORMAT_NAMES[exifTag.secondaryFormat]) + " (guess: " 3902 + IFD_FORMAT_NAMES[guess.first] + (guess.second == -1 ? "" : ", " 3903 + IFD_FORMAT_NAMES[guess.second]) + ")"); 3904 continue; 3905 } 3906 switch (dataFormat) { 3907 case IFD_FORMAT_BYTE: { 3908 mAttributes[i].put(tag, ExifAttribute.createByte(value)); 3909 break; 3910 } 3911 case IFD_FORMAT_UNDEFINED: 3912 case IFD_FORMAT_STRING: { 3913 mAttributes[i].put(tag, ExifAttribute.createString(value)); 3914 break; 3915 } 3916 case IFD_FORMAT_USHORT: { 3917 final String[] values = value.split(","); 3918 final int[] intArray = new int[values.length]; 3919 for (int j = 0; j < values.length; ++j) { 3920 intArray[j] = Integer.parseInt(values[j]); 3921 } 3922 mAttributes[i].put(tag, 3923 ExifAttribute.createUShort(intArray, mExifByteOrder)); 3924 break; 3925 } 3926 case IFD_FORMAT_SLONG: { 3927 final String[] values = value.split(","); 3928 final int[] intArray = new int[values.length]; 3929 for (int j = 0; j < values.length; ++j) { 3930 intArray[j] = Integer.parseInt(values[j]); 3931 } 3932 mAttributes[i].put(tag, 3933 ExifAttribute.createSLong(intArray, mExifByteOrder)); 3934 break; 3935 } 3936 case IFD_FORMAT_ULONG: { 3937 final String[] values = value.split(","); 3938 final long[] longArray = new long[values.length]; 3939 for (int j = 0; j < values.length; ++j) { 3940 longArray[j] = Long.parseLong(values[j]); 3941 } 3942 mAttributes[i].put(tag, 3943 ExifAttribute.createULong(longArray, mExifByteOrder)); 3944 break; 3945 } 3946 case IFD_FORMAT_URATIONAL: { 3947 final String[] values = value.split(","); 3948 final Rational[] rationalArray = new Rational[values.length]; 3949 for (int j = 0; j < values.length; ++j) { 3950 final String[] numbers = values[j].split("/"); 3951 rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]), 3952 (long) Double.parseDouble(numbers[1])); 3953 } 3954 mAttributes[i].put(tag, 3955 ExifAttribute.createURational(rationalArray, mExifByteOrder)); 3956 break; 3957 } 3958 case IFD_FORMAT_SRATIONAL: { 3959 final String[] values = value.split(","); 3960 final Rational[] rationalArray = new Rational[values.length]; 3961 for (int j = 0; j < values.length; ++j) { 3962 final String[] numbers = values[j].split("/"); 3963 rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]), 3964 (long) Double.parseDouble(numbers[1])); 3965 } 3966 mAttributes[i].put(tag, 3967 ExifAttribute.createSRational(rationalArray, mExifByteOrder)); 3968 break; 3969 } 3970 case IFD_FORMAT_DOUBLE: { 3971 final String[] values = value.split(","); 3972 final double[] doubleArray = new double[values.length]; 3973 for (int j = 0; j < values.length; ++j) { 3974 doubleArray[j] = Double.parseDouble(values[j]); 3975 } 3976 mAttributes[i].put(tag, 3977 ExifAttribute.createDouble(doubleArray, mExifByteOrder)); 3978 break; 3979 } 3980 default: 3981 Log.w(TAG, "Data format isn't one of expected formats: " + dataFormat); 3982 continue; 3983 } 3984 } 3985 } 3986 } 3987 3988 /** 3989 * Resets the {@link #TAG_ORIENTATION} of the image to be {@link #ORIENTATION_NORMAL}. 3990 */ 3991 public void resetOrientation() { 3992 setAttribute(TAG_ORIENTATION, Integer.toString(ORIENTATION_NORMAL)); 3993 } 3994 3995 /** 3996 * Rotates the image by the given degree clockwise. The degree should be a multiple of 3997 * 90 (e.g, 90, 180, -90, etc.). 3998 * 3999 * @param degree The degree of rotation. 4000 */ 4001 public void rotate(int degree) { 4002 if (degree % 90 !=0) { 4003 throw new IllegalArgumentException("degree should be a multiple of 90"); 4004 } 4005 4006 int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); 4007 int currentIndex, newIndex; 4008 int resultOrientation; 4009 if (ROTATION_ORDER.contains(currentOrientation)) { 4010 currentIndex = ROTATION_ORDER.indexOf(currentOrientation); 4011 newIndex = (currentIndex + degree / 90) % 4; 4012 newIndex += newIndex < 0 ? 4 : 0; 4013 resultOrientation = ROTATION_ORDER.get(newIndex); 4014 } else if (FLIPPED_ROTATION_ORDER.contains(currentOrientation)) { 4015 currentIndex = FLIPPED_ROTATION_ORDER.indexOf(currentOrientation); 4016 newIndex = (currentIndex + degree / 90) % 4; 4017 newIndex += newIndex < 0 ? 4 : 0; 4018 resultOrientation = FLIPPED_ROTATION_ORDER.get(newIndex); 4019 } else { 4020 resultOrientation = ORIENTATION_UNDEFINED; 4021 } 4022 4023 setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation)); 4024 } 4025 4026 /** 4027 * Flips the image vertically. 4028 */ 4029 public void flipVertically() { 4030 int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); 4031 int resultOrientation; 4032 switch (currentOrientation) { 4033 case ORIENTATION_FLIP_HORIZONTAL: 4034 resultOrientation = ORIENTATION_ROTATE_180; 4035 break; 4036 case ORIENTATION_ROTATE_180: 4037 resultOrientation = ORIENTATION_FLIP_HORIZONTAL; 4038 break; 4039 case ORIENTATION_FLIP_VERTICAL: 4040 resultOrientation = ORIENTATION_NORMAL; 4041 break; 4042 case ORIENTATION_TRANSPOSE: 4043 resultOrientation = ORIENTATION_ROTATE_270; 4044 break; 4045 case ORIENTATION_ROTATE_90: 4046 resultOrientation = ORIENTATION_TRANSVERSE; 4047 break; 4048 case ORIENTATION_TRANSVERSE: 4049 resultOrientation = ORIENTATION_ROTATE_90; 4050 break; 4051 case ORIENTATION_ROTATE_270: 4052 resultOrientation = ORIENTATION_TRANSPOSE; 4053 break; 4054 case ORIENTATION_NORMAL: 4055 resultOrientation = ORIENTATION_FLIP_VERTICAL; 4056 break; 4057 case ORIENTATION_UNDEFINED: 4058 default: 4059 resultOrientation = ORIENTATION_UNDEFINED; 4060 break; 4061 } 4062 setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation)); 4063 } 4064 4065 /** 4066 * Flips the image horizontally. 4067 */ 4068 public void flipHorizontally() { 4069 int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); 4070 int resultOrientation; 4071 switch (currentOrientation) { 4072 case ORIENTATION_FLIP_HORIZONTAL: 4073 resultOrientation = ORIENTATION_NORMAL; 4074 break; 4075 case ORIENTATION_ROTATE_180: 4076 resultOrientation = ORIENTATION_FLIP_VERTICAL; 4077 break; 4078 case ORIENTATION_FLIP_VERTICAL: 4079 resultOrientation = ORIENTATION_ROTATE_180; 4080 break; 4081 case ORIENTATION_TRANSPOSE: 4082 resultOrientation = ORIENTATION_ROTATE_90; 4083 break; 4084 case ORIENTATION_ROTATE_90: 4085 resultOrientation = ORIENTATION_TRANSPOSE; 4086 break; 4087 case ORIENTATION_TRANSVERSE: 4088 resultOrientation = ORIENTATION_ROTATE_270; 4089 break; 4090 case ORIENTATION_ROTATE_270: 4091 resultOrientation = ORIENTATION_TRANSVERSE; 4092 break; 4093 case ORIENTATION_NORMAL: 4094 resultOrientation = ORIENTATION_FLIP_HORIZONTAL; 4095 break; 4096 case ORIENTATION_UNDEFINED: 4097 default: 4098 resultOrientation = ORIENTATION_UNDEFINED; 4099 break; 4100 } 4101 setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation)); 4102 } 4103 4104 /** 4105 * Returns if the current image orientation is flipped. 4106 * 4107 * @see #getRotationDegrees() 4108 */ 4109 public boolean isFlipped() { 4110 int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); 4111 switch (orientation) { 4112 case ORIENTATION_FLIP_HORIZONTAL: 4113 case ORIENTATION_TRANSVERSE: 4114 case ORIENTATION_FLIP_VERTICAL: 4115 case ORIENTATION_TRANSPOSE: 4116 return true; 4117 default: 4118 return false; 4119 } 4120 } 4121 4122 /** 4123 * Returns the rotation degrees for the current image orientation. If the image is flipped, 4124 * i.e., {@link #isFlipped()} returns {@code true}, the rotation degrees will be base on 4125 * the assumption that the image is first flipped horizontally (along Y-axis), and then do 4126 * the rotation. For example, {@link #ORIENTATION_TRANSPOSE} will be interpreted as flipped 4127 * horizontally first, and then rotate 270 degrees clockwise. 4128 * 4129 * @return The rotation degrees of the image after the horizontal flipping is applied, if any. 4130 * 4131 * @see #isFlipped() 4132 */ 4133 public int getRotationDegrees() { 4134 int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); 4135 switch (orientation) { 4136 case ORIENTATION_ROTATE_90: 4137 case ORIENTATION_TRANSVERSE: 4138 return 90; 4139 case ORIENTATION_ROTATE_180: 4140 case ORIENTATION_FLIP_VERTICAL: 4141 return 180; 4142 case ORIENTATION_ROTATE_270: 4143 case ORIENTATION_TRANSPOSE: 4144 return 270; 4145 case ORIENTATION_UNDEFINED: 4146 case ORIENTATION_NORMAL: 4147 case ORIENTATION_FLIP_HORIZONTAL: 4148 default: 4149 return 0; 4150 } 4151 } 4152 4153 /** 4154 * Update the values of the tags in the tag groups if any value for the tag already was stored. 4155 * 4156 * @param tag the name of the tag. 4157 * @param value the value of the tag in a form of {@link ExifAttribute}. 4158 * @return Returns {@code true} if updating is placed. 4159 */ 4160 private boolean updateAttribute(String tag, ExifAttribute value) { 4161 boolean updated = false; 4162 for (int i = 0 ; i < EXIF_TAGS.length; ++i) { 4163 if (mAttributes[i].containsKey(tag)) { 4164 mAttributes[i].put(tag, value); 4165 updated = true; 4166 } 4167 } 4168 return updated; 4169 } 4170 4171 /** 4172 * Remove any values of the specified tag. 4173 * 4174 * @param tag the name of the tag. 4175 */ 4176 private void removeAttribute(String tag) { 4177 for (int i = 0 ; i < EXIF_TAGS.length; ++i) { 4178 mAttributes[i].remove(tag); 4179 } 4180 } 4181 4182 /** 4183 * This function decides which parser to read the image data according to the given input stream 4184 * type and the content of the input stream. In each case, it reads the first three bytes to 4185 * determine whether the image data format is JPEG or not. 4186 */ 4187 private void loadAttributes(@NonNull InputStream in) throws IOException { 4188 try { 4189 // Initialize mAttributes. 4190 for (int i = 0; i < EXIF_TAGS.length; ++i) { 4191 mAttributes[i] = new HashMap<>(); 4192 } 4193 4194 // Check file type 4195 in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE); 4196 mMimeType = getMimeType((BufferedInputStream) in); 4197 4198 // Create byte-ordered input stream 4199 ByteOrderedDataInputStream inputStream = new ByteOrderedDataInputStream(in); 4200 4201 switch (mMimeType) { 4202 case IMAGE_TYPE_JPEG: { 4203 getJpegAttributes(inputStream, 0, IFD_TYPE_PRIMARY); // 0 is offset 4204 break; 4205 } 4206 case IMAGE_TYPE_RAF: { 4207 getRafAttributes(inputStream); 4208 break; 4209 } 4210 case IMAGE_TYPE_ORF: { 4211 getOrfAttributes(inputStream); 4212 break; 4213 } 4214 case IMAGE_TYPE_RW2: { 4215 getRw2Attributes(inputStream); 4216 break; 4217 } 4218 case IMAGE_TYPE_ARW: 4219 case IMAGE_TYPE_CR2: 4220 case IMAGE_TYPE_DNG: 4221 case IMAGE_TYPE_NEF: 4222 case IMAGE_TYPE_NRW: 4223 case IMAGE_TYPE_PEF: 4224 case IMAGE_TYPE_SRW: 4225 case IMAGE_TYPE_UNKNOWN: { 4226 getRawAttributes(inputStream); 4227 break; 4228 } 4229 default: { 4230 break; 4231 } 4232 } 4233 // Set thumbnail image offset and length 4234 setThumbnailData(inputStream); 4235 mIsSupportedFile = true; 4236 } catch (IOException e) { 4237 // Ignore exceptions in order to keep the compatibility with the old versions of 4238 // ExifInterface. 4239 mIsSupportedFile = false; 4240 if (DEBUG) { 4241 Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file" 4242 + "(ExifInterface supports JPEG and some RAW image formats only) " 4243 + "or a corrupted JPEG file to ExifInterface.", e); 4244 } 4245 } finally { 4246 addDefaultValuesForCompatibility(); 4247 4248 if (DEBUG) { 4249 printAttributes(); 4250 } 4251 } 4252 } 4253 4254 // Prints out attributes for debugging. 4255 private void printAttributes() { 4256 for (int i = 0; i < mAttributes.length; ++i) { 4257 Log.d(TAG, "The size of tag group[" + i + "]: " + mAttributes[i].size()); 4258 for (Map.Entry<String, ExifAttribute> entry : mAttributes[i].entrySet()) { 4259 final ExifAttribute tagValue = entry.getValue(); 4260 Log.d(TAG, "tagName: " + entry.getKey() + ", tagType: " + tagValue.toString() 4261 + ", tagValue: '" + tagValue.getStringValue(mExifByteOrder) + "'"); 4262 } 4263 } 4264 } 4265 4266 /** 4267 * Save the tag data into the original image file. This is expensive because it involves 4268 * copying all the data from one file to another and deleting the old file and renaming the 4269 * other. It's best to use {@link #setAttribute(String,String)} to set all attributes to write 4270 * and make a single call rather than multiple calls for each attribute. 4271 * <p> 4272 * This method is only supported for JPEG files. 4273 * </p> 4274 */ 4275 public void saveAttributes() throws IOException { 4276 if (!mIsSupportedFile || mMimeType != IMAGE_TYPE_JPEG) { 4277 throw new IOException("ExifInterface only supports saving attributes on JPEG formats."); 4278 } 4279 if (mFilename == null) { 4280 throw new IOException( 4281 "ExifInterface does not support saving attributes for the current input."); 4282 } 4283 4284 // Keep the thumbnail in memory 4285 mThumbnailBytes = getThumbnail(); 4286 4287 File tempFile = new File(mFilename + ".tmp"); 4288 File originalFile = new File(mFilename); 4289 if (!originalFile.renameTo(tempFile)) { 4290 throw new IOException("Could not rename to " + tempFile.getAbsolutePath()); 4291 } 4292 4293 FileInputStream in = null; 4294 FileOutputStream out = null; 4295 try { 4296 // Save the new file. 4297 in = new FileInputStream(tempFile); 4298 out = new FileOutputStream(mFilename); 4299 saveJpegAttributes(in, out); 4300 } finally { 4301 closeQuietly(in); 4302 closeQuietly(out); 4303 tempFile.delete(); 4304 } 4305 4306 // Discard the thumbnail in memory 4307 mThumbnailBytes = null; 4308 } 4309 4310 /** 4311 * Returns true if the image file has a thumbnail. 4312 */ 4313 public boolean hasThumbnail() { 4314 return mHasThumbnail; 4315 } 4316 4317 /** 4318 * Returns the JPEG compressed thumbnail inside the image file, or {@code null} if there is no 4319 * JPEG compressed thumbnail. 4320 * The returned data can be decoded using 4321 * {@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)} 4322 */ 4323 public byte[] getThumbnail() { 4324 if (mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED) { 4325 return getThumbnailBytes(); 4326 } 4327 return null; 4328 } 4329 4330 /** 4331 * Returns the thumbnail bytes inside the image file, regardless of the compression type of the 4332 * thumbnail image. 4333 */ 4334 public byte[] getThumbnailBytes() { 4335 if (!mHasThumbnail) { 4336 return null; 4337 } 4338 if (mThumbnailBytes != null) { 4339 return mThumbnailBytes; 4340 } 4341 4342 // Read the thumbnail. 4343 InputStream in = null; 4344 try { 4345 if (mAssetInputStream != null) { 4346 in = mAssetInputStream; 4347 if (in.markSupported()) { 4348 in.reset(); 4349 } else { 4350 Log.d(TAG, "Cannot read thumbnail from inputstream without mark/reset support"); 4351 return null; 4352 } 4353 } else if (mFilename != null) { 4354 in = new FileInputStream(mFilename); 4355 } 4356 if (in == null) { 4357 // Should not be reached this. 4358 throw new FileNotFoundException(); 4359 } 4360 if (in.skip(mThumbnailOffset) != mThumbnailOffset) { 4361 throw new IOException("Corrupted image"); 4362 } 4363 byte[] buffer = new byte[mThumbnailLength]; 4364 if (in.read(buffer) != mThumbnailLength) { 4365 throw new IOException("Corrupted image"); 4366 } 4367 mThumbnailBytes = buffer; 4368 return buffer; 4369 } catch (IOException e) { 4370 // Couldn't get a thumbnail image. 4371 Log.d(TAG, "Encountered exception while getting thumbnail", e); 4372 } finally { 4373 closeQuietly(in); 4374 } 4375 return null; 4376 } 4377 4378 /** 4379 * Creates and returns a Bitmap object of the thumbnail image based on the byte array and the 4380 * thumbnail compression value, or {@code null} if the compression type is unsupported. 4381 */ 4382 public Bitmap getThumbnailBitmap() { 4383 if (!mHasThumbnail) { 4384 return null; 4385 } else if (mThumbnailBytes == null) { 4386 mThumbnailBytes = getThumbnailBytes(); 4387 } 4388 4389 if (mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED) { 4390 return BitmapFactory.decodeByteArray(mThumbnailBytes, 0, mThumbnailLength); 4391 } else if (mThumbnailCompression == DATA_UNCOMPRESSED) { 4392 int[] rgbValues = new int[mThumbnailBytes.length / 3]; 4393 byte alpha = (byte) 0xff000000; 4394 for (int i = 0; i < rgbValues.length; i++) { 4395 rgbValues[i] = alpha + (mThumbnailBytes[3 * i] << 16) 4396 + (mThumbnailBytes[3 * i + 1] << 8) + mThumbnailBytes[3 * i + 2]; 4397 } 4398 4399 ExifAttribute imageLengthAttribute = 4400 (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH); 4401 ExifAttribute imageWidthAttribute = 4402 (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH); 4403 if (imageLengthAttribute != null && imageWidthAttribute != null) { 4404 int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder); 4405 int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder); 4406 return Bitmap.createBitmap( 4407 rgbValues, imageWidth, imageLength, Bitmap.Config.ARGB_8888); 4408 } 4409 } 4410 return null; 4411 } 4412 4413 /** 4414 * Returns true if thumbnail image is JPEG Compressed, or false if either thumbnail image does 4415 * not exist or thumbnail image is uncompressed. 4416 */ 4417 public boolean isThumbnailCompressed() { 4418 return mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED; 4419 } 4420 4421 /** 4422 * Returns the offset and length of thumbnail inside the image file, or 4423 * {@code null} if there is no thumbnail. 4424 * 4425 * @return two-element array, the offset in the first value, and length in 4426 * the second, or {@code null} if no thumbnail was found. 4427 */ 4428 public long[] getThumbnailRange() { 4429 if (!mHasThumbnail) { 4430 return null; 4431 } 4432 4433 long[] range = new long[2]; 4434 range[0] = mThumbnailOffset; 4435 range[1] = mThumbnailLength; 4436 4437 return range; 4438 } 4439 4440 /** 4441 * Stores the latitude and longitude value in a float array. The first element is the latitude, 4442 * and the second element is the longitude. Returns false if the Exif tags are not available. 4443 * 4444 * @deprecated Use {@link #getLatLong()} instead. 4445 */ 4446 @Deprecated 4447 public boolean getLatLong(float output[]) { 4448 double[] latLong = getLatLong(); 4449 if (latLong == null) { 4450 return false; 4451 } 4452 4453 output[0] = (float) latLong[0]; 4454 output[1] = (float) latLong[1]; 4455 return true; 4456 } 4457 4458 /** 4459 * Gets the latitude and longitude values. 4460 * <p> 4461 * If there are valid latitude and longitude values in the image, this method returns a double 4462 * array where the first element is the latitude and the second element is the longitude. 4463 * Otherwise, it returns null. 4464 */ 4465 public double[] getLatLong() { 4466 String latValue = getAttribute(TAG_GPS_LATITUDE); 4467 String latRef = getAttribute(TAG_GPS_LATITUDE_REF); 4468 String lngValue = getAttribute(TAG_GPS_LONGITUDE); 4469 String lngRef = getAttribute(TAG_GPS_LONGITUDE_REF); 4470 4471 if (latValue != null && latRef != null && lngValue != null && lngRef != null) { 4472 try { 4473 double latitude = convertRationalLatLonToDouble(latValue, latRef); 4474 double longitude = convertRationalLatLonToDouble(lngValue, lngRef); 4475 return new double[] {latitude, longitude}; 4476 } catch (IllegalArgumentException e) { 4477 Log.w(TAG, "Latitude/longitude values are not parseable. " + 4478 String.format("latValue=%s, latRef=%s, lngValue=%s, lngRef=%s", 4479 latValue, latRef, lngValue, lngRef)); 4480 } 4481 } 4482 return null; 4483 } 4484 4485 /** 4486 * Sets the GPS-related information. It will set GPS processing method, latitude and longitude 4487 * values, GPS timestamp, and speed information at the same time. 4488 * 4489 * @param location the {@link Location} object returned by GPS service. 4490 */ 4491 public void setGpsInfo(Location location) { 4492 if (location == null) { 4493 return; 4494 } 4495 setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, location.getProvider()); 4496 setLatLong(location.getLatitude(), location.getLongitude()); 4497 setAltitude(location.getAltitude()); 4498 // Location objects store speeds in m/sec. Translates it to km/hr here. 4499 setAttribute(TAG_GPS_SPEED_REF, "K"); 4500 setAttribute(TAG_GPS_SPEED, new Rational(location.getSpeed() 4501 * TimeUnit.HOURS.toSeconds(1) / 1000).toString()); 4502 String[] dateTime = sFormatter.format(new Date(location.getTime())).split("\\s+"); 4503 setAttribute(ExifInterface.TAG_GPS_DATESTAMP, dateTime[0]); 4504 setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, dateTime[1]); 4505 } 4506 4507 /** 4508 * Sets the latitude and longitude values. 4509 * 4510 * @param latitude the decimal value of latitude. Must be a valid double value between -90.0 and 4511 * 90.0. 4512 * @param longitude the decimal value of longitude. Must be a valid double value between -180.0 4513 * and 180.0. 4514 * @throws IllegalArgumentException If {@code latitude} or {@code longitude} is outside the 4515 * specified range. 4516 */ 4517 public void setLatLong(double latitude, double longitude) { 4518 if (latitude < -90.0 || latitude > 90.0 || Double.isNaN(latitude)) { 4519 throw new IllegalArgumentException("Latitude value " + latitude + " is not valid."); 4520 } 4521 if (longitude < -180.0 || longitude > 180.0 || Double.isNaN(longitude)) { 4522 throw new IllegalArgumentException("Longitude value " + longitude + " is not valid."); 4523 } 4524 setAttribute(TAG_GPS_LATITUDE_REF, latitude >= 0 ? "N" : "S"); 4525 setAttribute(TAG_GPS_LATITUDE, convertDecimalDegree(Math.abs(latitude))); 4526 setAttribute(TAG_GPS_LONGITUDE_REF, longitude >= 0 ? "E" : "W"); 4527 setAttribute(TAG_GPS_LONGITUDE, convertDecimalDegree(Math.abs(longitude))); 4528 } 4529 4530 /** 4531 * Return the altitude in meters. If the exif tag does not exist, return 4532 * <var>defaultValue</var>. 4533 * 4534 * @param defaultValue the value to return if the tag is not available. 4535 */ 4536 public double getAltitude(double defaultValue) { 4537 double altitude = getAttributeDouble(TAG_GPS_ALTITUDE, -1); 4538 int ref = getAttributeInt(TAG_GPS_ALTITUDE_REF, -1); 4539 4540 if (altitude >= 0 && ref >= 0) { 4541 return (altitude * ((ref == 1) ? -1 : 1)); 4542 } else { 4543 return defaultValue; 4544 } 4545 } 4546 4547 /** 4548 * Sets the altitude in meters. 4549 */ 4550 public void setAltitude(double altitude) { 4551 String ref = altitude >= 0 ? "0" : "1"; 4552 setAttribute(TAG_GPS_ALTITUDE, new Rational(Math.abs(altitude)).toString()); 4553 setAttribute(TAG_GPS_ALTITUDE_REF, ref); 4554 } 4555 4556 /** 4557 * Set the date time value. 4558 * 4559 * @param timeStamp number of milliseconds since Jan. 1, 1970, midnight local time. 4560 * @hide 4561 */ 4562 public void setDateTime(long timeStamp) { 4563 long sub = timeStamp % 1000; 4564 setAttribute(TAG_DATETIME, sFormatter.format(new Date(timeStamp))); 4565 setAttribute(TAG_SUBSEC_TIME, Long.toString(sub)); 4566 } 4567 4568 /** 4569 * Returns number of milliseconds since Jan. 1, 1970, midnight local time. 4570 * Returns -1 if the date time information if not available. 4571 * @hide 4572 */ 4573 public long getDateTime() { 4574 String dateTimeString = getAttribute(TAG_DATETIME); 4575 if (dateTimeString == null 4576 || !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1; 4577 4578 ParsePosition pos = new ParsePosition(0); 4579 try { 4580 // The exif field is in local time. Parsing it as if it is UTC will yield time 4581 // since 1/1/1970 local time 4582 Date datetime = sFormatter.parse(dateTimeString, pos); 4583 if (datetime == null) return -1; 4584 long msecs = datetime.getTime(); 4585 4586 String subSecs = getAttribute(TAG_SUBSEC_TIME); 4587 if (subSecs != null) { 4588 try { 4589 long sub = Long.parseLong(subSecs); 4590 while (sub > 1000) { 4591 sub /= 10; 4592 } 4593 msecs += sub; 4594 } catch (NumberFormatException e) { 4595 // Ignored 4596 } 4597 } 4598 return msecs; 4599 } catch (IllegalArgumentException e) { 4600 return -1; 4601 } 4602 } 4603 4604 /** 4605 * Returns number of milliseconds since Jan. 1, 1970, midnight UTC. 4606 * Returns -1 if the date time information if not available. 4607 * @hide 4608 */ 4609 public long getGpsDateTime() { 4610 String date = getAttribute(TAG_GPS_DATESTAMP); 4611 String time = getAttribute(TAG_GPS_TIMESTAMP); 4612 if (date == null || time == null 4613 || (!sNonZeroTimePattern.matcher(date).matches() 4614 && !sNonZeroTimePattern.matcher(time).matches())) { 4615 return -1; 4616 } 4617 4618 String dateTimeString = date + ' ' + time; 4619 4620 ParsePosition pos = new ParsePosition(0); 4621 try { 4622 Date datetime = sFormatter.parse(dateTimeString, pos); 4623 if (datetime == null) return -1; 4624 return datetime.getTime(); 4625 } catch (IllegalArgumentException e) { 4626 return -1; 4627 } 4628 } 4629 4630 private static double convertRationalLatLonToDouble(String rationalString, String ref) { 4631 try { 4632 String [] parts = rationalString.split(","); 4633 4634 String [] pair; 4635 pair = parts[0].split("/"); 4636 double degrees = Double.parseDouble(pair[0].trim()) 4637 / Double.parseDouble(pair[1].trim()); 4638 4639 pair = parts[1].split("/"); 4640 double minutes = Double.parseDouble(pair[0].trim()) 4641 / Double.parseDouble(pair[1].trim()); 4642 4643 pair = parts[2].split("/"); 4644 double seconds = Double.parseDouble(pair[0].trim()) 4645 / Double.parseDouble(pair[1].trim()); 4646 4647 double result = degrees + (minutes / 60.0) + (seconds / 3600.0); 4648 if ((ref.equals("S") || ref.equals("W"))) { 4649 return -result; 4650 } else if (ref.equals("N") || ref.equals("E")) { 4651 return result; 4652 } else { 4653 // Not valid 4654 throw new IllegalArgumentException(); 4655 } 4656 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { 4657 // Not valid 4658 throw new IllegalArgumentException(); 4659 } 4660 } 4661 4662 private String convertDecimalDegree(double decimalDegree) { 4663 long degrees = (long) decimalDegree; 4664 long minutes = (long) ((decimalDegree - degrees) * 60.0); 4665 long seconds = Math.round((decimalDegree - degrees - minutes / 60.0) * 3600.0 * 1e7); 4666 return degrees + "/1," + minutes + "/1," + seconds + "/10000000"; 4667 } 4668 4669 // Checks the type of image file 4670 private int getMimeType(BufferedInputStream in) throws IOException { 4671 in.mark(SIGNATURE_CHECK_SIZE); 4672 byte[] signatureCheckBytes = new byte[SIGNATURE_CHECK_SIZE]; 4673 if (in.read(signatureCheckBytes) != SIGNATURE_CHECK_SIZE) { 4674 throw new EOFException(); 4675 } 4676 in.reset(); 4677 if (isJpegFormat(signatureCheckBytes)) { 4678 return IMAGE_TYPE_JPEG; 4679 } else if (isRafFormat(signatureCheckBytes)) { 4680 return IMAGE_TYPE_RAF; 4681 } else if (isOrfFormat(signatureCheckBytes)) { 4682 return IMAGE_TYPE_ORF; 4683 } else if (isRw2Format(signatureCheckBytes)) { 4684 return IMAGE_TYPE_RW2; 4685 } 4686 // Certain file formats (PEF) are identified in readImageFileDirectory() 4687 return IMAGE_TYPE_UNKNOWN; 4688 } 4689 4690 /** 4691 * This method looks at the first 3 bytes to determine if this file is a JPEG file. 4692 * See http://www.media.mit.edu/pia/Research/deepview/exif.html, "JPEG format and Marker" 4693 */ 4694 private static boolean isJpegFormat(byte[] signatureCheckBytes) throws IOException { 4695 for (int i = 0; i < JPEG_SIGNATURE.length; i++) { 4696 if (signatureCheckBytes[i] != JPEG_SIGNATURE[i]) { 4697 return false; 4698 } 4699 } 4700 return true; 4701 } 4702 4703 /** 4704 * This method looks at the first 15 bytes to determine if this file is a RAF file. 4705 * There is no official specification for RAF files from Fuji, but there is an online archive of 4706 * image file specifications: 4707 * http://fileformats.archiveteam.org/wiki/Fujifilm_RAF 4708 */ 4709 private boolean isRafFormat(byte[] signatureCheckBytes) throws IOException { 4710 byte[] rafSignatureBytes = RAF_SIGNATURE.getBytes(Charset.defaultCharset()); 4711 for (int i = 0; i < rafSignatureBytes.length; i++) { 4712 if (signatureCheckBytes[i] != rafSignatureBytes[i]) { 4713 return false; 4714 } 4715 } 4716 return true; 4717 } 4718 4719 /** 4720 * ORF has a similar structure to TIFF but it contains a different signature at the TIFF Header. 4721 * This method looks at the 2 bytes following the Byte Order bytes to determine if this file is 4722 * an ORF file. 4723 * There is no official specification for ORF files from Olympus, but there is an online archive 4724 * of image file specifications: 4725 * http://fileformats.archiveteam.org/wiki/Olympus_ORF 4726 */ 4727 private boolean isOrfFormat(byte[] signatureCheckBytes) throws IOException { 4728 ByteOrderedDataInputStream signatureInputStream = 4729 new ByteOrderedDataInputStream(signatureCheckBytes); 4730 // Read byte order 4731 mExifByteOrder = readByteOrder(signatureInputStream); 4732 // Set byte order 4733 signatureInputStream.setByteOrder(mExifByteOrder); 4734 4735 short orfSignature = signatureInputStream.readShort(); 4736 signatureInputStream.close(); 4737 return orfSignature == ORF_SIGNATURE_1 || orfSignature == ORF_SIGNATURE_2; 4738 } 4739 4740 /** 4741 * RW2 is TIFF-based, but stores 0x55 signature byte instead of 0x42 at the header 4742 * See http://lclevy.free.fr/raw/ 4743 */ 4744 private boolean isRw2Format(byte[] signatureCheckBytes) throws IOException { 4745 ByteOrderedDataInputStream signatureInputStream = 4746 new ByteOrderedDataInputStream(signatureCheckBytes); 4747 // Read byte order 4748 mExifByteOrder = readByteOrder(signatureInputStream); 4749 // Set byte order 4750 signatureInputStream.setByteOrder(mExifByteOrder); 4751 4752 short signatureByte = signatureInputStream.readShort(); 4753 signatureInputStream.close(); 4754 return signatureByte == RW2_SIGNATURE; 4755 } 4756 4757 /** 4758 * Loads EXIF attributes from a JPEG input stream. 4759 * 4760 * @param in The input stream that starts with the JPEG data. 4761 * @param jpegOffset The offset value in input stream for JPEG data. 4762 * @param imageType The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for 4763 * primary image, IFD_TYPE_PREVIEW for preview image, and 4764 * IFD_TYPE_THUMBNAIL for thumbnail image. 4765 * @throws IOException If the data contains invalid JPEG markers, offsets, or length values. 4766 */ 4767 private void getJpegAttributes(ByteOrderedDataInputStream in, int jpegOffset, int imageType) 4768 throws IOException { 4769 // See JPEG File Interchange Format Specification, "JFIF Specification" 4770 if (DEBUG) { 4771 Log.d(TAG, "getJpegAttributes starting with: " + in); 4772 } 4773 4774 // JPEG uses Big Endian by default. See https://people.cs.umass.edu/~verts/cs32/endian.html 4775 in.setByteOrder(ByteOrder.BIG_ENDIAN); 4776 4777 // Skip to JPEG data 4778 in.seek(jpegOffset); 4779 int bytesRead = jpegOffset; 4780 4781 byte marker; 4782 if ((marker = in.readByte()) != MARKER) { 4783 throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff)); 4784 } 4785 ++bytesRead; 4786 if (in.readByte() != MARKER_SOI) { 4787 throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff)); 4788 } 4789 ++bytesRead; 4790 while (true) { 4791 marker = in.readByte(); 4792 if (marker != MARKER) { 4793 throw new IOException("Invalid marker:" + Integer.toHexString(marker & 0xff)); 4794 } 4795 ++bytesRead; 4796 marker = in.readByte(); 4797 if (DEBUG) { 4798 Log.d(TAG, "Found JPEG segment indicator: " + Integer.toHexString(marker & 0xff)); 4799 } 4800 ++bytesRead; 4801 4802 // EOI indicates the end of an image and in case of SOS, JPEG image stream starts and 4803 // the image data will terminate right after. 4804 if (marker == MARKER_EOI || marker == MARKER_SOS) { 4805 break; 4806 } 4807 int length = in.readUnsignedShort() - 2; 4808 bytesRead += 2; 4809 if (DEBUG) { 4810 Log.d(TAG, "JPEG segment: " + Integer.toHexString(marker & 0xff) + " (length: " 4811 + (length + 2) + ")"); 4812 } 4813 if (length < 0) { 4814 throw new IOException("Invalid length"); 4815 } 4816 switch (marker) { 4817 case MARKER_APP1: { 4818 if (DEBUG) { 4819 Log.d(TAG, "MARKER_APP1"); 4820 } 4821 if (length < 6) { 4822 // Skip if it's not an EXIF APP1 segment. 4823 break; 4824 } 4825 byte[] identifier = new byte[6]; 4826 if (in.read(identifier) != 6) { 4827 throw new IOException("Invalid exif"); 4828 } 4829 bytesRead += 6; 4830 length -= 6; 4831 if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) { 4832 // Skip if it's not an EXIF APP1 segment. 4833 break; 4834 } 4835 if (length <= 0) { 4836 throw new IOException("Invalid exif"); 4837 } 4838 if (DEBUG) { 4839 Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")"); 4840 } 4841 // Save offset values for createJpegThumbnailBitmap() function 4842 mExifOffset = bytesRead; 4843 4844 byte[] bytes = new byte[length]; 4845 if (in.read(bytes) != length) { 4846 throw new IOException("Invalid exif"); 4847 } 4848 bytesRead += length; 4849 length = 0; 4850 4851 readExifSegment(bytes, imageType); 4852 break; 4853 } 4854 4855 case MARKER_COM: { 4856 byte[] bytes = new byte[length]; 4857 if (in.read(bytes) != length) { 4858 throw new IOException("Invalid exif"); 4859 } 4860 length = 0; 4861 if (getAttribute(TAG_USER_COMMENT) == null) { 4862 mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString( 4863 new String(bytes, ASCII))); 4864 } 4865 break; 4866 } 4867 4868 case MARKER_SOF0: 4869 case MARKER_SOF1: 4870 case MARKER_SOF2: 4871 case MARKER_SOF3: 4872 case MARKER_SOF5: 4873 case MARKER_SOF6: 4874 case MARKER_SOF7: 4875 case MARKER_SOF9: 4876 case MARKER_SOF10: 4877 case MARKER_SOF11: 4878 case MARKER_SOF13: 4879 case MARKER_SOF14: 4880 case MARKER_SOF15: { 4881 if (in.skipBytes(1) != 1) { 4882 throw new IOException("Invalid SOFx"); 4883 } 4884 mAttributes[imageType].put(TAG_IMAGE_LENGTH, ExifAttribute.createULong( 4885 in.readUnsignedShort(), mExifByteOrder)); 4886 mAttributes[imageType].put(TAG_IMAGE_WIDTH, ExifAttribute.createULong( 4887 in.readUnsignedShort(), mExifByteOrder)); 4888 length -= 5; 4889 break; 4890 } 4891 4892 default: { 4893 break; 4894 } 4895 } 4896 if (length < 0) { 4897 throw new IOException("Invalid length"); 4898 } 4899 if (in.skipBytes(length) != length) { 4900 throw new IOException("Invalid JPEG segment"); 4901 } 4902 bytesRead += length; 4903 } 4904 // Restore original byte order 4905 in.setByteOrder(mExifByteOrder); 4906 } 4907 4908 private void getRawAttributes(ByteOrderedDataInputStream in) throws IOException { 4909 // Parse TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1. 4910 parseTiffHeaders(in, in.available()); 4911 4912 // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6. 4913 readImageFileDirectory(in, IFD_TYPE_PRIMARY); 4914 4915 // Update ImageLength/Width tags for all image data. 4916 updateImageSizeValues(in, IFD_TYPE_PRIMARY); 4917 updateImageSizeValues(in, IFD_TYPE_PREVIEW); 4918 updateImageSizeValues(in, IFD_TYPE_THUMBNAIL); 4919 4920 // Check if each image data is in valid position. 4921 validateImages(in); 4922 4923 if (mMimeType == IMAGE_TYPE_PEF) { 4924 // PEF files contain a MakerNote data, which contains the data for ColorSpace tag. 4925 // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData() 4926 ExifAttribute makerNoteAttribute = 4927 (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE); 4928 if (makerNoteAttribute != null) { 4929 // Create an ordered DataInputStream for MakerNote 4930 ByteOrderedDataInputStream makerNoteDataInputStream = 4931 new ByteOrderedDataInputStream(makerNoteAttribute.bytes); 4932 makerNoteDataInputStream.setByteOrder(mExifByteOrder); 4933 4934 // Seek to MakerNote data 4935 makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE); 4936 4937 // Read IFD data from MakerNote 4938 readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF); 4939 4940 // Update ColorSpace tag 4941 ExifAttribute colorSpaceAttribute = 4942 (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE); 4943 if (colorSpaceAttribute != null) { 4944 mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute); 4945 } 4946 } 4947 } 4948 } 4949 4950 /** 4951 * RAF files contains a JPEG and a CFA data. 4952 * The JPEG contains two images, a preview and a thumbnail, while the CFA contains a RAW image. 4953 * This method looks at the first 160 bytes of a RAF file to retrieve the offset and length 4954 * values for the JPEG and CFA data. 4955 * Using that data, it parses the JPEG data to retrieve the preview and thumbnail image data, 4956 * then parses the CFA metadata to retrieve the primary image length/width values. 4957 * For data format details, see http://fileformats.archiveteam.org/wiki/Fujifilm_RAF 4958 */ 4959 private void getRafAttributes(ByteOrderedDataInputStream in) throws IOException { 4960 // Retrieve offset & length values 4961 in.skipBytes(RAF_OFFSET_TO_JPEG_IMAGE_OFFSET); 4962 byte[] jpegOffsetBytes = new byte[4]; 4963 byte[] cfaHeaderOffsetBytes = new byte[4]; 4964 in.read(jpegOffsetBytes); 4965 // Skip JPEG length value since it is not needed 4966 in.skipBytes(RAF_JPEG_LENGTH_VALUE_SIZE); 4967 in.read(cfaHeaderOffsetBytes); 4968 int rafJpegOffset = ByteBuffer.wrap(jpegOffsetBytes).getInt(); 4969 int rafCfaHeaderOffset = ByteBuffer.wrap(cfaHeaderOffsetBytes).getInt(); 4970 4971 // Retrieve JPEG image metadata 4972 getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW); 4973 4974 // Skip to CFA header offset. 4975 in.seek(rafCfaHeaderOffset); 4976 4977 // Retrieve primary image length/width values, if TAG_RAF_IMAGE_SIZE exists 4978 in.setByteOrder(ByteOrder.BIG_ENDIAN); 4979 int numberOfDirectoryEntry = in.readInt(); 4980 if (DEBUG) { 4981 Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry); 4982 } 4983 // CFA stores some metadata about the RAW image. Since CFA uses proprietary tags, can only 4984 // find and retrieve image size information tags, while skipping others. 4985 // See piex.cc RafGetDimension() 4986 for (int i = 0; i < numberOfDirectoryEntry; ++i) { 4987 int tagNumber = in.readUnsignedShort(); 4988 int numberOfBytes = in.readUnsignedShort(); 4989 if (tagNumber == TAG_RAF_IMAGE_SIZE.number) { 4990 int imageLength = in.readShort(); 4991 int imageWidth = in.readShort(); 4992 ExifAttribute imageLengthAttribute = 4993 ExifAttribute.createUShort(imageLength, mExifByteOrder); 4994 ExifAttribute imageWidthAttribute = 4995 ExifAttribute.createUShort(imageWidth, mExifByteOrder); 4996 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute); 4997 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute); 4998 if (DEBUG) { 4999 Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth); 5000 } 5001 return; 5002 } 5003 in.skipBytes(numberOfBytes); 5004 } 5005 } 5006 5007 /** 5008 * ORF files contains a primary image data and a MakerNote data that contains preview/thumbnail 5009 * images. Both data takes the form of IFDs and can therefore be read with the 5010 * readImageFileDirectory() method. 5011 * This method reads all the necessary data and updates the primary/preview/thumbnail image 5012 * information according to the GetOlympusPreviewImage() method in piex.cc. 5013 * For data format details, see the following: 5014 * http://fileformats.archiveteam.org/wiki/Olympus_ORF 5015 * https://libopenraw.freedesktop.org/wiki/Olympus_ORF 5016 */ 5017 private void getOrfAttributes(ByteOrderedDataInputStream in) throws IOException { 5018 // Retrieve primary image data 5019 // Other Exif data will be located in the Makernote. 5020 getRawAttributes(in); 5021 5022 // Additionally retrieve preview/thumbnail information from MakerNote tag, which contains 5023 // proprietary tags and therefore does not have offical documentation 5024 // See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html 5025 ExifAttribute makerNoteAttribute = 5026 (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE); 5027 if (makerNoteAttribute != null) { 5028 // Create an ordered DataInputStream for MakerNote 5029 ByteOrderedDataInputStream makerNoteDataInputStream = 5030 new ByteOrderedDataInputStream(makerNoteAttribute.bytes); 5031 makerNoteDataInputStream.setByteOrder(mExifByteOrder); 5032 5033 // There are two types of headers for Olympus MakerNotes 5034 // See http://www.exiv2.org/makernote.html#R1 5035 byte[] makerNoteHeader1Bytes = new byte[ORF_MAKER_NOTE_HEADER_1.length]; 5036 makerNoteDataInputStream.readFully(makerNoteHeader1Bytes); 5037 makerNoteDataInputStream.seek(0); 5038 byte[] makerNoteHeader2Bytes = new byte[ORF_MAKER_NOTE_HEADER_2.length]; 5039 makerNoteDataInputStream.readFully(makerNoteHeader2Bytes); 5040 // Skip the corresponding amount of bytes for each header type 5041 if (Arrays.equals(makerNoteHeader1Bytes, ORF_MAKER_NOTE_HEADER_1)) { 5042 makerNoteDataInputStream.seek(ORF_MAKER_NOTE_HEADER_1_SIZE); 5043 } else if (Arrays.equals(makerNoteHeader2Bytes, ORF_MAKER_NOTE_HEADER_2)) { 5044 makerNoteDataInputStream.seek(ORF_MAKER_NOTE_HEADER_2_SIZE); 5045 } 5046 5047 // Read IFD data from MakerNote 5048 readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE); 5049 5050 // Retrieve & update preview image offset & length values 5051 ExifAttribute imageStartAttribute = (ExifAttribute) 5052 mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START); 5053 ExifAttribute imageLengthAttribute = (ExifAttribute) 5054 mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH); 5055 5056 if (imageStartAttribute != null && imageLengthAttribute != null) { 5057 mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT, 5058 imageStartAttribute); 5059 mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 5060 imageLengthAttribute); 5061 } 5062 5063 // TODO: Check this behavior in other ORF files 5064 // Retrieve primary image length & width values 5065 // See piex.cc GetOlympusPreviewImage() 5066 ExifAttribute aspectFrameAttribute = (ExifAttribute) 5067 mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME); 5068 if (aspectFrameAttribute != null) { 5069 int[] aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder); 5070 if (aspectFrameValues == null || aspectFrameValues.length != 4) { 5071 Log.w(TAG, "Invalid aspect frame values. frame=" 5072 + Arrays.toString(aspectFrameValues)); 5073 return; 5074 } 5075 if (aspectFrameValues[2] > aspectFrameValues[0] && 5076 aspectFrameValues[3] > aspectFrameValues[1]) { 5077 int primaryImageWidth = aspectFrameValues[2] - aspectFrameValues[0] + 1; 5078 int primaryImageLength = aspectFrameValues[3] - aspectFrameValues[1] + 1; 5079 // Swap width & length values 5080 if (primaryImageWidth < primaryImageLength) { 5081 primaryImageWidth += primaryImageLength; 5082 primaryImageLength = primaryImageWidth - primaryImageLength; 5083 primaryImageWidth -= primaryImageLength; 5084 } 5085 ExifAttribute primaryImageWidthAttribute = 5086 ExifAttribute.createUShort(primaryImageWidth, mExifByteOrder); 5087 ExifAttribute primaryImageLengthAttribute = 5088 ExifAttribute.createUShort(primaryImageLength, mExifByteOrder); 5089 5090 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute); 5091 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute); 5092 } 5093 } 5094 } 5095 } 5096 5097 // RW2 contains the primary image data in IFD0 and the preview and/or thumbnail image data in 5098 // the JpgFromRaw tag 5099 // See https://libopenraw.freedesktop.org/wiki/Panasonic_RAW/ and piex.cc Rw2GetPreviewData() 5100 private void getRw2Attributes(ByteOrderedDataInputStream in) throws IOException { 5101 // Retrieve primary image data 5102 getRawAttributes(in); 5103 5104 // Retrieve preview and/or thumbnail image data 5105 ExifAttribute jpgFromRawAttribute = 5106 (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW); 5107 if (jpgFromRawAttribute != null) { 5108 getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW); 5109 } 5110 5111 // Set ISO tag value if necessary 5112 ExifAttribute rw2IsoAttribute = 5113 (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO); 5114 ExifAttribute exifIsoAttribute = 5115 (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PHOTOGRAPHIC_SENSITIVITY); 5116 if (rw2IsoAttribute != null && exifIsoAttribute == null) { 5117 // Place this attribute only if it doesn't exist 5118 mAttributes[IFD_TYPE_EXIF].put(TAG_PHOTOGRAPHIC_SENSITIVITY, rw2IsoAttribute); 5119 } 5120 } 5121 5122 // Stores a new JPEG image with EXIF attributes into a given output stream. 5123 private void saveJpegAttributes(InputStream inputStream, OutputStream outputStream) 5124 throws IOException { 5125 // See JPEG File Interchange Format Specification, "JFIF Specification" 5126 if (DEBUG) { 5127 Log.d(TAG, "saveJpegAttributes starting with (inputStream: " + inputStream 5128 + ", outputStream: " + outputStream + ")"); 5129 } 5130 DataInputStream dataInputStream = new DataInputStream(inputStream); 5131 ByteOrderedDataOutputStream dataOutputStream = 5132 new ByteOrderedDataOutputStream(outputStream, ByteOrder.BIG_ENDIAN); 5133 if (dataInputStream.readByte() != MARKER) { 5134 throw new IOException("Invalid marker"); 5135 } 5136 dataOutputStream.writeByte(MARKER); 5137 if (dataInputStream.readByte() != MARKER_SOI) { 5138 throw new IOException("Invalid marker"); 5139 } 5140 dataOutputStream.writeByte(MARKER_SOI); 5141 5142 // Write EXIF APP1 segment 5143 dataOutputStream.writeByte(MARKER); 5144 dataOutputStream.writeByte(MARKER_APP1); 5145 writeExifSegment(dataOutputStream, 6); 5146 5147 byte[] bytes = new byte[4096]; 5148 5149 while (true) { 5150 byte marker = dataInputStream.readByte(); 5151 if (marker != MARKER) { 5152 throw new IOException("Invalid marker"); 5153 } 5154 marker = dataInputStream.readByte(); 5155 switch (marker) { 5156 case MARKER_APP1: { 5157 int length = dataInputStream.readUnsignedShort() - 2; 5158 if (length < 0) { 5159 throw new IOException("Invalid length"); 5160 } 5161 byte[] identifier = new byte[6]; 5162 if (length >= 6) { 5163 if (dataInputStream.read(identifier) != 6) { 5164 throw new IOException("Invalid exif"); 5165 } 5166 if (Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) { 5167 // Skip the original EXIF APP1 segment. 5168 if (dataInputStream.skipBytes(length - 6) != length - 6) { 5169 throw new IOException("Invalid length"); 5170 } 5171 break; 5172 } 5173 } 5174 // Copy non-EXIF APP1 segment. 5175 dataOutputStream.writeByte(MARKER); 5176 dataOutputStream.writeByte(marker); 5177 dataOutputStream.writeUnsignedShort(length + 2); 5178 if (length >= 6) { 5179 length -= 6; 5180 dataOutputStream.write(identifier); 5181 } 5182 int read; 5183 while (length > 0 && (read = dataInputStream.read( 5184 bytes, 0, Math.min(length, bytes.length))) >= 0) { 5185 dataOutputStream.write(bytes, 0, read); 5186 length -= read; 5187 } 5188 break; 5189 } 5190 case MARKER_EOI: 5191 case MARKER_SOS: { 5192 dataOutputStream.writeByte(MARKER); 5193 dataOutputStream.writeByte(marker); 5194 // Copy all the remaining data 5195 copy(dataInputStream, dataOutputStream); 5196 return; 5197 } 5198 default: { 5199 // Copy JPEG segment 5200 dataOutputStream.writeByte(MARKER); 5201 dataOutputStream.writeByte(marker); 5202 int length = dataInputStream.readUnsignedShort(); 5203 dataOutputStream.writeUnsignedShort(length); 5204 length -= 2; 5205 if (length < 0) { 5206 throw new IOException("Invalid length"); 5207 } 5208 int read; 5209 while (length > 0 && (read = dataInputStream.read( 5210 bytes, 0, Math.min(length, bytes.length))) >= 0) { 5211 dataOutputStream.write(bytes, 0, read); 5212 length -= read; 5213 } 5214 break; 5215 } 5216 } 5217 } 5218 } 5219 5220 // Reads the given EXIF byte area and save its tag data into attributes. 5221 private void readExifSegment(byte[] exifBytes, int imageType) throws IOException { 5222 ByteOrderedDataInputStream dataInputStream = 5223 new ByteOrderedDataInputStream(exifBytes); 5224 5225 // Parse TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1. 5226 parseTiffHeaders(dataInputStream, exifBytes.length); 5227 5228 // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6. 5229 readImageFileDirectory(dataInputStream, imageType); 5230 } 5231 5232 private void addDefaultValuesForCompatibility() { 5233 // If DATETIME tag has no value, then set the value to DATETIME_ORIGINAL tag's. 5234 String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL); 5235 if (valueOfDateTimeOriginal != null && getAttribute(TAG_DATETIME) == null) { 5236 mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME, 5237 ExifAttribute.createString(valueOfDateTimeOriginal)); 5238 } 5239 5240 // Add the default value. 5241 if (getAttribute(TAG_IMAGE_WIDTH) == null) { 5242 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, 5243 ExifAttribute.createULong(0, mExifByteOrder)); 5244 } 5245 if (getAttribute(TAG_IMAGE_LENGTH) == null) { 5246 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, 5247 ExifAttribute.createULong(0, mExifByteOrder)); 5248 } 5249 if (getAttribute(TAG_ORIENTATION) == null) { 5250 mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION, 5251 ExifAttribute.createULong(0, mExifByteOrder)); 5252 } 5253 if (getAttribute(TAG_LIGHT_SOURCE) == null) { 5254 mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE, 5255 ExifAttribute.createULong(0, mExifByteOrder)); 5256 } 5257 } 5258 5259 private ByteOrder readByteOrder(ByteOrderedDataInputStream dataInputStream) 5260 throws IOException { 5261 // Read byte order. 5262 short byteOrder = dataInputStream.readShort(); 5263 switch (byteOrder) { 5264 case BYTE_ALIGN_II: 5265 if (DEBUG) { 5266 Log.d(TAG, "readExifSegment: Byte Align II"); 5267 } 5268 return ByteOrder.LITTLE_ENDIAN; 5269 case BYTE_ALIGN_MM: 5270 if (DEBUG) { 5271 Log.d(TAG, "readExifSegment: Byte Align MM"); 5272 } 5273 return ByteOrder.BIG_ENDIAN; 5274 default: 5275 throw new IOException("Invalid byte order: " + Integer.toHexString(byteOrder)); 5276 } 5277 } 5278 5279 private void parseTiffHeaders(ByteOrderedDataInputStream dataInputStream, 5280 int exifBytesLength) throws IOException { 5281 // Read byte order 5282 mExifByteOrder = readByteOrder(dataInputStream); 5283 // Set byte order 5284 dataInputStream.setByteOrder(mExifByteOrder); 5285 5286 // Check start code 5287 int startCode = dataInputStream.readUnsignedShort(); 5288 if (mMimeType != IMAGE_TYPE_ORF && mMimeType != IMAGE_TYPE_RW2 && startCode != START_CODE) { 5289 throw new IOException("Invalid start code: " + Integer.toHexString(startCode)); 5290 } 5291 5292 // Read and skip to first ifd offset 5293 int firstIfdOffset = dataInputStream.readInt(); 5294 if (firstIfdOffset < 8 || firstIfdOffset >= exifBytesLength) { 5295 throw new IOException("Invalid first Ifd offset: " + firstIfdOffset); 5296 } 5297 firstIfdOffset -= 8; 5298 if (firstIfdOffset > 0) { 5299 if (dataInputStream.skipBytes(firstIfdOffset) != firstIfdOffset) { 5300 throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset); 5301 } 5302 } 5303 } 5304 5305 // Reads image file directory, which is a tag group in EXIF. 5306 private void readImageFileDirectory(ByteOrderedDataInputStream dataInputStream, 5307 @IfdType int ifdType) throws IOException { 5308 if (dataInputStream.mPosition + 2 > dataInputStream.mLength) { 5309 // Return if there is no data from the offset. 5310 return; 5311 } 5312 // See TIFF 6.0 Section 2: TIFF Structure, Figure 1. 5313 short numberOfDirectoryEntry = dataInputStream.readShort(); 5314 if (DEBUG) { 5315 Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry); 5316 } 5317 if (dataInputStream.mPosition + 12 * numberOfDirectoryEntry > dataInputStream.mLength) { 5318 // Return if the size of entries is too big. 5319 return; 5320 } 5321 5322 // See TIFF 6.0 Section 2: TIFF Structure, "Image File Directory". 5323 for (short i = 0; i < numberOfDirectoryEntry; ++i) { 5324 int tagNumber = dataInputStream.readUnsignedShort(); 5325 int dataFormat = dataInputStream.readUnsignedShort(); 5326 int numberOfComponents = dataInputStream.readInt(); 5327 // Next four bytes is for data offset or value. 5328 long nextEntryOffset = dataInputStream.peek() + 4; 5329 5330 // Look up a corresponding tag from tag number 5331 ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber); 5332 5333 if (DEBUG) { 5334 Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " 5335 + "numberOfComponents: %d", ifdType, tagNumber, 5336 tag != null ? tag.name : null, dataFormat, numberOfComponents)); 5337 } 5338 5339 long byteCount = 0; 5340 boolean valid = false; 5341 if (tag == null) { 5342 Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber); 5343 } else if (dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) { 5344 Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat); 5345 } else if (!tag.isFormatCompatible(dataFormat)) { 5346 Log.w(TAG, "Skip the tag entry since data format (" + IFD_FORMAT_NAMES[dataFormat] 5347 + ") is unexpected for tag: " + tag.name); 5348 } else { 5349 if (dataFormat == IFD_FORMAT_UNDEFINED) { 5350 dataFormat = tag.primaryFormat; 5351 } 5352 byteCount = (long) numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat]; 5353 if (byteCount < 0 || byteCount > Integer.MAX_VALUE) { 5354 Log.w(TAG, "Skip the tag entry since the number of components is invalid: " 5355 + numberOfComponents); 5356 } else { 5357 valid = true; 5358 } 5359 } 5360 if (!valid) { 5361 dataInputStream.seek(nextEntryOffset); 5362 continue; 5363 } 5364 5365 // Read a value from data field or seek to the value offset which is stored in data 5366 // field if the size of the entry value is bigger than 4. 5367 if (byteCount > 4) { 5368 int offset = dataInputStream.readInt(); 5369 if (DEBUG) { 5370 Log.d(TAG, "seek to data offset: " + offset); 5371 } 5372 if (mMimeType == IMAGE_TYPE_ORF) { 5373 if (TAG_MAKER_NOTE.equals(tag.name)) { 5374 // Save offset value for reading thumbnail 5375 mOrfMakerNoteOffset = offset; 5376 } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE 5377 && TAG_ORF_THUMBNAIL_IMAGE.equals(tag.name)) { 5378 // Retrieve & update values for thumbnail offset and length values for ORF 5379 mOrfThumbnailOffset = offset; 5380 mOrfThumbnailLength = numberOfComponents; 5381 5382 ExifAttribute compressionAttribute = 5383 ExifAttribute.createUShort(DATA_JPEG, mExifByteOrder); 5384 ExifAttribute jpegInterchangeFormatAttribute = 5385 ExifAttribute.createULong(mOrfThumbnailOffset, mExifByteOrder); 5386 ExifAttribute jpegInterchangeFormatLengthAttribute = 5387 ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder); 5388 5389 mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute); 5390 mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT, 5391 jpegInterchangeFormatAttribute); 5392 mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 5393 jpegInterchangeFormatLengthAttribute); 5394 } 5395 } else if (mMimeType == IMAGE_TYPE_RW2) { 5396 if (TAG_RW2_JPG_FROM_RAW.equals(tag.name)) { 5397 mRw2JpgFromRawOffset = offset; 5398 } 5399 } 5400 if (offset + byteCount <= dataInputStream.mLength) { 5401 dataInputStream.seek(offset); 5402 } else { 5403 // Skip if invalid data offset. 5404 Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset); 5405 dataInputStream.seek(nextEntryOffset); 5406 continue; 5407 } 5408 } 5409 5410 // Recursively parse IFD when a IFD pointer tag appears. 5411 Integer nextIfdType = sExifPointerTagMap.get(tagNumber); 5412 if (DEBUG) { 5413 Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount); 5414 } 5415 5416 if (nextIfdType != null) { 5417 long offset = -1L; 5418 // Get offset from data field 5419 switch (dataFormat) { 5420 case IFD_FORMAT_USHORT: { 5421 offset = dataInputStream.readUnsignedShort(); 5422 break; 5423 } 5424 case IFD_FORMAT_SSHORT: { 5425 offset = dataInputStream.readShort(); 5426 break; 5427 } 5428 case IFD_FORMAT_ULONG: { 5429 offset = dataInputStream.readUnsignedInt(); 5430 break; 5431 } 5432 case IFD_FORMAT_SLONG: 5433 case IFD_FORMAT_IFD: { 5434 offset = dataInputStream.readInt(); 5435 break; 5436 } 5437 default: { 5438 // Nothing to do 5439 break; 5440 } 5441 } 5442 if (DEBUG) { 5443 Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tag.name)); 5444 } 5445 if (offset > 0L && offset < dataInputStream.mLength) { 5446 dataInputStream.seek(offset); 5447 readImageFileDirectory(dataInputStream, nextIfdType); 5448 } else { 5449 Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset); 5450 } 5451 5452 dataInputStream.seek(nextEntryOffset); 5453 continue; 5454 } 5455 5456 byte[] bytes = new byte[(int) byteCount]; 5457 dataInputStream.readFully(bytes); 5458 ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes); 5459 mAttributes[ifdType].put(tag.name, attribute); 5460 5461 // DNG files have a DNG Version tag specifying the version of specifications that the 5462 // image file is following. 5463 // See http://fileformats.archiveteam.org/wiki/DNG 5464 if (TAG_DNG_VERSION.equals(tag.name)) { 5465 mMimeType = IMAGE_TYPE_DNG; 5466 } 5467 5468 // PEF files have a Make or Model tag that begins with "PENTAX" or a compression tag 5469 // that is 65535. 5470 // See http://fileformats.archiveteam.org/wiki/Pentax_PEF 5471 if (((TAG_MAKE.equals(tag.name) || TAG_MODEL.equals(tag.name)) 5472 && attribute.getStringValue(mExifByteOrder).contains(PEF_SIGNATURE)) 5473 || (TAG_COMPRESSION.equals(tag.name) 5474 && attribute.getIntValue(mExifByteOrder) == 65535)) { 5475 mMimeType = IMAGE_TYPE_PEF; 5476 } 5477 5478 // Seek to next tag offset 5479 if (dataInputStream.peek() != nextEntryOffset) { 5480 dataInputStream.seek(nextEntryOffset); 5481 } 5482 } 5483 5484 if (dataInputStream.peek() + 4 <= dataInputStream.mLength) { 5485 int nextIfdOffset = dataInputStream.readInt(); 5486 if (DEBUG) { 5487 Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset)); 5488 } 5489 // The next IFD offset needs to be bigger than 8 5490 // since the first IFD offset is at least 8. 5491 if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) { 5492 dataInputStream.seek(nextIfdOffset); 5493 if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { 5494 // Do not overwrite thumbnail IFD data if it alreay exists. 5495 readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL); 5496 } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) { 5497 readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW); 5498 } 5499 } 5500 } 5501 } 5502 5503 /** 5504 * JPEG compressed images do not contain IMAGE_LENGTH & IMAGE_WIDTH tags. 5505 * This value uses JpegInterchangeFormat(JPEG data offset) value, and calls getJpegAttributes() 5506 * to locate SOF(Start of Frame) marker and update the image length & width values. 5507 * See JEITA CP-3451C Table 5 and Section 4.8.1. B. 5508 */ 5509 private void retrieveJpegImageSize(ByteOrderedDataInputStream in, int imageType) 5510 throws IOException { 5511 // Check if image already has IMAGE_LENGTH & IMAGE_WIDTH values 5512 ExifAttribute imageLengthAttribute = 5513 (ExifAttribute) mAttributes[imageType].get(TAG_IMAGE_LENGTH); 5514 ExifAttribute imageWidthAttribute = 5515 (ExifAttribute) mAttributes[imageType].get(TAG_IMAGE_WIDTH); 5516 5517 if (imageLengthAttribute == null || imageWidthAttribute == null) { 5518 // Find if offset for JPEG data exists 5519 ExifAttribute jpegInterchangeFormatAttribute = 5520 (ExifAttribute) mAttributes[imageType].get(TAG_JPEG_INTERCHANGE_FORMAT); 5521 if (jpegInterchangeFormatAttribute != null) { 5522 int jpegInterchangeFormat = 5523 jpegInterchangeFormatAttribute.getIntValue(mExifByteOrder); 5524 5525 // Searches for SOF marker in JPEG data and updates IMAGE_LENGTH & IMAGE_WIDTH tags 5526 getJpegAttributes(in, jpegInterchangeFormat, imageType); 5527 } 5528 } 5529 } 5530 5531 // Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags 5532 private void setThumbnailData(ByteOrderedDataInputStream in) throws IOException { 5533 HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL]; 5534 5535 ExifAttribute compressionAttribute = 5536 (ExifAttribute) thumbnailData.get(TAG_COMPRESSION); 5537 if (compressionAttribute != null) { 5538 mThumbnailCompression = compressionAttribute.getIntValue(mExifByteOrder); 5539 switch (mThumbnailCompression) { 5540 case DATA_JPEG: { 5541 handleThumbnailFromJfif(in, thumbnailData); 5542 break; 5543 } 5544 case DATA_UNCOMPRESSED: 5545 case DATA_JPEG_COMPRESSED: { 5546 if (isSupportedDataType(thumbnailData)) { 5547 handleThumbnailFromStrips(in, thumbnailData); 5548 } 5549 break; 5550 } 5551 } 5552 } else { 5553 // Thumbnail data may not contain Compression tag value 5554 mThumbnailCompression = DATA_JPEG; 5555 handleThumbnailFromJfif(in, thumbnailData); 5556 } 5557 } 5558 5559 // Check JpegInterchangeFormat(JFIF) tags to retrieve thumbnail offset & length values 5560 // and reads the corresponding bytes if stream does not support seek function 5561 private void handleThumbnailFromJfif(ByteOrderedDataInputStream in, HashMap thumbnailData) 5562 throws IOException { 5563 ExifAttribute jpegInterchangeFormatAttribute = 5564 (ExifAttribute) thumbnailData.get(TAG_JPEG_INTERCHANGE_FORMAT); 5565 ExifAttribute jpegInterchangeFormatLengthAttribute = 5566 (ExifAttribute) thumbnailData.get(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); 5567 if (jpegInterchangeFormatAttribute != null 5568 && jpegInterchangeFormatLengthAttribute != null) { 5569 int thumbnailOffset = jpegInterchangeFormatAttribute.getIntValue(mExifByteOrder); 5570 int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder); 5571 5572 // The following code limits the size of thumbnail size not to overflow EXIF data area. 5573 thumbnailLength = Math.min(thumbnailLength, in.available() - thumbnailOffset); 5574 if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF 5575 || mMimeType == IMAGE_TYPE_RW2) { 5576 thumbnailOffset += mExifOffset; 5577 } else if (mMimeType == IMAGE_TYPE_ORF) { 5578 // Update offset value since RAF files have IFD data preceding MakerNote data. 5579 thumbnailOffset += mOrfMakerNoteOffset; 5580 } 5581 if (DEBUG) { 5582 Log.d(TAG, "Setting thumbnail attributes with offset: " + thumbnailOffset 5583 + ", length: " + thumbnailLength); 5584 } 5585 if (thumbnailOffset > 0 && thumbnailLength > 0) { 5586 mHasThumbnail = true; 5587 mThumbnailOffset = thumbnailOffset; 5588 mThumbnailLength = thumbnailLength; 5589 if (mFilename == null && mAssetInputStream == null) { 5590 // Save the thumbnail in memory if the input doesn't support reading again. 5591 byte[] thumbnailBytes = new byte[thumbnailLength]; 5592 in.seek(thumbnailOffset); 5593 in.readFully(thumbnailBytes); 5594 mThumbnailBytes = thumbnailBytes; 5595 } 5596 } 5597 } 5598 } 5599 5600 // Check StripOffsets & StripByteCounts tags to retrieve thumbnail offset & length values 5601 private void handleThumbnailFromStrips(ByteOrderedDataInputStream in, HashMap thumbnailData) 5602 throws IOException { 5603 ExifAttribute stripOffsetsAttribute = 5604 (ExifAttribute) thumbnailData.get(TAG_STRIP_OFFSETS); 5605 ExifAttribute stripByteCountsAttribute = 5606 (ExifAttribute) thumbnailData.get(TAG_STRIP_BYTE_COUNTS); 5607 5608 if (stripOffsetsAttribute != null && stripByteCountsAttribute != null) { 5609 long[] stripOffsets = 5610 convertToLongArray(stripOffsetsAttribute.getValue(mExifByteOrder)); 5611 long[] stripByteCounts = 5612 convertToLongArray(stripByteCountsAttribute.getValue(mExifByteOrder)); 5613 5614 if (stripOffsets == null) { 5615 Log.w(TAG, "stripOffsets should not be null."); 5616 return; 5617 } 5618 if (stripByteCounts == null) { 5619 Log.w(TAG, "stripByteCounts should not be null."); 5620 return; 5621 } 5622 5623 long totalStripByteCount = 0; 5624 for (long byteCount : stripByteCounts) { 5625 totalStripByteCount += byteCount; 5626 } 5627 5628 // Set thumbnail byte array data for non-consecutive strip bytes 5629 byte[] totalStripBytes = new byte[(int) totalStripByteCount]; 5630 5631 int bytesRead = 0; 5632 int bytesAdded = 0; 5633 for (int i = 0; i < stripOffsets.length; i++) { 5634 int stripOffset = (int) stripOffsets[i]; 5635 int stripByteCount = (int) stripByteCounts[i]; 5636 5637 // Skip to offset 5638 int skipBytes = stripOffset - bytesRead; 5639 if (skipBytes < 0) { 5640 Log.d(TAG, "Invalid strip offset value"); 5641 } 5642 in.seek(skipBytes); 5643 bytesRead += skipBytes; 5644 5645 // Read strip bytes 5646 byte[] stripBytes = new byte[stripByteCount]; 5647 in.read(stripBytes); 5648 bytesRead += stripByteCount; 5649 5650 // Add bytes to array 5651 System.arraycopy(stripBytes, 0, totalStripBytes, bytesAdded, 5652 stripBytes.length); 5653 bytesAdded += stripBytes.length; 5654 } 5655 5656 mHasThumbnail = true; 5657 mThumbnailBytes = totalStripBytes; 5658 mThumbnailLength = totalStripBytes.length; 5659 } 5660 } 5661 5662 // Check if thumbnail data type is currently supported or not 5663 private boolean isSupportedDataType(HashMap thumbnailData) throws IOException { 5664 ExifAttribute bitsPerSampleAttribute = 5665 (ExifAttribute) thumbnailData.get(TAG_BITS_PER_SAMPLE); 5666 if (bitsPerSampleAttribute != null) { 5667 int[] bitsPerSampleValue = (int[]) bitsPerSampleAttribute.getValue(mExifByteOrder); 5668 5669 if (Arrays.equals(BITS_PER_SAMPLE_RGB, bitsPerSampleValue)) { 5670 return true; 5671 } 5672 5673 // See DNG Specification 1.4.0.0. Section 3, Compression. 5674 if (mMimeType == IMAGE_TYPE_DNG) { 5675 ExifAttribute photometricInterpretationAttribute = 5676 (ExifAttribute) thumbnailData.get(TAG_PHOTOMETRIC_INTERPRETATION); 5677 if (photometricInterpretationAttribute != null) { 5678 int photometricInterpretationValue 5679 = photometricInterpretationAttribute.getIntValue(mExifByteOrder); 5680 if ((photometricInterpretationValue == PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO 5681 && Arrays.equals(bitsPerSampleValue, BITS_PER_SAMPLE_GREYSCALE_2)) 5682 || ((photometricInterpretationValue == PHOTOMETRIC_INTERPRETATION_YCBCR) 5683 && (Arrays.equals(bitsPerSampleValue, BITS_PER_SAMPLE_RGB)))) { 5684 return true; 5685 } else { 5686 // TODO: Add support for lossless Huffman JPEG data 5687 } 5688 } 5689 } 5690 } 5691 if (DEBUG) { 5692 Log.d(TAG, "Unsupported data type value"); 5693 } 5694 return false; 5695 } 5696 5697 // Returns true if the image length and width values are <= 512. 5698 // See Section 4.8 of http://standardsproposals.bsigroup.com/Home/getPDF/567 5699 private boolean isThumbnail(HashMap map) throws IOException { 5700 ExifAttribute imageLengthAttribute = (ExifAttribute) map.get(TAG_IMAGE_LENGTH); 5701 ExifAttribute imageWidthAttribute = (ExifAttribute) map.get(TAG_IMAGE_WIDTH); 5702 5703 if (imageLengthAttribute != null && imageWidthAttribute != null) { 5704 int imageLengthValue = imageLengthAttribute.getIntValue(mExifByteOrder); 5705 int imageWidthValue = imageWidthAttribute.getIntValue(mExifByteOrder); 5706 if (imageLengthValue <= MAX_THUMBNAIL_SIZE && imageWidthValue <= MAX_THUMBNAIL_SIZE) { 5707 return true; 5708 } 5709 } 5710 return false; 5711 } 5712 5713 // Validate primary, preview, thumbnail image data by comparing image size 5714 private void validateImages(InputStream in) throws IOException { 5715 // Swap images based on size (primary > preview > thumbnail) 5716 swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW); 5717 swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL); 5718 swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL); 5719 5720 // Check if image has PixelXDimension/PixelYDimension tags, which contain valid image 5721 // sizes, excluding padding at the right end or bottom end of the image to make sure that 5722 // the values are multiples of 64. See JEITA CP-3451C Table 5 and Section 4.8.1. B. 5723 ExifAttribute pixelXDimAttribute = 5724 (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION); 5725 ExifAttribute pixelYDimAttribute = 5726 (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION); 5727 if (pixelXDimAttribute != null && pixelYDimAttribute != null) { 5728 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, pixelXDimAttribute); 5729 mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, pixelYDimAttribute); 5730 } 5731 5732 // Check whether thumbnail image exists and whether preview image satisfies the thumbnail 5733 // image requirements 5734 if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { 5735 if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) { 5736 mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW]; 5737 mAttributes[IFD_TYPE_PREVIEW] = new HashMap<>(); 5738 } 5739 } 5740 5741 // Check if the thumbnail image satisfies the thumbnail size requirements 5742 if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) { 5743 Log.d(TAG, "No image meets the size requirements of a thumbnail image."); 5744 } 5745 } 5746 5747 /** 5748 * If image is uncompressed, ImageWidth/Length tags are used to store size info. 5749 * However, uncompressed images often store extra pixels around the edges of the final image, 5750 * which results in larger values for TAG_IMAGE_WIDTH and TAG_IMAGE_LENGTH tags. 5751 * This method corrects those tag values by checking first the values of TAG_DEFAULT_CROP_SIZE 5752 * See DNG Specification 1.4.0.0. Section 4. (DefaultCropSize) 5753 * 5754 * If image is a RW2 file, valid image sizes are stored in SensorBorder tags. 5755 * See tiff_parser.cc GetFullDimension32() 5756 * */ 5757 private void updateImageSizeValues(ByteOrderedDataInputStream in, int imageType) 5758 throws IOException { 5759 // Uncompressed image valid image size values 5760 ExifAttribute defaultCropSizeAttribute = 5761 (ExifAttribute) mAttributes[imageType].get(TAG_DEFAULT_CROP_SIZE); 5762 // RW2 image valid image size values 5763 ExifAttribute topBorderAttribute = 5764 (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_TOP_BORDER); 5765 ExifAttribute leftBorderAttribute = 5766 (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_LEFT_BORDER); 5767 ExifAttribute bottomBorderAttribute = 5768 (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_BOTTOM_BORDER); 5769 ExifAttribute rightBorderAttribute = 5770 (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_RIGHT_BORDER); 5771 5772 if (defaultCropSizeAttribute != null) { 5773 // Update for uncompressed image 5774 ExifAttribute defaultCropSizeXAttribute, defaultCropSizeYAttribute; 5775 if (defaultCropSizeAttribute.format == IFD_FORMAT_URATIONAL) { 5776 Rational[] defaultCropSizeValue = 5777 (Rational[]) defaultCropSizeAttribute.getValue(mExifByteOrder); 5778 if (defaultCropSizeValue == null || defaultCropSizeValue.length != 2) { 5779 Log.w(TAG, "Invalid crop size values. cropSize=" 5780 + Arrays.toString(defaultCropSizeValue)); 5781 return; 5782 } 5783 defaultCropSizeXAttribute = 5784 ExifAttribute.createURational(defaultCropSizeValue[0], mExifByteOrder); 5785 defaultCropSizeYAttribute = 5786 ExifAttribute.createURational(defaultCropSizeValue[1], mExifByteOrder); 5787 } else { 5788 int[] defaultCropSizeValue = 5789 (int[]) defaultCropSizeAttribute.getValue(mExifByteOrder); 5790 if (defaultCropSizeValue == null || defaultCropSizeValue.length != 2) { 5791 Log.w(TAG, "Invalid crop size values. cropSize=" 5792 + Arrays.toString(defaultCropSizeValue)); 5793 return; 5794 } 5795 defaultCropSizeXAttribute = 5796 ExifAttribute.createUShort(defaultCropSizeValue[0], mExifByteOrder); 5797 defaultCropSizeYAttribute = 5798 ExifAttribute.createUShort(defaultCropSizeValue[1], mExifByteOrder); 5799 } 5800 mAttributes[imageType].put(TAG_IMAGE_WIDTH, defaultCropSizeXAttribute); 5801 mAttributes[imageType].put(TAG_IMAGE_LENGTH, defaultCropSizeYAttribute); 5802 } else if (topBorderAttribute != null && leftBorderAttribute != null && 5803 bottomBorderAttribute != null && rightBorderAttribute != null) { 5804 // Update for RW2 image 5805 int topBorderValue = topBorderAttribute.getIntValue(mExifByteOrder); 5806 int bottomBorderValue = bottomBorderAttribute.getIntValue(mExifByteOrder); 5807 int rightBorderValue = rightBorderAttribute.getIntValue(mExifByteOrder); 5808 int leftBorderValue = leftBorderAttribute.getIntValue(mExifByteOrder); 5809 if (bottomBorderValue > topBorderValue && rightBorderValue > leftBorderValue) { 5810 int length = bottomBorderValue - topBorderValue; 5811 int width = rightBorderValue - leftBorderValue; 5812 ExifAttribute imageLengthAttribute = 5813 ExifAttribute.createUShort(length, mExifByteOrder); 5814 ExifAttribute imageWidthAttribute = 5815 ExifAttribute.createUShort(width, mExifByteOrder); 5816 mAttributes[imageType].put(TAG_IMAGE_LENGTH, imageLengthAttribute); 5817 mAttributes[imageType].put(TAG_IMAGE_WIDTH, imageWidthAttribute); 5818 } 5819 } else { 5820 retrieveJpegImageSize(in, imageType); 5821 } 5822 } 5823 5824 // Writes an Exif segment into the given output stream. 5825 private int writeExifSegment(ByteOrderedDataOutputStream dataOutputStream, 5826 int exifOffsetFromBeginning) throws IOException { 5827 // The following variables are for calculating each IFD tag group size in bytes. 5828 int[] ifdOffsets = new int[EXIF_TAGS.length]; 5829 int[] ifdDataSizes = new int[EXIF_TAGS.length]; 5830 5831 // Remove IFD pointer tags (we'll re-add it later.) 5832 for (ExifTag tag : EXIF_POINTER_TAGS) { 5833 removeAttribute(tag.name); 5834 } 5835 // Remove old thumbnail data 5836 removeAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name); 5837 removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name); 5838 5839 // Remove null value tags. 5840 for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { 5841 for (Object obj : mAttributes[ifdType].entrySet().toArray()) { 5842 final Map.Entry entry = (Map.Entry) obj; 5843 if (entry.getValue() == null) { 5844 mAttributes[ifdType].remove(entry.getKey()); 5845 } 5846 } 5847 } 5848 5849 // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD 5850 // offset when there is one or more tags in the thumbnail IFD. 5851 if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) { 5852 mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name, 5853 ExifAttribute.createULong(0, mExifByteOrder)); 5854 } 5855 if (!mAttributes[IFD_TYPE_GPS].isEmpty()) { 5856 mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name, 5857 ExifAttribute.createULong(0, mExifByteOrder)); 5858 } 5859 if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) { 5860 mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, 5861 ExifAttribute.createULong(0, mExifByteOrder)); 5862 } 5863 if (mHasThumbnail) { 5864 mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name, 5865 ExifAttribute.createULong(0, mExifByteOrder)); 5866 mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, 5867 ExifAttribute.createULong(mThumbnailLength, mExifByteOrder)); 5868 } 5869 5870 // Calculate IFD group data area sizes. IFD group data area is assigned to save the entry 5871 // value which has a bigger size than 4 bytes. 5872 for (int i = 0; i < EXIF_TAGS.length; ++i) { 5873 int sum = 0; 5874 for (Map.Entry<String, ExifAttribute> entry : mAttributes[i].entrySet()) { 5875 final ExifAttribute exifAttribute = entry.getValue(); 5876 final int size = exifAttribute.size(); 5877 if (size > 4) { 5878 sum += size; 5879 } 5880 } 5881 ifdDataSizes[i] += sum; 5882 } 5883 5884 // Calculate IFD offsets. 5885 int position = 8; 5886 for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { 5887 if (!mAttributes[ifdType].isEmpty()) { 5888 ifdOffsets[ifdType] = position; 5889 position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType]; 5890 } 5891 } 5892 if (mHasThumbnail) { 5893 int thumbnailOffset = position; 5894 mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name, 5895 ExifAttribute.createULong(thumbnailOffset, mExifByteOrder)); 5896 mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset; 5897 position += mThumbnailLength; 5898 } 5899 5900 // Calculate the total size 5901 int totalSize = position + 8; // eight bytes is for header part. 5902 if (DEBUG) { 5903 Log.d(TAG, "totalSize length: " + totalSize); 5904 for (int i = 0; i < EXIF_TAGS.length; ++i) { 5905 Log.d(TAG, String.format("index: %d, offsets: %d, tag count: %d, data sizes: %d", 5906 i, ifdOffsets[i], mAttributes[i].size(), ifdDataSizes[i])); 5907 } 5908 } 5909 5910 // Update IFD pointer tags with the calculated offsets. 5911 if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) { 5912 mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name, 5913 ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder)); 5914 } 5915 if (!mAttributes[IFD_TYPE_GPS].isEmpty()) { 5916 mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name, 5917 ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder)); 5918 } 5919 if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) { 5920 mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong( 5921 ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder)); 5922 } 5923 5924 // Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1. 5925 dataOutputStream.writeUnsignedShort(totalSize); 5926 dataOutputStream.write(IDENTIFIER_EXIF_APP1); 5927 dataOutputStream.writeShort(mExifByteOrder == ByteOrder.BIG_ENDIAN 5928 ? BYTE_ALIGN_MM : BYTE_ALIGN_II); 5929 dataOutputStream.setByteOrder(mExifByteOrder); 5930 dataOutputStream.writeUnsignedShort(START_CODE); 5931 dataOutputStream.writeUnsignedInt(IFD_OFFSET); 5932 5933 // Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9. 5934 for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { 5935 if (!mAttributes[ifdType].isEmpty()) { 5936 // See JEITA CP-3451C Section 4.6.2: IFD structure. 5937 // Write entry count 5938 dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size()); 5939 5940 // Write entry info 5941 int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4; 5942 for (Map.Entry<String, ExifAttribute> entry : mAttributes[ifdType].entrySet()) { 5943 // Convert tag name to tag number. 5944 final ExifTag tag = sExifTagMapsForWriting[ifdType].get(entry.getKey()); 5945 final int tagNumber = tag.number; 5946 final ExifAttribute attribute = entry.getValue(); 5947 final int size = attribute.size(); 5948 5949 dataOutputStream.writeUnsignedShort(tagNumber); 5950 dataOutputStream.writeUnsignedShort(attribute.format); 5951 dataOutputStream.writeInt(attribute.numberOfComponents); 5952 if (size > 4) { 5953 dataOutputStream.writeUnsignedInt(dataOffset); 5954 dataOffset += size; 5955 } else { 5956 dataOutputStream.write(attribute.bytes); 5957 // Fill zero up to 4 bytes 5958 if (size < 4) { 5959 for (int i = size; i < 4; ++i) { 5960 dataOutputStream.writeByte(0); 5961 } 5962 } 5963 } 5964 } 5965 5966 // Write the next offset. It writes the offset of thumbnail IFD if there is one or 5967 // more tags in the thumbnail IFD when the current IFD is the primary image TIFF 5968 // IFD; Otherwise 0. 5969 if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { 5970 dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]); 5971 } else { 5972 dataOutputStream.writeUnsignedInt(0); 5973 } 5974 5975 // Write values of data field exceeding 4 bytes after the next offset. 5976 for (Map.Entry<String, ExifAttribute> entry : mAttributes[ifdType].entrySet()) { 5977 ExifAttribute attribute = entry.getValue(); 5978 5979 if (attribute.bytes.length > 4) { 5980 dataOutputStream.write(attribute.bytes, 0, attribute.bytes.length); 5981 } 5982 } 5983 } 5984 } 5985 5986 // Write thumbnail 5987 if (mHasThumbnail) { 5988 dataOutputStream.write(getThumbnailBytes()); 5989 } 5990 5991 // Reset the byte order to big endian in order to write remaining parts of the JPEG file. 5992 dataOutputStream.setByteOrder(ByteOrder.BIG_ENDIAN); 5993 5994 return totalSize; 5995 } 5996 5997 /** 5998 * Determines the data format of EXIF entry value. 5999 * 6000 * @param entryValue The value to be determined. 6001 * @return Returns two data formats gussed as a pair in integer. If there is no two candidate 6002 data formats for the given entry value, returns {@code -1} in the second of the pair. 6003 */ 6004 private static Pair<Integer, Integer> guessDataFormat(String entryValue) { 6005 // See TIFF 6.0 Section 2, "Image File Directory". 6006 // Take the first component if there are more than one component. 6007 if (entryValue.contains(",")) { 6008 String[] entryValues = entryValue.split(","); 6009 Pair<Integer, Integer> dataFormat = guessDataFormat(entryValues[0]); 6010 if (dataFormat.first == IFD_FORMAT_STRING) { 6011 return dataFormat; 6012 } 6013 for (int i = 1; i < entryValues.length; ++i) { 6014 final Pair<Integer, Integer> guessDataFormat = guessDataFormat(entryValues[i]); 6015 int first = -1, second = -1; 6016 if (guessDataFormat.first.equals(dataFormat.first) 6017 || guessDataFormat.second.equals(dataFormat.first)) { 6018 first = dataFormat.first; 6019 } 6020 if (dataFormat.second != -1 && (guessDataFormat.first.equals(dataFormat.second) 6021 || guessDataFormat.second.equals(dataFormat.second))) { 6022 second = dataFormat.second; 6023 } 6024 if (first == -1 && second == -1) { 6025 return new Pair<>(IFD_FORMAT_STRING, -1); 6026 } 6027 if (first == -1) { 6028 dataFormat = new Pair<>(second, -1); 6029 continue; 6030 } 6031 if (second == -1) { 6032 dataFormat = new Pair<>(first, -1); 6033 continue; 6034 } 6035 } 6036 return dataFormat; 6037 } 6038 6039 if (entryValue.contains("/")) { 6040 String[] rationalNumber = entryValue.split("/"); 6041 if (rationalNumber.length == 2) { 6042 try { 6043 long numerator = (long) Double.parseDouble(rationalNumber[0]); 6044 long denominator = (long) Double.parseDouble(rationalNumber[1]); 6045 if (numerator < 0L || denominator < 0L) { 6046 return new Pair<>(IFD_FORMAT_SRATIONAL, -1); 6047 } 6048 if (numerator > Integer.MAX_VALUE || denominator > Integer.MAX_VALUE) { 6049 return new Pair<>(IFD_FORMAT_URATIONAL, -1); 6050 } 6051 return new Pair<>(IFD_FORMAT_SRATIONAL, IFD_FORMAT_URATIONAL); 6052 } catch (NumberFormatException e) { 6053 // Ignored 6054 } 6055 } 6056 return new Pair<>(IFD_FORMAT_STRING, -1); 6057 } 6058 try { 6059 Long longValue = Long.parseLong(entryValue); 6060 if (longValue >= 0 && longValue <= 65535) { 6061 return new Pair<>(IFD_FORMAT_USHORT, IFD_FORMAT_ULONG); 6062 } 6063 if (longValue < 0) { 6064 return new Pair<>(IFD_FORMAT_SLONG, -1); 6065 } 6066 return new Pair<>(IFD_FORMAT_ULONG, -1); 6067 } catch (NumberFormatException e) { 6068 // Ignored 6069 } 6070 try { 6071 Double.parseDouble(entryValue); 6072 return new Pair<>(IFD_FORMAT_DOUBLE, -1); 6073 } catch (NumberFormatException e) { 6074 // Ignored 6075 } 6076 return new Pair<>(IFD_FORMAT_STRING, -1); 6077 } 6078 6079 // An input stream to parse EXIF data area, which can be written in either little or big endian 6080 // order. 6081 private static class ByteOrderedDataInputStream extends InputStream implements DataInput { 6082 private static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN; 6083 private static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN; 6084 6085 private DataInputStream mDataInputStream; 6086 private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN; 6087 private final int mLength; 6088 private int mPosition; 6089 6090 public ByteOrderedDataInputStream(InputStream in) throws IOException { 6091 mDataInputStream = new DataInputStream(in); 6092 mLength = mDataInputStream.available(); 6093 mPosition = 0; 6094 mDataInputStream.mark(mLength); 6095 } 6096 6097 public ByteOrderedDataInputStream(byte[] bytes) throws IOException { 6098 this(new ByteArrayInputStream(bytes)); 6099 } 6100 6101 public void setByteOrder(ByteOrder byteOrder) { 6102 mByteOrder = byteOrder; 6103 } 6104 6105 public void seek(long byteCount) throws IOException { 6106 if (mPosition > byteCount) { 6107 mPosition = 0; 6108 mDataInputStream.reset(); 6109 mDataInputStream.mark(mLength); 6110 } else { 6111 byteCount -= mPosition; 6112 } 6113 6114 if (skipBytes((int) byteCount) != (int) byteCount) { 6115 throw new IOException("Couldn't seek up to the byteCount"); 6116 } 6117 } 6118 6119 public int peek() { 6120 return mPosition; 6121 } 6122 6123 @Override 6124 public int available() throws IOException { 6125 return mDataInputStream.available(); 6126 } 6127 6128 @Override 6129 public int read() throws IOException { 6130 ++mPosition; 6131 return mDataInputStream.read(); 6132 } 6133 6134 @Override 6135 public int read(byte[] b, int off, int len) throws IOException { 6136 int bytesRead = mDataInputStream.read(b, off, len); 6137 mPosition += bytesRead; 6138 return bytesRead; 6139 } 6140 6141 @Override 6142 public int readUnsignedByte() throws IOException { 6143 ++mPosition; 6144 return mDataInputStream.readUnsignedByte(); 6145 } 6146 6147 @Override 6148 public String readLine() throws IOException { 6149 Log.d(TAG, "Currently unsupported"); 6150 return null; 6151 } 6152 6153 @Override 6154 public boolean readBoolean() throws IOException { 6155 ++mPosition; 6156 return mDataInputStream.readBoolean(); 6157 } 6158 6159 @Override 6160 public char readChar() throws IOException { 6161 mPosition += 2; 6162 return mDataInputStream.readChar(); 6163 } 6164 6165 @Override 6166 public String readUTF() throws IOException { 6167 mPosition += 2; 6168 return mDataInputStream.readUTF(); 6169 } 6170 6171 @Override 6172 public void readFully(byte[] buffer, int offset, int length) throws IOException { 6173 mPosition += length; 6174 if (mPosition > mLength) { 6175 throw new EOFException(); 6176 } 6177 if (mDataInputStream.read(buffer, offset, length) != length) { 6178 throw new IOException("Couldn't read up to the length of buffer"); 6179 } 6180 } 6181 6182 @Override 6183 public void readFully(byte[] buffer) throws IOException { 6184 mPosition += buffer.length; 6185 if (mPosition > mLength) { 6186 throw new EOFException(); 6187 } 6188 if (mDataInputStream.read(buffer, 0, buffer.length) != buffer.length) { 6189 throw new IOException("Couldn't read up to the length of buffer"); 6190 } 6191 } 6192 6193 @Override 6194 public byte readByte() throws IOException { 6195 ++mPosition; 6196 if (mPosition > mLength) { 6197 throw new EOFException(); 6198 } 6199 int ch = mDataInputStream.read(); 6200 if (ch < 0) { 6201 throw new EOFException(); 6202 } 6203 return (byte) ch; 6204 } 6205 6206 @Override 6207 public short readShort() throws IOException { 6208 mPosition += 2; 6209 if (mPosition > mLength) { 6210 throw new EOFException(); 6211 } 6212 int ch1 = mDataInputStream.read(); 6213 int ch2 = mDataInputStream.read(); 6214 if ((ch1 | ch2) < 0) { 6215 throw new EOFException(); 6216 } 6217 if (mByteOrder == LITTLE_ENDIAN) { 6218 return (short) ((ch2 << 8) + (ch1)); 6219 } else if (mByteOrder == BIG_ENDIAN) { 6220 return (short) ((ch1 << 8) + (ch2)); 6221 } 6222 throw new IOException("Invalid byte order: " + mByteOrder); 6223 } 6224 6225 @Override 6226 public int readInt() throws IOException { 6227 mPosition += 4; 6228 if (mPosition > mLength) { 6229 throw new EOFException(); 6230 } 6231 int ch1 = mDataInputStream.read(); 6232 int ch2 = mDataInputStream.read(); 6233 int ch3 = mDataInputStream.read(); 6234 int ch4 = mDataInputStream.read(); 6235 if ((ch1 | ch2 | ch3 | ch4) < 0) { 6236 throw new EOFException(); 6237 } 6238 if (mByteOrder == LITTLE_ENDIAN) { 6239 return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1); 6240 } else if (mByteOrder == BIG_ENDIAN) { 6241 return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4); 6242 } 6243 throw new IOException("Invalid byte order: " + mByteOrder); 6244 } 6245 6246 @Override 6247 public int skipBytes(int byteCount) throws IOException { 6248 int totalSkip = Math.min(byteCount, mLength - mPosition); 6249 int skipped = 0; 6250 while (skipped < totalSkip) { 6251 skipped += mDataInputStream.skipBytes(totalSkip - skipped); 6252 } 6253 mPosition += skipped; 6254 return skipped; 6255 } 6256 6257 @Override 6258 public int readUnsignedShort() throws IOException { 6259 mPosition += 2; 6260 if (mPosition > mLength) { 6261 throw new EOFException(); 6262 } 6263 int ch1 = mDataInputStream.read(); 6264 int ch2 = mDataInputStream.read(); 6265 if ((ch1 | ch2) < 0) { 6266 throw new EOFException(); 6267 } 6268 if (mByteOrder == LITTLE_ENDIAN) { 6269 return ((ch2 << 8) + (ch1)); 6270 } else if (mByteOrder == BIG_ENDIAN) { 6271 return ((ch1 << 8) + (ch2)); 6272 } 6273 throw new IOException("Invalid byte order: " + mByteOrder); 6274 } 6275 6276 public long readUnsignedInt() throws IOException { 6277 return readInt() & 0xffffffffL; 6278 } 6279 6280 @Override 6281 public long readLong() throws IOException { 6282 mPosition += 8; 6283 if (mPosition > mLength) { 6284 throw new EOFException(); 6285 } 6286 int ch1 = mDataInputStream.read(); 6287 int ch2 = mDataInputStream.read(); 6288 int ch3 = mDataInputStream.read(); 6289 int ch4 = mDataInputStream.read(); 6290 int ch5 = mDataInputStream.read(); 6291 int ch6 = mDataInputStream.read(); 6292 int ch7 = mDataInputStream.read(); 6293 int ch8 = mDataInputStream.read(); 6294 if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) { 6295 throw new EOFException(); 6296 } 6297 if (mByteOrder == LITTLE_ENDIAN) { 6298 return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40) 6299 + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16) 6300 + ((long) ch2 << 8) + (long) ch1); 6301 } else if (mByteOrder == BIG_ENDIAN) { 6302 return (((long) ch1 << 56) + ((long) ch2 << 48) + ((long) ch3 << 40) 6303 + ((long) ch4 << 32) + ((long) ch5 << 24) + ((long) ch6 << 16) 6304 + ((long) ch7 << 8) + (long) ch8); 6305 } 6306 throw new IOException("Invalid byte order: " + mByteOrder); 6307 } 6308 6309 @Override 6310 public float readFloat() throws IOException { 6311 return Float.intBitsToFloat(readInt()); 6312 } 6313 6314 @Override 6315 public double readDouble() throws IOException { 6316 return Double.longBitsToDouble(readLong()); 6317 } 6318 } 6319 6320 // An output stream to write EXIF data area, which can be written in either little or big endian 6321 // order. 6322 private static class ByteOrderedDataOutputStream extends FilterOutputStream { 6323 private final OutputStream mOutputStream; 6324 private ByteOrder mByteOrder; 6325 6326 public ByteOrderedDataOutputStream(OutputStream out, ByteOrder byteOrder) { 6327 super(out); 6328 mOutputStream = out; 6329 mByteOrder = byteOrder; 6330 } 6331 6332 public void setByteOrder(ByteOrder byteOrder) { 6333 mByteOrder = byteOrder; 6334 } 6335 6336 @Override 6337 public void write(byte[] bytes) throws IOException { 6338 mOutputStream.write(bytes); 6339 } 6340 6341 @Override 6342 public void write(byte[] bytes, int offset, int length) throws IOException { 6343 mOutputStream.write(bytes, offset, length); 6344 } 6345 6346 public void writeByte(int val) throws IOException { 6347 mOutputStream.write(val); 6348 } 6349 6350 public void writeShort(short val) throws IOException { 6351 if (mByteOrder == ByteOrder.LITTLE_ENDIAN) { 6352 mOutputStream.write((val >>> 0) & 0xFF); 6353 mOutputStream.write((val >>> 8) & 0xFF); 6354 } else if (mByteOrder == ByteOrder.BIG_ENDIAN) { 6355 mOutputStream.write((val >>> 8) & 0xFF); 6356 mOutputStream.write((val >>> 0) & 0xFF); 6357 } 6358 } 6359 6360 public void writeInt(int val) throws IOException { 6361 if (mByteOrder == ByteOrder.LITTLE_ENDIAN) { 6362 mOutputStream.write((val >>> 0) & 0xFF); 6363 mOutputStream.write((val >>> 8) & 0xFF); 6364 mOutputStream.write((val >>> 16) & 0xFF); 6365 mOutputStream.write((val >>> 24) & 0xFF); 6366 } else if (mByteOrder == ByteOrder.BIG_ENDIAN) { 6367 mOutputStream.write((val >>> 24) & 0xFF); 6368 mOutputStream.write((val >>> 16) & 0xFF); 6369 mOutputStream.write((val >>> 8) & 0xFF); 6370 mOutputStream.write((val >>> 0) & 0xFF); 6371 } 6372 } 6373 6374 public void writeUnsignedShort(int val) throws IOException { 6375 writeShort((short) val); 6376 } 6377 6378 public void writeUnsignedInt(long val) throws IOException { 6379 writeInt((int) val); 6380 } 6381 } 6382 6383 // Swaps image data based on image size 6384 private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType) 6385 throws IOException { 6386 if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) { 6387 if (DEBUG) { 6388 Log.d(TAG, "Cannot perform swap since only one image data exists"); 6389 } 6390 return; 6391 } 6392 6393 ExifAttribute firstImageLengthAttribute = 6394 (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH); 6395 ExifAttribute firstImageWidthAttribute = 6396 (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH); 6397 ExifAttribute secondImageLengthAttribute = 6398 (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH); 6399 ExifAttribute secondImageWidthAttribute = 6400 (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH); 6401 6402 if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) { 6403 if (DEBUG) { 6404 Log.d(TAG, "First image does not contain valid size information"); 6405 } 6406 } else if (secondImageLengthAttribute == null || secondImageWidthAttribute == null) { 6407 if (DEBUG) { 6408 Log.d(TAG, "Second image does not contain valid size information"); 6409 } 6410 } else { 6411 int firstImageLengthValue = firstImageLengthAttribute.getIntValue(mExifByteOrder); 6412 int firstImageWidthValue = firstImageWidthAttribute.getIntValue(mExifByteOrder); 6413 int secondImageLengthValue = secondImageLengthAttribute.getIntValue(mExifByteOrder); 6414 int secondImageWidthValue = secondImageWidthAttribute.getIntValue(mExifByteOrder); 6415 6416 if (firstImageLengthValue < secondImageLengthValue && 6417 firstImageWidthValue < secondImageWidthValue) { 6418 HashMap<String, ExifAttribute> tempMap = mAttributes[firstIfdType]; 6419 mAttributes[firstIfdType] = mAttributes[secondIfdType]; 6420 mAttributes[secondIfdType] = tempMap; 6421 } 6422 } 6423 } 6424 6425 /** 6426 * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null. 6427 */ 6428 private static void closeQuietly(Closeable closeable) { 6429 if (closeable != null) { 6430 try { 6431 closeable.close(); 6432 } catch (RuntimeException rethrown) { 6433 throw rethrown; 6434 } catch (Exception ignored) { 6435 } 6436 } 6437 } 6438 6439 /** 6440 * Copies all of the bytes from {@code in} to {@code out}. Neither stream is closed. 6441 * Returns the total number of bytes transferred. 6442 */ 6443 private static int copy(InputStream in, OutputStream out) throws IOException { 6444 int total = 0; 6445 byte[] buffer = new byte[8192]; 6446 int c; 6447 while ((c = in.read(buffer)) != -1) { 6448 total += c; 6449 out.write(buffer, 0, c); 6450 } 6451 return total; 6452 } 6453 6454 /** 6455 * Convert given int[] to long[]. If long[] is given, just return it. 6456 * Return null for other types of input. 6457 */ 6458 private static long[] convertToLongArray(Object inputObj) { 6459 if (inputObj instanceof int[]) { 6460 int[] input = (int[]) inputObj; 6461 long[] result = new long[input.length]; 6462 for (int i = 0; i < input.length; i++) { 6463 result[i] = input[i]; 6464 } 6465 return result; 6466 } else if (inputObj instanceof long[]) { 6467 return (long[]) inputObj; 6468 } 6469 return null; 6470 } 6471} 6472