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