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