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