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> 40using Timestamp = time_t; 41#define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm) 42#else 43#include <time64.h> 44using Timestamp = time64_t; 45#define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm) 46#endif 47 48namespace 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 53static 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. 60static 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 68static 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| 87template<size_t N> 88static 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| 113static 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|. 125static 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| 142static 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| 153static 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| 162static 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|. 176static 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 191static 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 202static 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 213static 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>" 231static 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. 248static 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 270ExifData* 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 ×tamp)) { 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 367void freeExifData(ExifData* exifData) { 368 exif_data_free(exifData); 369} 370 371} // namespace android 372 373