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                        &degrees)) {
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                        &timestamp)) {
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