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                       &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
367void freeExifData(ExifData* exifData) {
368    exif_data_free(exifData);
369}
370
371}  // namespace android
372
373