• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2023 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 FAILURE_DEBUG_PREFIX "exif"
18  
19  #include <vector>
20  
21  #if defined(__LP64__)
22  #include <time.h>
23  using Timestamp = time_t;
24  #define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm)
25  #else
26  #include <time64.h>
27  using Timestamp = time64_t;
28  #define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm)
29  #endif
30  
31  #include <math.h>
32  
33  #include <android-base/properties.h>
34  #include <system/camera_metadata.h>
35  
36  #include "exif.h"
37  #include "debug.h"
38  
39  namespace android {
40  namespace hardware {
41  namespace camera {
42  namespace provider {
43  namespace implementation {
44  namespace exif {
45  namespace {
46  
47  struct ExifMemDeleter {
operator ()android::hardware::camera::provider::implementation::exif::__anon7dead4430111::ExifMemDeleter48      void operator()(ExifMem* allocator) const {
49          exif_mem_unref(allocator);
50      }
51  };
52  
53  typedef std::unique_ptr<ExifMem, ExifMemDeleter> ExifMemPtr;
54  
allocateEntry(ExifMem * mem,const ExifTag tag,const ExifFormat format,const size_t numComponents)55  ExifEntry* allocateEntry(ExifMem* mem, const ExifTag tag, const ExifFormat format,
56                           const size_t numComponents) {
57      ExifEntry* e = exif_entry_new_mem(mem);
58      const size_t size = numComponents * exif_format_get_size(format);
59      e->data = static_cast<unsigned char*>(exif_mem_alloc(mem, size));
60      e->size = size;
61      e->tag = tag;
62      e->components = numComponents;
63      e->format = format;
64      return e;
65  }
66  
appendEntry(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag)67  void appendEntry(ExifData* edata, ExifMem* mem,
68                   const ExifIfd ifd, const ExifTag tag) {
69      ExifEntry* e = exif_entry_new_mem(mem);
70      exif_entry_initialize(e, tag);
71      exif_content_add_entry(edata->ifd[ifd], e);
72      exif_entry_unref(e);
73  }
74  
appendEntryU8(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint8_t value)75  void appendEntryU8(ExifData* edata, ExifMem* mem,
76                      const ExifIfd ifd, const ExifTag tag,
77                      const uint8_t value) {
78      ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_BYTE, 1);
79      *e->data = value;
80      exif_content_add_entry(edata->ifd[ifd], e);
81      exif_entry_unref(e);
82  }
83  
appendEntryU16(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint16_t value)84  void appendEntryU16(ExifData* edata, ExifMem* mem,
85                      const ExifIfd ifd, const ExifTag tag,
86                      const uint16_t value) {
87      ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_SHORT, 1);
88      exif_set_short(e->data, exif_data_get_byte_order(edata), value);
89      exif_content_add_entry(edata->ifd[ifd], e);
90      exif_entry_unref(e);
91  }
92  
appendEntryU32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint32_t value)93  void appendEntryU32(ExifData* edata, ExifMem* mem,
94                      const ExifIfd ifd, const ExifTag tag,
95                      const uint32_t value) {
96      ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_LONG, 1);
97      exif_set_long(e->data, exif_data_get_byte_order(edata), value);
98      exif_content_add_entry(edata->ifd[ifd], e);
99      exif_entry_unref(e);
100  }
101  
appendEntryR32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const ExifRational * src,size_t n)102  void appendEntryR32(ExifData* edata, ExifMem* mem,
103                      const ExifIfd ifd, const ExifTag tag,
104                      const ExifRational* src, size_t n) {
105      ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_RATIONAL, n);
106  
107      for (uint8_t* dst = e->data; n > 0; --n, ++src, dst += sizeof(ExifRational)) {
108          exif_set_rational(dst, exif_data_get_byte_order(edata), *src);
109      }
110  
111      exif_content_add_entry(edata->ifd[ifd], e);
112      exif_entry_unref(e);
113  }
114  
appendEntryR32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint32_t num,const uint32_t dem)115  void appendEntryR32(ExifData* edata, ExifMem* mem,
116                      const ExifIfd ifd, const ExifTag tag,
117                      const uint32_t num, const uint32_t dem) {
118      const ExifRational value = { num, dem };
119      appendEntryR32(edata, mem, ifd, tag, &value, 1);
120  }
121  
appendEntryS(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const char * value,const size_t size,const ExifFormat format)122  void appendEntryS(ExifData* edata, ExifMem* mem,
123                    const ExifIfd ifd, const ExifTag tag,
124                    const char* value, const size_t size,
125                    const ExifFormat format) {
126      ExifEntry* e = allocateEntry(mem, tag, format, size);
127      memcpy(e->data, value, size);
128      exif_content_add_entry(edata->ifd[ifd], e);
129      exif_entry_unref(e);
130  }
131  
convertDegToDegMmSs(double v)132  std::tuple<uint32_t, uint32_t, uint32_t> convertDegToDegMmSs(double v) {
133      const uint32_t ideg = floor(v);
134      v = (v - ideg) * 60;
135      const uint32_t minutes = floor(v);
136      v = (v - minutes) * 60;
137      const uint32_t secondsM = round(v * 1000000);
138      return {ideg, minutes, secondsM};
139  }
140  
convertT64ToTm(const int64_t t)141  struct tm convertT64ToTm(const int64_t t) {
142      Timestamp t2 = t;
143      struct tm result;
144      TIMESTAMP_TO_TM(&t2, &result);
145      return result;
146  }
147  
148  }  // namespace
149  
createExifData(const CameraMetadata & metadata,const Rect<uint16_t> size)150  ExifDataPtr createExifData(const CameraMetadata& metadata,
151                             const Rect<uint16_t> size) {
152      const camera_metadata_t* const rawMetadata =
153          reinterpret_cast<const camera_metadata_t*>(metadata.metadata.data());
154      camera_metadata_ro_entry_t metadataEntry;
155  
156      ExifMemPtr allocator(exif_mem_new_default());
157      ExifDataPtr exifData(exif_data_new_mem(allocator.get()));
158  
159      exif_data_set_option(exifData.get(), EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
160      exif_data_set_data_type(exifData.get(), EXIF_DATA_TYPE_COMPRESSED);
161      exif_data_set_byte_order(exifData.get(), EXIF_BYTE_ORDER_INTEL);
162      exif_data_fix(exifData.get());
163  
164      {
165          const std::string v = base::GetProperty("ro.product.manufacturer", "");
166          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0, EXIF_TAG_MAKE,
167                       v.c_str(), v.size() + 1, EXIF_FORMAT_ASCII);
168      }
169      {
170          const std::string v = base::GetProperty("ro.product.model", "");
171          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0, EXIF_TAG_MODEL,
172                       v.c_str(), v.size() + 1, EXIF_FORMAT_ASCII);
173      }
174  
175      {
176          struct tm now;
177          {
178              time_t t = time(nullptr);
179              localtime_r(&t, &now);
180          }
181  
182          char timeStr[20];
183          const int len = snprintf(timeStr, sizeof(timeStr),
184                                   "%04d:%02d:%02d %02d:%02d:%02d",
185                                   now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
186                                   now.tm_hour, now.tm_min, now.tm_sec) + 1;
187          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0,
188                       EXIF_TAG_DATE_TIME, timeStr, len, EXIF_FORMAT_ASCII);
189          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
190                       EXIF_TAG_DATE_TIME_ORIGINAL, timeStr, len, EXIF_FORMAT_ASCII);
191          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
192                       EXIF_TAG_DATE_TIME_DIGITIZED, timeStr, len, EXIF_FORMAT_ASCII);
193      }
194      {
195          char ddd[4];
196          const int len = snprintf(ddd, sizeof(ddd), "%03d", 0);
197          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
198                       EXIF_TAG_SUB_SEC_TIME, ddd, len, EXIF_FORMAT_ASCII);
199          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
200                       EXIF_TAG_SUB_SEC_TIME_ORIGINAL, ddd, len, EXIF_FORMAT_ASCII);
201          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
202                       EXIF_TAG_SUB_SEC_TIME_DIGITIZED, ddd, len, EXIF_FORMAT_ASCII);
203      }
204  
205      if ((size.width > 0) && (size.height > 0)) {
206          appendEntryU32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
207                         EXIF_TAG_PIXEL_X_DIMENSION, size.width);
208          appendEntryU32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
209                         EXIF_TAG_PIXEL_Y_DIMENSION, size.width);
210      }
211  
212      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_ORIENTATION,
213                                         &metadataEntry)) {
214          unsigned v;
215          switch (metadataEntry.data.i32[0]) {
216          default:
217          case 0:     v = 1; break;
218          case 90:    v = 6; break;
219          case 180:   v = 3; break;
220          case 270:   v = 8; break;
221          }
222  
223          appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_0,
224                         EXIF_TAG_ORIENTATION, v);
225      }
226  
227      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_LENS_APERTURE,
228                                         &metadataEntry)) {
229          const float v = metadataEntry.data.f[0];
230          appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
231                         EXIF_TAG_FNUMBER, uint32_t(v * 1000U), 1000U);
232      }
233  
234      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_LENS_FOCAL_LENGTH,
235                                         &metadataEntry)) {
236          const float v = metadataEntry.data.f[0];
237          appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
238                         EXIF_TAG_FOCAL_LENGTH, uint32_t(v * 1000U), 1000U);
239      }
240  
241      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_FLASH_MODE,
242                                         &metadataEntry)) {
243          const unsigned v =
244              (metadataEntry.data.i32[0] == ANDROID_FLASH_MODE_OFF) ? 0 : 1;
245          appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
246                         EXIF_TAG_FLASH, v);
247      }
248  
249      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_SENSOR_EXPOSURE_TIME,
250                                         &metadataEntry)) {
251          int64_t num = metadataEntry.data.i64[0];
252          uint32_t dem = 1000000000U;
253          while (num > std::numeric_limits<uint32_t>::max()) {
254              num /= 10;
255              dem /= 10;
256          }
257  
258          appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
259                         EXIF_TAG_EXPOSURE_TIME, uint32_t(num), dem);
260      }
261  
262      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_SENSOR_SENSITIVITY,
263                                         &metadataEntry)) {
264          appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
265                         EXIF_TAG_ISO_SPEED_RATINGS, metadataEntry.data.i32[0]);
266      }
267  
268      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_CONTROL_AWB_MODE,
269                                         &metadataEntry)) {
270          const unsigned v =
271              (metadataEntry.data.i32[0] == ANDROID_CONTROL_AWB_MODE_AUTO) ? 0 : 1;
272  
273          appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
274                         EXIF_TAG_WHITE_BALANCE, v);
275      }
276  
277      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_COORDINATES,
278                                         &metadataEntry)) {
279          {
280              const auto [ideg, minutes, secondsM] = convertDegToDegMmSs(
281                  fabs(metadataEntry.data.d[0]));
282              ExifRational degmmss[3] = {{ideg, 1}, {minutes, 1},
283                                         {secondsM, 1000000}};
284              appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
285                             static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE),
286                             degmmss, 3);
287  
288              const char* latRef = (metadataEntry.data.d[0] < 0.0) ? "S" : "N";
289              appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
290                           static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF),
291                           latRef, 2, EXIF_FORMAT_ASCII);
292          }
293          {
294              const auto [ideg, minutes, secondsM] = convertDegToDegMmSs(
295                  fabs(metadataEntry.data.d[1]));
296              ExifRational degmmss[3] = {{ideg, 1}, {minutes, 1},
297                                         {secondsM, 1000000}};
298              appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
299                             static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE),
300                             degmmss, 3);
301  
302              const char* latRef = (metadataEntry.data.d[1] < 0.0) ? "W" : "E";
303              appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
304                           static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF),
305                           latRef, 2, EXIF_FORMAT_ASCII);
306          }
307          {
308              appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
309                             static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE),
310                             static_cast<uint32_t>(fabs(metadataEntry.data.d[2]) * 1000.0),
311                             1000);
312              appendEntryU8(exifData.get(), allocator.get(), EXIF_IFD_GPS,
313                            static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF),
314                            (metadataEntry.data.d[2] < 0.0) ? 1 : 0);
315          }
316      }
317  
318      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_TIMESTAMP,
319                                         &metadataEntry)) {
320          struct tm gpsTime = convertT64ToTm(metadataEntry.data.i64[0]);
321  
322          {
323              char yyyymmdd[12];
324              const int len = snprintf(yyyymmdd, sizeof(yyyymmdd), "%04d:%02d:%02d",
325                                       gpsTime.tm_year + 1900, gpsTime.tm_mon + 1,
326                                       gpsTime.tm_mday) + 1;
327              appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
328                           static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP),
329                           yyyymmdd, len, EXIF_FORMAT_ASCII);
330          }
331          {
332              ExifRational hhmmss[3] = {{static_cast<ExifLong>(gpsTime.tm_hour), 1},
333                                        {static_cast<ExifLong>(gpsTime.tm_min), 1},
334                                        {static_cast<ExifLong>(gpsTime.tm_sec), 1}};
335              appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
336                             static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP),
337                             hhmmss, 3);
338          }
339      }
340  
341      if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_PROCESSING_METHOD,
342                                         &metadataEntry)) {
343          // EXIF_FORMAT_UNDEFINED requires this prefix
344          std::vector<char> value = {0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00};
345          value.insert(value.end(),
346                       reinterpret_cast<const char*>(metadataEntry.data.u8),
347                       reinterpret_cast<const char*>(metadataEntry.data.u8) + metadataEntry.count);
348  
349          appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
350                       static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD),
351                       value.data(), value.size(), EXIF_FORMAT_UNDEFINED);
352      }
353  
354      return exifData;
355  }
356  
exifDataAllocThumbnail(ExifData * const edata,const size_t size)357  void* exifDataAllocThumbnail(ExifData* const edata, const size_t size) {
358      // WARNING: maloc and free must match the functions that are used in
359      // exif_mem_new_default (see above) to manage memory. They will be used in
360      // exif_data_free to deallocate memory allocated here.
361      void* mem = malloc(size);
362      if (mem) {
363          if (edata->data) {
364              free(edata->data);
365          }
366          edata->size = size;
367          edata->data = static_cast<uint8_t*>(mem);
368      }
369      return mem;
370  }
371  
operator ()(ExifData * p) const372  void ExifDataDeleter::operator()(ExifData* p) const {
373      exif_data_free(p);
374  }
375  
376  }  // namespace exif
377  }  // namespace implementation
378  }  // namespace provider
379  }  // namespace camera
380  }  // namespace hardware
381  }  // namespace android
382