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