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