• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                        &degrees)) {
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                        &timestamp)) {
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