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>
40 using Timestamp = time_t;
41 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm)
42 #else
43 #include <time64.h>
44 using Timestamp = time64_t;
45 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm)
46 #endif
47 
48 namespace 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
53 static 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.
removeExistingEntry(ExifData * exifData,ExifIfd ifd,int tag)60 static 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 
allocateEntry(int tag,ExifFormat format,unsigned int numComponents)68 static 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|
87 template<size_t N>
createEntry(ExifData * exifData,ExifIfd ifd,int tag,const float (& values)[N],float denominator=1000.0)88 static 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|
createEntry(ExifData * exifData,ExifIfd ifd,int tag,const float value,float denominator=1000.0)113 static 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|.
createEntry(ExifData * exifData,ExifIfd ifd,int tag,const unsigned char * data,size_t size,ExifFormat format=EXIF_FORMAT_UNDEFINED)125 static 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|
createEntry(ExifData * exifData,ExifIfd ifd,int tag,const char * value)142 static 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|
createEntry(ExifData * exifData,ExifIfd ifd,int tag,uint8_t value)153 static 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|
createEntry(ExifData * exifData,ExifIfd ifd,int tag)162 static 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|.
createEntry(ExifData * exifData,ExifIfd ifd,int tag,int value)176 static 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 
getCameraParam(const CameraParameters & parameters,const char * parameterKey,const char ** outValue)191 static 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 
getCameraParam(const CameraParameters & parameters,const char * parameterKey,float * outValue)202 static 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 
getCameraParam(const CameraParameters & parameters,const char * parameterKey,int64_t * outValue)213 static 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>"
convertGpsCoordinate(float degrees,float (* result)[3])231 static 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.
convertTimestampToTimeAndDate(int64_t timestamp,float (* timeValues)[3],std::string * date)248 static 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 
createExifData(const CameraParameters & params)270 ExifData* 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                        &timestamp)) {
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 
freeExifData(ExifData * exifData)367 void freeExifData(ExifData* exifData) {
368     exif_data_free(exifData);
369 }
370 
371 }  // namespace android
372 
373