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 <cutils/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 °rees)) { 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 ×tamp)) { 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