114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon *
414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * Licensed under the Apache License, Version 2.0 (the "License");
514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * you may not use this file except in compliance with the License.
614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * You may obtain a copy of the License at
714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon *
814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon *      http://www.apache.org/licenses/LICENSE-2.0
914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon *
1014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * Unless required by applicable law or agreed to in writing, software
1114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * distributed under the License is distributed on an "AS IS" BASIS,
1214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * See the License for the specific language governing permissions and
1414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * limitations under the License.
1514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon */
1614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.exifinterface.media;
1814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
1914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport android.content.res.AssetManager;
2014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport android.graphics.Bitmap;
2114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport android.graphics.BitmapFactory;
22c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chenimport android.location.Location;
23bc494df67fc94fb970e913eac8bf35ea44edc32cAurimas Liutikasimport android.util.Log;
24bc494df67fc94fb970e913eac8bf35ea44edc32cAurimas Liutikasimport android.util.Pair;
25bc494df67fc94fb970e913eac8bf35ea44edc32cAurimas Liutikas
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntDef;
27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull;
28ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable;
29ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo;
3014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
3114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.BufferedInputStream;
3214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.ByteArrayInputStream;
3314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.Closeable;
3414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.DataInput;
3514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.DataInputStream;
3614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.EOFException;
3714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.File;
3814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.FileInputStream;
3914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.FileNotFoundException;
4014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.FileOutputStream;
4114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.FilterOutputStream;
4214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.IOException;
4314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.InputStream;
4414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.io.OutputStream;
4514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.lang.annotation.Retention;
4614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.lang.annotation.RetentionPolicy;
4714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.nio.ByteBuffer;
4814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.nio.ByteOrder;
4914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.nio.charset.Charset;
5014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.text.ParsePosition;
5114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.text.SimpleDateFormat;
5214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.Arrays;
5314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.Date;
5414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.HashMap;
5514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.HashSet;
56bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangrenimport java.util.List;
5714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.Map;
5814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.TimeZone;
59c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chenimport java.util.concurrent.TimeUnit;
6014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.regex.Matcher;
6114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonimport java.util.regex.Pattern;
6214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
6314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon/**
6414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
6514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * <p>
6614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW and RAF.
6714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * <p>
6814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon * Attribute mutation is supported for JPEG image files.
6914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon */
7014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moonpublic class ExifInterface {
7114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final String TAG = "ExifInterface";
7214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final boolean DEBUG = false;
7314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // The Exif tag names. See JEITA CP-3451C specifications (Exif 2.3) Section 3-8.
758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // A. Tags related to image data structure
768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of columns of image data, equal to the number of pixels per row. In JPEG
788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p>
798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 256</li>
828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_IMAGE_WIDTH = "ImageWidth";
888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of rows of image data. In JPEG compressed data, this tag shall not be used
908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  because a JPEG marker is used instead of it.</p>
918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 257</li>
948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_IMAGE_LENGTH = "ImageLength";
1008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of bits per image component. In this standard each component of the image is
1028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  8 bits, so the value for this tag is 8. See also {@link #TAG_SAMPLES_PER_PIXEL}. In JPEG
1038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p>
1048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 258</li>
1078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
1088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
1098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #BITS_PER_SAMPLE_RGB}</li>
1108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
1138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The compression scheme used for the image data. When a primary image is JPEG compressed,
1158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  this designation is not necessary. So, this tag shall not be recorded. When thumbnails use
1168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  JPEG compression, this tag value is set to 6.</p>
1178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 259</li>
1208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
1218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
1228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
1238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #DATA_UNCOMPRESSED
1268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #DATA_JPEG
1278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_COMPRESSION = "Compression";
1298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The pixel composition. In JPEG compressed data, this tag shall not be used because a JPEG
1318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  marker is used instead of it.</p>
1328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 262</li>
1358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = SHORT</li>
1368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
1378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
1388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #PHOTOMETRIC_INTERPRETATION_RGB
1418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #PHOTOMETRIC_INTERPRETATION_YCBCR
1428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
1448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The image orientation viewed in terms of rows and columns.</p>
1468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 274</li>
1498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
1508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
1518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #ORIENTATION_NORMAL}</li>
1528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_UNDEFINED
1558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_NORMAL
1568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_FLIP_HORIZONTAL
1578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_ROTATE_180
1588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_FLIP_VERTICAL
1598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_TRANSPOSE
1608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_ROTATE_90
1618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_TRANSVERSE
1628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ORIENTATION_ROTATE_270
1638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
1648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ORIENTATION = "Orientation";
1658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of components per pixel. Since this standard applies to RGB and YCbCr images,
1678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the value set for this tag is 3. In JPEG compressed data, this tag shall not be used because
1688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a JPEG marker is used instead of it.</p>
1698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 277</li>
1728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
1738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
1748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 3</li>
1758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
1778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
1788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether pixel components are recorded in chunky or planar format. In JPEG
1808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.
1818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  If this field does not exist, the TIFF default, {@link #FORMAT_CHUNKY}, is assumed.</p>
1828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 284</li>
1858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
1868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
1878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
1888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FORMAT_CHUNKY
1908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FORMAT_PLANAR
1918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
1938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
1948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The sampling ratio of chrominance components in relation to the luminance component.
1958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  In JPEG compressed data a JPEG marker is used instead of this tag. So, this tag shall not
1968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be recorded.</p>
1978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
1988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
1998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 530</li>
2008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
2018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 2</li>
2028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <ul>
2038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>[2, 1] = YCbCr4:2:2</li>
2048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>[2, 2] = YCbCr4:2:0</li>
2058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Other = reserved</li>
2068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      </ul>
2078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
2098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
2108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
2118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The position of chrominance components in relation to the luminance component. This field
2128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is designated only for JPEG compressed data or uncompressed YCbCr data. The TIFF default is
2138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #Y_CB_CR_POSITIONING_CENTERED}; but when Y:Cb:Cr = 4:2:2 it is recommended in this
2148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  standard that {@link #Y_CB_CR_POSITIONING_CO_SITED} be used to record data, in order to
2158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  improve the image quality when viewed on TV systems. When this field does not exist,
2168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the reader shall assume the TIFF default. In the case of Y:Cb:Cr = 4:2:0, the TIFF default
2178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  ({@link #Y_CB_CR_POSITIONING_CENTERED}) is recommended. If the Exif/DCF reader does not
2188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  have the capability of supporting both kinds of positioning, it shall follow the TIFF
2198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  default regardless of the value in this field. It is preferable that readers can support
2208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  both centered and co-sited positioning.</p>
2218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
2238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 531</li>
2248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
2258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
2268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #Y_CB_CR_POSITIONING_CENTERED}</li>
2278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #Y_CB_CR_POSITIONING_CENTERED
2308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #Y_CB_CR_POSITIONING_CO_SITED
2318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
2328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
2338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
2348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH}
2358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  direction. When the image resolution is unknown, 72 [dpi] shall be designated.</p>
2368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
2388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 282</li>
2398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
2408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
2418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 72</li>
2428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_Y_RESOLUTION
2458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_RESOLUTION_UNIT
2468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
2478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_X_RESOLUTION = "XResolution";
2488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
2498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH}
2508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  direction. The same value as {@link #TAG_X_RESOLUTION} shall be designated.</p>
2518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
2538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 283</li>
2548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
2558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
2568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 72</li>
2578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_X_RESOLUTION
2608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_RESOLUTION_UNIT
2618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
2628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_Y_RESOLUTION = "YResolution";
2638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
2648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The unit for measuring {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. The same
2658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  unit is used for both {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. If the image
2668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  resolution is unknown, {@link #RESOLUTION_UNIT_INCHES} shall be designated.</p>
2678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
2698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 296</li>
2708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
2718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
2728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li>
2738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RESOLUTION_UNIT_INCHES
2768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RESOLUTION_UNIT_CENTIMETERS
2778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_X_RESOLUTION
2788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_Y_RESOLUTION
2798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
2818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
2828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // B. Tags related to recording offset
2838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
2848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>For each strip, the byte offset of that strip. It is recommended that this be selected
2858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  so the number of strip bytes does not exceed 64 KBytes.In the case of JPEG compressed data,
2868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  this designation is not necessary. So, this tag shall not be recorded.</p>
2878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
2898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 273</li>
2908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
2918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = StripsPerImage (for {@link #FORMAT_CHUNKY})
2928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *               or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage
2938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *               (for {@link #FORMAT_PLANAR})</li>
2948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
2958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
2968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
2978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1)
2988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  / {@link #TAG_ROWS_PER_STRIP})</p>
2998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_ROWS_PER_STRIP
3018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_STRIP_BYTE_COUNTS
3028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
3038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_STRIP_OFFSETS = "StripOffsets";
3048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of rows per strip. This is the number of rows in the image of one strip when
3068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  an image is divided into strips. In the case of JPEG compressed data, this designation is
3078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  not necessary. So, this tag shall not be recorded.</p>
3088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 278</li>
3118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
3128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
3138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_STRIP_OFFSETS
3178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_STRIP_BYTE_COUNTS
3188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
31914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
3208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The total number of bytes in each strip. In the case of JPEG compressed data, this
3228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  designation is not necessary. So, this tag shall not be recorded.</p>
3238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 279</li>
3268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
3278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = StripsPerImage (when using {@link #FORMAT_CHUNKY})
3288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *               or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage
3298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *               (when using {@link #FORMAT_PLANAR})</li>
3308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1)
3348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  / {@link #TAG_ROWS_PER_STRIP})</p>
3358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
33614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
3378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The offset to the start byte (SOI) of JPEG compressed thumbnail data. This shall not be
3398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  used for primary image JPEG data.</p>
3408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 513</li>
3438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
3448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
3478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
3488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The number of bytes of JPEG compressed thumbnail data. This is not used for primary image
3508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  JPEG data. JPEG thumbnails are not divided but are recorded as a continuous JPEG bitstream
3518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  from SOI to EOI. APPn and COM markers should not be recorded. Compressed thumbnails shall be
3528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  recorded in no more than 64 KBytes, including all other data to be recorded in APP1.</p>
3538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 514</li>
3568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
3578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
3608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
3618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
3628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // C. Tags related to Image Data Characteristics
3638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A transfer function for the image, described in tabular style. Normally this tag need not
3658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
3668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 301</li>
3698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
3708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3 * 256</li>
3718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
37414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
3758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The chromaticity of the white point of the image. Normally this tag need not be used,
3778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
3788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 318</li>
3818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
3828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 2</li>
3838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
38614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_WHITE_POINT = "WhitePoint";
3878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
3888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The chromaticity of the three primary colors of the image. Normally this tag need not
3898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
3908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
3918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
3928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 319</li>
3938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
3948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 6</li>
3958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
3968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
3978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
3988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
3998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The matrix coefficients for transformation from RGB to YCbCr image data. About
4018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the default value, please refer to JEITA CP-3451C Spec, Annex D.</p>
4028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 529</li>
4058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
4068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
4078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
40914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
4108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The reference black point value and reference white point value. No defaults are given
4128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  in TIFF, but the values below are given as defaults here. The color space is declared in
4138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a color space information tag, with the default being the value that gives the optimal image
4148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  characteristics Interoperability these conditions</p>
4158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 532</li>
4188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = RATIONAL</li>
4198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 6</li>
4208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = [0, 255, 0, 255, 0, 255] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION}
4218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                 is {@link #PHOTOMETRIC_INTERPRETATION_RGB})
4228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                 or [0, 255, 0, 128, 0, 128] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION}
4238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                 is {@link #PHOTOMETRIC_INTERPRETATION_YCBCR})</li>
4248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
4278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
4288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // D. Other tags
4298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The date and time of image creation. In this standard it is the date and time the file
4318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  was changed. The format is "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and
4328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the date and time separated by one blank character ({@code 0x20}). When the date and time
4338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  are unknown, all the character spaces except colons (":") should be filled with blank
4348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  characters, or else the Interoperability field should be filled with blank characters.
4358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The character string length is 20 Bytes including NULL for termination. When the field is
4368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  left blank, it is treated as unknown.</p>
4378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 306</li>
4408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
4418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 19</li>
4428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
4438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DATETIME = "DateTime";
4468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>An ASCII string giving the title of the image. It is possible to be added a comment
4488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  such as "1988 company picnic" or the like. Two-byte character codes cannot be used. When
4498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a 2-byte code is necessary, {@link #TAG_USER_COMMENT} is to be used.</p>
4508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 270</li>
4538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
4548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
4558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
4588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The manufacturer of the recording equipment. This is the manufacturer of the DSC,
4608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  scanner, video digitizer or other equipment that generated the image. When the field is left
4618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  blank, it is treated as unknown.</p>
4628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 271</li>
4658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
4668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
4678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_MAKE = "Make";
4708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The model name or model number of the equipment. This is the model name of number of
4728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the DSC, scanner, video digitizer or other equipment that generated the image. When
4738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the field is left blank, it is treated as unknown.</p>
4748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 272</li>
4778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
4788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
4798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_MODEL = "Model";
4828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the name and version of the software or firmware of the camera or image
4848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  input device used to generate the image. The detailed format is not specified, but it is
4858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  recommended that the example shown below be followed. When the field is left blank, it is
4868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  treated as unknown.</p>
4878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Ex.) "Exif Software Version 1.00a".</p>
4898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
4908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
4918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 305</li>
4928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
4938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
4948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
4958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
4968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SOFTWARE = "Software";
4978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
4988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the name of the camera owner, photographer or image creator.
4998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The detailed format is not specified, but it is recommended that the information be written
5008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  as in the example below for ease of Interoperability. When the field is left blank, it is
5018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  treated as unknown.</p>
5028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Ex.) "Camera owner, John Smith; Photographer, Michael Brown; Image creator,
5048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Ken James"</p>
5058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
5078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 315</li>
5088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
5098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
5108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
5118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
5128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ARTIST = "Artist";
5138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
5148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Copyright information. In this standard the tag is used to indicate both the photographer
5158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  and editor copyrights. It is the copyright notice of the person or organization claiming
5168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  rights to the image. The Interoperability copyright statement including date and rights
5178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  should be written in this field; e.g., "Copyright, John Smith, 19xx. All rights reserved."
5188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  In this standard the field records both the photographer and editor copyrights, with each
5198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  recorded in a separate part of the statement. When there is a clear distinction between
5208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the photographer and editor copyrights, these are to be written in the order of photographer
5218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  followed by editor copyright, separated by NULL (in this case, since the statement also ends
5228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  with a NULL, there are two NULL codes) (see example 1). When only the photographer copyright
5238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is given, it is terminated by one NULL code (see example 2). When only the editor copyright
5248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is given, the photographer copyright part consists of one space followed by a terminating
5258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  NULL code, then the editor copyright is given (see example 3). When the field is left blank,
5268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  it is treated as unknown.</p>
5278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Ex. 1) When both the photographer copyright and editor copyright are given.
5298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul><li>Photographer copyright + NULL + editor copyright + NULL</li></ul></p>
5308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Ex. 2) When only the photographer copyright is given.
5318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul><li>Photographer copyright + NULL</li></ul></p>
5328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Ex. 3) When only the editor copyright is given.
5338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul><li>Space ({@code 0x20}) + NULL + editor copyright + NULL</li></ul></p>
5348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
5368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 315</li>
5378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
5388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
5398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
5408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
5418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_COPYRIGHT = "Copyright";
5428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
5438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // Exif IFD Attribute Information
5448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // A. Tags related to version
5458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
5468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The version of this standard supported. Nonexistence of this field is taken to mean
5478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  nonconformance to the standard. In according with conformance to this standard, this tag
5488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  shall be recorded like "0230” as 4-byte ASCII.</p>
5498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
5518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 36864</li>
5528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
5538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 4</li>
5548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = "0230"</li>
5558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
5568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
55714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_EXIF_VERSION = "ExifVersion";
5588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
5598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The Flashpix format version supported by a FPXR file. If the FPXR function supports
5608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Flashpix format Ver. 1.0, this is indicated similarly to {@link #TAG_EXIF_VERSION} by
5618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  recording "0100" as 4-byte ASCII.</p>
5628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
5648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 40960</li>
5658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
5668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 4</li>
5678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = "0100"</li>
5688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
5698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
57014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
5718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
5728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // B. Tags related to image data characteristics
5738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
5748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The color space information tag is always recorded as the color space specifier.
5758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Normally {@link #COLOR_SPACE_S_RGB} is used to define the color space based on the PC
5768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  monitor conditions and environment. If a color space other than {@link #COLOR_SPACE_S_RGB}
5778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is used, {@link #COLOR_SPACE_UNCALIBRATED} is set. Image data recorded as
5788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #COLOR_SPACE_UNCALIBRATED} may be treated as {@link #COLOR_SPACE_S_RGB} when it is
5798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  converted to Flashpix.</p>
5808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
5828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 40961</li>
5838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
5848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
5858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
5868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #COLOR_SPACE_S_RGB
5888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #COLOR_SPACE_UNCALIBRATED
5898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
5908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_COLOR_SPACE = "ColorSpace";
5918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
5928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the value of coefficient gamma. The formula of transfer function used for image
5938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  reproduction is expressed as follows.</p>
5948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>(Reproduced value) = (Input value) ^ gamma</p>
5968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
5978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Both reproduced value and input value indicate normalized value, whose minimum value is
5988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  0 and maximum value is 1.</p>
5998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42240</li>
6028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
6038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
6048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
6058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
6078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GAMMA = "Gamma";
6088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
6098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // C. Tags related to image configuration
6108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Information specific to compressed data. When a compressed file is recorded, the valid
6128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  width of the meaningful image shall be recorded in this tag, whether or not there is padding
6138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  data or a restart marker. This tag shall not exist in an uncompressed file.</p>
6148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 40962</li>
6178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
6188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
6198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
6208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
62214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
6238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Information specific to compressed data. When a compressed file is recorded, the valid
6258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  height of the meaningful image shall be recorded in this tag, whether or not there is
6268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  padding data or a restart marker. This tag shall not exist in an uncompressed file.
6278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Since data padding is unnecessary in the vertical direction, the number of lines recorded
6288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  in this valid image height tag will in fact be the same as that recorded in the SOF.</p>
6298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 40963</li>
6328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short or Unsigned long</li>
6338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
6348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
63614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
6378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Information specific to compressed data. The channels of each component are arranged
6398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  in order from the 1st component to the 4th. For uncompressed data the data arrangement is
6408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  given in the {@link #TAG_PHOTOMETRIC_INTERPRETATION}. However, since
6418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_PHOTOMETRIC_INTERPRETATION} can only express the order of Y, Cb and Cr, this tag
6428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is provided for cases when compressed data uses components other than Y, Cb, and Cr and to
6438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  enable support of other sequences.</p>
6448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37121</li>
6478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
6488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 4</li>
6498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 4 5 6 0 (if RGB uncompressed) or 1 2 3 0 (other cases)</li>
6508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <ul>
6518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>0 = does not exist</li>
6528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>1 = Y</li>
6538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>2 = Cb</li>
6548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>3 = Cr</li>
6558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>4 = R</li>
6568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>5 = G</li>
6578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>6 = B</li>
6588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>other = reserved</li>
6598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      </ul>
6608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
6628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
6638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Information specific to compressed data. The compression mode used for a compressed image
6658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is indicated in unit bits per pixel.</p>
6668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37122</li>
6698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
6708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
6718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
6728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
6748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
6758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
6768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // D. Tags related to user information
6778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A tag for manufacturers of Exif/DCF writers to record any desired information.
6798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The contents are up to the manufacturer, but this tag shall not be used for any other than
6808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  its intended purpose.</p>
6818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37500</li>
6848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
6858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
6868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
6888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_MAKER_NOTE = "MakerNote";
6898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
6908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A tag for Exif users to write keywords or comments on the image besides those in
6918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_IMAGE_DESCRIPTION}, and without the character code limitations of it.</p>
6928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
6938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
6948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37510</li>
6958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
6968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
6978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
6988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
6998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_USER_COMMENT = "UserComment";
7008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
7018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // E. Tags related to related file information
7028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag is used to record the name of an audio file related to the image data. The only
7048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  relational information recorded here is the Exif audio file name and extension (an ASCII
7058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  string consisting of 8 characters + '.' + 3 characters). The path is not recorded.</p>
7068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>When using this tag, audio files shall be recorded in conformance to the Exif audio
7088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  format. Writers can also store the data such as Audio within APP2 as Flashpix extension
7098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  stream data. Audio files shall be recorded in conformance to the Exif audio format.</p>
7108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 40964</li>
7138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 12</li>
7158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
71814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
7198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
7208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // F. Tags related to date and time
7218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The date and time when the original image data was generated. For a DSC the date and time
7238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the picture was taken are recorded. The format is "YYYY:MM:DD HH:MM:SS" with time shown in
7248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  24-hour format, and the date and time separated by one blank character ({@code 0x20}).
7258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  When the date and time are unknown, all the character spaces except colons (":") should be
7268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  filled with blank characters, or else the Interoperability field should be filled with blank
7278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  characters. When the field is left blank, it is treated as unknown.</p>
7288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 36867</li>
7318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 19</li>
7338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
7368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
7378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The date and time when the image was stored as digital data. If, for example, an image
7398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  was captured by DSC and at the same time the file was recorded, then
7408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_DATETIME_ORIGINAL} and this tag will have the same contents. The format is
7418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and the date and time separated by
7428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  one blank character ({@code 0x20}). When the date and time are unknown, all the character
7438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  spaces except colons (":")should be filled with blank characters, or else
7448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the Interoperability field should be filled with blank characters. When the field is left
7458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  blank, it is treated as unknown.</p>
7468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 36868</li>
7498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 19</li>
7518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
7548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
7558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME}.</p>
7578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37520</li>
7608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
76414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_SUBSEC_TIME = "SubSecTime";
7658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_ORIGINAL}.</p>
7678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37521</li>
7708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
77414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
7758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_DIGITIZED}.</p>
7778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37522</li>
7808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
7818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
7848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
7858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
7868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // G. Tags related to picture-taking condition
7878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Exposure time, given in seconds.</p>
7898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
7908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
7918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 33434</li>
7928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
7938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
7948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
7958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
7968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
7978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_EXPOSURE_TIME = "ExposureTime";
7988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
7998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The F number.</p>
8008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 33437</li>
8038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
8048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
8058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
8068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_F_NUMBER = "FNumber";
8098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>TThe class of the program used by the camera to set exposure when the picture is taken.
8118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The tag values are as follows.</p>
8128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34850</li>
8158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
8168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
8178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #EXPOSURE_PROGRAM_NOT_DEFINED}</li>
8188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_NOT_DEFINED
8218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_MANUAL
8228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_NORMAL
8238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_APERTURE_PRIORITY
8248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_SHUTTER_PRIORITY
8258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_CREATIVE
8268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_ACTION
8278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_PORTRAIT_MODE
8288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_PROGRAM_LANDSCAPE_MODE
8298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
8318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the spectral sensitivity of each channel of the camera used. The tag value is
8338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  an ASCII string compatible with the standard developed by the ASTM Technical committee.</p>
8348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34852</li>
8378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
8388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
8398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
8428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @deprecated Use {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} instead.
8448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_PHOTOGRAPHIC_SENSITIVITY
8458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
8478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the sensitivity of the camera or input device when the image was shot.
8498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  More specifically, it indicates one of the following values that are parameters defined in
8508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  ISO 12232: standard output sensitivity (SOS), recommended exposure index (REI), or ISO
8518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  speed. Accordingly, if a tag corresponding to a parameter that is designated by
8528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_SENSITIVITY_TYPE} is recorded, the values of the tag and of this tag are
8538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the same. However, if the value is 65535 or higher, the value of this tag shall be 65535.
8548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  When recording this tag, {@link #TAG_SENSITIVITY_TYPE} should also be recorded. In addition,
8558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  while “Count = Any”, only 1 count should be used when recording this tag.</p>
8568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34855</li>
8598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
8608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = Any</li>
8618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
8628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
8658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524. OECF is
8678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the relationship between the camera optical input and the image values.</p>
8688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34856</li>
8718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
8728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
8738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_OECF = "OECF";
8768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates which one of the parameters of ISO12232 is
8788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_PHOTOGRAPHIC_SENSITIVITY}. Although it is an optional tag, it should be recorded
8798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  when {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} is recorded.</p>
8808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
8828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34864</li>
8838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
8848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
8858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
8868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
8878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
8888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_UNKNOWN
8898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_SOS
8908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_REI
8918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_ISO_SPEED
8928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_SOS_AND_REI
8938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_SOS_AND_ISO
8948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_REI_AND_ISO
8958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO
8968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
8978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SENSITIVITY_TYPE = "SensitivityType";
8988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
8998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the standard output sensitivity value of a camera or input device
9008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
9018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
9028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34865</li>
9058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
9068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
9118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the recommended exposure index value of a camera or input device
9138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
9148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
9158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34866</li>
9188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
9198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
9248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the ISO speed value of a camera or input device that is defined in
9268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
9278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
9288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34867</li>
9318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
9328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ISO_SPEED = "ISOSpeed";
9378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the ISO speed latitude yyy value of a camera or input device that is
9398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED}
9408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  and {@link #TAG_ISO_SPEED_LATITUDE_ZZZ}.</p>
9418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34868</li>
9448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
9458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
9508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the ISO speed latitude zzz value of a camera or input device that is
9528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED}
9538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  and {@link #TAG_ISO_SPEED_LATITUDE_YYY}.</p>
9548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 34869</li>
9578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned long</li>
9588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
9638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Shutter speed. The unit is the APEX setting.</p>
9658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37377</li>
9688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Signed rational</li>
9698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
9748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The lens aperture. The unit is the APEX value.</p>
9768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37378</li>
9798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
9808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_APERTURE_VALUE = "ApertureValue";
9858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The value of brightness. The unit is the APEX value. Ordinarily it is given in the range
9878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  of -99.99 to 99.99. Note that if the numerator of the recorded value is 0xFFFFFFFF,
9888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Unknown shall be indicated.</p>
9898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
9908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
9918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37379</li>
9928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Signed rational</li>
9938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
9948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
9958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
9968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
9978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
9988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
9998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The exposure bias. The unit is the APEX value. Ordinarily it is given in the range of
10008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  -99.99 to 99.99.</p>
10018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37380</li>
10048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Signed rational</li>
10058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
10078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
10088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
10098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
10108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
10118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The smallest F number of the lens. The unit is the APEX value. Ordinarily it is given
10128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  in the range of 00.00 to 99.99, but it is not limited to this range.</p>
10138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37381</li>
10168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
10178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
10198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
10208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
10218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
10228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
10238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The distance to the subject, given in meters. Note that if the numerator of the recorded
10248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  value is 0xFFFFFFFF, Infinity shall be indicated; and if the numerator is 0, Distance
10258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  unknown shall be indicated.</p>
10268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37382</li>
10298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
10308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
10328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
10338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
10348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
10358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
10368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The metering mode.</p>
10378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37383</li>
10408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
10418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #METERING_MODE_UNKNOWN}</li>
10438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
10448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_UNKNOWN
10468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_AVERAGE
10478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_CENTER_WEIGHT_AVERAGE
10488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_SPOT
10498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_MULTI_SPOT
10508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_PATTERN
10518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_PARTIAL
10528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #METERING_MODE_OTHER
10538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
10548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_METERING_MODE = "MeteringMode";
10558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
10568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The kind of light source.</p>
10578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37384</li>
10608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
10618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #LIGHT_SOURCE_UNKNOWN}</li>
10638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
10648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_UNKNOWN
10668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_DAYLIGHT
10678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_FLUORESCENT
10688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_TUNGSTEN
10698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_FLASH
10708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_FINE_WEATHER
10718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_CLOUDY_WEATHER
10728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_SHADE
10738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_DAYLIGHT_FLUORESCENT
10748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_DAY_WHITE_FLUORESCENT
10758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_COOL_WHITE_FLUORESCENT
10768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_WHITE_FLUORESCENT
10778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_WARM_WHITE_FLUORESCENT
10788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_A
10798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_B
10808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_C
10818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_D55
10828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_D65
10838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_D75
10848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_D50
10858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN
10868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LIGHT_SOURCE_OTHER
10878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
10888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_LIGHT_SOURCE = "LightSource";
10898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
10908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the status of flash when the image was shot. Bit 0 indicates the flash
10918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  firing status, bits 1 and 2 indicate the flash return status, bits 3 and 4 indicate
10928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the flash mode, bit 5 indicates whether the flash function is present, and bit 6 indicates
10938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  "red eye" mode.</p>
10948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
10958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
10968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37385</li>
10978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
10988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
10998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_FIRED
11028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED
11038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_RETURN_LIGHT_DETECTED
11048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
11058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
11068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_MODE_AUTO
11078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_NO_FLASH_FUNCTION
11088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FLAG_FLASH_RED_EYE_SUPPORTED
11098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FLASH = "Flash";
11118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the location and area of the main subject in the overall scene.</p>
11138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37396</li>
11168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
11178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 2 or 3 or 4</li>
11188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The subject location and area are defined by Count values as follows.</p>
11228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 2 Indicates the location of the main subject as coordinates. The first value
11258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    is the X coordinate and the second is the Y coordinate.</li>
11268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3 The area of the main subject is given as a circle. The circular area is
11278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    expressed as center coordinates and diameter. The first value is
11288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    the center X coordinate, the second is the center Y coordinate, and
11298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    the third is the diameter.</li>
11308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 4 The area of the main subject is given as a rectangle. The rectangular
11318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    area is expressed as center coordinates and area dimensions. The first
11328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    value is the center X coordinate, the second is the center Y coordinate,
11338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    the third is the width of the area, and the fourth is the height of
11348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                    the area.</li>
11358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Note that the coordinate values, width, and height are expressed in relation to the upper
11388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  left as origin, prior to rotation processing as per {@link #TAG_ORIENTATION}.</p>
11398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SUBJECT_AREA = "SubjectArea";
11418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>The actual focal length of the lens, in mm. Conversion is not made to the focal length
11438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  of a 35mm film camera.</p>
11448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 37386</li>
11478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
11488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
11498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FOCAL_LENGTH = "FocalLength";
11538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the strobe energy at the time the image is captured, as measured in Beam Candle
11558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Power Seconds (BCPS).</p>
11568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41483</li>
11598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
11608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
11618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FLASH_ENERGY = "FlashEnergy";
11658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the camera or input device spatial frequency table and SFR values in
11678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the direction of image width, image height, and diagonal direction, as specified in
11688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  ISO 12233.</p>
11698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41484</li>
11728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
11738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
11778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the number of pixels in the image width (X) direction per
11798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p>
11808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41486</li>
11838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
11848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
11858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
11888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
11898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
11908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the number of pixels in the image height (Y) direction per
11918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p>
11928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
11938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
11948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41487</li>
11958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
11968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
11978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
11988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
11998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
12018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the unit for measuring {@link #TAG_FOCAL_PLANE_X_RESOLUTION} and
12038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_FOCAL_PLANE_Y_RESOLUTION}. This value is the same as
12048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_RESOLUTION_UNIT}.</p>
12058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41488</li>
12088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
12098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
12108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li>
12118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_RESOLUTION_UNIT
12148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RESOLUTION_UNIT_INCHES
12158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RESOLUTION_UNIT_CENTIMETERS
12168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
12188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the location of the main subject in the scene. The value of this tag represents
12208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the pixel at the center of the main subject relative to the left edge, prior to rotation
12218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  processing as per {@link #TAG_ORIENTATION}. The first value indicates the X column number
12228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  and second indicates the Y row number. When a camera records the main subject location,
12238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  it is recommended that {@link #TAG_SUBJECT_AREA} be used instead of this tag.</p>
12248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41492</li>
12278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
12288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 2</li>
12298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
12308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
123214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
12338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the exposure index selected on the camera or input device at the time the image
12358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  is captured.</p>
12368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41493</li>
12398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
12408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
12418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
12428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
12458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the image sensor type on the camera or input device.</p>
12478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41495</li>
12508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
12518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
12528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
12538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_NOT_DEFINED
12568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_ONE_CHIP
12578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_TWO_CHIP
12588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_THREE_CHIP
12598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_COLOR_SEQUENTIAL
12608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_TRILINEAR
12618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR
12628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SENSING_METHOD = "SensingMethod";
12648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the image source. If a DSC recorded the image, this tag value always shall
12668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be set to {@link #FILE_SOURCE_DSC}.</p>
12678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41728</li>
12708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
12718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
12728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #FILE_SOURCE_DSC}</li>
12738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FILE_SOURCE_OTHER
12768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FILE_SOURCE_TRANSPARENT_SCANNER
12778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FILE_SOURCE_REFLEX_SCANNER
12788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #FILE_SOURCE_DSC
12798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FILE_SOURCE = "FileSource";
12818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the type of scene. If a DSC recorded the image, this tag value shall always
12838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be set to {@link #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED}.</p>
12848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
12868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41729</li>
12878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
12888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
12898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 1</li>
12908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
12918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED
12938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
12948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SCENE_TYPE = "SceneType";
12958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
12968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the color filter array (CFA) geometric pattern of the image sensor when
12978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a one-chip color area sensor is used. It does not apply to all sensing methods.</p>
12988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
12998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41730</li>
13018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
13028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
13038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #TAG_SENSING_METHOD
13068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SENSOR_TYPE_ONE_CHIP
13078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_CFA_PATTERN = "CFAPattern";
13098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
13108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the use of special processing on image data, such as rendering geared
13118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  to output. When special processing is performed, the Exif/DCF reader is expected to disable
13128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  or minimize any further processing.</p>
13138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41985</li>
13168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
13178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #RENDERED_PROCESS_NORMAL}</li>
13198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RENDERED_PROCESS_NORMAL
13228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #RENDERED_PROCESS_CUSTOM
13238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
13258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
13268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the exposure mode set when the image was shot.
13278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  In {@link #EXPOSURE_MODE_AUTO_BRACKET}, the camera shoots a series of frames of the same
13288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  scene at different exposure settings.</p>
13298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41986</li>
13328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
13338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
13358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_MODE_AUTO
13388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_MODE_MANUAL
13398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #EXPOSURE_MODE_AUTO_BRACKET
13408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
13428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
13438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the white balance mode set when the image was shot.</p>
13448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41987</li>
13478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
13488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
13508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #WHITEBALANCE_AUTO
13538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #WHITEBALANCE_MANUAL
13548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
135514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public static final String TAG_WHITE_BALANCE = "WhiteBalance";
135614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
13578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the digital zoom ratio when the image was shot. If the numerator of
13588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the recorded value is 0, this indicates that digital zoom was not used.</p>
13598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41988</li>
13628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
13638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
13658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
13688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
13698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the equivalent focal length assuming a 35mm film camera, in mm.
13708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  A value of 0 means the focal length is unknown. Note that this tag differs from
13718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_FOCAL_LENGTH}.</p>
13728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41989</li>
13758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
13768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
13788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
13818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
13828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the type of scene that was shot. It may also be used to record
13838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the mode in which the image was shot. Note that this differs from
13848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_SCENE_TYPE}.</p>
13858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
13878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41990</li>
13888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
13898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
13908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 0</li>
13918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
13928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
13938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SCENE_CAPTURE_TYPE_STANDARD
13948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SCENE_CAPTURE_TYPE_LANDSCAPE
13958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SCENE_CAPTURE_TYPE_PORTRAIT
13968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SCENE_CAPTURE_TYPE_NIGHT
13978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
13988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
13998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the degree of overall image gain adjustment.</p>
14018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41991</li>
14048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
14058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
14068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
14078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GAIN_CONTROL_NONE
14108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GAIN_CONTROL_LOW_GAIN_UP
14118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GAIN_CONTROL_HIGH_GAIN_UP
14128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GAIN_CONTROL_LOW_GAIN_DOWN
14138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GAIN_CONTROL_HIGH_GAIN_DOWN
14148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GAIN_CONTROL = "GainControl";
14168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the direction of contrast processing applied by the camera when
14188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the image was shot.</p>
14198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41992</li>
14228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
14238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
14248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #CONTRAST_NORMAL}</li>
14258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #CONTRAST_NORMAL
14288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #CONTRAST_SOFT
14298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #CONTRAST_HARD
14308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_CONTRAST = "Contrast";
14328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the direction of saturation processing applied by the camera when
14348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the image was shot.</p>
14358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41993</li>
14388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
14398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
14408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #SATURATION_NORMAL}</li>
14418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SATURATION_NORMAL
14448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SATURATION_LOW
14458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SATURATION_HIGH
14468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SATURATION = "Saturation";
14488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the direction of sharpness processing applied by the camera when
14508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the image was shot.</p>
14518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41994</li>
14548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
14558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
14568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #SHARPNESS_NORMAL}</li>
14578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SHARPNESS_NORMAL
14608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SHARPNESS_SOFT
14618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SHARPNESS_HARD
14628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SHARPNESS = "Sharpness";
14648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates information on the picture-taking conditions of a particular camera
14668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  model. The tag is used only to indicate the picture-taking conditions in the Exif/DCF
14678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  reader.</p>
14688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41995</li>
14718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
14728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
14738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
14768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates the distance to the subject.</p>
14788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 41996</li>
14818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
14828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
14838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
14848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
14858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SUBJECT_DISTANCE_RANGE_UNKNOWN
14878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SUBJECT_DISTANCE_RANGE_MACRO
14888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SUBJECT_DISTANCE_RANGE_CLOSE_VIEW
14898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #SUBJECT_DISTANCE_RANGE_DISTANT_VIEW
14908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
14918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
14928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
14938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // H. Other tags
14948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
14958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates an identifier assigned uniquely to each image. It is recorded as
14968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  an ASCII string equivalent to hexadecimal notation and 128-bit fixed length.</p>
14978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
14988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
14998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42016</li>
15008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 32</li>
15028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
15068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the owner of a camera used in photography as an ASCII string.</p>
15088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42032</li>
15118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
15168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the serial number of the body of the camera that was used in photography
15188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  as an ASCII string.</p>
15198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42033</li>
15228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
15278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag notes minimum focal length, maximum focal length, minimum F number in the
15298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  minimum focal length, and minimum F number in the maximum focal length, which are
15308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  specification information for the lens that was used in photography. When the minimum
15318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  F number is unknown, the notation is 0/0.</p>
15328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42034</li>
15358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
15368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 4</li>
15378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <ul>
15398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Value 1 := Minimum focal length (unit: mm)</li>
15408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Value 2 : = Maximum focal length (unit: mm)</li>
15418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Value 3 : = Minimum F number in the minimum focal length</li>
15428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Value 4 : = Minimum F number in the maximum focal length</li>
15438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      </ul>
15448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_LENS_SPECIFICATION = "LensSpecification";
15478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the lens manufacturer as an ASCII string.</p>
15498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42035</li>
15528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_LENS_MAKE = "LensMake";
15578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the lens’s model name and model number as an ASCII string.</p>
15598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42036</li>
15628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_LENS_MODEL = "LensModel";
15678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag records the serial number of the interchangeable lens that was used in
15698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  photography as an ASCII string.</p>
15708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 42037</li>
15738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
15748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
15758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
15788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
15798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // GPS Attribute Information
15808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the version of GPS Info IFD. The version is given as 2.3.0.0. This tag is
15828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  mandatory when GPS-related tags are present. Note that this tag is written as a different
15838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  byte than {@link #TAG_EXIF_VERSION}.</p>
15848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
15858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
15868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 0</li>
15878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Byte</li>
15888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 4</li>
15898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 2.3.0.0</li>
15908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <ul>
15918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>2300 = Version 2.3</li>
15928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>Other = reserved</li>
15938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      </ul>
15948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
15958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
15968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
15978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
15988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether the latitude is north or south latitude.</p>
15998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 1</li>
16028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
16038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
16048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LATITUDE_NORTH
16088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LATITUDE_SOUTH
16098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
16118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the latitude. The latitude is expressed as three RATIONAL values giving
16138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the degrees, minutes, and seconds, respectively. If latitude is expressed as degrees,
16148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  minutes and seconds, a typical format would be dd/1,mm/1,ss/1. When degrees and minutes are
16158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  used and, for example, fractions of minutes are given up to two decimal places, the format
16168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  would be dd/1,mmmm/100,0/1.</p>
16178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 2</li>
16208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
16218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
16228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
16268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether the longitude is east or west longitude.</p>
16288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 3</li>
16318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
16328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
16338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LONGITUDE_EAST
16378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LONGITUDE_WEST
16388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
16408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the longitude. The longitude is expressed as three RATIONAL values giving
16428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the degrees, minutes, and seconds, respectively. If longitude is expressed as degrees,
16438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  minutes and seconds, a typical format would be ddd/1,mm/1,ss/1. When degrees and minutes
16448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  are used and, for example, fractions of minutes are given up to two decimal places,
16458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the format would be ddd/1,mmmm/100,0/1.</p>
16468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 4</li>
16498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
16508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
16518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
16558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the altitude used as the reference altitude. If the reference is sea level
16578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  and the altitude is above sea level, 0 is given. If the altitude is below sea level,
16588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a value of 1 is given and the altitude is indicated as an absolute value in
16598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  {@link #TAG_GPS_ALTITUDE}.</p>
16608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 5</li>
16638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Byte</li>
16648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
16658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = 0</li>
16668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ALTITUDE_ABOVE_SEA_LEVEL
16698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #ALTITUDE_BELOW_SEA_LEVEL
16708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
16728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the altitude based on the reference in {@link #TAG_GPS_ALTITUDE_REF}.
16748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The reference unit is meters.</p>
16758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 6</li>
16788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
16798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
16808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
16848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the time as UTC (Coordinated Universal Time). TimeStamp is expressed as three
16868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  unsigned rational values giving the hour, minute, and second.</p>
16878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
16888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
16898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 7</li>
16908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
16918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
16928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
16938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
16948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
16958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
16968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
16978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the GPS satellites used for measurements. This tag may be used to describe
16988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the number of satellites, their ID number, angle of elevation, azimuth, SNR and other
16998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  information in ASCII notation. The format is not specified. If the GPS receiver is incapable
17008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  of taking measurements, value of the tag shall be set to {@code null}.</p>
17018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 8</li>
17048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
17058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
17068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_SATELLITES = "GPSSatellites";
17098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the status of the GPS receiver when the image is recorded. 'A' means
17118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  measurement is in progress, and 'V' means the measurement is interrupted.</p>
17128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 9</li>
17158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
17168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
17178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
17188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_IN_PROGRESS
17218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_INTERRUPTED
17228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_STATUS = "GPSStatus";
17248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the GPS measurement mode. Originally it was defined for GPS, but it may
17268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  be used for recording a measure mode to record the position information provided from
17278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  a mobile base station or wireless LAN as well as GPS.</p>
17288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 10</li>
17318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
17328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
17338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
17348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_2D
17378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_3D
17388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
17408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the GPS DOP (data degree of precision). An HDOP value is written during
17428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  two-dimensional measurement, and PDOP during three-dimensional measurement.</p>
17438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 11</li>
17468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
17478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
17488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
17498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DOP = "GPSDOP";
17528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the unit used to express the GPS receiver speed of movement.</p>
17548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 12</li>
17578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
17588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
17598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #GPS_SPEED_KILOMETERS_PER_HOUR}</li>
17608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_SPEED_KILOMETERS_PER_HOUR
17638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_SPEED_MILES_PER_HOUR
17648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_SPEED_KNOTS
17658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
17678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the speed of GPS receiver movement.</p>
17698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 13</li>
17728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
17738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
17748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
17758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_SPEED = "GPSSpeed";
17788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the reference for giving the direction of GPS receiver movement.</p>
17808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 14</li>
17838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
17848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
17858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
17868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
17878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_TRUE
17898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_MAGNETIC
17908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
17918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
17928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
17938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the direction of GPS receiver movement.
17948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The range of values is from 0.00 to 359.99.</p>
17958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
17968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
17978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 15</li>
17988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
17998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
18008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_TRACK = "GPSTrack";
18048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the reference for giving the direction of the image when it is captured.</p>
18068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 16</li>
18098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
18108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
18118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
18128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_TRUE
18158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_MAGNETIC
18168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
18188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>ndicates the direction of the image when it was captured.
18208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The range of values is from 0.00 to 359.99.</p>
18218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 17</li>
18248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
18258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
18268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
18308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the geodetic survey data used by the GPS receiver. If the survey data is
18328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  restricted to Japan,the value of this tag is 'TOKYO' or 'WGS-84'. If a GPS Info tag is
18338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  recorded, it is strongly recommended that this tag be recorded.</p>
18348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 18</li>
18378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
18388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
18428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether the latitude of the destination point is north or south latitude.</p>
18448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 19</li>
18478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
18488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
18498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LATITUDE_NORTH
18538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LATITUDE_SOUTH
18548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
18568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the latitude of the destination point. The latitude is expressed as three
18588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  unsigned rational values giving the degrees, minutes, and seconds, respectively.
18598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  If latitude is expressed as degrees, minutes and seconds, a typical format would be
18608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  dd/1,mm/1,ss/1. When degrees and minutes are used and, for example, fractions of minutes
18618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  are given up to two decimal places, the format would be dd/1, mmmm/100, 0/1.</p>
18628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 20</li>
18658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
18668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
18678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
18718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether the longitude of the destination point is east or west longitude.</p>
18738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 21</li>
18768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
18778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
18788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LONGITUDE_EAST
18828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #LONGITUDE_WEST
18838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
18858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
18868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the longitude of the destination point. The longitude is expressed as three
18878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  unsigned rational values giving the degrees, minutes, and seconds, respectively.
18888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  If longitude is expressed as degrees, minutes and seconds, a typical format would be ddd/1,
18898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are
18908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  given up to two decimal places, the format would be ddd/1, mmmm/100, 0/1.</p>
18918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
18928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
18938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 22</li>
18948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
18958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 3</li>
18968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
18978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
18988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
18998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
19008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the reference used for giving the bearing to the destination point.</p>
19028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 23</li>
19058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
19068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
19078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
19088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_TRUE
19118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DIRECTION_MAGNETIC
19128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
19148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the bearing to the destination point.
19168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The range of values is from 0.00 to 359.99.</p>
19178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 24</li>
19208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
19218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
19228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
19268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the unit used to express the distance to the destination point.</p>
19288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 25</li>
19318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
19328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 1</li>
19338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = {@link #GPS_DISTANCE_KILOMETERS}</li>
19348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DISTANCE_KILOMETERS
19378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DISTANCE_MILES
19388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_DISTANCE_NAUTICAL_MILES
19398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
19418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the distance to the destination point.</p>
19438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 26</li>
19468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
19478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
19488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
19528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A character string recording the name of the method used for location finding.
19548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  The first byte indicates the character code used, and this is followed by the name of
19558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the method.</p>
19568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 27</li>
19598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
19608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
19648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A character string recording the name of the GPS area. The first byte indicates
19668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  the character code used, and this is followed by the name of the GPS area.</p>
19678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 28</li>
19708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Undefined</li>
19718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
19758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>A character string recording date and time information relative to UTC (Coordinated
19778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  Universal Time). The format is "YYYY:MM:DD".</p>
19788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 29</li>
19818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
19828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 10</li>
19838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
19868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
19878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
19888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates whether differential correction is applied to the GPS receiver.</p>
19898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
19918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 30</li>
19928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned short</li>
19938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
19948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
19958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
19968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
19978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_NO_DIFFERENTIAL
19988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  @see #GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED
19998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
20018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>This tag indicates horizontal positioning errors in meters.</p>
20038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
20048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
20058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 31</li>
20068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = Unsigned rational</li>
20078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Count = 1</li>
20088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
20098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
20108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
20128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
20138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // Interoperability IFD Attribute Information
20148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <p>Indicates the identification of the Interoperability rule.</p>
20168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
20178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  <ul>
20188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Tag = 1</li>
20198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Type = String</li>
20208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Length = 4</li>
20218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <li>Default = None</li>
20228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      <ul>
20238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>"R98" = Indicates a file conforming to R98 file specification of Recommended
20248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                      Exif Interoperability Rules (Exif R 98) or to DCF basic file stipulated
20258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                      by Design Rule for Camera File System.</li>
20268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>"THM" = Indicates a file conforming to DCF thumbnail file stipulated by Design
20278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                      rule for Camera File System.</li>
20288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *          <li>“R03” = Indicates a file conforming to DCF Option File stipulated by Design rule
20298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *                      for Camera File System.</li>
20308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *      </ul>
20318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *  </ul>
20328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
20348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
20358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_IMAGE_LENGTH
20378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
20398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_IMAGE_WIDTH
20418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
20438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. DNG Specification 1.4.0.0. Section 4 */
20448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DNG_VERSION = "DNGVersion";
20458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. DNG Specification 1.4.0.0. Section 4 */
20468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_DEFAULT_CROP_SIZE = "DefaultCropSize";
20478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is undefined. See Olympus MakerNote tags in http://www.exiv2.org/tags-olympus.html. */
20488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
20498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. See Olympus Camera Settings tags in http://www.exiv2.org/tags-olympus.html. */
20508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
20518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. See Olympus Camera Settings tags in http://www.exiv2.org/tags-olympus.html. */
20528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ORF_PREVIEW_IMAGE_LENGTH = "PreviewImageLength";
20538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. See Olympus Image Processing tags in http://www.exiv2.org/tags-olympus.html. */
20548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_ORF_ASPECT_FRAME = "AspectFrame";
20558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is int. See PanasonicRaw tags in
20578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_SENSOR_BOTTOM_BORDER = "SensorBottomBorder";
20608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is int. See PanasonicRaw tags in
20628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_SENSOR_LEFT_BORDER = "SensorLeftBorder";
20658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is int. See PanasonicRaw tags in
20678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_SENSOR_RIGHT_BORDER = "SensorRightBorder";
20708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is int. See PanasonicRaw tags in
20728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_SENSOR_TOP_BORDER = "SensorTopBorder";
20758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is int. See PanasonicRaw tags in
20778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_ISO = "ISO";
20808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Type is undefined. See PanasonicRaw tags in
20828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
20838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw";
20858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */
20868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
20878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */
20888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String TAG_SUBFILE_TYPE = "SubfileType";
20898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
20908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
20918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Private tags used for pointing the other IFD offsets.
20928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The types of the following tags are int.
20938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * See JEITA CP-3451C Section 4.6.3: Exif-specific IFD.
20948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * For SubIFD, see Note 1 of Adobe PageMaker® 6.0 TIFF Technical Notes.
20958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
20968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_EXIF_IFD_POINTER = "ExifIFDPointer";
20978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_GPS_INFO_IFD_POINTER = "GPSInfoIFDPointer";
20988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_INTEROPERABILITY_IFD_POINTER = "InteroperabilityIFDPointer";
20998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_SUB_IFD_POINTER = "SubIFDPointer";
21008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // Proprietary pointer tags used for ORF files.
21018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // See http://www.exiv2.org/tags-olympus.html
21028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_ORF_CAMERA_SETTINGS_IFD_POINTER = "CameraSettingsIFDPointer";
21038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_ORF_IMAGE_PROCESSING_IFD_POINTER = "ImageProcessingIFDPointer";
21048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // Private tags used for thumbnail information.
21068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_HAS_THUMBNAIL = "HasThumbnail";
21078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_THUMBNAIL_OFFSET = "ThumbnailOffset";
21088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_THUMBNAIL_LENGTH = "ThumbnailLength";
21098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final String TAG_THUMBNAIL_DATA = "ThumbnailData";
21108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final int MAX_THUMBNAIL_SIZE = 512;
21118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    // Constants used for the Orientation Exif tag.
21138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIENTATION_UNDEFINED = 0;
21148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIENTATION_NORMAL = 1;
211508146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
211608146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is left right reversed mirror.
211708146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
211808146a611e0516946e36d5cb958445ea01896c23Conrad Chen    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
211908146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
212008146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is rotated by 180 degree clockwise.
212108146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
21228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIENTATION_ROTATE_180 = 3;
212308146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
212408146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is upside down mirror, it can also be represented by flip
212508146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * horizontally firstly and rotate 180 degree clockwise.
212608146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
212708146a611e0516946e36d5cb958445ea01896c23Conrad Chen    public static final int ORIENTATION_FLIP_VERTICAL = 4;
212808146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
212908146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is flipped about top-left <--> bottom-right axis, it can also be
213008146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * represented by flip horizontally firstly and rotate 270 degree clockwise.
213108146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
21328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIENTATION_TRANSPOSE = 5;
213308146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
213408146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is rotated by 90 degree clockwise.
213508146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
213608146a611e0516946e36d5cb958445ea01896c23Conrad Chen    public static final int ORIENTATION_ROTATE_90 = 6;
213708146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
213808146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is flipped about top-right <--> bottom-left axis, it can also be
213908146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * represented by flip horizontally firstly and rotate 90 degree clockwise.
214008146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
21418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIENTATION_TRANSVERSE = 7;
214208146a611e0516946e36d5cb958445ea01896c23Conrad Chen    /**
214308146a611e0516946e36d5cb958445ea01896c23Conrad Chen     * Indicates the image is rotated by 270 degree clockwise.
214408146a611e0516946e36d5cb958445ea01896c23Conrad Chen     */
214508146a611e0516946e36d5cb958445ea01896c23Conrad Chen    public static final int ORIENTATION_ROTATE_270 = 8;
21468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final List<Integer> ROTATION_ORDER = Arrays.asList(ORIENTATION_NORMAL,
21478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen            ORIENTATION_ROTATE_90, ORIENTATION_ROTATE_180, ORIENTATION_ROTATE_270);
21488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    private static final List<Integer> FLIPPED_ROTATION_ORDER = Arrays.asList(
21498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen            ORIENTATION_FLIP_HORIZONTAL, ORIENTATION_TRANSVERSE, ORIENTATION_FLIP_VERTICAL,
21508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen            ORIENTATION_TRANSPOSE);
21518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Chunky format.
21548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FORMAT_CHUNKY = 1;
21568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Planar format.
21588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FORMAT_PLANAR = 2;
21608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Centered positioning.
21638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short Y_CB_CR_POSITIONING_CENTERED = 1;
21658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Co-sited positioning.
21678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short Y_CB_CR_POSITIONING_CO_SITED = 2;
21698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used to denote resolution unit as inches.
21728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short RESOLUTION_UNIT_INCHES = 2;
21748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used to denote resolution unit as centimeters.
21768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short RESOLUTION_UNIT_CENTIMETERS = 3;
21788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_COLOR_SPACE} to denote sRGB color space.
21818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int COLOR_SPACE_S_RGB = 1;
21838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_COLOR_SPACE} to denote Uncalibrated.
21858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int COLOR_SPACE_UNCALIBRATED = 65535;
21878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
21888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is not defined.
21908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0;
21928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Manual.
21948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_MANUAL = 1;
21968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
21978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Normal.
21988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
21998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_NORMAL = 2;
22008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is
22028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Aperture priority.
22038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3;
22058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is
22078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Shutter priority.
22088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4;
22108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Creative
22128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * program (biased toward depth of field).
22138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_CREATIVE = 5;
22158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Action
22178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * program (biased toward fast shutter speed).
22188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_ACTION = 6;
22208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Portrait mode
22228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * (for closeup photos with the background out of focus).
22238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7;
22258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Landscape
22278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * mode (for landscape photos with the background in focus).
22288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8;
22308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
22318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is unknown.
22338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_UNKNOWN = 0;
22358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
22378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * output sensitivity (SOS).
22388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_SOS = 1;
22408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended
22428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * exposure index (REI).
22438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_REI = 2;
22458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is ISO speed.
22478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_ISO_SPEED = 3;
22498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
22518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * output sensitivity (SOS) and recommended exposure index (REI).
22528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4;
22548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
22568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * output sensitivity (SOS) and ISO speed.
22578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5;
22598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended
22618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * exposure index (REI) and ISO speed.
22628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6;
22648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
22668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * output sensitivity (SOS) and recommended exposure index (REI) and ISO speed.
22678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7;
22698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
22708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is unknown.
22728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_UNKNOWN = 0;
22748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Average.
22768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_AVERAGE = 1;
22788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is
22808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * CenterWeightedAverage.
22818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2;
22838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Spot.
22858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_SPOT = 3;
22878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is MultiSpot.
22898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_MULTI_SPOT = 4;
22918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Pattern.
22938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_PATTERN = 5;
22958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
22968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Partial.
22978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
22988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_PARTIAL = 6;
22998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is other.
23018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short METERING_MODE_OTHER = 255;
23038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
23048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is unknown.
23068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_UNKNOWN = 0;
23088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight.
23108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_DAYLIGHT = 1;
23128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fluorescent.
23148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_FLUORESCENT = 2;
23168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Tungsten
23188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * (incandescent light).
23198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_TUNGSTEN = 3;
23218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Flash.
23238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_FLASH = 4;
23258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fine weather.
23278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_FINE_WEATHER = 9;
23298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cloudy weather.
23318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10;
23338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Shade.
23358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_SHADE = 11;
23378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight fluorescent
23398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * (D 5700 - 7100K).
23408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12;
23428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Day white fluorescent
23448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * (N 4600 - 5500K).
23458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13;
23478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cool white
23498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * fluorescent (W 3800 - 4500K).
23508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14;
23528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is White fluorescent
23548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * (WW 3250 - 3800K).
23558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15;
23578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Warm white
23598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * fluorescent (L 2600 - 3250K).
23608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16;
23628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light A.
23648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17;
23668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light B.
23688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18;
23708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light C.
23728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19;
23748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D55.
23768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_D55 = 20;
23788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D65.
23808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_D65 = 21;
23828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D75.
23848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_D75 = 22;
23868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D50.
23888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_D50 = 23;
23908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is ISO studio tungsten.
23928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24;
23948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
23958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is other.
23968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
23978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short LIGHT_SOURCE_OTHER = 255;
23988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
23998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate whether the flash is fired.
24018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_FIRED = 0b0000_0001;
24038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate strobe return light is not detected.
24058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 0b0000_0100;
24078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate strobe return light is detected.
24098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 0b0000_0110;
24118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash
24138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * firing.
24148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
24158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
24168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_AUTO
24178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 0b0000_1000;
24198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash
24218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * suppression.
24228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
24238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
24248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_AUTO
24258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 0b0001_0000;
24278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Auto.
24298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
24308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
24318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
24328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_MODE_AUTO = 0b0001_1000;
24348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate no flash function is present.
24368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 0b0010_0000;
24388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The flag used by {@link #TAG_FLASH} to indicate red-eye reduction is supported.
24408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 0b0100_0000;
24428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
24438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is not
24458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * defined.
24468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_NOT_DEFINED = 1;
24488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is One-chip
24508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * color area sensor.
24518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_ONE_CHIP = 2;
24538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Two-chip
24558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * color area sensor.
24568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_TWO_CHIP = 3;
24588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Three-chip
24608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * color area sensor.
24618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_THREE_CHIP = 4;
24638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color
24658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * sequential area sensor.
24668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5;
24688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Trilinear
24708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * sensor.
24718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_TRILINEAR = 7;
24738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color
24758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * sequential linear sensor.
24768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
24778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8;
24788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
24798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
24808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is other.
248114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
24828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FILE_SOURCE_OTHER = 0;
248314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
24848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of transparent
24858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * type.
248614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
24878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1;
248814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
24898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of reflex type.
249014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
24918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FILE_SOURCE_REFLEX_SCANNER = 2;
249214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
24938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is DSC.
249414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
24958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short FILE_SOURCE_DSC = 3;
24968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
249714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
24988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SCENE_TYPE} to denote the scene is directly photographed.
249914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1;
25018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
250214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote no special processing is used.
250414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short RENDERED_PROCESS_NORMAL = 0;
250614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote special processing is used.
250814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short RENDERED_PROCESS_CUSTOM = 1;
25108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
251114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto.
251314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_MODE_AUTO = 0;
251514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Manual.
251714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_MODE_MANUAL = 1;
251914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto bracket.
252114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short EXPOSURE_MODE_AUTO_BRACKET = 2;
252314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
252414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto.
25268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
25278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @deprecated Use {@link #WHITE_BALANCE_AUTO} instead.
252814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    @Deprecated public static final int WHITEBALANCE_AUTO = 0;
25308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual.
25328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
25338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @deprecated Use {@link #WHITE_BALANCE_MANUAL} instead.
25348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    @Deprecated public static final int WHITEBALANCE_MANUAL = 1;
25368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto.
25388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short WHITE_BALANCE_AUTO = 0;
25408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual.
25428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short WHITE_BALANCE_MANUAL = 1;
254414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
254514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
25468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
25478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Standard.
254814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
25498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SCENE_CAPTURE_TYPE_STANDARD = 0;
25508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
25528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Landscape.
25538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1;
25558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
25578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Portrait.
25588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2;
25608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is Night
25628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * scene.
25638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SCENE_CAPTURE_TYPE_NIGHT = 3;
256514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
25664553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GAIN_CONTROL} to denote none gain adjustment.
25684553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GAIN_CONTROL_NONE = 0;
25704553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain up.
25724553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GAIN_CONTROL_LOW_GAIN_UP = 1;
25744553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain up.
25764553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2;
25784553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain down.
25804553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3;
25824553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain down.
25844553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4;
258614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
25874553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_CONTRAST} to denote normal contrast.
25894553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short CONTRAST_NORMAL = 0;
25914553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
25928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_CONTRAST} to denote soft contrast.
25934553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
25948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short CONTRAST_SOFT = 1;
25958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
25968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_CONTRAST} to denote hard contrast.
25978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
25988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short CONTRAST_HARD = 2;
25998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SATURATION} to denote normal saturation.
26028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SATURATION_NORMAL = 0;
26048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SATURATION} to denote low saturation.
26068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SATURATION_LOW = 0;
26088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SHARPNESS} to denote high saturation.
26108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SATURATION_HIGH = 0;
26128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SHARPNESS} to denote normal sharpness.
26158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SHARPNESS_NORMAL = 0;
26178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SHARPNESS} to denote soft sharpness.
26198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SHARPNESS_SOFT = 1;
26218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SHARPNESS} to denote hard sharpness.
26238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SHARPNESS_HARD = 2;
26258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
26288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * is unknown.
26298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0;
26318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
26338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * is Macro.
26348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1;
26368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
26388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * is Close view.
26398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2;
26418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
26438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * is Distant view.
26448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3;
26468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS latitude-related tags to denote the latitude is North latitude.
26498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
26508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_LATITUDE_REF
26518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_DEST_LATITUDE_REF
26528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String LATITUDE_NORTH = "N";
26548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS latitude-related tags to denote the latitude is South latitude.
26568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
26578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_LATITUDE_REF
26588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_DEST_LATITUDE_REF
26598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String LATITUDE_SOUTH = "S";
26618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS longitude-related tags to denote the longitude is East longitude.
26648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
26658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_LONGITUDE_REF
26668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_DEST_LONGITUDE_REF
26678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String LONGITUDE_EAST = "E";
26698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS longitude-related tags to denote the longitude is West longitude.
26718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     *
26728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_LONGITUDE_REF
26738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * @see #TAG_GPS_DEST_LONGITUDE_REF
26748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String LONGITUDE_WEST = "W";
26768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is above sea level.
26798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0;
26818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is below sea level.
26838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short ALTITUDE_BELOW_SEA_LEVEL = 1;
26858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is in progress.
26888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_MEASUREMENT_IN_PROGRESS = "A";
26908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is interrupted.
26928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_MEASUREMENT_INTERRUPTED = "V";
26948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
26958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
26968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 2-dimensional.
26978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
26988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_MEASUREMENT_2D = "2";
26998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 3-dimensional.
27018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_MEASUREMENT_3D = "3";
27038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is kilometers per
27068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * hour.
27078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
27098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is miles per hour.
27118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_SPEED_MILES_PER_HOUR = "M";
27138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is knots.
27158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_SPEED_KNOTS = "N";
27178945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS attributes to denote the direction is true direction.
27208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_DIRECTION_TRUE = "T";
27228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by GPS attributes to denote the direction is magnetic direction.
27248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_DIRECTION_MAGNETIC = "M";
27268945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27288945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is
27298945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * kilometers.
27308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27318945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_DISTANCE_KILOMETERS = "K";
27328945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27338945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is miles.
27348945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27358945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_DISTANCE_MILES = "M";
27368945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27378945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is
27388945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * nautical miles.
27398945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27408945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final String GPS_DISTANCE_NAUTICAL_MILES = "N";
27418945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27428945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27438945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote no differential correction is
27448945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * applied.
27458945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27468945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0;
27478945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27488945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote differential correction is
27498945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * applied.
27508945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27518945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1;
27528945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27538945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27548945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION} to denote the image is not compressed.
27558945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27568945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_UNCOMPRESSED = 1;
27578945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27588945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION} to denote the image is huffman compressed.
27598945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27608945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_HUFFMAN_COMPRESSED = 2;
27618945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27628945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION} to denote the image is JPEG.
27638945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27648945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_JPEG = 6;
27658945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27668945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
27678945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Section 3, Compression
27688945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27698945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_JPEG_COMPRESSED = 7;
27708945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27718945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
27728945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Section 3, Compression
27738945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27748945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_DEFLATE_ZIP = 8;
27758945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27768945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION} to denote the image is pack-bits compressed.
27778945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27788945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_PACK_BITS_COMPRESSED = 32773;
27798945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27808945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
27818945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * Section 3, Compression
27828945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27838945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int DATA_LOSSY_JPEG = 34892;
27848945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
27858945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27868945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
27878945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * See JEITA CP-3451C Spec Section 6, Differences from Palette Color Images
27888945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27898945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int[] BITS_PER_SAMPLE_RGB = new int[] { 8, 8, 8 };
27908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27918945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
27928945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images
27938945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27948945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int[] BITS_PER_SAMPLE_GREYSCALE_1 = new int[] { 4 };
27958945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
27968945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
27978945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images
27988945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
27998945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int[] BITS_PER_SAMPLE_GREYSCALE_2 = new int[] { 8 };
28008945d24b8dece3446b1393c01defd51c88439d04Conrad Chen
28018945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28028945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
28038945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28048945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0;
28058945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28068945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
28078945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28088945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1;
28098945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28108945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
28118945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28128945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2;
28138945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28148945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
28158945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28168945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
281714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
28188945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28198945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8.
28208945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28218945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int ORIGINAL_RESOLUTION_IMAGE = 0;
28228945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    /**
28238945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8.
28248945d24b8dece3446b1393c01defd51c88439d04Conrad Chen     */
28258945d24b8dece3446b1393c01defd51c88439d04Conrad Chen    public static final int REDUCED_RESOLUTION_IMAGE = 1;
282614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
282714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Maximum size for checking file type signature (see image_type_recognition_lite.cc)
282814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int SIGNATURE_CHECK_SIZE = 5000;
282914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
2830db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte[] JPEG_SIGNATURE = new byte[] {(byte) 0xff, (byte) 0xd8, (byte) 0xff};
283114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final String RAF_SIGNATURE = "FUJIFILMCCD-RAW";
283214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int RAF_OFFSET_TO_JPEG_IMAGE_OFFSET = 84;
283314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int RAF_INFO_SIZE = 160;
283414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int RAF_JPEG_LENGTH_VALUE_SIZE = 4;
283514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
283614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See http://fileformats.archiveteam.org/wiki/Olympus_ORF
283714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final short ORF_SIGNATURE_1 = 0x4f52;
283814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final short ORF_SIGNATURE_2 = 0x5352;
283914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // There are two formats for Olympus Makernote Headers. Each has different identifiers and
284014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // offsets to the actual data.
284114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See http://www.exiv2.org/makernote.html#R1
284214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte[] ORF_MAKER_NOTE_HEADER_1 = new byte[] {(byte) 0x4f, (byte) 0x4c,
284314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            (byte) 0x59, (byte) 0x4d, (byte) 0x50, (byte) 0x00}; // "OLYMP\0"
284414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte[] ORF_MAKER_NOTE_HEADER_2 = new byte[] {(byte) 0x4f, (byte) 0x4c,
284514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            (byte) 0x59, (byte) 0x4d, (byte) 0x50, (byte) 0x55, (byte) 0x53, (byte) 0x00,
284614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            (byte) 0x49, (byte) 0x49}; // "OLYMPUS\0II"
284714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int ORF_MAKER_NOTE_HEADER_1_SIZE = 8;
284814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int ORF_MAKER_NOTE_HEADER_2_SIZE = 12;
284914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
285014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See http://fileformats.archiveteam.org/wiki/RW2
285114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final short RW2_SIGNATURE = 0x0055;
285214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
285314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See http://fileformats.archiveteam.org/wiki/Pentax_PEF
285414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final String PEF_SIGNATURE = "PENTAX";
285514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See http://www.exiv2.org/makernote.html#R11
285614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int PEF_MAKER_NOTE_SKIP_SIZE = 6;
285714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
285814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static SimpleDateFormat sFormatter;
285914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
286014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See Exchangeable image file format for digital still cameras: Exif version 2.2.
286114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // The following values are for parsing EXIF data area. There are tag groups in EXIF data area.
286214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // They are called "Image File Directory". They have multiple data formats to cover various
286314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // image metadata from GPS longitude to camera model name.
286414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
286514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Types of Exif byte alignments (see JEITA CP-3451C Section 4.5.2)
2866db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final short BYTE_ALIGN_II = 0x4949;  // II: Intel order
2867db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final short BYTE_ALIGN_MM = 0x4d4d;  // MM: Motorola order
286814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
286914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // TIFF Header Fixed Constant (see JEITA CP-3451C Section 4.5.2)
2870db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte START_CODE = 0x2a; // 42
287114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_OFFSET = 8;
287214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
287314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Formats for the value in IFD entry (See TIFF 6.0 Section 2, "Image File Directory".)
287414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_BYTE = 1;
287514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_STRING = 2;
287614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_USHORT = 3;
287714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_ULONG = 4;
287814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_URATIONAL = 5;
287914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_SBYTE = 6;
288014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_UNDEFINED = 7;
288114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_SSHORT = 8;
288214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_SLONG = 9;
288314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_SRATIONAL = 10;
288414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_SINGLE = 11;
288514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_DOUBLE = 12;
288614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Format indicating a new IFD entry (See Adobe PageMaker® 6.0 TIFF Technical Notes, "New Tag")
288714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_FORMAT_IFD = 13;
288814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Names for the data formats for debugging purpose.
2889db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final String[] IFD_FORMAT_NAMES = new String[] {
289014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            "", "BYTE", "STRING", "USHORT", "ULONG", "URATIONAL", "SBYTE", "UNDEFINED", "SSHORT",
289114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            "SLONG", "SRATIONAL", "SINGLE", "DOUBLE"
289214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
289314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Sizes of the components of each IFD value format
2894db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final int[] IFD_FORMAT_BYTES_PER_FORMAT = new int[] {
289514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 1
289614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
289714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte[] EXIF_ASCII_PREFIX = new byte[] {
289814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0
289914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
290014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
290114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // A class for indicating EXIF rational type.
290214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static class Rational {
290314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final long numerator;
290414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final long denominator;
290514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
2906c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        private Rational(double value) {
2907c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen            this((long) (value * 10000), 10000);
2908c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        }
2909c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen
291014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private Rational(long numerator, long denominator) {
291114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Handle erroneous case
291214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (denominator == 0) {
291314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                this.numerator = 0;
291414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                this.denominator = 1;
291514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return;
291614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
291714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.numerator = numerator;
291814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.denominator = denominator;
291914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
292014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
292114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
292214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public String toString() {
292314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return numerator + "/" + denominator;
292414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
292514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
292614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public double calculate() {
292714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return (double) numerator / denominator;
292814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
292914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
293014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
293114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // A class for indicating EXIF attribute.
293214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static class ExifAttribute {
293314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final int format;
293414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final int numberOfComponents;
293514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final byte[] bytes;
293614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
293714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private ExifAttribute(int format, int numberOfComponents, byte[] bytes) {
293814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.format = format;
293914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.numberOfComponents = numberOfComponents;
294014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.bytes = bytes;
294114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
294214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
294314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createUShort(int[] values, ByteOrder byteOrder) {
294414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
294514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_USHORT] * values.length]);
294614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
294714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int value : values) {
294814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putShort((short) value);
294914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
295014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_USHORT, values.length, buffer.array());
295114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
295214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
295314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createUShort(int value, ByteOrder byteOrder) {
295414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createUShort(new int[] {value}, byteOrder);
295514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
295614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
295714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createULong(long[] values, ByteOrder byteOrder) {
295814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
295914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_ULONG] * values.length]);
296014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
296114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (long value : values) {
296214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt((int) value);
296314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
296414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_ULONG, values.length, buffer.array());
296514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
296614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
296714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createULong(long value, ByteOrder byteOrder) {
296814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createULong(new long[] {value}, byteOrder);
296914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
297014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
297114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createSLong(int[] values, ByteOrder byteOrder) {
297214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
297314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_SLONG] * values.length]);
297414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
297514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int value : values) {
297614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt(value);
297714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
297814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_SLONG, values.length, buffer.array());
297914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
298014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
298114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createSLong(int value, ByteOrder byteOrder) {
298214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createSLong(new int[] {value}, byteOrder);
298314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
298414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
298514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createByte(String value) {
298614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Exception for GPSAltitudeRef tag
298714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value.length() == 1 && value.charAt(0) >= '0' && value.charAt(0) <= '1') {
298814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                final byte[] bytes = new byte[] { (byte) (value.charAt(0) - '0') };
298914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return new ExifAttribute(IFD_FORMAT_BYTE, bytes.length, bytes);
299014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
299114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final byte[] ascii = value.getBytes(ASCII);
299214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_BYTE, ascii.length, ascii);
299314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
299414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
299514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createString(String value) {
299614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final byte[] ascii = (value + '\0').getBytes(ASCII);
299714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_STRING, ascii.length, ascii);
299814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
299914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
300014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createURational(Rational[] values, ByteOrder byteOrder) {
300114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
300214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_URATIONAL] * values.length]);
300314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
300414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (Rational value : values) {
300514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt((int) value.numerator);
300614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt((int) value.denominator);
300714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
300814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_URATIONAL, values.length, buffer.array());
300914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
301014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
301114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createURational(Rational value, ByteOrder byteOrder) {
301214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createURational(new Rational[] {value}, byteOrder);
301314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
301414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
301514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createSRational(Rational[] values, ByteOrder byteOrder) {
301614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
301714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_SRATIONAL] * values.length]);
301814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
301914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (Rational value : values) {
302014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt((int) value.numerator);
302114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putInt((int) value.denominator);
302214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
302314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_SRATIONAL, values.length, buffer.array());
302414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
302514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
302614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createSRational(Rational value, ByteOrder byteOrder) {
302714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createSRational(new Rational[] {value}, byteOrder);
302814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
302914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
303014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createDouble(double[] values, ByteOrder byteOrder) {
303114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final ByteBuffer buffer = ByteBuffer.wrap(
303214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new byte[IFD_FORMAT_BYTES_PER_FORMAT[IFD_FORMAT_DOUBLE] * values.length]);
303314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            buffer.order(byteOrder);
303414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (double value : values) {
303514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                buffer.putDouble(value);
303614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
303714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new ExifAttribute(IFD_FORMAT_DOUBLE, values.length, buffer.array());
303814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
303914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
304014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public static ExifAttribute createDouble(double value, ByteOrder byteOrder) {
304114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return createDouble(new double[] {value}, byteOrder);
304214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
304314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
304414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
304514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public String toString() {
304614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return "(" + IFD_FORMAT_NAMES[format] + ", data length:" + bytes.length + ")";
304714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
304814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
304914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private Object getValue(ByteOrder byteOrder) {
3050f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes            ByteOrderedDataInputStream inputStream = null;
305114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            try {
3052f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                inputStream = new ByteOrderedDataInputStream(bytes);
305314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                inputStream.setByteOrder(byteOrder);
305414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                switch (format) {
305514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_BYTE:
305614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SBYTE: {
305714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Exception for GPSAltitudeRef tag
305814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        if (bytes.length == 1 && bytes[0] >= 0 && bytes[0] <= 1) {
305914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            return new String(new char[] { (char) (bytes[0] + '0') });
306014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
306114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return new String(bytes, ASCII);
306214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
306314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_UNDEFINED:
306414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_STRING: {
306514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        int index = 0;
306614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        if (numberOfComponents >= EXIF_ASCII_PREFIX.length) {
306714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            boolean same = true;
306814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            for (int i = 0; i < EXIF_ASCII_PREFIX.length; ++i) {
306914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                if (bytes[i] != EXIF_ASCII_PREFIX[i]) {
307014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                    same = false;
307114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                    break;
307214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                }
307314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
307414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            if (same) {
307514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                index = EXIF_ASCII_PREFIX.length;
307614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
307714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
307814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
307914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        StringBuilder stringBuilder = new StringBuilder();
308014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        while (index < numberOfComponents) {
308114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            int ch = bytes[index];
308214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            if (ch == 0) {
308314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                break;
308414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
308514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            if (ch >= 32) {
308614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                stringBuilder.append((char) ch);
308714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            } else {
308814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                stringBuilder.append('?');
308914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
309014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            ++index;
309114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
309214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return stringBuilder.toString();
309314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
309414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_USHORT: {
309514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final int[] values = new int[numberOfComponents];
309614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
309714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readUnsignedShort();
309814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
309914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
310014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
310114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_ULONG: {
310214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final long[] values = new long[numberOfComponents];
310314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
310414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readUnsignedInt();
310514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
310614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
310714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
310814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_URATIONAL: {
310914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final Rational[] values = new Rational[numberOfComponents];
311014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
311114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            final long numerator = inputStream.readUnsignedInt();
311214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            final long denominator = inputStream.readUnsignedInt();
311314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = new Rational(numerator, denominator);
311414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
311514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
311614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
311714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SSHORT: {
311814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final int[] values = new int[numberOfComponents];
311914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
312014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readShort();
312114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
312214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
312314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
312414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SLONG: {
312514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final int[] values = new int[numberOfComponents];
312614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
312714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readInt();
312814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
312914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
313014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
313114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SRATIONAL: {
313214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final Rational[] values = new Rational[numberOfComponents];
313314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
313414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            final long numerator = inputStream.readInt();
313514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            final long denominator = inputStream.readInt();
313614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = new Rational(numerator, denominator);
313714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
313814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
313914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
314014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SINGLE: {
314114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final double[] values = new double[numberOfComponents];
314214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
314314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readFloat();
314414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
314514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
314614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
314714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_DOUBLE: {
314814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final double[] values = new double[numberOfComponents];
314914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int i = 0; i < numberOfComponents; ++i) {
315014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            values[i] = inputStream.readDouble();
315114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
315214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return values;
315314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
315414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    default:
315514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return null;
315614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
315714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } catch (IOException e) {
315814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "IOException occurred during reading a value", e);
315914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return null;
3160f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes            } finally {
3161f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                if (inputStream != null) {
3162f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                    try {
3163f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                        inputStream.close();
3164f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                    } catch (IOException e) {
3165f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                        Log.e(TAG, "IOException occurred while closing InputStream", e);
3166f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                    }
3167f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes                }
316814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
316914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
317014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
317114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public double getDoubleValue(ByteOrder byteOrder) {
317214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Object value = getValue(byteOrder);
317314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value == null) {
317414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("NULL can't be converted to a double value");
317514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
317614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof String) {
317714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return Double.parseDouble((String) value);
317814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
317914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof long[]) {
318014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                long[] array = (long[]) value;
318114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
318214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return array[0];
318314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
318414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
318514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
318614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof int[]) {
318714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int[] array = (int[]) value;
318814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
318914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return array[0];
319014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
319114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
319214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
319314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof double[]) {
319414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                double[] array = (double[]) value;
319514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
319614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return array[0];
319714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
319814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
319914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
320014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof Rational[]) {
320114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Rational[] array = (Rational[]) value;
320214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
320314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return array[0].calculate();
320414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
320514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
320614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
320714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new NumberFormatException("Couldn't find a double value");
320814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
320914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
321014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int getIntValue(ByteOrder byteOrder) {
321114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Object value = getValue(byteOrder);
321214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value == null) {
321314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("NULL can't be converted to a integer value");
321414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
321514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof String) {
321614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return Integer.parseInt((String) value);
321714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
321814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof long[]) {
321914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                long[] array = (long[]) value;
322014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
322114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return (int) array[0];
322214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
322314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
322414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
322514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof int[]) {
322614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int[] array = (int[]) value;
322714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array.length == 1) {
322814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return array[0];
322914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
323014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new NumberFormatException("There are more than one component");
323114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
323214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new NumberFormatException("Couldn't find a integer value");
323314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
323414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
323514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public String getStringValue(ByteOrder byteOrder) {
323614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Object value = getValue(byteOrder);
323714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value == null) {
323814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return null;
323914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
324014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof String) {
324114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return (String) value;
324214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
324314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
324414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            final StringBuilder stringBuilder = new StringBuilder();
324514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof long[]) {
324614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                long[] array = (long[]) value;
324714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                for (int i = 0; i < array.length; ++i) {
324814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append(array[i]);
324914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (i + 1 != array.length) {
325014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        stringBuilder.append(",");
325114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
325214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
325314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return stringBuilder.toString();
325414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
325514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof int[]) {
325614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int[] array = (int[]) value;
325714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                for (int i = 0; i < array.length; ++i) {
325814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append(array[i]);
325914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (i + 1 != array.length) {
326014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        stringBuilder.append(",");
326114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
326214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
326314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return stringBuilder.toString();
326414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
326514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof double[]) {
326614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                double[] array = (double[]) value;
326714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                for (int i = 0; i < array.length; ++i) {
326814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append(array[i]);
326914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (i + 1 != array.length) {
327014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        stringBuilder.append(",");
327114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
327214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
327314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return stringBuilder.toString();
327414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
327514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value instanceof Rational[]) {
327614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Rational[] array = (Rational[]) value;
327714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                for (int i = 0; i < array.length; ++i) {
327814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append(array[i].numerator);
327914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append('/');
328014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    stringBuilder.append(array[i].denominator);
328114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (i + 1 != array.length) {
328214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        stringBuilder.append(",");
328314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
328414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
328514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return stringBuilder.toString();
328614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
328714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return null;
328814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
328914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
329014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int size() {
329114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return IFD_FORMAT_BYTES_PER_FORMAT[format] * numberOfComponents;
329214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
329314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
329414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
329514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // A class for indicating EXIF tag.
3296db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static class ExifTag {
329714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final int number;
329814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final String name;
329914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final int primaryFormat;
330014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public final int secondaryFormat;
330114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
330214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private ExifTag(String name, int number, int format) {
330314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.name = name;
330414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.number = number;
330514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.primaryFormat = format;
330614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.secondaryFormat = -1;
330714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
330814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
330914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private ExifTag(String name, int number, int primaryFormat, int secondaryFormat) {
331014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.name = name;
331114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.number = number;
331214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.primaryFormat = primaryFormat;
331314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this.secondaryFormat = secondaryFormat;
331414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
3315db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen
3316db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen        private boolean isFormatCompatible(int format) {
3317db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            if (primaryFormat == IFD_FORMAT_UNDEFINED || format == IFD_FORMAT_UNDEFINED) {
3318db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                return true;
3319db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            } else if (primaryFormat == format || secondaryFormat == format) {
3320db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                return true;
3321db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            } else if ((primaryFormat == IFD_FORMAT_ULONG || secondaryFormat == IFD_FORMAT_ULONG)
3322db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                    && format == IFD_FORMAT_USHORT) {
3323db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                return true;
3324db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            } else if ((primaryFormat == IFD_FORMAT_SLONG || secondaryFormat == IFD_FORMAT_SLONG)
3325db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                    && format == IFD_FORMAT_SSHORT) {
3326db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                return true;
3327db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            } else if ((primaryFormat == IFD_FORMAT_DOUBLE || secondaryFormat == IFD_FORMAT_DOUBLE)
3328db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                    && format == IFD_FORMAT_SINGLE) {
3329db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                return true;
3330db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            }
3331db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            return false;
3332db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen        }
333314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
333414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
333514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Primary image IFD TIFF tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
333614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] IFD_TIFF_TAGS = new ExifTag[] {
333714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // For below two, see TIFF 6.0 Spec Section 3: Bilevel Images.
333814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_NEW_SUBFILE_TYPE, 254, IFD_FORMAT_ULONG),
333914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBFILE_TYPE, 255, IFD_FORMAT_ULONG),
334014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_IMAGE_WIDTH, 256, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
334114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_IMAGE_LENGTH, 257, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
334214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_BITS_PER_SAMPLE, 258, IFD_FORMAT_USHORT),
334314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COMPRESSION, 259, IFD_FORMAT_USHORT),
334414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262, IFD_FORMAT_USHORT),
334514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_IMAGE_DESCRIPTION, 270, IFD_FORMAT_STRING),
334614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MAKE, 271, IFD_FORMAT_STRING),
334714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MODEL, 272, IFD_FORMAT_STRING),
334814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
334914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORIENTATION, 274, IFD_FORMAT_USHORT),
335014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277, IFD_FORMAT_USHORT),
335114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ROWS_PER_STRIP, 278, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
335214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
335314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_X_RESOLUTION, 282, IFD_FORMAT_URATIONAL),
335414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_RESOLUTION, 283, IFD_FORMAT_URATIONAL),
335514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PLANAR_CONFIGURATION, 284, IFD_FORMAT_USHORT),
335614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RESOLUTION_UNIT, 296, IFD_FORMAT_USHORT),
335714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_TRANSFER_FUNCTION, 301, IFD_FORMAT_USHORT),
335814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SOFTWARE, 305, IFD_FORMAT_STRING),
335914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DATETIME, 306, IFD_FORMAT_STRING),
336014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ARTIST, 315, IFD_FORMAT_STRING),
336114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_WHITE_POINT, 318, IFD_FORMAT_URATIONAL),
336214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319, IFD_FORMAT_URATIONAL),
336314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See Adobe PageMaker® 6.0 TIFF Technical Notes, Note 1.
336414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG),
336514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG),
336614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG),
336714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529, IFD_FORMAT_URATIONAL),
336814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530, IFD_FORMAT_USHORT),
336914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531, IFD_FORMAT_USHORT),
337014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532, IFD_FORMAT_URATIONAL),
337114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COPYRIGHT, 33432, IFD_FORMAT_STRING),
337214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG),
337314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG),
337414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // RW2 file tags
337514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html)
337614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_SENSOR_TOP_BORDER, 4, IFD_FORMAT_ULONG),
337714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_SENSOR_LEFT_BORDER, 5, IFD_FORMAT_ULONG),
337814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_SENSOR_BOTTOM_BORDER, 6, IFD_FORMAT_ULONG),
337914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_SENSOR_RIGHT_BORDER, 7, IFD_FORMAT_ULONG),
338014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_ISO, 23, IFD_FORMAT_USHORT),
338114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RW2_JPG_FROM_RAW, 46, IFD_FORMAT_UNDEFINED)
338214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
338314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
338414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Primary image IFD Exif Private tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
338514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] {
338614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXPOSURE_TIME, 33434, IFD_FORMAT_URATIONAL),
338714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_F_NUMBER, 33437, IFD_FORMAT_URATIONAL),
338814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXPOSURE_PROGRAM, 34850, IFD_FORMAT_USHORT),
338914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852, IFD_FORMAT_STRING),
33908945d24b8dece3446b1393c01defd51c88439d04Conrad Chen            new ExifTag(TAG_PHOTOGRAPHIC_SENSITIVITY, 34855, IFD_FORMAT_USHORT),
339114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_OECF, 34856, IFD_FORMAT_UNDEFINED),
339214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING),
339314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING),
339414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DATETIME_DIGITIZED, 36868, IFD_FORMAT_STRING),
339514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121, IFD_FORMAT_UNDEFINED),
339614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122, IFD_FORMAT_URATIONAL),
339714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377, IFD_FORMAT_SRATIONAL),
339814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_APERTURE_VALUE, 37378, IFD_FORMAT_URATIONAL),
339914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_BRIGHTNESS_VALUE, 37379, IFD_FORMAT_SRATIONAL),
340014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXPOSURE_BIAS_VALUE, 37380, IFD_FORMAT_SRATIONAL),
340114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MAX_APERTURE_VALUE, 37381, IFD_FORMAT_URATIONAL),
340214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBJECT_DISTANCE, 37382, IFD_FORMAT_URATIONAL),
340314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_METERING_MODE, 37383, IFD_FORMAT_USHORT),
340414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_LIGHT_SOURCE, 37384, IFD_FORMAT_USHORT),
340514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FLASH, 37385, IFD_FORMAT_USHORT),
340614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FOCAL_LENGTH, 37386, IFD_FORMAT_URATIONAL),
340714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBJECT_AREA, 37396, IFD_FORMAT_USHORT),
340814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MAKER_NOTE, 37500, IFD_FORMAT_UNDEFINED),
340914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_USER_COMMENT, 37510, IFD_FORMAT_UNDEFINED),
341014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBSEC_TIME, 37520, IFD_FORMAT_STRING),
341114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBSEC_TIME_ORIGINAL, 37521, IFD_FORMAT_STRING),
341214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBSEC_TIME_DIGITIZED, 37522, IFD_FORMAT_STRING),
341314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FLASHPIX_VERSION, 40960, IFD_FORMAT_UNDEFINED),
341414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COLOR_SPACE, 40961, IFD_FORMAT_USHORT),
341514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PIXEL_X_DIMENSION, 40962, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
341614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PIXEL_Y_DIMENSION, 40963, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
341714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RELATED_SOUND_FILE, 40964, IFD_FORMAT_STRING),
341814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965, IFD_FORMAT_ULONG),
341914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FLASH_ENERGY, 41483, IFD_FORMAT_URATIONAL),
342014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SPATIAL_FREQUENCY_RESPONSE, 41484, IFD_FORMAT_UNDEFINED),
342114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FOCAL_PLANE_X_RESOLUTION, 41486, IFD_FORMAT_URATIONAL),
342214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FOCAL_PLANE_Y_RESOLUTION, 41487, IFD_FORMAT_URATIONAL),
342314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FOCAL_PLANE_RESOLUTION_UNIT, 41488, IFD_FORMAT_USHORT),
342414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBJECT_LOCATION, 41492, IFD_FORMAT_USHORT),
342514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXPOSURE_INDEX, 41493, IFD_FORMAT_URATIONAL),
342614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SENSING_METHOD, 41495, IFD_FORMAT_USHORT),
342714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FILE_SOURCE, 41728, IFD_FORMAT_UNDEFINED),
342814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SCENE_TYPE, 41729, IFD_FORMAT_UNDEFINED),
342914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_CFA_PATTERN, 41730, IFD_FORMAT_UNDEFINED),
343014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_CUSTOM_RENDERED, 41985, IFD_FORMAT_USHORT),
343114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXPOSURE_MODE, 41986, IFD_FORMAT_USHORT),
343214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_WHITE_BALANCE, 41987, IFD_FORMAT_USHORT),
343314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DIGITAL_ZOOM_RATIO, 41988, IFD_FORMAT_URATIONAL),
343414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_FOCAL_LENGTH_IN_35MM_FILM, 41989, IFD_FORMAT_USHORT),
343514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SCENE_CAPTURE_TYPE, 41990, IFD_FORMAT_USHORT),
343614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GAIN_CONTROL, 41991, IFD_FORMAT_USHORT),
343714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_CONTRAST, 41992, IFD_FORMAT_USHORT),
343814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SATURATION, 41993, IFD_FORMAT_USHORT),
343914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SHARPNESS, 41994, IFD_FORMAT_USHORT),
344014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DEVICE_SETTING_DESCRIPTION, 41995, IFD_FORMAT_UNDEFINED),
344114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBJECT_DISTANCE_RANGE, 41996, IFD_FORMAT_USHORT),
344214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_IMAGE_UNIQUE_ID, 42016, IFD_FORMAT_STRING),
344314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DNG_VERSION, 50706, IFD_FORMAT_BYTE),
344414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DEFAULT_CROP_SIZE, 50720, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG)
344514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
344614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
344714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Primary image IFD GPS Info tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
344814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] IFD_GPS_TAGS = new ExifTag[] {
344914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_VERSION_ID, 0, IFD_FORMAT_BYTE),
345014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_LATITUDE_REF, 1, IFD_FORMAT_STRING),
345114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_LATITUDE, 2, IFD_FORMAT_URATIONAL),
345214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_LONGITUDE_REF, 3, IFD_FORMAT_STRING),
345314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_LONGITUDE, 4, IFD_FORMAT_URATIONAL),
345414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_ALTITUDE_REF, 5, IFD_FORMAT_BYTE),
345514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_ALTITUDE, 6, IFD_FORMAT_URATIONAL),
345614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_TIMESTAMP, 7, IFD_FORMAT_URATIONAL),
345714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_SATELLITES, 8, IFD_FORMAT_STRING),
345814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_STATUS, 9, IFD_FORMAT_STRING),
345914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_MEASURE_MODE, 10, IFD_FORMAT_STRING),
346014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DOP, 11, IFD_FORMAT_URATIONAL),
346114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_SPEED_REF, 12, IFD_FORMAT_STRING),
346214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_SPEED, 13, IFD_FORMAT_URATIONAL),
346314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_TRACK_REF, 14, IFD_FORMAT_STRING),
346414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_TRACK, 15, IFD_FORMAT_URATIONAL),
346514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_IMG_DIRECTION_REF, 16, IFD_FORMAT_STRING),
346614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_IMG_DIRECTION, 17, IFD_FORMAT_URATIONAL),
346714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_MAP_DATUM, 18, IFD_FORMAT_STRING),
346814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_LATITUDE_REF, 19, IFD_FORMAT_STRING),
346914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_LATITUDE, 20, IFD_FORMAT_URATIONAL),
347014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_LONGITUDE_REF, 21, IFD_FORMAT_STRING),
347114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_LONGITUDE, 22, IFD_FORMAT_URATIONAL),
347214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_BEARING_REF, 23, IFD_FORMAT_STRING),
347314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_BEARING, 24, IFD_FORMAT_URATIONAL),
347414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_DISTANCE_REF, 25, IFD_FORMAT_STRING),
347514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DEST_DISTANCE, 26, IFD_FORMAT_URATIONAL),
347614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_PROCESSING_METHOD, 27, IFD_FORMAT_UNDEFINED),
347714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_AREA_INFORMATION, 28, IFD_FORMAT_UNDEFINED),
347814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DATESTAMP, 29, IFD_FORMAT_STRING),
347914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_DIFFERENTIAL, 30, IFD_FORMAT_USHORT)
348014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
348114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Primary image IFD Interoperability tag (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
348214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] IFD_INTEROPERABILITY_TAGS = new ExifTag[] {
348314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_INTEROPERABILITY_INDEX, 1, IFD_FORMAT_STRING)
348414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
348514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // IFD Thumbnail tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
348614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] IFD_THUMBNAIL_TAGS = new ExifTag[] {
348714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // For below two, see TIFF 6.0 Spec Section 3: Bilevel Images.
348814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_NEW_SUBFILE_TYPE, 254, IFD_FORMAT_ULONG),
348914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUBFILE_TYPE, 255, IFD_FORMAT_ULONG),
349014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_THUMBNAIL_IMAGE_WIDTH, 256, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
349114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_THUMBNAIL_IMAGE_LENGTH, 257, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
349214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_BITS_PER_SAMPLE, 258, IFD_FORMAT_USHORT),
349314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COMPRESSION, 259, IFD_FORMAT_USHORT),
349414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262, IFD_FORMAT_USHORT),
349514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_IMAGE_DESCRIPTION, 270, IFD_FORMAT_STRING),
349614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MAKE, 271, IFD_FORMAT_STRING),
349714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_MODEL, 272, IFD_FORMAT_STRING),
349814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
349914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORIENTATION, 274, IFD_FORMAT_USHORT),
350014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277, IFD_FORMAT_USHORT),
350114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ROWS_PER_STRIP, 278, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
350214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
350314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_X_RESOLUTION, 282, IFD_FORMAT_URATIONAL),
350414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_RESOLUTION, 283, IFD_FORMAT_URATIONAL),
350514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PLANAR_CONFIGURATION, 284, IFD_FORMAT_USHORT),
350614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_RESOLUTION_UNIT, 296, IFD_FORMAT_USHORT),
350714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_TRANSFER_FUNCTION, 301, IFD_FORMAT_USHORT),
350814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SOFTWARE, 305, IFD_FORMAT_STRING),
350914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DATETIME, 306, IFD_FORMAT_STRING),
351014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ARTIST, 315, IFD_FORMAT_STRING),
351114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_WHITE_POINT, 318, IFD_FORMAT_URATIONAL),
351214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319, IFD_FORMAT_URATIONAL),
351314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See Adobe PageMaker® 6.0 TIFF Technical Notes, Note 1.
351414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG),
351514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG),
351614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG),
351714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529, IFD_FORMAT_URATIONAL),
351814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530, IFD_FORMAT_USHORT),
351914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531, IFD_FORMAT_USHORT),
352014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532, IFD_FORMAT_URATIONAL),
352114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COPYRIGHT, 33432, IFD_FORMAT_STRING),
352214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG),
352314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG),
352414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DNG_VERSION, 50706, IFD_FORMAT_BYTE),
352514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_DEFAULT_CROP_SIZE, 50720, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG)
352614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
352714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
352814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // RAF file tag (See piex.cc line 372)
352914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag TAG_RAF_IMAGE_SIZE =
353014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT);
353114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
353214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // ORF file tags (See http://www.exiv2.org/tags-olympus.html)
353314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] ORF_MAKER_NOTE_TAGS = new ExifTag[] {
353414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_THUMBNAIL_IMAGE, 256, IFD_FORMAT_UNDEFINED),
353514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_ULONG),
353614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_ULONG)
353714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
353814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] ORF_CAMERA_SETTINGS_TAGS = new ExifTag[] {
353914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_PREVIEW_IMAGE_START, 257, IFD_FORMAT_ULONG),
354014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_PREVIEW_IMAGE_LENGTH, 258, IFD_FORMAT_ULONG)
354114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
354214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] ORF_IMAGE_PROCESSING_TAGS = new ExifTag[] {
354314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_ASPECT_FRAME, 4371, IFD_FORMAT_USHORT)
354414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
354514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // PEF file tag (See http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html)
354614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] PEF_TAGS = new ExifTag[] {
354714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_COLOR_SPACE, 55, IFD_FORMAT_USHORT)
354814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
354914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
355014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See JEITA CP-3451C Section 4.6.3: Exif-specific IFD.
355114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // The following values are used for indicating pointers to the other Image File Directories.
355214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
355314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Indices of Exif Ifd tag groups
355414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /** @hide */
355504c9e28ea0be0cedcee58e4d29343ac08733d58aAurimas Liutikas    @RestrictTo(RestrictTo.Scope.LIBRARY)
355614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    @Retention(RetentionPolicy.SOURCE)
355714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY,
355814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE,
355914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF})
356014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public @interface IfdType {}
356114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
3562db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final int IFD_TYPE_PRIMARY = 0;
356314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_EXIF = 1;
356414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_GPS = 2;
356514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_INTEROPERABILITY = 3;
3566db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final int IFD_TYPE_THUMBNAIL = 4;
3567db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final int IFD_TYPE_PREVIEW = 5;
356814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_ORF_MAKER_NOTE = 6;
356914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7;
357014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8;
357114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IFD_TYPE_PEF = 9;
357214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
357314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // List of Exif tag groups
3574db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final ExifTag[][] EXIF_TAGS = new ExifTag[][] {
357514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS,
357614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            IFD_THUMBNAIL_TAGS, IFD_TIFF_TAGS, ORF_MAKER_NOTE_TAGS, ORF_CAMERA_SETTINGS_TAGS,
357714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ORF_IMAGE_PROCESSING_TAGS, PEF_TAGS
357814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
357914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // List of tags for pointing to the other image file directory offset.
358014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag[] EXIF_POINTER_TAGS = new ExifTag[] {
358114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_SUB_IFD_POINTER, 330, IFD_FORMAT_ULONG),
358214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG),
358314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG),
358414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965, IFD_FORMAT_ULONG),
358514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE),
358614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE)
358714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    };
358814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
358914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Tags for indicating the thumbnail offset and length
359014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
359114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG);
359214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final ExifTag JPEG_INTERCHANGE_FORMAT_LENGTH_TAG =
359314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514, IFD_FORMAT_ULONG);
359414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
359514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Mappings from tag number to tag name and each item represents one IFD tag group.
3596abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    @SuppressWarnings("unchecked")
3597abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    private static final HashMap<Integer, ExifTag>[] sExifTagMapsForReading =
3598abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            new HashMap[EXIF_TAGS.length];
359914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Mappings from tag name to tag number and each item represents one IFD tag group.
3600abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    @SuppressWarnings("unchecked")
3601abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    private static final HashMap<String, ExifTag>[] sExifTagMapsForWriting =
3602abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            new HashMap[EXIF_TAGS.length];
360314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList(
360414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE,
360514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            TAG_GPS_TIMESTAMP));
360614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Mappings from tag number to IFD type for pointer tags.
3607abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    @SuppressWarnings("unchecked")
3608abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    private static final HashMap<Integer, Integer> sExifPointerTagMap = new HashMap();
360914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
361014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See JPEG File Interchange Format Version 1.02.
361114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // The following values are defined for handling JPEG streams. In this implementation, we are
361214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // not only getting information from EXIF but also from some JPEG special segments such as
361314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // MARKER_COM for user comment and MARKER_SOFx for image width and height.
361414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
361514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final Charset ASCII = Charset.forName("US-ASCII");
361614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Identifier for EXIF APP1 segment in JPEG
3617db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte[] IDENTIFIER_EXIF_APP1 = "Exif\0\0".getBytes(ASCII);
361814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // JPEG segment markers, that each marker consumes two bytes beginning with 0xff and ending with
361914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // the indicator. There is no SOF4, SOF8, SOF16 markers in JPEG and SOFx markers indicates start
362014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // of frame(baseline DCT) and the image size info exists in its beginning part.
3621db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte MARKER = (byte) 0xff;
362214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOI = (byte) 0xd8;
362314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF0 = (byte) 0xc0;
362414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF1 = (byte) 0xc1;
362514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF2 = (byte) 0xc2;
362614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF3 = (byte) 0xc3;
362714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF5 = (byte) 0xc5;
362814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF6 = (byte) 0xc6;
362914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF7 = (byte) 0xc7;
363014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF9 = (byte) 0xc9;
363114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF10 = (byte) 0xca;
363214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF11 = (byte) 0xcb;
363314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF13 = (byte) 0xcd;
363414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF14 = (byte) 0xce;
363514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOF15 = (byte) 0xcf;
363614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_SOS = (byte) 0xda;
3637db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte MARKER_APP1 = (byte) 0xe1;
363814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final byte MARKER_COM = (byte) 0xfe;
3639db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen    static final byte MARKER_EOI = (byte) 0xd9;
364014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
364114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Supported Image File Types
364214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_UNKNOWN = 0;
364314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_ARW = 1;
364414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_CR2 = 2;
364514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_DNG = 3;
364614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_JPEG = 4;
364714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_NEF = 5;
364814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_NRW = 6;
364914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_ORF = 7;
365014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_PEF = 8;
365114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_RAF = 9;
365214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_RW2 = 10;
365314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final int IMAGE_TYPE_SRW = 11;
365414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
365514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    static {
365614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
365714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
365814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
365914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Build up the hash tables to look up Exif tags for reading Exif tags.
366014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
3661abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            sExifTagMapsForReading[ifdType] = new HashMap<>();
3662abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            sExifTagMapsForWriting[ifdType] = new HashMap<>();
366314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (ExifTag tag : EXIF_TAGS[ifdType]) {
366414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                sExifTagMapsForReading[ifdType].put(tag.number, tag);
366514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                sExifTagMapsForWriting[ifdType].put(tag.name, tag);
366614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
366714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
366814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
366914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Build up the hash table to look up Exif pointer tags.
367014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330
367114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665
367214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853
367314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965
367414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224
367514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256
367614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
367714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
367814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private final String mFilename;
367914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private final AssetManager.AssetInputStream mAssetInputStream;
368014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mMimeType;
3681abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    @SuppressWarnings("unchecked")
3682abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas    private final HashMap<String, ExifAttribute>[] mAttributes = new HashMap[EXIF_TAGS.length];
368314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN;
368414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean mHasThumbnail;
368514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // The following values used for indicating a thumbnail position.
368614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mThumbnailOffset;
368714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mThumbnailLength;
368814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private byte[] mThumbnailBytes;
368914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mThumbnailCompression;
369014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mExifOffset;
369114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mOrfMakerNoteOffset;
369214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mOrfThumbnailOffset;
369314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mOrfThumbnailLength;
369414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int mRw2JpgFromRawOffset;
369514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean mIsSupportedFile;
369614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
369714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Pattern to check non zero timestamp
369814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*");
369914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Pattern to check gps timestamp
370014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static final Pattern sGpsTimestampPattern =
370114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Pattern.compile("^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$");
370214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
370314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
370414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Reads Exif tags from the specified image file.
370514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
37068936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public ExifInterface(@NonNull String filename) throws IOException {
370714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (filename == null) {
370814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IllegalArgumentException("filename cannot be null");
370914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
371014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        FileInputStream in = null;
371114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mAssetInputStream = null;
371214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mFilename = filename;
371314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
371414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            in = new FileInputStream(filename);
371514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            loadAttributes(in);
371614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } finally {
371714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            closeQuietly(in);
371814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
371914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
372014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
372114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
372214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Reads Exif tags from the specified image input stream. Attribute mutation is not supported
372314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * for input streams. The given input stream will proceed its current position. Developers
372446ffc16f1c2e80e8fc401a5a440c3c3a847b4ba7Hyundo Moon     * should close the input stream after use. This constructor is not intended to be used with
372546ffc16f1c2e80e8fc401a5a440c3c3a847b4ba7Hyundo Moon     * an input stream that performs any networking operations.
372614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
37278936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public ExifInterface(@NonNull InputStream inputStream) throws IOException {
372814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (inputStream == null) {
372914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IllegalArgumentException("inputStream cannot be null");
373014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
373114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mFilename = null;
373214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (inputStream instanceof AssetManager.AssetInputStream) {
373314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAssetInputStream = (AssetManager.AssetInputStream) inputStream;
373414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else {
373514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAssetInputStream = null;
373614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
373714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        loadAttributes(inputStream);
373814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
373914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
374014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
374114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the EXIF attribute of the specified tag or {@code null} if there is no such tag in
374214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * the image file.
374314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
374414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
374514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
37468936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
37478936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    private ExifAttribute getExifAttribute(@NonNull String tag) {
3748ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon        if (TAG_ISO_SPEED_RATINGS.equals(tag)) {
3749ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            if (DEBUG) {
3750ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon                Log.d(TAG, "getExifAttribute: Replacing TAG_ISO_SPEED_RATINGS with "
3751ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon                        + "TAG_PHOTOGRAPHIC_SENSITIVITY.");
3752ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            }
3753ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            tag = TAG_PHOTOGRAPHIC_SENSITIVITY;
3754ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon        }
375514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieves all tag groups. The value from primary image tag group has a higher priority
375614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // than the value from the thumbnail tag group if there are more than one candidates.
375714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < EXIF_TAGS.length; ++i) {
3758abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            ExifAttribute value = mAttributes[i].get(tag);
375914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (value != null) {
3760abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                return value;
376114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
376214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
376314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return null;
376414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
376514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
376614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
376714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the value of the specified tag or {@code null} if there
376814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * is no such tag in the image file.
376914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
377014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
377114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
37728936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
37738936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public String getAttribute(@NonNull String tag) {
377414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute attribute = getExifAttribute(tag);
377514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (attribute != null) {
377614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (!sTagSetForCompatibility.contains(tag)) {
377714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return attribute.getStringValue(mExifByteOrder);
377814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
377914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (tag.equals(TAG_GPS_TIMESTAMP)) {
378014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Convert the rational values to the custom formats for backwards compatibility.
378114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (attribute.format != IFD_FORMAT_URATIONAL
378214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        && attribute.format != IFD_FORMAT_SRATIONAL) {
378314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "GPS Timestamp format is not rational. format=" + attribute.format);
378414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return null;
378514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
378614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Rational[] array = (Rational[]) attribute.getValue(mExifByteOrder);
378714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (array == null || array.length != 3) {
378814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid GPS Timestamp array. array=" + Arrays.toString(array));
378914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return null;
379014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
379114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return String.format("%02d:%02d:%02d",
379214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (int) ((float) array[0].numerator / array[0].denominator),
379314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (int) ((float) array[1].numerator / array[1].denominator),
379414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (int) ((float) array[2].numerator / array[2].denominator));
379514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
379614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            try {
379714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return Double.toString(attribute.getDoubleValue(mExifByteOrder));
379814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } catch (NumberFormatException e) {
379914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return null;
380014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
380114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
380214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return null;
380314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
380414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
380514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
380614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the integer value of the specified tag. If there is no such tag
380714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * in the image file or the value cannot be parsed as integer, return
380814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * <var>defaultValue</var>.
380914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
381014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
381114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param defaultValue the value to return if the tag is not available.
381214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
38138936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public int getAttributeInt(@NonNull String tag, int defaultValue) {
381414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute exifAttribute = getExifAttribute(tag);
381514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (exifAttribute == null) {
381614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return defaultValue;
381714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
381814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
381914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
382014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return exifAttribute.getIntValue(mExifByteOrder);
382114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (NumberFormatException e) {
382214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return defaultValue;
382314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
382414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
382514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
382614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
382714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the double value of the tag that is specified as rational or contains a
382814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * double-formatted value. If there is no such tag in the image file or the value cannot be
382914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * parsed as double, return <var>defaultValue</var>.
383014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
383114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
383214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param defaultValue the value to return if the tag is not available.
383314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
38348936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public double getAttributeDouble(@NonNull String tag, double defaultValue) {
383514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute exifAttribute = getExifAttribute(tag);
383614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (exifAttribute == null) {
383714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return defaultValue;
383814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
383914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
384014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
384114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return exifAttribute.getDoubleValue(mExifByteOrder);
384214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (NumberFormatException e) {
384314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return defaultValue;
384414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
384514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
384614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
384714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
3848bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * Sets the value of the specified tag.
384914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
385014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
385114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param value the value of the tag.
385214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
38538936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    public void setAttribute(@NonNull String tag, @Nullable String value) {
3854ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon        if (TAG_ISO_SPEED_RATINGS.equals(tag)) {
3855ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            if (DEBUG) {
3856ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon                Log.d(TAG, "setAttribute: Replacing TAG_ISO_SPEED_RATINGS with "
3857ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon                        + "TAG_PHOTOGRAPHIC_SENSITIVITY.");
3858ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            }
3859ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon            tag = TAG_PHOTOGRAPHIC_SENSITIVITY;
3860ab68451b27e13a861135d8ff147d515a4c4fdff5Hyundo Moon        }
386114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Convert the given value to rational values for backwards compatibility.
386214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (value != null && sTagSetForCompatibility.contains(tag)) {
386314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (tag.equals(TAG_GPS_TIMESTAMP)) {
386414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Matcher m = sGpsTimestampPattern.matcher(value);
386514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (!m.find()) {
386614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid value for " + tag + " : " + value);
386714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
386814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
386914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                value = Integer.parseInt(m.group(1)) + "/1," + Integer.parseInt(m.group(2)) + "/1,"
387014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + Integer.parseInt(m.group(3)) + "/1";
387114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else {
387214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                try {
387314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    double doubleValue = Double.parseDouble(value);
3874c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen                    value = new Rational(doubleValue).toString();
387514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } catch (NumberFormatException e) {
387614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid value for " + tag + " : " + value);
387714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
387814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
387914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
388014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
388114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
388214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
388314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) {
388414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                continue;
388514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
3886abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            final ExifTag exifTag = sExifTagMapsForWriting[i].get(tag);
3887abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            if (exifTag != null) {
388814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (value == null) {
388914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[i].remove(tag);
389014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    continue;
389114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
389214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Pair<Integer, Integer> guess = guessDataFormat(value);
389314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int dataFormat;
389414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (exifTag.primaryFormat == guess.first || exifTag.primaryFormat == guess.second) {
389514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataFormat = exifTag.primaryFormat;
389614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else if (exifTag.secondaryFormat != -1 && (exifTag.secondaryFormat == guess.first
389714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        || exifTag.secondaryFormat == guess.second)) {
389814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataFormat = exifTag.secondaryFormat;
389914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else if (exifTag.primaryFormat == IFD_FORMAT_BYTE
390014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        || exifTag.primaryFormat == IFD_FORMAT_UNDEFINED
390114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        || exifTag.primaryFormat == IFD_FORMAT_STRING) {
390214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataFormat = exifTag.primaryFormat;
390314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
390414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Given tag (" + tag + ") value didn't match with one of expected "
390514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + "formats: " + IFD_FORMAT_NAMES[exifTag.primaryFormat]
390614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + (exifTag.secondaryFormat == -1 ? "" : ", "
390714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + IFD_FORMAT_NAMES[exifTag.secondaryFormat]) + " (guess: "
390814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + IFD_FORMAT_NAMES[guess.first] + (guess.second == -1 ? "" : ", "
390914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + IFD_FORMAT_NAMES[guess.second]) + ")");
391014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    continue;
391114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
391214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                switch (dataFormat) {
391314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_BYTE: {
391414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag, ExifAttribute.createByte(value));
391514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
391614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
391714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_UNDEFINED:
391814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_STRING: {
391914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag, ExifAttribute.createString(value));
392014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
392114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
392214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_USHORT: {
3923244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
392414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final int[] intArray = new int[values.length];
392514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
392614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            intArray[j] = Integer.parseInt(values[j]);
392714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
392814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
392914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createUShort(intArray, mExifByteOrder));
393014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
393114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
393214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SLONG: {
3933244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
393414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final int[] intArray = new int[values.length];
393514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
393614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            intArray[j] = Integer.parseInt(values[j]);
393714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
393814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
393914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createSLong(intArray, mExifByteOrder));
394014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
394114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
394214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_ULONG: {
3943244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
394414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final long[] longArray = new long[values.length];
394514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
394614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            longArray[j] = Long.parseLong(values[j]);
394714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
394814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
394914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createULong(longArray, mExifByteOrder));
395014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
395114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
395214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_URATIONAL: {
3953244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
395414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final Rational[] rationalArray = new Rational[values.length];
395514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
3956244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                            final String[] numbers = values[j].split("/", -1);
395777966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                            rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
395877966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                                    (long) Double.parseDouble(numbers[1]));
395914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
396014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
396114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createURational(rationalArray, mExifByteOrder));
396214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
396314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
396414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SRATIONAL: {
3965244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
396614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final Rational[] rationalArray = new Rational[values.length];
396714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
3968244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                            final String[] numbers = values[j].split("/", -1);
396977966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                            rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
397077966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                                    (long) Double.parseDouble(numbers[1]));
397114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
397214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
397314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createSRational(rationalArray, mExifByteOrder));
397414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
397514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
397614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_DOUBLE: {
3977244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas                        final String[] values = value.split(",", -1);
397814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        final double[] doubleArray = new double[values.length];
397914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        for (int j = 0; j < values.length; ++j) {
398014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            doubleArray[j] = Double.parseDouble(values[j]);
398114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
398214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[i].put(tag,
398314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createDouble(doubleArray, mExifByteOrder));
398414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
398514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
398614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    default:
398714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        Log.w(TAG, "Data format isn't one of expected formats: " + dataFormat);
398814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        continue;
398914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
399014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
399114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
399214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
399314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
399414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
3995bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * Resets the {@link #TAG_ORIENTATION} of the image to be {@link #ORIENTATION_NORMAL}.
3996bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     */
3997bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    public void resetOrientation() {
3998bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        setAttribute(TAG_ORIENTATION, Integer.toString(ORIENTATION_NORMAL));
3999bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    }
4000bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4001bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    /**
4002bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * Rotates the image by the given degree clockwise. The degree should be a multiple of
4003bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * 90 (e.g, 90, 180, -90, etc.).
4004bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     *
4005bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * @param degree The degree of rotation.
4006bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     */
4007bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    public void rotate(int degree) {
4008bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        if (degree % 90 !=0) {
4009bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            throw new IllegalArgumentException("degree should be a multiple of 90");
4010bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        }
4011bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4012bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
4013bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int currentIndex, newIndex;
4014bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int resultOrientation;
4015bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        if (ROTATION_ORDER.contains(currentOrientation)) {
4016bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            currentIndex = ROTATION_ORDER.indexOf(currentOrientation);
4017bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            newIndex = (currentIndex + degree / 90) % 4;
4018bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            newIndex += newIndex < 0 ? 4 : 0;
4019bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            resultOrientation = ROTATION_ORDER.get(newIndex);
4020bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        } else if (FLIPPED_ROTATION_ORDER.contains(currentOrientation)) {
4021bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            currentIndex = FLIPPED_ROTATION_ORDER.indexOf(currentOrientation);
4022bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            newIndex = (currentIndex + degree / 90) % 4;
4023bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            newIndex += newIndex < 0 ? 4 : 0;
4024bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            resultOrientation = FLIPPED_ROTATION_ORDER.get(newIndex);
4025bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        } else {
4026bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            resultOrientation = ORIENTATION_UNDEFINED;
4027bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        }
4028bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4029bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation));
4030bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    }
4031bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4032bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    /**
4033bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * Flips the image vertically.
4034bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     */
4035bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    public void flipVertically() {
4036bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
4037bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int resultOrientation;
4038bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        switch (currentOrientation) {
4039bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_FLIP_HORIZONTAL:
4040bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_180;
4041bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4042bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_180:
4043bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_FLIP_HORIZONTAL;
4044bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4045bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_FLIP_VERTICAL:
4046bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_NORMAL;
4047bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4048bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_TRANSPOSE:
4049bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_270;
4050bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4051bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_90:
4052bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_TRANSVERSE;
4053bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4054bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_TRANSVERSE:
4055bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_90;
4056bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4057bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_270:
4058bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_TRANSPOSE;
4059bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4060bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_NORMAL:
4061bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_FLIP_VERTICAL;
4062bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4063bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_UNDEFINED:
4064bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            default:
4065bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_UNDEFINED;
4066bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4067bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        }
4068bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation));
4069bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    }
4070bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4071bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    /**
4072bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     * Flips the image horizontally.
4073bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren     */
4074bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    public void flipHorizontally() {
4075bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int currentOrientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
4076bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        int resultOrientation;
4077bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        switch (currentOrientation) {
4078bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_FLIP_HORIZONTAL:
4079bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_NORMAL;
4080bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4081bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_180:
4082bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_FLIP_VERTICAL;
4083bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4084bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_FLIP_VERTICAL:
4085bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_180;
4086bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4087bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_TRANSPOSE:
4088bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_90;
4089bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4090bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_90:
4091bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_TRANSPOSE;
4092bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4093bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_TRANSVERSE:
4094bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_ROTATE_270;
4095bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4096bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_ROTATE_270:
4097bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_TRANSVERSE;
4098bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4099bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_NORMAL:
4100bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_FLIP_HORIZONTAL;
4101bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4102bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            case ORIENTATION_UNDEFINED:
4103bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren            default:
4104bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                resultOrientation = ORIENTATION_UNDEFINED;
4105bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren                break;
4106bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        }
4107bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren        setAttribute(TAG_ORIENTATION, Integer.toString(resultOrientation));
4108bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    }
4109bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren
4110bc4fd2c642f7db0a091fe6e9179b0380eda16b36yangren    /**
41114553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * Returns if the current image orientation is flipped.
41124553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     *
41134553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * @see #getRotationDegrees()
41144553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
41154553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    public boolean isFlipped() {
41164553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
41174553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        switch (orientation) {
41184553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_FLIP_HORIZONTAL:
41194553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_TRANSVERSE:
41204553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_FLIP_VERTICAL:
41214553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_TRANSPOSE:
41224553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return true;
41234553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            default:
41244553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return false;
41254553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        }
41264553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    }
41274553d8dff998f532ed5243f5fd91e531adb2f8a0yangren
41284553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
41294553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * Returns the rotation degrees for the current image orientation. If the image is flipped,
41304553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * i.e., {@link #isFlipped()} returns {@code true}, the rotation degrees will be base on
41314553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * the assumption that the image is first flipped horizontally (along Y-axis), and then do
41324553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * the rotation. For example, {@link #ORIENTATION_TRANSPOSE} will be interpreted as flipped
41334553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * horizontally first, and then rotate 270 degrees clockwise.
41344553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     *
41354553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * @return The rotation degrees of the image after the horizontal flipping is applied, if any.
41364553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     *
41374553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     * @see #isFlipped()
41384553d8dff998f532ed5243f5fd91e531adb2f8a0yangren     */
41394553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    public int getRotationDegrees() {
41404553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
41414553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        switch (orientation) {
41424553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_ROTATE_90:
41434553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_TRANSVERSE:
41444553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return 90;
41454553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_ROTATE_180:
41464553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_FLIP_VERTICAL:
41474553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return 180;
41484553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_ROTATE_270:
41494553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_TRANSPOSE:
41504553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return 270;
41514553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_UNDEFINED:
41524553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_NORMAL:
41534553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            case ORIENTATION_FLIP_HORIZONTAL:
41544553d8dff998f532ed5243f5fd91e531adb2f8a0yangren            default:
41554553d8dff998f532ed5243f5fd91e531adb2f8a0yangren                return 0;
41564553d8dff998f532ed5243f5fd91e531adb2f8a0yangren        }
41574553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    }
41584553d8dff998f532ed5243f5fd91e531adb2f8a0yangren
41594553d8dff998f532ed5243f5fd91e531adb2f8a0yangren    /**
416014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Update the values of the tags in the tag groups if any value for the tag already was stored.
416114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
416214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
416314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param value the value of the tag in a form of {@link ExifAttribute}.
416414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @return Returns {@code true} if updating is placed.
416514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
416614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean updateAttribute(String tag, ExifAttribute value) {
416714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        boolean updated = false;
416814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
416914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mAttributes[i].containsKey(tag)) {
417014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[i].put(tag, value);
417114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                updated = true;
417214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
417314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
417414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return updated;
417514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
417614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
417714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
417814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Remove any values of the specified tag.
417914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
418014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param tag the name of the tag.
418114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
418214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void removeAttribute(String tag) {
418314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
418414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[i].remove(tag);
418514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
418614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
418714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
418814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
418914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This function decides which parser to read the image data according to the given input stream
419014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * type and the content of the input stream. In each case, it reads the first three bytes to
419114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * determine whether the image data format is JPEG or not.
419214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
419314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void loadAttributes(@NonNull InputStream in) throws IOException {
419414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
419514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Initialize mAttributes.
419614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int i = 0; i < EXIF_TAGS.length; ++i) {
4197abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                mAttributes[i] = new HashMap<>();
419814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
419914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
420014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Check file type
420114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE);
420214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mMimeType = getMimeType((BufferedInputStream) in);
420314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
420414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Create byte-ordered input stream
420514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ByteOrderedDataInputStream inputStream = new ByteOrderedDataInputStream(in);
420614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
420714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            switch (mMimeType) {
420814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_JPEG: {
420914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    getJpegAttributes(inputStream, 0, IFD_TYPE_PRIMARY); // 0 is offset
421014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
421114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
421214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_RAF: {
421314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    getRafAttributes(inputStream);
421414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
421514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
421614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_ORF: {
421714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    getOrfAttributes(inputStream);
421814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
421914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
422014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_RW2: {
422114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    getRw2Attributes(inputStream);
422214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
422314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
422414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_ARW:
422514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_CR2:
422614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_DNG:
422714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_NEF:
422814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_NRW:
422914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_PEF:
423014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_SRW:
423114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case IMAGE_TYPE_UNKNOWN: {
423214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    getRawAttributes(inputStream);
423314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
423414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
423514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                default: {
423614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
423714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
423814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
423914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Set thumbnail image offset and length
424014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            setThumbnailData(inputStream);
424114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mIsSupportedFile = true;
424214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (IOException e) {
424314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Ignore exceptions in order to keep the compatibility with the old versions of
424414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // ExifInterface.
424514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mIsSupportedFile = false;
424614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
424714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file"
424814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + "(ExifInterface supports JPEG and some RAW image formats only) "
424914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + "or a corrupted JPEG file to ExifInterface.", e);
425014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
425114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } finally {
425214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            addDefaultValuesForCompatibility();
425314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
425414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
425514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                printAttributes();
425614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
425714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
425814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
425914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
426014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Prints out attributes for debugging.
426114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void printAttributes() {
426214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < mAttributes.length; ++i) {
426314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "The size of tag group[" + i + "]: " + mAttributes[i].size());
4264abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            for (Map.Entry<String, ExifAttribute> entry : mAttributes[i].entrySet()) {
4265abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                final ExifAttribute tagValue = entry.getValue();
426614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "tagName: " + entry.getKey() + ", tagType: " + tagValue.toString()
426714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ", tagValue: '" + tagValue.getStringValue(mExifByteOrder) + "'");
426814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
426914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
427014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
427114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
427214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
427314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Save the tag data into the original image file. This is expensive because it involves
427414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * copying all the data from one file to another and deleting the old file and renaming the
427514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * other. It's best to use {@link #setAttribute(String,String)} to set all attributes to write
427614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * and make a single call rather than multiple calls for each attribute.
427714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * <p>
427814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method is only supported for JPEG files.
427914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * </p>
428014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
428114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public void saveAttributes() throws IOException {
428214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mIsSupportedFile || mMimeType != IMAGE_TYPE_JPEG) {
428314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("ExifInterface only supports saving attributes on JPEG formats.");
428414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
428514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mFilename == null) {
428614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException(
428714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    "ExifInterface does not support saving attributes for the current input.");
428814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
428914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
429014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Keep the thumbnail in memory
429114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mThumbnailBytes = getThumbnail();
429214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
429314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        File tempFile = new File(mFilename + ".tmp");
429414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        File originalFile = new File(mFilename);
429514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!originalFile.renameTo(tempFile)) {
429614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Could not rename to " + tempFile.getAbsolutePath());
429714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
429814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
429914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        FileInputStream in = null;
430014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        FileOutputStream out = null;
430114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
430214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Save the new file.
430314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            in = new FileInputStream(tempFile);
430414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            out = new FileOutputStream(mFilename);
430514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            saveJpegAttributes(in, out);
430614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } finally {
430714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            closeQuietly(in);
430814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            closeQuietly(out);
430914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            tempFile.delete();
431014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
431114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
431214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Discard the thumbnail in memory
431314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mThumbnailBytes = null;
431414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
431514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
431614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
431714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns true if the image file has a thumbnail.
431814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
431914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public boolean hasThumbnail() {
432014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return mHasThumbnail;
432114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
432214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
432314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
432414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the JPEG compressed thumbnail inside the image file, or {@code null} if there is no
432514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * JPEG compressed thumbnail.
432614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * The returned data can be decoded using
432714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * {@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)}
432814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
43298936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
433014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public byte[] getThumbnail() {
433114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED) {
433214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return getThumbnailBytes();
433314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
433414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return null;
433514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
433614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
433714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
433814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the thumbnail bytes inside the image file, regardless of the compression type of the
433914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * thumbnail image.
434014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
43418936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
434214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public byte[] getThumbnailBytes() {
434314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mHasThumbnail) {
434414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return null;
434514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
434614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mThumbnailBytes != null) {
434714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mThumbnailBytes;
434814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
434914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
435014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read the thumbnail.
435114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        InputStream in = null;
435214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
435314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mAssetInputStream != null) {
435414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                in = mAssetInputStream;
435514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (in.markSupported()) {
435614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    in.reset();
435714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
435814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "Cannot read thumbnail from inputstream without mark/reset support");
435914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return null;
436014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
436114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mFilename != null) {
436214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                in = new FileInputStream(mFilename);
436314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
436414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (in == null) {
436514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Should not be reached this.
436614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new FileNotFoundException();
436714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
436814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (in.skip(mThumbnailOffset) != mThumbnailOffset) {
436914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Corrupted image");
437014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
437114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte[] buffer = new byte[mThumbnailLength];
437214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (in.read(buffer) != mThumbnailLength) {
437314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Corrupted image");
437414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
437514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailBytes = buffer;
437614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return buffer;
437714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (IOException e) {
437814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Couldn't get a thumbnail image.
437914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "Encountered exception while getting thumbnail", e);
438014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } finally {
438114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            closeQuietly(in);
438214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
438314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return null;
438414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
438514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
438614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
438714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Creates and returns a Bitmap object of the thumbnail image based on the byte array and the
438814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * thumbnail compression value, or {@code null} if the compression type is unsupported.
438914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
43908936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
439114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public Bitmap getThumbnailBitmap() {
439214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mHasThumbnail) {
439314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return null;
439414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (mThumbnailBytes == null) {
439514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailBytes = getThumbnailBytes();
439614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
439714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
439814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED) {
439914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return BitmapFactory.decodeByteArray(mThumbnailBytes, 0, mThumbnailLength);
440014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (mThumbnailCompression == DATA_UNCOMPRESSED) {
440114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int[] rgbValues = new int[mThumbnailBytes.length / 3];
440214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte alpha = (byte) 0xff000000;
440314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int i = 0; i < rgbValues.length; i++) {
440414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                rgbValues[i] = alpha + (mThumbnailBytes[3 * i] << 16)
440514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + (mThumbnailBytes[3 * i + 1] << 8) + mThumbnailBytes[3 * i + 2];
440614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
440714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
440814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute imageLengthAttribute =
440914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH);
441014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute imageWidthAttribute =
441114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH);
441214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (imageLengthAttribute != null && imageWidthAttribute != null) {
441314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder);
441414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder);
441514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return Bitmap.createBitmap(
441614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        rgbValues, imageWidth, imageLength, Bitmap.Config.ARGB_8888);
441714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
441814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
441914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return null;
442014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
442114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
442214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
442314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns true if thumbnail image is JPEG Compressed, or false if either thumbnail image does
442414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * not exist or thumbnail image is uncompressed.
442514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
442614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public boolean isThumbnailCompressed() {
442714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED;
442814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
442914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
443014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
443114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the offset and length of thumbnail inside the image file, or
443214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * {@code null} if there is no thumbnail.
443314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
443414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @return two-element array, the offset in the first value, and length in
443514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *         the second, or {@code null} if no thumbnail was found.
443614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
44378936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
443814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public long[] getThumbnailRange() {
443914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mHasThumbnail) {
444014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return null;
444114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
444214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
444314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        long[] range = new long[2];
444414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        range[0] = mThumbnailOffset;
444514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        range[1] = mThumbnailLength;
444614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
444714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return range;
444814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
444914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
445014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
4451d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * Stores the latitude and longitude value in a float array. The first element is the latitude,
4452d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * and the second element is the longitude. Returns false if the Exif tags are not available.
4453d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     *
4454d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * @deprecated Use {@link #getLatLong()} instead.
445514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
4456d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    @Deprecated
445714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public boolean getLatLong(float output[]) {
4458d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        double[] latLong = getLatLong();
4459d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        if (latLong == null) {
4460d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon            return false;
4461d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        }
4462d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon
4463d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        output[0] = (float) latLong[0];
4464d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        output[1] = (float) latLong[1];
4465d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        return true;
4466d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    }
4467d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon
4468d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    /**
4469d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * Gets the latitude and longitude values.
4470d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * <p>
4471d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * If there are valid latitude and longitude values in the image, this method returns a double
4472d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * array where the first element is the latitude and the second element is the longitude.
4473d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * Otherwise, it returns null.
4474d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     */
44758936a10da590d6d050ddd2632c8182c860d29315Jake Wharton    @Nullable
4476d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    public double[] getLatLong() {
447714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String latValue = getAttribute(TAG_GPS_LATITUDE);
447814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String latRef = getAttribute(TAG_GPS_LATITUDE_REF);
447914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String lngValue = getAttribute(TAG_GPS_LONGITUDE);
448014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String lngRef = getAttribute(TAG_GPS_LONGITUDE_REF);
448114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
448214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
448314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            try {
4484d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                double latitude = convertRationalLatLonToDouble(latValue, latRef);
4485d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                double longitude = convertRationalLatLonToDouble(lngValue, lngRef);
4486d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                return new double[] {latitude, longitude};
448714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } catch (IllegalArgumentException e) {
448814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "Latitude/longitude values are not parseable. " +
448914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        String.format("latValue=%s, latRef=%s, lngValue=%s, lngRef=%s",
449014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                latValue, latRef, lngValue, lngRef));
449114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
449214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
4493d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        return null;
4494d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    }
4495d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon
4496d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    /**
4497c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     * Sets the GPS-related information. It will set GPS processing method, latitude and longitude
4498c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     * values, GPS timestamp, and speed information at the same time.
4499c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     *
4500c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     * @param location the {@link Location} object returned by GPS service.
4501c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     */
4502c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    public void setGpsInfo(Location location) {
4503c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        if (location == null) {
4504c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen            return;
4505c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        }
4506c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, location.getProvider());
4507c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setLatLong(location.getLatitude(), location.getLongitude());
4508c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAltitude(location.getAltitude());
4509c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        // Location objects store speeds in m/sec. Translates it to km/hr here.
4510c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(TAG_GPS_SPEED_REF, "K");
4511c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(TAG_GPS_SPEED, new Rational(location.getSpeed()
4512c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen                * TimeUnit.HOURS.toSeconds(1) / 1000).toString());
4513244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas        String[] dateTime = sFormatter.format(new Date(location.getTime())).split("\\s+", -1);
4514c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(ExifInterface.TAG_GPS_DATESTAMP, dateTime[0]);
4515c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, dateTime[1]);
4516c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    }
4517c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen
4518c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    /**
4519d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * Sets the latitude and longitude values.
4520d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     *
4521d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * @param latitude the decimal value of latitude. Must be a valid double value between -90.0 and
4522d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     *                 90.0.
4523d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * @param longitude the decimal value of longitude. Must be a valid double value between -180.0
4524d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     *                  and 180.0.
4525d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     * @throws IllegalArgumentException If {@code latitude} or {@code longitude} is outside the
4526d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     *                                  specified range.
4527d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon     */
4528d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    public void setLatLong(double latitude, double longitude) {
4529d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        if (latitude < -90.0 || latitude > 90.0 || Double.isNaN(latitude)) {
4530d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon            throw new IllegalArgumentException("Latitude value " + latitude + " is not valid.");
4531d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        }
4532d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        if (longitude < -180.0 || longitude > 180.0 || Double.isNaN(longitude)) {
4533d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon            throw new IllegalArgumentException("Longitude value " + longitude + " is not valid.");
4534d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        }
4535d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        setAttribute(TAG_GPS_LATITUDE_REF, latitude >= 0 ? "N" : "S");
4536d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        setAttribute(TAG_GPS_LATITUDE, convertDecimalDegree(Math.abs(latitude)));
4537d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        setAttribute(TAG_GPS_LONGITUDE_REF, longitude >= 0 ? "E" : "W");
4538d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        setAttribute(TAG_GPS_LONGITUDE, convertDecimalDegree(Math.abs(longitude)));
453914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
454014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
454114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
454214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Return the altitude in meters. If the exif tag does not exist, return
454314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * <var>defaultValue</var>.
454414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
454514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param defaultValue the value to return if the tag is not available.
454614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
454714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public double getAltitude(double defaultValue) {
454814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        double altitude = getAttributeDouble(TAG_GPS_ALTITUDE, -1);
454914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int ref = getAttributeInt(TAG_GPS_ALTITUDE_REF, -1);
455014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
455114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (altitude >= 0 && ref >= 0) {
455214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return (altitude * ((ref == 1) ? -1 : 1));
455314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else {
455414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return defaultValue;
455514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
455614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
455714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
455814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
4559c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     * Sets the altitude in meters.
4560c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen     */
4561c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    public void setAltitude(double altitude) {
4562c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        String ref = altitude >= 0 ? "0" : "1";
4563c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(TAG_GPS_ALTITUDE, new Rational(Math.abs(altitude)).toString());
4564c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen        setAttribute(TAG_GPS_ALTITUDE_REF, ref);
4565c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    }
4566c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen
4567c5d30247a9f0ae2d36b4db80c0d7fa6e73bb008dConrad Chen    /**
45688f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren     * Set the date time value.
45698f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren     *
45708f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren     * @param timeStamp number of milliseconds since Jan. 1, 1970, midnight local time.
45718f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren     * @hide
45728f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren     */
457304c9e28ea0be0cedcee58e4d29343ac08733d58aAurimas Liutikas    @RestrictTo(RestrictTo.Scope.LIBRARY)
45748f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren    public void setDateTime(long timeStamp) {
45758f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren        long sub = timeStamp % 1000;
45768f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren        setAttribute(TAG_DATETIME, sFormatter.format(new Date(timeStamp)));
45778f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren        setAttribute(TAG_SUBSEC_TIME, Long.toString(sub));
45788f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren    }
45798f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren
45808f31117b0d0b9cb24ef4ef0464f526ace39e2709yangren    /**
458114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns number of milliseconds since Jan. 1, 1970, midnight local time.
458214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns -1 if the date time information if not available.
458314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @hide
458414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
458504c9e28ea0be0cedcee58e4d29343ac08733d58aAurimas Liutikas    @RestrictTo(RestrictTo.Scope.LIBRARY)
458614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public long getDateTime() {
458714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String dateTimeString = getAttribute(TAG_DATETIME);
458814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dateTimeString == null
458914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                || !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
459014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
459114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ParsePosition pos = new ParsePosition(0);
459214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
459314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // The exif field is in local time. Parsing it as if it is UTC will yield time
459414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // since 1/1/1970 local time
459514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Date datetime = sFormatter.parse(dateTimeString, pos);
459614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (datetime == null) return -1;
459714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            long msecs = datetime.getTime();
459814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
459914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            String subSecs = getAttribute(TAG_SUBSEC_TIME);
460014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (subSecs != null) {
460114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                try {
460214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    long sub = Long.parseLong(subSecs);
460314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    while (sub > 1000) {
460414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        sub /= 10;
460514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
460614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    msecs += sub;
460714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } catch (NumberFormatException e) {
460814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Ignored
460914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
461014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
461114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return msecs;
461214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (IllegalArgumentException e) {
461314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return -1;
461414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
461514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
461614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
461714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
461814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns number of milliseconds since Jan. 1, 1970, midnight UTC.
461914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns -1 if the date time information if not available.
462014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @hide
462114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
462204c9e28ea0be0cedcee58e4d29343ac08733d58aAurimas Liutikas    @RestrictTo(RestrictTo.Scope.LIBRARY)
462314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    public long getGpsDateTime() {
462414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String date = getAttribute(TAG_GPS_DATESTAMP);
462514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String time = getAttribute(TAG_GPS_TIMESTAMP);
462614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (date == null || time == null
462714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                || (!sNonZeroTimePattern.matcher(date).matches()
462814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                && !sNonZeroTimePattern.matcher(time).matches())) {
462914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return -1;
463014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
463114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
463214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String dateTimeString = date + ' ' + time;
463314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
463414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ParsePosition pos = new ParsePosition(0);
463514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
463614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Date datetime = sFormatter.parse(dateTimeString, pos);
463714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (datetime == null) return -1;
463814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return datetime.getTime();
463914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (IllegalArgumentException e) {
464014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return -1;
464114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
464214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
464314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
4644d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    private static double convertRationalLatLonToDouble(String rationalString, String ref) {
464514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
4646244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            String [] parts = rationalString.split(",", -1);
464714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
464814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            String [] pair;
4649244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            pair = parts[0].split("/", -1);
465014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            double degrees = Double.parseDouble(pair[0].trim())
465114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    / Double.parseDouble(pair[1].trim());
465214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
4653244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            pair = parts[1].split("/", -1);
465414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            double minutes = Double.parseDouble(pair[0].trim())
465514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    / Double.parseDouble(pair[1].trim());
465614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
4657244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            pair = parts[2].split("/", -1);
465814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            double seconds = Double.parseDouble(pair[0].trim())
465914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    / Double.parseDouble(pair[1].trim());
466014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
466114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
466214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if ((ref.equals("S") || ref.equals("W"))) {
4663d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                return -result;
4664d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon            } else if (ref.equals("N") || ref.equals("E")) {
4665d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                return result;
4666d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon            } else {
4667d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                // Not valid
4668d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon                throw new IllegalArgumentException();
466914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
467014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
467114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Not valid
467214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IllegalArgumentException();
467314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
467414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
467514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
4676d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    private String convertDecimalDegree(double decimalDegree) {
4677d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        long degrees = (long) decimalDegree;
4678d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        long minutes = (long) ((decimalDegree - degrees) * 60.0);
4679d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        long seconds = Math.round((decimalDegree - degrees - minutes / 60.0) * 3600.0 * 1e7);
4680d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon        return degrees + "/1," + minutes + "/1," + seconds + "/10000000";
4681d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon    }
4682d56d8611e9a0e06799114a3d4716ac5921c06342Hyundo Moon
468314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Checks the type of image file
468414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int getMimeType(BufferedInputStream in) throws IOException {
468514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.mark(SIGNATURE_CHECK_SIZE);
468614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte[] signatureCheckBytes = new byte[SIGNATURE_CHECK_SIZE];
46871bd1d122e9aec38b7d46be73688a0bb4bad1d678Jin Seok Park        in.read(signatureCheckBytes);
468814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.reset();
468914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (isJpegFormat(signatureCheckBytes)) {
469014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return IMAGE_TYPE_JPEG;
469114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (isRafFormat(signatureCheckBytes)) {
469214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return IMAGE_TYPE_RAF;
469314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (isOrfFormat(signatureCheckBytes)) {
469414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return IMAGE_TYPE_ORF;
469514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (isRw2Format(signatureCheckBytes)) {
469614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return IMAGE_TYPE_RW2;
469714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
469814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Certain file formats (PEF) are identified in readImageFileDirectory()
469914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return IMAGE_TYPE_UNKNOWN;
470014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
470114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
470214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
470314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method looks at the first 3 bytes to determine if this file is a JPEG file.
470414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * See http://www.media.mit.edu/pia/Research/deepview/exif.html, "JPEG format and Marker"
470514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
470614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static boolean isJpegFormat(byte[] signatureCheckBytes) throws IOException {
470714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < JPEG_SIGNATURE.length; i++) {
470814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (signatureCheckBytes[i] != JPEG_SIGNATURE[i]) {
470914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return false;
471014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
471114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
471214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return true;
471314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
471414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
471514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
471614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method looks at the first 15 bytes to determine if this file is a RAF file.
471714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * There is no official specification for RAF files from Fuji, but there is an online archive of
471814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * image file specifications:
471914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * http://fileformats.archiveteam.org/wiki/Fujifilm_RAF
472014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
472114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean isRafFormat(byte[] signatureCheckBytes) throws IOException {
472289889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon        byte[] rafSignatureBytes = RAF_SIGNATURE.getBytes(Charset.defaultCharset());
472314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < rafSignatureBytes.length; i++) {
472414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (signatureCheckBytes[i] != rafSignatureBytes[i]) {
472514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return false;
472614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
472714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
472814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return true;
472914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
473014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
473114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
473214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * ORF has a similar structure to TIFF but it contains a different signature at the TIFF Header.
473314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method looks at the 2 bytes following the Byte Order bytes to determine if this file is
473414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * an ORF file.
473514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * There is no official specification for ORF files from Olympus, but there is an online archive
473614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * of image file specifications:
473714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * http://fileformats.archiveteam.org/wiki/Olympus_ORF
473814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
473914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean isOrfFormat(byte[] signatureCheckBytes) throws IOException {
474014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ByteOrderedDataInputStream signatureInputStream =
474114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                new ByteOrderedDataInputStream(signatureCheckBytes);
474214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read byte order
474314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mExifByteOrder = readByteOrder(signatureInputStream);
474414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Set byte order
474514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        signatureInputStream.setByteOrder(mExifByteOrder);
474614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
474714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        short orfSignature = signatureInputStream.readShort();
4748f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes        signatureInputStream.close();
474914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return orfSignature == ORF_SIGNATURE_1 || orfSignature == ORF_SIGNATURE_2;
475014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
475114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
475214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
475314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * RW2 is TIFF-based, but stores 0x55 signature byte instead of 0x42 at the header
475414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * See http://lclevy.free.fr/raw/
475514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
475614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean isRw2Format(byte[] signatureCheckBytes) throws IOException {
475714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ByteOrderedDataInputStream signatureInputStream =
475814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                new ByteOrderedDataInputStream(signatureCheckBytes);
475914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read byte order
476014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mExifByteOrder = readByteOrder(signatureInputStream);
476114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Set byte order
476214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        signatureInputStream.setByteOrder(mExifByteOrder);
476314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
476414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        short signatureByte = signatureInputStream.readShort();
4765f83358389f0c4ea37a7e7d9e493857f99baf0440Chris Banes        signatureInputStream.close();
476614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return signatureByte == RW2_SIGNATURE;
476714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
476814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
476914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
477014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Loads EXIF attributes from a JPEG input stream.
477114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
477214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param in The input stream that starts with the JPEG data.
477314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param jpegOffset The offset value in input stream for JPEG data.
477414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param imageType The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for
477514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *                   primary image, IFD_TYPE_PREVIEW for preview image, and
477614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *                   IFD_TYPE_THUMBNAIL for thumbnail image.
477714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @throws IOException If the data contains invalid JPEG markers, offsets, or length values.
477814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
477914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void getJpegAttributes(ByteOrderedDataInputStream in, int jpegOffset, int imageType)
478014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
478114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See JPEG File Interchange Format Specification, "JFIF Specification"
478214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (DEBUG) {
478314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "getJpegAttributes starting with: " + in);
478414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
478514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
478614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // JPEG uses Big Endian by default. See https://people.cs.umass.edu/~verts/cs32/endian.html
478714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.setByteOrder(ByteOrder.BIG_ENDIAN);
478814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
478914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Skip to JPEG data
479014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.seek(jpegOffset);
479114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int bytesRead = jpegOffset;
479214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
479314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte marker;
479414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if ((marker = in.readByte()) != MARKER) {
479514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
479614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
479714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ++bytesRead;
479814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (in.readByte() != MARKER_SOI) {
479914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
480014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
480114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ++bytesRead;
480214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        while (true) {
480314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            marker = in.readByte();
480414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (marker != MARKER) {
480514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid marker:" + Integer.toHexString(marker & 0xff));
480614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
480714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++bytesRead;
480814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            marker = in.readByte();
480914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
481014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "Found JPEG segment indicator: " + Integer.toHexString(marker & 0xff));
481114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
481214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++bytesRead;
481314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
481414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // EOI indicates the end of an image and in case of SOS, JPEG image stream starts and
481514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // the image data will terminate right after.
481614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (marker == MARKER_EOI || marker == MARKER_SOS) {
481714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                break;
481814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
481914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int length = in.readUnsignedShort() - 2;
482014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            bytesRead += 2;
482114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
482214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "JPEG segment: " + Integer.toHexString(marker & 0xff) + " (length: "
482314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + (length + 2) + ")");
482414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
482514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (length < 0) {
482614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid length");
482714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
482814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            switch (marker) {
482914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_APP1: {
483014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (DEBUG) {
483114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        Log.d(TAG, "MARKER_APP1");
483214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
483314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length < 6) {
483414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Skip if it's not an EXIF APP1 segment.
483514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
483614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
483714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    byte[] identifier = new byte[6];
483814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (in.read(identifier) != 6) {
483914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid exif");
484014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
484114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    bytesRead += 6;
484214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    length -= 6;
484314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
484414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Skip if it's not an EXIF APP1 segment.
484514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
484614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
484714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length <= 0) {
484814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid exif");
484914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
485014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (DEBUG) {
485114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")");
485214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
485314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Save offset values for createJpegThumbnailBitmap() function
485414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mExifOffset = bytesRead;
485514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
485614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    byte[] bytes = new byte[length];
485714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (in.read(bytes) != length) {
485814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid exif");
485914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
486014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    bytesRead += length;
486114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    length = 0;
486214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
486314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    readExifSegment(bytes, imageType);
486414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
486514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
486614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
486714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_COM: {
486814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    byte[] bytes = new byte[length];
486914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (in.read(bytes) != length) {
487014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid exif");
487114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
487214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    length = 0;
487314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (getAttribute(TAG_USER_COMMENT) == null) {
487414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString(
487514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                new String(bytes, ASCII)));
487614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
487714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
487814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
487914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
488014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF0:
488114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF1:
488214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF2:
488314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF3:
488414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF5:
488514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF6:
488614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF7:
488714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF9:
488814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF10:
488914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF11:
489014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF13:
489114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF14:
489214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOF15: {
489314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (in.skipBytes(1) != 1) {
489414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid SOFx");
489514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
489614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[imageType].put(TAG_IMAGE_LENGTH, ExifAttribute.createULong(
489714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            in.readUnsignedShort(), mExifByteOrder));
489814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[imageType].put(TAG_IMAGE_WIDTH, ExifAttribute.createULong(
489914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            in.readUnsignedShort(), mExifByteOrder));
490014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    length -= 5;
490114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
490214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
490314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
490414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                default: {
490514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
490614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
490714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
490814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (length < 0) {
490914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid length");
491014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
491114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (in.skipBytes(length) != length) {
491214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid JPEG segment");
491314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
491414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            bytesRead += length;
491514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
491614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Restore original byte order
491714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.setByteOrder(mExifByteOrder);
491814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
491914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
492014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void getRawAttributes(ByteOrderedDataInputStream in) throws IOException {
492114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Parse TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
492214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        parseTiffHeaders(in, in.available());
492314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
492414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6.
492514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        readImageFileDirectory(in, IFD_TYPE_PRIMARY);
492614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
492714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Update ImageLength/Width tags for all image data.
492814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        updateImageSizeValues(in, IFD_TYPE_PRIMARY);
492914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        updateImageSizeValues(in, IFD_TYPE_PREVIEW);
493014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        updateImageSizeValues(in, IFD_TYPE_THUMBNAIL);
493114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
493214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check if each image data is in valid position.
493314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        validateImages(in);
493414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
493514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mMimeType == IMAGE_TYPE_PEF) {
493614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // PEF files contain a MakerNote data, which contains the data for ColorSpace tag.
493714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData()
493814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute makerNoteAttribute =
493914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
494014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (makerNoteAttribute != null) {
494114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Create an ordered DataInputStream for MakerNote
494214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ByteOrderedDataInputStream makerNoteDataInputStream =
494314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        new ByteOrderedDataInputStream(makerNoteAttribute.bytes);
494414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                makerNoteDataInputStream.setByteOrder(mExifByteOrder);
494514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
494614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Seek to MakerNote data
494714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE);
494814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
494914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Read IFD data from MakerNote
495014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF);
495114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
495214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Update ColorSpace tag
495314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute colorSpaceAttribute =
495414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE);
495514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (colorSpaceAttribute != null) {
495614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute);
495714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
495814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
495914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
496014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
496114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
496214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
496314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * RAF files contains a JPEG and a CFA data.
496414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * The JPEG contains two images, a preview and a thumbnail, while the CFA contains a RAW image.
496514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method looks at the first 160 bytes of a RAF file to retrieve the offset and length
496614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * values for the JPEG and CFA data.
496714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Using that data, it parses the JPEG data to retrieve the preview and thumbnail image data,
496814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * then parses the CFA metadata to retrieve the primary image length/width values.
496914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * For data format details, see http://fileformats.archiveteam.org/wiki/Fujifilm_RAF
497014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
497114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void getRafAttributes(ByteOrderedDataInputStream in) throws IOException {
497214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve offset & length values
497314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.skipBytes(RAF_OFFSET_TO_JPEG_IMAGE_OFFSET);
497414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte[] jpegOffsetBytes = new byte[4];
497514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte[] cfaHeaderOffsetBytes = new byte[4];
497614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.read(jpegOffsetBytes);
497714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Skip JPEG length value since it is not needed
497814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.skipBytes(RAF_JPEG_LENGTH_VALUE_SIZE);
497914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.read(cfaHeaderOffsetBytes);
498014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int rafJpegOffset = ByteBuffer.wrap(jpegOffsetBytes).getInt();
498114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int rafCfaHeaderOffset = ByteBuffer.wrap(cfaHeaderOffsetBytes).getInt();
498214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
498314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve JPEG image metadata
498414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW);
498514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
498614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Skip to CFA header offset.
498714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.seek(rafCfaHeaderOffset);
498814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
498914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve primary image length/width values, if TAG_RAF_IMAGE_SIZE exists
499014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        in.setByteOrder(ByteOrder.BIG_ENDIAN);
499114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int numberOfDirectoryEntry = in.readInt();
499214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (DEBUG) {
499314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry);
499414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
499514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // CFA stores some metadata about the RAW image. Since CFA uses proprietary tags, can only
499614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // find and retrieve image size information tags, while skipping others.
499714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See piex.cc RafGetDimension()
499814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < numberOfDirectoryEntry; ++i) {
499914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int tagNumber = in.readUnsignedShort();
500014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int numberOfBytes = in.readUnsignedShort();
500114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (tagNumber == TAG_RAF_IMAGE_SIZE.number) {
500214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int imageLength = in.readShort();
500314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int imageWidth = in.readShort();
500414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute imageLengthAttribute =
500514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(imageLength, mExifByteOrder);
500614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute imageWidthAttribute =
500714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(imageWidth, mExifByteOrder);
500814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
500914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
501014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (DEBUG) {
501114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth);
501214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
501314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return;
501414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
501514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            in.skipBytes(numberOfBytes);
501614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
501714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
501814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
501914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
502014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * ORF files contains a primary image data and a MakerNote data that contains preview/thumbnail
502114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * images. Both data takes the form of IFDs and can therefore be read with the
502214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * readImageFileDirectory() method.
502314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method reads all the necessary data and updates the primary/preview/thumbnail image
502414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * information according to the GetOlympusPreviewImage() method in piex.cc.
502514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * For data format details, see the following:
502614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * http://fileformats.archiveteam.org/wiki/Olympus_ORF
502714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * https://libopenraw.freedesktop.org/wiki/Olympus_ORF
502814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
502914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void getOrfAttributes(ByteOrderedDataInputStream in) throws IOException {
503014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve primary image data
503114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Other Exif data will be located in the Makernote.
503214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        getRawAttributes(in);
503314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
503414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Additionally retrieve preview/thumbnail information from MakerNote tag, which contains
503514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // proprietary tags and therefore does not have offical documentation
503614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html
503714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute makerNoteAttribute =
503814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE);
503914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (makerNoteAttribute != null) {
504014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Create an ordered DataInputStream for MakerNote
504114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ByteOrderedDataInputStream makerNoteDataInputStream =
504214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    new ByteOrderedDataInputStream(makerNoteAttribute.bytes);
504314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            makerNoteDataInputStream.setByteOrder(mExifByteOrder);
504414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
504514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // There are two types of headers for Olympus MakerNotes
504614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See http://www.exiv2.org/makernote.html#R1
504714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte[] makerNoteHeader1Bytes = new byte[ORF_MAKER_NOTE_HEADER_1.length];
504814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            makerNoteDataInputStream.readFully(makerNoteHeader1Bytes);
504914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            makerNoteDataInputStream.seek(0);
505014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte[] makerNoteHeader2Bytes = new byte[ORF_MAKER_NOTE_HEADER_2.length];
505114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            makerNoteDataInputStream.readFully(makerNoteHeader2Bytes);
505214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Skip the corresponding amount of bytes for each header type
505314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (Arrays.equals(makerNoteHeader1Bytes, ORF_MAKER_NOTE_HEADER_1)) {
505414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                makerNoteDataInputStream.seek(ORF_MAKER_NOTE_HEADER_1_SIZE);
505514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (Arrays.equals(makerNoteHeader2Bytes, ORF_MAKER_NOTE_HEADER_2)) {
505614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                makerNoteDataInputStream.seek(ORF_MAKER_NOTE_HEADER_2_SIZE);
505714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
505814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
505914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Read IFD data from MakerNote
506014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE);
506114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
506214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Retrieve & update preview image offset & length values
5063db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            ExifAttribute imageStartAttribute = (ExifAttribute)
506414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START);
5065db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            ExifAttribute imageLengthAttribute = (ExifAttribute)
506614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH);
506714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
5068db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            if (imageStartAttribute != null && imageLengthAttribute != null) {
506914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT,
5070db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                        imageStartAttribute);
507114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
5072db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                        imageLengthAttribute);
507314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
507414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
507514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // TODO: Check this behavior in other ORF files
507614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Retrieve primary image length & width values
507714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See piex.cc GetOlympusPreviewImage()
507814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute aspectFrameAttribute = (ExifAttribute)
507914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME);
508014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (aspectFrameAttribute != null) {
508114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int[] aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder);
508214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (aspectFrameValues == null || aspectFrameValues.length != 4) {
508314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid aspect frame values. frame="
508414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + Arrays.toString(aspectFrameValues));
508514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
508614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
508714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (aspectFrameValues[2] > aspectFrameValues[0] &&
508814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        aspectFrameValues[3] > aspectFrameValues[1]) {
508914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int primaryImageWidth = aspectFrameValues[2] - aspectFrameValues[0] + 1;
509014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int primaryImageLength = aspectFrameValues[3] - aspectFrameValues[1] + 1;
509114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Swap width & length values
509214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (primaryImageWidth < primaryImageLength) {
509314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        primaryImageWidth += primaryImageLength;
509414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        primaryImageLength = primaryImageWidth - primaryImageLength;
509514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        primaryImageWidth -= primaryImageLength;
509614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
509714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute primaryImageWidthAttribute =
509814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            ExifAttribute.createUShort(primaryImageWidth, mExifByteOrder);
509914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute primaryImageLengthAttribute =
510014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            ExifAttribute.createUShort(primaryImageLength, mExifByteOrder);
510114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
510214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute);
510314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute);
510414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
510514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
510614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
510714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
510814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
510914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // RW2 contains the primary image data in IFD0 and the preview and/or thumbnail image data in
511014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // the JpgFromRaw tag
511114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See https://libopenraw.freedesktop.org/wiki/Panasonic_RAW/ and piex.cc Rw2GetPreviewData()
511214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void getRw2Attributes(ByteOrderedDataInputStream in) throws IOException {
511314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve primary image data
511414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        getRawAttributes(in);
511514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
511614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Retrieve preview and/or thumbnail image data
511714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute jpgFromRawAttribute =
511814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW);
511914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (jpgFromRawAttribute != null) {
512014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW);
512114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
512214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
512314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Set ISO tag value if necessary
512414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute rw2IsoAttribute =
512514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO);
512614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute exifIsoAttribute =
51278945d24b8dece3446b1393c01defd51c88439d04Conrad Chen                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PHOTOGRAPHIC_SENSITIVITY);
512814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (rw2IsoAttribute != null && exifIsoAttribute == null) {
512914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Place this attribute only if it doesn't exist
51308945d24b8dece3446b1393c01defd51c88439d04Conrad Chen            mAttributes[IFD_TYPE_EXIF].put(TAG_PHOTOGRAPHIC_SENSITIVITY, rw2IsoAttribute);
513114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
513214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
513314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
513414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Stores a new JPEG image with EXIF attributes into a given output stream.
513514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void saveJpegAttributes(InputStream inputStream, OutputStream outputStream)
513614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
513714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See JPEG File Interchange Format Specification, "JFIF Specification"
513814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (DEBUG) {
513914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "saveJpegAttributes starting with (inputStream: " + inputStream
514014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    + ", outputStream: " + outputStream + ")");
514114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
514214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        DataInputStream dataInputStream = new DataInputStream(inputStream);
514314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ByteOrderedDataOutputStream dataOutputStream =
514414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                new ByteOrderedDataOutputStream(outputStream, ByteOrder.BIG_ENDIAN);
514514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dataInputStream.readByte() != MARKER) {
514614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid marker");
514714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
514814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeByte(MARKER);
514914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dataInputStream.readByte() != MARKER_SOI) {
515014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid marker");
515114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
515214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeByte(MARKER_SOI);
515314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
515414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Write EXIF APP1 segment
515514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeByte(MARKER);
515614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeByte(MARKER_APP1);
515714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        writeExifSegment(dataOutputStream, 6);
515814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
515914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte[] bytes = new byte[4096];
516014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
516114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        while (true) {
516214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte marker = dataInputStream.readByte();
516314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (marker != MARKER) {
516414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid marker");
516514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
516614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            marker = dataInputStream.readByte();
516714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            switch (marker) {
516814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_APP1: {
516914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int length = dataInputStream.readUnsignedShort() - 2;
517014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length < 0) {
517114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid length");
517214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
517314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    byte[] identifier = new byte[6];
517414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length >= 6) {
517514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        if (dataInputStream.read(identifier) != 6) {
517614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            throw new IOException("Invalid exif");
517714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
517814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        if (Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
517914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            // Skip the original EXIF APP1 segment.
518014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            if (dataInputStream.skipBytes(length - 6) != length - 6) {
518114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                throw new IOException("Invalid length");
518214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
518314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            break;
518414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
518514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
518614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Copy non-EXIF APP1 segment.
518714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(MARKER);
518814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(marker);
518914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedShort(length + 2);
519014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length >= 6) {
519114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        length -= 6;
519214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.write(identifier);
519314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
519414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int read;
519514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    while (length > 0 && (read = dataInputStream.read(
519614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            bytes, 0, Math.min(length, bytes.length))) >= 0) {
519714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.write(bytes, 0, read);
519814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        length -= read;
519914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
520014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
520114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
520214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_EOI:
520314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case MARKER_SOS: {
520414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(MARKER);
520514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(marker);
520614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Copy all the remaining data
520714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    copy(dataInputStream, dataOutputStream);
520814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
520914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
521014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                default: {
521114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Copy JPEG segment
521214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(MARKER);
521314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeByte(marker);
521414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int length = dataInputStream.readUnsignedShort();
521514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedShort(length);
521614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    length -= 2;
521714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (length < 0) {
521814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        throw new IOException("Invalid length");
521914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
522014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int read;
522114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    while (length > 0 && (read = dataInputStream.read(
522214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            bytes, 0, Math.min(length, bytes.length))) >= 0) {
522314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.write(bytes, 0, read);
522414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        length -= read;
522514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
522614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
522714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
522814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
522914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
523014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
523114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
523214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Reads the given EXIF byte area and save its tag data into attributes.
523314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void readExifSegment(byte[] exifBytes, int imageType) throws IOException {
523414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ByteOrderedDataInputStream dataInputStream =
523514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                new ByteOrderedDataInputStream(exifBytes);
523614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
523714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Parse TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
523814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        parseTiffHeaders(dataInputStream, exifBytes.length);
523914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
524014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6.
524114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        readImageFileDirectory(dataInputStream, imageType);
524214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
524314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
524414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void addDefaultValuesForCompatibility() {
5245a39fc6268fbf33ad5d39829cacebf49b11f35c3eHyundo Moon        // If DATETIME tag has no value, then set the value to DATETIME_ORIGINAL tag's.
524614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL);
5247a39fc6268fbf33ad5d39829cacebf49b11f35c3eHyundo Moon        if (valueOfDateTimeOriginal != null && getAttribute(TAG_DATETIME) == null) {
524814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME,
524914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createString(valueOfDateTimeOriginal));
525014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
525114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
525214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Add the default value.
525314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (getAttribute(TAG_IMAGE_WIDTH) == null) {
525414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH,
525514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
525614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
525714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (getAttribute(TAG_IMAGE_LENGTH) == null) {
525814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH,
525914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
526014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
526114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (getAttribute(TAG_ORIENTATION) == null) {
526214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION,
526314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
526414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
526514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (getAttribute(TAG_LIGHT_SOURCE) == null) {
526614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE,
526714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
526814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
526914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
527014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
527114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private ByteOrder readByteOrder(ByteOrderedDataInputStream dataInputStream)
527214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
527314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read byte order.
527414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        short byteOrder = dataInputStream.readShort();
527514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        switch (byteOrder) {
527614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            case BYTE_ALIGN_II:
527714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (DEBUG) {
527814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "readExifSegment: Byte Align II");
527914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
528014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ByteOrder.LITTLE_ENDIAN;
528114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            case BYTE_ALIGN_MM:
528214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (DEBUG) {
528314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "readExifSegment: Byte Align MM");
528414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
528514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ByteOrder.BIG_ENDIAN;
528614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            default:
528714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Invalid byte order: " + Integer.toHexString(byteOrder));
528814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
528914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
529014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
529114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void parseTiffHeaders(ByteOrderedDataInputStream dataInputStream,
529214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int exifBytesLength) throws IOException {
529314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read byte order
529414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        mExifByteOrder = readByteOrder(dataInputStream);
529514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Set byte order
529614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataInputStream.setByteOrder(mExifByteOrder);
529714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
529814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check start code
529914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int startCode = dataInputStream.readUnsignedShort();
530014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mMimeType != IMAGE_TYPE_ORF && mMimeType != IMAGE_TYPE_RW2 && startCode != START_CODE) {
530114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid start code: " + Integer.toHexString(startCode));
530214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
530314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
530414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Read and skip to first ifd offset
530514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int firstIfdOffset = dataInputStream.readInt();
530614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (firstIfdOffset < 8 || firstIfdOffset >= exifBytesLength) {
530714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid first Ifd offset: " + firstIfdOffset);
530814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
530914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        firstIfdOffset -= 8;
531014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (firstIfdOffset > 0) {
531114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (dataInputStream.skipBytes(firstIfdOffset) != firstIfdOffset) {
531214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset);
531314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
531414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
531514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
531614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
531714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Reads image file directory, which is a tag group in EXIF.
531814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void readImageFileDirectory(ByteOrderedDataInputStream dataInputStream,
531914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            @IfdType int ifdType) throws IOException {
532014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dataInputStream.mPosition + 2 > dataInputStream.mLength) {
532114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Return if there is no data from the offset.
532214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return;
532314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
532414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See TIFF 6.0 Section 2: TIFF Structure, Figure 1.
532514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        short numberOfDirectoryEntry = dataInputStream.readShort();
5326db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen        if (DEBUG) {
5327db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry);
5328db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen        }
532914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dataInputStream.mPosition + 12 * numberOfDirectoryEntry > dataInputStream.mLength) {
533014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Return if the size of entries is too big.
533114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return;
533214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
533314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
533414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See TIFF 6.0 Section 2: TIFF Structure, "Image File Directory".
533514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (short i = 0; i < numberOfDirectoryEntry; ++i) {
533614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int tagNumber = dataInputStream.readUnsignedShort();
533714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int dataFormat = dataInputStream.readUnsignedShort();
533814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int numberOfComponents = dataInputStream.readInt();
533914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Next four bytes is for data offset or value.
5340775da40ca0bcee27c4b29ce1e6df899b8e8e9113Jake Wharton            long nextEntryOffset = dataInputStream.peek() + 4L;
534114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
534214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Look up a corresponding tag from tag number
534314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber);
534414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
534514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
534614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, "
534714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + "numberOfComponents: %d", ifdType, tagNumber,
534814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        tag != null ? tag.name : null, dataFormat, numberOfComponents));
534914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
535014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
535114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            long byteCount = 0;
535214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            boolean valid = false;
535314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (tag == null) {
535414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber);
535514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
535614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat);
5357db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen            } else if (!tag.isFormatCompatible(dataFormat)) {
5358db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                Log.w(TAG, "Skip the tag entry since data format (" + IFD_FORMAT_NAMES[dataFormat]
5359db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                        + ") is unexpected for tag: " + tag.name);
536014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else {
5361db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                if (dataFormat == IFD_FORMAT_UNDEFINED) {
5362db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                    dataFormat = tag.primaryFormat;
5363db4a5b23d1ccd3096cc27657c2b1b95bf68d8739Conrad Chen                }
536414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                byteCount = (long) numberOfComponents * IFD_FORMAT_BYTES_PER_FORMAT[dataFormat];
536514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (byteCount < 0 || byteCount > Integer.MAX_VALUE) {
536614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Skip the tag entry since the number of components is invalid: "
536714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + numberOfComponents);
536814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
536914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    valid = true;
537014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
537114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
537214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (!valid) {
537314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                dataInputStream.seek(nextEntryOffset);
537414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                continue;
537514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
537614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
537714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Read a value from data field or seek to the value offset which is stored in data
537814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // field if the size of the entry value is bigger than 4.
537914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (byteCount > 4) {
538014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int offset = dataInputStream.readInt();
538114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (DEBUG) {
538214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "seek to data offset: " + offset);
538314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
538414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (mMimeType == IMAGE_TYPE_ORF) {
538589889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                    if (TAG_MAKER_NOTE.equals(tag.name)) {
538614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Save offset value for reading thumbnail
538714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mOrfMakerNoteOffset = offset;
538814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE
538989889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                            && TAG_ORF_THUMBNAIL_IMAGE.equals(tag.name)) {
539014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Retrieve & update values for thumbnail offset and length values for ORF
539114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mOrfThumbnailOffset = offset;
539214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mOrfThumbnailLength = numberOfComponents;
539314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
539414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute compressionAttribute =
539514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createUShort(DATA_JPEG, mExifByteOrder);
539614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute jpegInterchangeFormatAttribute =
539714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createULong(mOrfThumbnailOffset, mExifByteOrder);
539814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute jpegInterchangeFormatLengthAttribute =
539914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder);
540014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
540114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute);
540214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT,
540314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                jpegInterchangeFormatAttribute);
540414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
540514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                jpegInterchangeFormatLengthAttribute);
540614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
540714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else if (mMimeType == IMAGE_TYPE_RW2) {
540889889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                    if (TAG_RW2_JPG_FROM_RAW.equals(tag.name)) {
540914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        mRw2JpgFromRawOffset = offset;
541014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
541114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
541214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (offset + byteCount <= dataInputStream.mLength) {
541314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataInputStream.seek(offset);
541414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
541514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Skip if invalid data offset.
541614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset);
541714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataInputStream.seek(nextEntryOffset);
541814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    continue;
541914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
542014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
542114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
542214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Recursively parse IFD when a IFD pointer tag appears.
5423abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            Integer nextIfdType = sExifPointerTagMap.get(tagNumber);
542414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
542514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount);
542614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
542714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
542814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (nextIfdType != null) {
542914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                long offset = -1L;
543014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Get offset from data field
543114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                switch (dataFormat) {
543214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_USHORT: {
543314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        offset = dataInputStream.readUnsignedShort();
543414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
543514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
543614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SSHORT: {
543714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        offset = dataInputStream.readShort();
543814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
543914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
544014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_ULONG: {
544114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        offset = dataInputStream.readUnsignedInt();
544214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
544314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
544414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_SLONG:
544514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    case IFD_FORMAT_IFD: {
544614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        offset = dataInputStream.readInt();
544714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
544814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
544914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    default: {
545014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Nothing to do
545114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        break;
545214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
545314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
545414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (DEBUG) {
545514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tag.name));
545614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
545714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (offset > 0L && offset < dataInputStream.mLength) {
545814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataInputStream.seek(offset);
5459abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                    readImageFileDirectory(dataInputStream, nextIfdType);
546014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
546114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
546214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
546314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
546414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                dataInputStream.seek(nextEntryOffset);
546514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                continue;
546614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
546714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
546814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte[] bytes = new byte[(int) byteCount];
546914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            dataInputStream.readFully(bytes);
547014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
547114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[ifdType].put(tag.name, attribute);
547214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
547314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // DNG files have a DNG Version tag specifying the version of specifications that the
547414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // image file is following.
547514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See http://fileformats.archiveteam.org/wiki/DNG
547689889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon            if (TAG_DNG_VERSION.equals(tag.name)) {
547714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mMimeType = IMAGE_TYPE_DNG;
547814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
547914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
548014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // PEF files have a Make or Model tag that begins with "PENTAX" or a compression tag
548114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // that is 65535.
548214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See http://fileformats.archiveteam.org/wiki/Pentax_PEF
548389889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon            if (((TAG_MAKE.equals(tag.name) || TAG_MODEL.equals(tag.name))
548414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    && attribute.getStringValue(mExifByteOrder).contains(PEF_SIGNATURE))
548589889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                    || (TAG_COMPRESSION.equals(tag.name)
548614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    && attribute.getIntValue(mExifByteOrder) == 65535)) {
548714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mMimeType = IMAGE_TYPE_PEF;
548814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
548914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
549014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Seek to next tag offset
549114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (dataInputStream.peek() != nextEntryOffset) {
549214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                dataInputStream.seek(nextEntryOffset);
549314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
549414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
549514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
549614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (dataInputStream.peek() + 4 <= dataInputStream.mLength) {
549714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int nextIfdOffset = dataInputStream.readInt();
549814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
549914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
550014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
550114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // The next IFD offset needs to be bigger than 8
550214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // since the first IFD offset is at least 8.
550314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
550414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                dataInputStream.seek(nextIfdOffset);
550514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
550614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Do not overwrite thumbnail IFD data if it alreay exists.
550714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL);
550814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) {
550914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW);
551014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
551114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
551214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
551314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
551414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
551514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
551614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * JPEG compressed images do not contain IMAGE_LENGTH & IMAGE_WIDTH tags.
551714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This value uses JpegInterchangeFormat(JPEG data offset) value, and calls getJpegAttributes()
551814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * to locate SOF(Start of Frame) marker and update the image length & width values.
551914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * See JEITA CP-3451C Table 5 and Section 4.8.1. B.
552014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
552114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void retrieveJpegImageSize(ByteOrderedDataInputStream in, int imageType)
552214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
552314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check if image already has IMAGE_LENGTH & IMAGE_WIDTH values
552414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute imageLengthAttribute =
552514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_IMAGE_LENGTH);
552614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute imageWidthAttribute =
552714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_IMAGE_WIDTH);
552814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
552914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (imageLengthAttribute == null || imageWidthAttribute == null) {
553014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Find if offset for JPEG data exists
553114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute jpegInterchangeFormatAttribute =
553214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    (ExifAttribute) mAttributes[imageType].get(TAG_JPEG_INTERCHANGE_FORMAT);
553314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (jpegInterchangeFormatAttribute != null) {
553414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int jpegInterchangeFormat =
553514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        jpegInterchangeFormatAttribute.getIntValue(mExifByteOrder);
553614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
553714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Searches for SOF marker in JPEG data and updates IMAGE_LENGTH & IMAGE_WIDTH tags
553814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                getJpegAttributes(in, jpegInterchangeFormat, imageType);
553914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
554014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
554114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
554214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
554314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags
554414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void setThumbnailData(ByteOrderedDataInputStream in) throws IOException {
554514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL];
554614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
554714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute compressionAttribute =
554814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_COMPRESSION);
554914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (compressionAttribute != null) {
555014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailCompression = compressionAttribute.getIntValue(mExifByteOrder);
555114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            switch (mThumbnailCompression) {
555214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case DATA_JPEG: {
555314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    handleThumbnailFromJfif(in, thumbnailData);
555414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
555514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
555614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case DATA_UNCOMPRESSED:
555714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                case DATA_JPEG_COMPRESSED: {
555814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (isSupportedDataType(thumbnailData)) {
555914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        handleThumbnailFromStrips(in, thumbnailData);
556014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
556114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    break;
556214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
556314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
556414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else {
556514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Thumbnail data may not contain Compression tag value
556614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailCompression = DATA_JPEG;
556714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            handleThumbnailFromJfif(in, thumbnailData);
556814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
556914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
557014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
557114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Check JpegInterchangeFormat(JFIF) tags to retrieve thumbnail offset & length values
557214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // and reads the corresponding bytes if stream does not support seek function
557314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void handleThumbnailFromJfif(ByteOrderedDataInputStream in, HashMap thumbnailData)
557414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
557514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute jpegInterchangeFormatAttribute =
557614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_JPEG_INTERCHANGE_FORMAT);
557714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute jpegInterchangeFormatLengthAttribute =
557814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
557914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (jpegInterchangeFormatAttribute != null
558014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                && jpegInterchangeFormatLengthAttribute != null) {
558114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int thumbnailOffset = jpegInterchangeFormatAttribute.getIntValue(mExifByteOrder);
558214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder);
558314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
558414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // The following code limits the size of thumbnail size not to overflow EXIF data area.
558514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            thumbnailLength = Math.min(thumbnailLength, in.available() - thumbnailOffset);
558614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF
558714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    || mMimeType == IMAGE_TYPE_RW2) {
558814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                thumbnailOffset += mExifOffset;
558914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mMimeType == IMAGE_TYPE_ORF) {
559014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Update offset value since RAF files have IFD data preceding MakerNote data.
559114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                thumbnailOffset += mOrfMakerNoteOffset;
559214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
559314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
559414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "Setting thumbnail attributes with offset: " + thumbnailOffset
559514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ", length: " + thumbnailLength);
559614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
559714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (thumbnailOffset > 0 && thumbnailLength > 0) {
559814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mHasThumbnail = true;
559914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mThumbnailOffset = thumbnailOffset;
560014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mThumbnailLength = thumbnailLength;
560114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (mFilename == null && mAssetInputStream == null) {
560214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Save the thumbnail in memory if the input doesn't support reading again.
560314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    byte[] thumbnailBytes = new byte[thumbnailLength];
560414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    in.seek(thumbnailOffset);
560514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    in.readFully(thumbnailBytes);
560614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mThumbnailBytes = thumbnailBytes;
560714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
560814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
560914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
561014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
561114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
561214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Check StripOffsets & StripByteCounts tags to retrieve thumbnail offset & length values
561314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void handleThumbnailFromStrips(ByteOrderedDataInputStream in, HashMap thumbnailData)
561414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
561514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute stripOffsetsAttribute =
561614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_STRIP_OFFSETS);
561714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute stripByteCountsAttribute =
561814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_STRIP_BYTE_COUNTS);
561914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
562014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (stripOffsetsAttribute != null && stripByteCountsAttribute != null) {
562114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            long[] stripOffsets =
5622f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon                    convertToLongArray(stripOffsetsAttribute.getValue(mExifByteOrder));
562314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            long[] stripByteCounts =
5624f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon                    convertToLongArray(stripByteCountsAttribute.getValue(mExifByteOrder));
562514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
562614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (stripOffsets == null) {
562714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "stripOffsets should not be null.");
562814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return;
562914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
563014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (stripByteCounts == null) {
563114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.w(TAG, "stripByteCounts should not be null.");
563214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return;
563314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
563414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
563514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            long totalStripByteCount = 0;
563614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (long byteCount : stripByteCounts) {
563714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                totalStripByteCount += byteCount;
563814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
563914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
564014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Set thumbnail byte array data for non-consecutive strip bytes
564114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            byte[] totalStripBytes = new byte[(int) totalStripByteCount];
564214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
564314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int bytesRead = 0;
564414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int bytesAdded = 0;
564514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int i = 0; i < stripOffsets.length; i++) {
564614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int stripOffset = (int) stripOffsets[i];
564714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int stripByteCount = (int) stripByteCounts[i];
564814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
564914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Skip to offset
565014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int skipBytes = stripOffset - bytesRead;
565114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (skipBytes < 0) {
565214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.d(TAG, "Invalid strip offset value");
565314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
565414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                in.seek(skipBytes);
565514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                bytesRead += skipBytes;
565614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
565714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Read strip bytes
565814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                byte[] stripBytes = new byte[stripByteCount];
565914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                in.read(stripBytes);
566014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                bytesRead += stripByteCount;
566114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
566214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Add bytes to array
566314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                System.arraycopy(stripBytes, 0, totalStripBytes, bytesAdded,
566414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        stripBytes.length);
566514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                bytesAdded += stripBytes.length;
566614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
566714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
566814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mHasThumbnail = true;
566914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailBytes = totalStripBytes;
567014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailLength = totalStripBytes.length;
567114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
567214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
567314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
567414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Check if thumbnail data type is currently supported or not
567514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean isSupportedDataType(HashMap thumbnailData) throws IOException {
567614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute bitsPerSampleAttribute =
567714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) thumbnailData.get(TAG_BITS_PER_SAMPLE);
567814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (bitsPerSampleAttribute != null) {
567914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int[] bitsPerSampleValue = (int[]) bitsPerSampleAttribute.getValue(mExifByteOrder);
568014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
568114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (Arrays.equals(BITS_PER_SAMPLE_RGB, bitsPerSampleValue)) {
568214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return true;
568314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
568414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
568514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // See DNG Specification 1.4.0.0. Section 3, Compression.
568614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mMimeType == IMAGE_TYPE_DNG) {
568714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute photometricInterpretationAttribute =
568814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (ExifAttribute) thumbnailData.get(TAG_PHOTOMETRIC_INTERPRETATION);
568914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (photometricInterpretationAttribute != null) {
569014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    int photometricInterpretationValue
569114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            = photometricInterpretationAttribute.getIntValue(mExifByteOrder);
569214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if ((photometricInterpretationValue == PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO
569314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            && Arrays.equals(bitsPerSampleValue, BITS_PER_SAMPLE_GREYSCALE_2))
569414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            || ((photometricInterpretationValue == PHOTOMETRIC_INTERPRETATION_YCBCR)
569514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            && (Arrays.equals(bitsPerSampleValue, BITS_PER_SAMPLE_RGB)))) {
569614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return true;
569714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    } else {
569814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // TODO: Add support for lossless Huffman JPEG data
569914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
570014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
570114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
570214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
570314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (DEBUG) {
570414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "Unsupported data type value");
570514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
570614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return false;
570714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
570814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
570914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Returns true if the image length and width values are <= 512.
571014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // See Section 4.8 of http://standardsproposals.bsigroup.com/Home/getPDF/567
571114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private boolean isThumbnail(HashMap map) throws IOException {
571214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute imageLengthAttribute = (ExifAttribute) map.get(TAG_IMAGE_LENGTH);
571314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute imageWidthAttribute = (ExifAttribute) map.get(TAG_IMAGE_WIDTH);
571414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
571514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (imageLengthAttribute != null && imageWidthAttribute != null) {
571614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int imageLengthValue = imageLengthAttribute.getIntValue(mExifByteOrder);
571714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int imageWidthValue = imageWidthAttribute.getIntValue(mExifByteOrder);
571814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (imageLengthValue <= MAX_THUMBNAIL_SIZE && imageWidthValue <= MAX_THUMBNAIL_SIZE) {
571914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return true;
572014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
572114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
572214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return false;
572314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
572414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
572514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Validate primary, preview, thumbnail image data by comparing image size
572614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void validateImages(InputStream in) throws IOException {
572714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Swap images based on size (primary > preview > thumbnail)
572814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW);
572914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL);
573014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL);
573114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
573214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check if image has PixelXDimension/PixelYDimension tags, which contain valid image
573314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // sizes, excluding padding at the right end or bottom end of the image to make sure that
573414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // the values are multiples of 64. See JEITA CP-3451C Table 5 and Section 4.8.1. B.
573514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute pixelXDimAttribute =
573614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION);
573714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute pixelYDimAttribute =
573814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION);
573914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (pixelXDimAttribute != null && pixelYDimAttribute != null) {
574014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, pixelXDimAttribute);
574114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, pixelYDimAttribute);
574214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
574314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
574414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check whether thumbnail image exists and whether preview image satisfies the thumbnail
574514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // image requirements
574614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
574714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) {
574814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW];
5749abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                mAttributes[IFD_TYPE_PREVIEW] = new HashMap<>();
575014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
575114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
575214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
575314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Check if the thumbnail image satisfies the thumbnail size requirements
575414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) {
575514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "No image meets the size requirements of a thumbnail image.");
575614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
575714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
575814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
575914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
576014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * If image is uncompressed, ImageWidth/Length tags are used to store size info.
576114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * However, uncompressed images often store extra pixels around the edges of the final image,
576214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * which results in larger values for TAG_IMAGE_WIDTH and TAG_IMAGE_LENGTH tags.
576314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * This method corrects those tag values by checking first the values of TAG_DEFAULT_CROP_SIZE
576414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * See DNG Specification 1.4.0.0. Section 4. (DefaultCropSize)
576514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
576614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * If image is a RW2 file, valid image sizes are stored in SensorBorder tags.
576714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * See tiff_parser.cc GetFullDimension32()
576814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * */
576914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void updateImageSizeValues(ByteOrderedDataInputStream in, int imageType)
577014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
577114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Uncompressed image valid image size values
577214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute defaultCropSizeAttribute =
577314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_DEFAULT_CROP_SIZE);
577414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // RW2 image valid image size values
577514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute topBorderAttribute =
577614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_TOP_BORDER);
577714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute leftBorderAttribute =
577814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_LEFT_BORDER);
577914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute bottomBorderAttribute =
578014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_BOTTOM_BORDER);
578114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute rightBorderAttribute =
578214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[imageType].get(TAG_RW2_SENSOR_RIGHT_BORDER);
578314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
578414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (defaultCropSizeAttribute != null) {
578514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Update for uncompressed image
578614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ExifAttribute defaultCropSizeXAttribute, defaultCropSizeYAttribute;
578714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (defaultCropSizeAttribute.format == IFD_FORMAT_URATIONAL) {
578814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Rational[] defaultCropSizeValue =
578914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (Rational[]) defaultCropSizeAttribute.getValue(mExifByteOrder);
579014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (defaultCropSizeValue == null || defaultCropSizeValue.length != 2) {
579114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid crop size values. cropSize="
579214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + Arrays.toString(defaultCropSizeValue));
579314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
579414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
579514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                defaultCropSizeXAttribute =
579614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createURational(defaultCropSizeValue[0], mExifByteOrder);
579714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                defaultCropSizeYAttribute =
579814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createURational(defaultCropSizeValue[1], mExifByteOrder);
579914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else {
580014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int[] defaultCropSizeValue =
580114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        (int[]) defaultCropSizeAttribute.getValue(mExifByteOrder);
580214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (defaultCropSizeValue == null || defaultCropSizeValue.length != 2) {
580314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    Log.w(TAG, "Invalid crop size values. cropSize="
580414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            + Arrays.toString(defaultCropSizeValue));
580514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return;
580614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
580714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                defaultCropSizeXAttribute =
580814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(defaultCropSizeValue[0], mExifByteOrder);
580914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                defaultCropSizeYAttribute =
581014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(defaultCropSizeValue[1], mExifByteOrder);
581114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
581214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[imageType].put(TAG_IMAGE_WIDTH, defaultCropSizeXAttribute);
581314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[imageType].put(TAG_IMAGE_LENGTH, defaultCropSizeYAttribute);
581414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (topBorderAttribute != null && leftBorderAttribute != null &&
581514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                bottomBorderAttribute != null && rightBorderAttribute != null) {
581614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Update for RW2 image
581714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int topBorderValue = topBorderAttribute.getIntValue(mExifByteOrder);
581814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int bottomBorderValue = bottomBorderAttribute.getIntValue(mExifByteOrder);
581914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int rightBorderValue = rightBorderAttribute.getIntValue(mExifByteOrder);
582014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int leftBorderValue = leftBorderAttribute.getIntValue(mExifByteOrder);
582114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (bottomBorderValue > topBorderValue && rightBorderValue > leftBorderValue) {
582214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int length = bottomBorderValue - topBorderValue;
582314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int width = rightBorderValue - leftBorderValue;
582414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute imageLengthAttribute =
582514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(length, mExifByteOrder);
582614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ExifAttribute imageWidthAttribute =
582714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        ExifAttribute.createUShort(width, mExifByteOrder);
582814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[imageType].put(TAG_IMAGE_LENGTH, imageLengthAttribute);
582914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[imageType].put(TAG_IMAGE_WIDTH, imageWidthAttribute);
583014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
583114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else {
583214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            retrieveJpegImageSize(in, imageType);
583314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
583414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
583514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
583614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Writes an Exif segment into the given output stream.
583714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private int writeExifSegment(ByteOrderedDataOutputStream dataOutputStream,
583814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int exifOffsetFromBeginning) throws IOException {
583914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // The following variables are for calculating each IFD tag group size in bytes.
584014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int[] ifdOffsets = new int[EXIF_TAGS.length];
584114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int[] ifdDataSizes = new int[EXIF_TAGS.length];
584214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
584314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Remove IFD pointer tags (we'll re-add it later.)
584414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (ExifTag tag : EXIF_POINTER_TAGS) {
584514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            removeAttribute(tag.name);
584614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
584714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Remove old thumbnail data
584814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        removeAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name);
584914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
585014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
585114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Remove null value tags.
585214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
585314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (Object obj : mAttributes[ifdType].entrySet().toArray()) {
585414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                final Map.Entry entry = (Map.Entry) obj;
585514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (entry.getValue() == null) {
585614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    mAttributes[ifdType].remove(entry.getKey());
585714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
585814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
585914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
586014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
586114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
586214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // offset when there is one or more tags in the thumbnail IFD.
586314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
586414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
586514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
586614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
586714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
586814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
586914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
587014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
587114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
587214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name,
587314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
587414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
587514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mHasThumbnail) {
587614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
587714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(0, mExifByteOrder));
587814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
587914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(mThumbnailLength, mExifByteOrder));
588014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
588114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
588214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Calculate IFD group data area sizes. IFD group data area is assigned to save the entry
588314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // value which has a bigger size than 4 bytes.
588414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int i = 0; i < EXIF_TAGS.length; ++i) {
588514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int sum = 0;
5886abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas            for (Map.Entry<String, ExifAttribute> entry : mAttributes[i].entrySet()) {
5887abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                final ExifAttribute exifAttribute = entry.getValue();
588814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                final int size = exifAttribute.size();
588914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (size > 4) {
589014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    sum += size;
589114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
589214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
589314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ifdDataSizes[i] += sum;
589414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
589514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
589614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Calculate IFD offsets.
589714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int position = 8;
589814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
589914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (!mAttributes[ifdType].isEmpty()) {
590014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ifdOffsets[ifdType] = position;
590114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType];
590214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
590314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
590414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mHasThumbnail) {
590514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int thumbnailOffset = position;
590614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
590714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(thumbnailOffset, mExifByteOrder));
590814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
590914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            position += mThumbnailLength;
591014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
591114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
591214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Calculate the total size
591314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int totalSize = position + 8;  // eight bytes is for header part.
591414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (DEBUG) {
591514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "totalSize length: " + totalSize);
591614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int i = 0; i < EXIF_TAGS.length; ++i) {
591714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, String.format("index: %d, offsets: %d, tag count: %d, data sizes: %d",
591814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        i, ifdOffsets[i], mAttributes[i].size(), ifdDataSizes[i]));
591914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
592014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
592114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
592214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Update IFD pointer tags with the calculated offsets.
592314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) {
592414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name,
592514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder));
592614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
592714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_GPS].isEmpty()) {
592814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name,
592914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder));
593014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
593114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) {
593214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(
593314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder));
593414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
593514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
593614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
593714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeUnsignedShort(totalSize);
593814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.write(IDENTIFIER_EXIF_APP1);
593914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeShort(mExifByteOrder == ByteOrder.BIG_ENDIAN
594014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                ? BYTE_ALIGN_MM : BYTE_ALIGN_II);
594114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.setByteOrder(mExifByteOrder);
594214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeUnsignedShort(START_CODE);
594314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.writeUnsignedInt(IFD_OFFSET);
594414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
594514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9.
594614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
594714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (!mAttributes[ifdType].isEmpty()) {
594814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // See JEITA CP-3451C Section 4.6.2: IFD structure.
594914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Write entry count
595014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size());
595114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
595214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Write entry info
595314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4;
5954abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                for (Map.Entry<String, ExifAttribute> entry : mAttributes[ifdType].entrySet()) {
595514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Convert tag name to tag number.
5956abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                    final ExifTag tag = sExifTagMapsForWriting[ifdType].get(entry.getKey());
595714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    final int tagNumber = tag.number;
5958abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                    final ExifAttribute attribute = entry.getValue();
595914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    final int size = attribute.size();
596014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
596114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedShort(tagNumber);
596214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedShort(attribute.format);
596314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeInt(attribute.numberOfComponents);
596414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (size > 4) {
596514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.writeUnsignedInt(dataOffset);
596614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOffset += size;
596714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    } else {
596814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.write(attribute.bytes);
596914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        // Fill zero up to 4 bytes
597014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        if (size < 4) {
597114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            for (int i = size; i < 4; ++i) {
597214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                                dataOutputStream.writeByte(0);
597314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                            }
597414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        }
597514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
597614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
597714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
597814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Write the next offset. It writes the offset of thumbnail IFD if there is one or
597914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // more tags in the thumbnail IFD when the current IFD is the primary image TIFF
598014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // IFD; Otherwise 0.
598114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) {
598214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]);
598314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } else {
598414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataOutputStream.writeUnsignedInt(0);
598514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
598614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
598714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                // Write values of data field exceeding 4 bytes after the next offset.
5988abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                for (Map.Entry<String, ExifAttribute> entry : mAttributes[ifdType].entrySet()) {
5989abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                    ExifAttribute attribute = entry.getValue();
599014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
599114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (attribute.bytes.length > 4) {
599214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        dataOutputStream.write(attribute.bytes, 0, attribute.bytes.length);
599314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
599414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
599514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
599614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
599714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
599814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Write thumbnail
599914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mHasThumbnail) {
600014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            dataOutputStream.write(getThumbnailBytes());
600114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
600214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
600314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Reset the byte order to big endian in order to write remaining parts of the JPEG file.
600414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        dataOutputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
600514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
600614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return totalSize;
600714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
600814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
600914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
601014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Determines the data format of EXIF entry value.
601114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     *
601214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @param entryValue The value to be determined.
601314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * @return Returns two data formats gussed as a pair in integer. If there is no two candidate
601414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon               data formats for the given entry value, returns {@code -1} in the second of the pair.
601514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
601614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static Pair<Integer, Integer> guessDataFormat(String entryValue) {
601714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // See TIFF 6.0 Section 2, "Image File Directory".
601814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        // Take the first component if there are more than one component.
601914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (entryValue.contains(",")) {
6020244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            String[] entryValues = entryValue.split(",", -1);
602114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Pair<Integer, Integer> dataFormat = guessDataFormat(entryValues[0]);
602214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (dataFormat.first == IFD_FORMAT_STRING) {
602314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return dataFormat;
602414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
602514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            for (int i = 1; i < entryValues.length; ++i) {
602614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                final Pair<Integer, Integer> guessDataFormat = guessDataFormat(entryValues[i]);
602714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                int first = -1, second = -1;
602889889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                if (guessDataFormat.first.equals(dataFormat.first)
602989889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                        || guessDataFormat.second.equals(dataFormat.first)) {
603014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    first = dataFormat.first;
603114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
603289889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                if (dataFormat.second != -1 && (guessDataFormat.first.equals(dataFormat.second)
603389889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon                        || guessDataFormat.second.equals(dataFormat.second))) {
603414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    second = dataFormat.second;
603514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
603614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (first == -1 && second == -1) {
603714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return new Pair<>(IFD_FORMAT_STRING, -1);
603814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
603914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (first == -1) {
604014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataFormat = new Pair<>(second, -1);
604114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    continue;
604214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
604314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                if (second == -1) {
604414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    dataFormat = new Pair<>(first, -1);
604514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    continue;
604614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
604714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
604814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return dataFormat;
604914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
605014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
605114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (entryValue.contains("/")) {
6052244232024786c3715124b4488fd48722f10c22fbAurimas Liutikas            String[] rationalNumber = entryValue.split("/", -1);
605314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (rationalNumber.length == 2) {
605414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                try {
605577966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                    long numerator = (long) Double.parseDouble(rationalNumber[0]);
605677966fe1cfca14edf5d1d95e1decb57cff9ccd47Hyundo Moon                    long denominator = (long) Double.parseDouble(rationalNumber[1]);
605714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (numerator < 0L || denominator < 0L) {
605814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return new Pair<>(IFD_FORMAT_SRATIONAL, -1);
605914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
606014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    if (numerator > Integer.MAX_VALUE || denominator > Integer.MAX_VALUE) {
606114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        return new Pair<>(IFD_FORMAT_URATIONAL, -1);
606214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    }
606314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    return new Pair<>(IFD_FORMAT_SRATIONAL, IFD_FORMAT_URATIONAL);
606414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                } catch (NumberFormatException e)  {
606514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    // Ignored
606614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                }
606714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
606814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new Pair<>(IFD_FORMAT_STRING, -1);
606914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
607014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
607114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Long longValue = Long.parseLong(entryValue);
607214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (longValue >= 0 && longValue <= 65535) {
607314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return new Pair<>(IFD_FORMAT_USHORT, IFD_FORMAT_ULONG);
607414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
607514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (longValue < 0) {
607614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return new Pair<>(IFD_FORMAT_SLONG, -1);
607714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
607814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new Pair<>(IFD_FORMAT_ULONG, -1);
607914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (NumberFormatException e) {
608014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Ignored
608114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
608214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        try {
608314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Double.parseDouble(entryValue);
608414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return new Pair<>(IFD_FORMAT_DOUBLE, -1);
608514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } catch (NumberFormatException e) {
608614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            // Ignored
608714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
608814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return new Pair<>(IFD_FORMAT_STRING, -1);
608914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
609014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
609114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // An input stream to parse EXIF data area, which can be written in either little or big endian
609214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // order.
609314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static class ByteOrderedDataInputStream extends InputStream implements DataInput {
609414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;
609514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
609614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
609714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private DataInputStream mDataInputStream;
609814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN;
609914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private final int mLength;
610014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private int mPosition;
610114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
610214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public ByteOrderedDataInputStream(InputStream in) throws IOException {
610314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mDataInputStream = new DataInputStream(in);
610414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mLength = mDataInputStream.available();
610514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition = 0;
610614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mDataInputStream.mark(mLength);
610714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
610814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
610914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public ByteOrderedDataInputStream(byte[] bytes) throws IOException {
611014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            this(new ByteArrayInputStream(bytes));
611114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
611214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
611314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void setByteOrder(ByteOrder byteOrder) {
611414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mByteOrder = byteOrder;
611514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
611614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
611714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void seek(long byteCount) throws IOException {
611814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > byteCount) {
611914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mPosition = 0;
612014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mDataInputStream.reset();
612114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mDataInputStream.mark(mLength);
612214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else {
612314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                byteCount -= mPosition;
612414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
612514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
612614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (skipBytes((int) byteCount) != (int) byteCount) {
612714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Couldn't seek up to the byteCount");
612814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
612914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
613014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
613114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int peek() {
613214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mPosition;
613314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
613414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
613514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
613614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int available() throws IOException {
613714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.available();
613814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
613914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
614014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
614114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int read() throws IOException {
614214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++mPosition;
614314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.read();
614414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
614514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
614614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
614789889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon        public int read(byte[] b, int off, int len) throws IOException {
614889889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon            int bytesRead = mDataInputStream.read(b, off, len);
614989889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon            mPosition += bytesRead;
615089889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon            return bytesRead;
615189889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon        }
615289889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon
615389889c49482aed4e9dec66b33f733065e3e1580cHyundo Moon        @Override
615414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int readUnsignedByte() throws IOException {
615514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++mPosition;
615614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.readUnsignedByte();
615714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
615814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
615914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
616014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public String readLine() throws IOException {
616114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            Log.d(TAG, "Currently unsupported");
616214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return null;
616314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
616414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
616514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
616614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public boolean readBoolean() throws IOException {
616714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++mPosition;
616814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.readBoolean();
616914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
617014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
617114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
617214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public char readChar() throws IOException {
617314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 2;
617414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.readChar();
617514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
617614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
617714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
617814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public String readUTF() throws IOException {
617914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 2;
618014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return mDataInputStream.readUTF();
618114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
618214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
618314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
618414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void readFully(byte[] buffer, int offset, int length) throws IOException {
618514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += length;
618614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
618714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
618814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
618914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mDataInputStream.read(buffer, offset, length) != length) {
619014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Couldn't read up to the length of buffer");
619114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
619214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
619314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
619414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
619514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void readFully(byte[] buffer) throws IOException {
619614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += buffer.length;
619714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
619814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
619914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
620014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mDataInputStream.read(buffer, 0, buffer.length) != buffer.length) {
620114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new IOException("Couldn't read up to the length of buffer");
620214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
620314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
620414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
620514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
620614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public byte readByte() throws IOException {
620714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            ++mPosition;
620814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
620914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
621014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
621114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch = mDataInputStream.read();
621214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (ch < 0) {
621314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
621414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
621514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return (byte) ch;
621614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
621714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
621814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
621914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public short readShort() throws IOException {
622014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 2;
622114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
622214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
622314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
622414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch1 = mDataInputStream.read();
622514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch2 = mDataInputStream.read();
622614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if ((ch1 | ch2) < 0) {
622714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
622814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
622914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == LITTLE_ENDIAN) {
623014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return (short) ((ch2 << 8) + (ch1));
623114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == BIG_ENDIAN) {
623214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return (short) ((ch1 << 8) + (ch2));
623314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
623414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid byte order: " + mByteOrder);
623514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
623614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
623714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
623814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int readInt() throws IOException {
623914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 4;
624014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
624114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
624214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
624314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch1 = mDataInputStream.read();
624414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch2 = mDataInputStream.read();
624514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch3 = mDataInputStream.read();
624614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch4 = mDataInputStream.read();
624714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if ((ch1 | ch2 | ch3 | ch4) < 0) {
624814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
624914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
625014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == LITTLE_ENDIAN) {
625114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1);
625214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == BIG_ENDIAN) {
625314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
625414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
625514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid byte order: " + mByteOrder);
625614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
625714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
625814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
625914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int skipBytes(int byteCount) throws IOException {
626014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int totalSkip = Math.min(byteCount, mLength - mPosition);
626114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int skipped = 0;
626214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            while (skipped < totalSkip) {
626314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                skipped += mDataInputStream.skipBytes(totalSkip - skipped);
626414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
626514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += skipped;
626614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return skipped;
626714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
626814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
6269e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas        @Override
627014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public int readUnsignedShort() throws IOException {
627114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 2;
627214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
627314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
627414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
627514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch1 = mDataInputStream.read();
627614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch2 = mDataInputStream.read();
627714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if ((ch1 | ch2) < 0) {
627814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
627914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
628014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == LITTLE_ENDIAN) {
628114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ((ch2 << 8) + (ch1));
628214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == BIG_ENDIAN) {
628314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return ((ch1 << 8) + (ch2));
628414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
628514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid byte order: " + mByteOrder);
628614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
628714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
628814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public long readUnsignedInt() throws IOException {
628914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return readInt() & 0xffffffffL;
629014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
629114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
629214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
629314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public long readLong() throws IOException {
629414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mPosition += 8;
629514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mPosition > mLength) {
629614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
629714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
629814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch1 = mDataInputStream.read();
629914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch2 = mDataInputStream.read();
630014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch3 = mDataInputStream.read();
630114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch4 = mDataInputStream.read();
630214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch5 = mDataInputStream.read();
630314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch6 = mDataInputStream.read();
630414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch7 = mDataInputStream.read();
630514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int ch8 = mDataInputStream.read();
630614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
630714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw new EOFException();
630814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
630914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == LITTLE_ENDIAN) {
631014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40)
631114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16)
631214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ((long) ch2 << 8) + (long) ch1);
631314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == BIG_ENDIAN) {
631414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                return (((long) ch1 << 56) + ((long) ch2 << 48) + ((long) ch3 << 40)
631514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ((long) ch4 << 32) + ((long) ch5 << 24) + ((long) ch6 << 16)
631614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                        + ((long) ch7 << 8) + (long) ch8);
631714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
631814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throw new IOException("Invalid byte order: " + mByteOrder);
631914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
632014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
632114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
632214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public float readFloat() throws IOException {
632314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return Float.intBitsToFloat(readInt());
632414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
632514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
632614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        @Override
632714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public double readDouble() throws IOException {
632814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return Double.longBitsToDouble(readLong());
632914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
633014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
633114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
633214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // An output stream to write EXIF data area, which can be written in either little or big endian
633314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // order.
633414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static class ByteOrderedDataOutputStream extends FilterOutputStream {
633514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private final OutputStream mOutputStream;
633614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        private ByteOrder mByteOrder;
633714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
633814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public ByteOrderedDataOutputStream(OutputStream out, ByteOrder byteOrder) {
633914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            super(out);
634014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mOutputStream = out;
634114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mByteOrder = byteOrder;
634214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
634314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
634414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void setByteOrder(ByteOrder byteOrder) {
634514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mByteOrder = byteOrder;
634614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
634714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
6348e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas        @Override
634914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void write(byte[] bytes) throws IOException {
635014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mOutputStream.write(bytes);
635114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
635214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
6353e2104f4b5c8e3ad63570306a25e61502dfe4c418Aurimas Liutikas        @Override
635414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void write(byte[] bytes, int offset, int length) throws IOException {
635514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mOutputStream.write(bytes, offset, length);
635614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
635714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
635814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void writeByte(int val) throws IOException {
635914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            mOutputStream.write(val);
636014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
636114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
636214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void writeShort(short val) throws IOException {
636314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == ByteOrder.LITTLE_ENDIAN) {
636414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 0) & 0xFF);
636514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 8) & 0xFF);
636614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == ByteOrder.BIG_ENDIAN) {
636714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 8) & 0xFF);
636814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 0) & 0xFF);
636914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
637014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
637114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
637214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void writeInt(int val) throws IOException {
637314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (mByteOrder == ByteOrder.LITTLE_ENDIAN) {
637414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 0) & 0xFF);
637514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 8) & 0xFF);
637614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 16) & 0xFF);
637714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 24) & 0xFF);
637814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } else if (mByteOrder == ByteOrder.BIG_ENDIAN) {
637914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 24) & 0xFF);
638014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 16) & 0xFF);
638114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 8) & 0xFF);
638214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mOutputStream.write((val >>> 0) & 0xFF);
638314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
638414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
638514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
638614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void writeUnsignedShort(int val) throws IOException {
638714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            writeShort((short) val);
638814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
638914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
639014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        public void writeUnsignedInt(long val) throws IOException {
639114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            writeInt((int) val);
639214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
639314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
639414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
639514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    // Swaps image data based on image size
639614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType)
639714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            throws IOException {
639814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) {
639914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
640014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "Cannot perform swap since only one image data exists");
640114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
640214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            return;
640314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
640414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
640514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute firstImageLengthAttribute =
640614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH);
640714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute firstImageWidthAttribute =
640814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH);
640914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute secondImageLengthAttribute =
641014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH);
641114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        ExifAttribute secondImageWidthAttribute =
641214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH);
641314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
641414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) {
641514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
641614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "First image does not contain valid size information");
641714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
641814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else if (secondImageLengthAttribute == null || secondImageWidthAttribute == null) {
641914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (DEBUG) {
642014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                Log.d(TAG, "Second image does not contain valid size information");
642114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
642214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        } else {
642314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int firstImageLengthValue = firstImageLengthAttribute.getIntValue(mExifByteOrder);
642414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int firstImageWidthValue = firstImageWidthAttribute.getIntValue(mExifByteOrder);
642514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int secondImageLengthValue = secondImageLengthAttribute.getIntValue(mExifByteOrder);
642614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            int secondImageWidthValue = secondImageWidthAttribute.getIntValue(mExifByteOrder);
642714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
642814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            if (firstImageLengthValue < secondImageLengthValue &&
642914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                    firstImageWidthValue < secondImageWidthValue) {
6430abc73958d264e1eed7fd401a18be1d9ede8304ebAurimas Liutikas                HashMap<String, ExifAttribute> tempMap = mAttributes[firstIfdType];
643114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[firstIfdType] = mAttributes[secondIfdType];
643214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                mAttributes[secondIfdType] = tempMap;
643314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
643414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
643514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
643614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
643714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
643814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
643914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
644014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static void closeQuietly(Closeable closeable) {
644114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        if (closeable != null) {
644214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            try {
644314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                closeable.close();
644414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } catch (RuntimeException rethrown) {
644514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon                throw rethrown;
644614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            } catch (Exception ignored) {
644714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            }
644814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
644914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
645014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon
645114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    /**
645214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Copies all of the bytes from {@code in} to {@code out}. Neither stream is closed.
645314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     * Returns the total number of bytes transferred.
645414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon     */
645514ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    private static int copy(InputStream in, OutputStream out) throws IOException {
645614ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int total = 0;
645714ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        byte[] buffer = new byte[8192];
645814ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        int c;
645914ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        while ((c = in.read(buffer)) != -1) {
646014ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            total += c;
646114ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon            out.write(buffer, 0, c);
646214ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        }
646314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon        return total;
646414ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon    }
6465f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon
6466f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon    /**
6467f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon     * Convert given int[] to long[]. If long[] is given, just return it.
6468f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon     * Return null for other types of input.
6469f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon     */
6470f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon    private static long[] convertToLongArray(Object inputObj) {
6471f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon        if (inputObj instanceof int[]) {
6472f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            int[] input = (int[]) inputObj;
6473f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            long[] result = new long[input.length];
6474f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            for (int i = 0; i < input.length; i++) {
6475f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon                result[i] = input[i];
6476f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            }
6477f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            return result;
6478f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon        } else if (inputObj instanceof long[]) {
6479f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon            return (long[]) inputObj;
6480f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon        }
6481f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon        return null;
6482f96abe0f8ae38bbb9810d2205e050ebe4ef613a1Hyundo Moon    }
648314ea3100458369949fffba9978db2a51dde21bf2Hyundo Moon}
6484