Home | History | Annotate | Download | only in camera
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "Exif.h"
     18 
     19 #define LOG_NDEBUG 0
     20 #define LOG_TAG "EmulatedCamera_Exif"
     21 #include <cutils/log.h>
     22 
     23 #include <inttypes.h>
     24 #include <math.h>
     25 #include <stdint.h>
     26 
     27 #include <camera/CameraParameters.h>
     28 #include <libexif/exif-data.h>
     29 #include <libexif/exif-entry.h>
     30 #include <libexif/exif-ifd.h>
     31 #include <libexif/exif-tag.h>
     32 
     33 #include <string>
     34 #include <vector>
     35 
     36 // For GPS timestamping we want to ensure we use a 64-bit time_t, 32-bit
     37 // platforms have time64_t but 64-bit platforms do not.
     38 #if defined(__LP64__)
     39 #include <time.h>
     40 using Timestamp = time_t;
     41 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm)
     42 #else
     43 #include <time64.h>
     44 using Timestamp = time64_t;
     45 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm)
     46 #endif
     47 
     48 namespace android {
     49 
     50 // A prefix that is used for tags with the "undefined" format to indicate that
     51 // the contents are ASCII encoded. See the user comment section of the EXIF spec
     52 // for more details http://www.exif.org/Exif2-2.PDF
     53 static const unsigned char kAsciiPrefix[] = {
     54     0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 // "ASCII\0\0\0"
     55 };
     56 
     57 // Remove an existing EXIF entry from |exifData| if it exists. This is useful
     58 // when replacing existing data, it's easier to just remove the data and
     59 // re-allocate it than to adjust the amount of allocated data.
     60 static void removeExistingEntry(ExifData* exifData, ExifIfd ifd, int tag) {
     61     ExifEntry* entry = exif_content_get_entry(exifData->ifd[ifd],
     62                                               static_cast<ExifTag>(tag));
     63     if (entry) {
     64         exif_content_remove_entry(exifData->ifd[ifd], entry);
     65     }
     66 }
     67 
     68 static ExifEntry* allocateEntry(int tag,
     69                                 ExifFormat format,
     70                                 unsigned int numComponents) {
     71     ExifMem* mem = exif_mem_new_default();
     72     ExifEntry* entry = exif_entry_new_mem(mem);
     73 
     74     unsigned int size = numComponents * exif_format_get_size(format);
     75     entry->data = reinterpret_cast<unsigned char*>(exif_mem_alloc(mem, size));
     76     entry->size = size;
     77     entry->tag = static_cast<ExifTag>(tag);
     78     entry->components = numComponents;
     79     entry->format = format;
     80 
     81     exif_mem_unref(mem);
     82     return entry;
     83 }
     84 
     85 // Create an entry and place it in |exifData|, the entry is initialized with an
     86 // array of floats from |values|
     87 template<size_t N>
     88 static bool createEntry(ExifData* exifData,
     89                         ExifIfd ifd,
     90                         int tag,
     91                         const float (&values)[N],
     92                         float denominator = 1000.0) {
     93     removeExistingEntry(exifData, ifd, tag);
     94     ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
     95     ExifEntry* entry = allocateEntry(tag, EXIF_FORMAT_RATIONAL, N);
     96     exif_content_add_entry(exifData->ifd[ifd], entry);
     97     unsigned int rationalSize = exif_format_get_size(EXIF_FORMAT_RATIONAL);
     98     for (size_t i = 0; i < N; ++i) {
     99         ExifRational rational = {
    100             static_cast<uint32_t>(values[i] * denominator),
    101             static_cast<uint32_t>(denominator)
    102         };
    103 
    104         exif_set_rational(&entry->data[i * rationalSize], byteOrder, rational);
    105     }
    106 
    107     // Unref entry after changing owner to the ExifData struct
    108     exif_entry_unref(entry);
    109     return true;
    110 }
    111 
    112 // Create an entry with a single float |value| in it and place it in |exifData|
    113 static bool createEntry(ExifData* exifData,
    114                         ExifIfd ifd,
    115                         int tag,
    116                         const float value,
    117                         float denominator = 1000.0) {
    118     float values[1] = { value };
    119     // Recycling functions is good for the environment
    120     return createEntry(exifData, ifd, tag, values, denominator);
    121 }
    122 
    123 // Create an entry and place it in |exifData|, the entry contains the raw data
    124 // pointed to by |data| of length |size|.
    125 static bool createEntry(ExifData* exifData,
    126                         ExifIfd ifd,
    127                         int tag,
    128                         const unsigned char* data,
    129                         size_t size,
    130                         ExifFormat format = EXIF_FORMAT_UNDEFINED) {
    131     removeExistingEntry(exifData, ifd, tag);
    132     ExifEntry* entry = allocateEntry(tag, format, size);
    133     memcpy(entry->data, data, size);
    134     exif_content_add_entry(exifData->ifd[ifd], entry);
    135     // Unref entry after changing owner to the ExifData struct
    136     exif_entry_unref(entry);
    137     return true;
    138 }
    139 
    140 // Create an entry and place it in |exifData|, the entry is initialized with
    141 // the string provided in |value|
    142 static bool createEntry(ExifData* exifData,
    143                         ExifIfd ifd,
    144                         int tag,
    145                         const char* value) {
    146     unsigned int length = strlen(value) + 1;
    147     const unsigned char* data = reinterpret_cast<const unsigned char*>(value);
    148     return createEntry(exifData, ifd, tag, data, length, EXIF_FORMAT_ASCII);
    149 }
    150 
    151 // Create an entry and place it in |exifData|, the entry is initialized with a
    152 // single byte in |value|
    153 static bool createEntry(ExifData* exifData,
    154                         ExifIfd ifd,
    155                         int tag,
    156                         uint8_t value) {
    157     return createEntry(exifData, ifd, tag, &value, 1, EXIF_FORMAT_BYTE);
    158 }
    159 
    160 // Create an entry and place it in |exifData|, the entry is default initialized
    161 // by the exif library based on |tag|
    162 static bool createEntry(ExifData* exifData,
    163                         ExifIfd ifd,
    164                         int tag) {
    165     removeExistingEntry(exifData, ifd, tag);
    166     ExifEntry* entry = exif_entry_new();
    167     exif_content_add_entry(exifData->ifd[ifd], entry);
    168     exif_entry_initialize(entry, static_cast<ExifTag>(tag));
    169     // Unref entry after changing owner to the ExifData struct
    170     exif_entry_unref(entry);
    171     return true;
    172 }
    173 
    174 // Create an entry with a single EXIF LONG (32-bit value) and place it in
    175 // |exifData|.
    176 static bool createEntry(ExifData* exifData,
    177                         ExifIfd ifd,
    178                         int tag,
    179                         int value) {
    180     removeExistingEntry(exifData, ifd, tag);
    181     ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
    182     ExifEntry* entry = allocateEntry(tag, EXIF_FORMAT_LONG, 1);
    183     exif_content_add_entry(exifData->ifd[ifd], entry);
    184     exif_set_long(entry->data, byteOrder, value);
    185 
    186     // Unref entry after changing owner to the ExifData struct
    187     exif_entry_unref(entry);
    188     return true;
    189 }
    190 
    191 static bool getCameraParam(const CameraParameters& parameters,
    192                            const char* parameterKey,
    193                            const char** outValue) {
    194     const char* value = parameters.get(parameterKey);
    195     if (value) {
    196         *outValue = value;
    197         return true;
    198     }
    199     return false;
    200 }
    201 
    202 static bool getCameraParam(const CameraParameters& parameters,
    203                            const char* parameterKey,
    204                            float* outValue) {
    205     const char* value = parameters.get(parameterKey);
    206     if (value) {
    207         *outValue = parameters.getFloat(parameterKey);
    208         return true;
    209     }
    210     return false;
    211 }
    212 
    213 static bool getCameraParam(const CameraParameters& parameters,
    214                            const char* parameterKey,
    215                            int64_t* outValue) {
    216     const char* value = parameters.get(parameterKey);
    217     if (value) {
    218         char dummy = 0;
    219         // Attempt to scan an extra character and then make sure it was not
    220         // scanned by checking that the return value indicates only one item.
    221         // This way we fail on any trailing characters
    222         if (sscanf(value, "%" SCNd64 "%c", outValue, &dummy) == 1) {
    223             return true;
    224         }
    225     }
    226     return false;
    227 }
    228 
    229 // Convert a GPS coordinate represented as a decimal degree value to sexagesimal
    230 // GPS coordinates comprised of <degrees> <minutes>' <seconds>"
    231 static void convertGpsCoordinate(float degrees, float (*result)[3]) {
    232     float absDegrees = fabs(degrees);
    233     // First value is degrees without any decimal digits
    234     (*result)[0] = floor(absDegrees);
    235 
    236     // Subtract degrees so we only have the fraction left, then multiply by
    237     // 60 to get the minutes
    238     float minutes = (absDegrees - (*result)[0]) * 60.0f;
    239     (*result)[1] = floor(minutes);
    240 
    241     // Same thing for seconds but here we store seconds with the fraction
    242     float seconds = (minutes - (*result)[1]) * 60.0f;
    243     (*result)[2] = seconds;
    244 }
    245 
    246 // Convert a UNIX epoch timestamp to a timestamp comprised of three floats for
    247 // hour, minute and second, and a date part that is represented as a string.
    248 static bool convertTimestampToTimeAndDate(int64_t timestamp,
    249                                           float (*timeValues)[3],
    250                                           std::string* date) {
    251     Timestamp time = timestamp;
    252     struct tm utcTime;
    253     if (TIMESTAMP_TO_TM(&time, &utcTime) == nullptr) {
    254         ALOGE("Could not decompose timestamp into components");
    255         return false;
    256     }
    257     (*timeValues)[0] = utcTime.tm_hour;
    258     (*timeValues)[1] = utcTime.tm_min;
    259     (*timeValues)[2] = utcTime.tm_sec;
    260 
    261     char buffer[64] = {};
    262     if (strftime(buffer, sizeof(buffer), "%Y:%m:%d", &utcTime) == 0) {
    263         ALOGE("Could not construct date string from timestamp");
    264         return false;
    265     }
    266     *date = buffer;
    267     return true;
    268 }
    269 
    270 ExifData* createExifData(const CameraParameters& params) {
    271     ExifData* exifData = exif_data_new();
    272 
    273     exif_data_set_option(exifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
    274     exif_data_set_data_type(exifData, EXIF_DATA_TYPE_COMPRESSED);
    275     exif_data_set_byte_order(exifData, EXIF_BYTE_ORDER_INTEL);
    276 
    277     // Create mandatory exif fields and set their default values
    278     exif_data_fix(exifData);
    279 
    280     float triplet[3];
    281     float floatValue = 0.0f;
    282     const char* stringValue;
    283 
    284     // Datetime, creating and initializing a datetime tag will automatically
    285     // set the current date and time in the tag so just do that.
    286     createEntry(exifData, EXIF_IFD_0, EXIF_TAG_DATE_TIME);
    287 
    288     // Picture size
    289     int width = -1, height = -1;
    290     params.getPictureSize(&width, &height);
    291     if (width >= 0 && height >= 0) {
    292         createEntry(exifData, EXIF_IFD_EXIF,
    293                     EXIF_TAG_PIXEL_X_DIMENSION, width);
    294         createEntry(exifData, EXIF_IFD_EXIF,
    295                     EXIF_TAG_PIXEL_Y_DIMENSION, height);
    296     }
    297     // Focal length
    298     if (getCameraParam(params,
    299                        CameraParameters::KEY_FOCAL_LENGTH,
    300                        &floatValue)) {
    301         createEntry(exifData, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, floatValue);
    302     }
    303     // GPS latitude and reference, reference indicates sign, store unsigned
    304     if (getCameraParam(params,
    305                        CameraParameters::KEY_GPS_LATITUDE,
    306                        &floatValue)) {
    307         convertGpsCoordinate(floatValue, &triplet);
    308         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, triplet);
    309 
    310         const char* ref = floatValue < 0.0f ? "S" : "N";
    311         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, ref);
    312     }
    313     // GPS longitude and reference, reference indicates sign, store unsigned
    314     if (getCameraParam(params,
    315                        CameraParameters::KEY_GPS_LONGITUDE,
    316                        &floatValue)) {
    317         convertGpsCoordinate(floatValue, &triplet);
    318         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, triplet);
    319 
    320         const char* ref = floatValue < 0.0f ? "W" : "E";
    321         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, ref);
    322     }
    323     // GPS altitude and reference, reference indicates sign, store unsigned
    324     if (getCameraParam(params,
    325                        CameraParameters::KEY_GPS_ALTITUDE,
    326                        &floatValue)) {
    327         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
    328                     static_cast<float>(fabs(floatValue)));
    329 
    330         // 1 indicated below sea level, 0 indicates above sea level
    331         uint8_t ref = floatValue < 0.0f ? 1 : 0;
    332         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF, ref);
    333     }
    334     // GPS timestamp and datestamp
    335     int64_t timestamp = 0;
    336     if (getCameraParam(params,
    337                        CameraParameters::KEY_GPS_TIMESTAMP,
    338                        &timestamp)) {
    339         std::string date;
    340         if (convertTimestampToTimeAndDate(timestamp, &triplet, &date)) {
    341             createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
    342                         triplet, 1.0f);
    343             createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
    344                         date.c_str());
    345         }
    346     }
    347 
    348     // GPS processing method
    349     if (getCameraParam(params,
    350                        CameraParameters::KEY_GPS_PROCESSING_METHOD,
    351                        &stringValue)) {
    352         std::vector<unsigned char> data;
    353         // Because this is a tag with an undefined format it has to be prefixed
    354         // with the encoding type. Insert an ASCII prefix first, then the
    355         // actual string. Undefined tags do not have to be null terminated.
    356         data.insert(data.end(),
    357                     std::begin(kAsciiPrefix),
    358                     std::end(kAsciiPrefix));
    359         data.insert(data.end(), stringValue, stringValue + strlen(stringValue));
    360         createEntry(exifData, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
    361                     &data[0], data.size());
    362     }
    363 
    364     return exifData;
    365 }
    366 
    367 void freeExifData(ExifData* exifData) {
    368     exif_data_free(exifData);
    369 }
    370 
    371 }  // namespace android
    372 
    373