/libcamera/JpegEncoderEXIF.cpp

https://github.com/waleedq/android_device_samsung_galaxysl · C++ · 558 lines · 448 code · 94 blank · 16 comment · 69 complexity · b992bba1f2dfbf9ef3154515b6b30fe6 MD5 · raw file

  1. #include <libexif/exif-entry.h>
  2. #include <libexif/exif-data.h>
  3. #include <libexif/exif-ifd.h>
  4. #include <libexif/exif-loader.h>
  5. #include <stdio.h>
  6. #include <time.h>
  7. #include <sys/time.h>
  8. #include <errno.h>
  9. #include "JpegEncoderEXIF.h"
  10. void exif_buf_free (exif_buffer * buf)
  11. {
  12. free (buf->data);
  13. free (buf);
  14. }
  15. exif_buffer *exif_new_buf(unsigned char *data, unsigned int size)
  16. {
  17. exif_buffer *res;
  18. res = (exif_buffer *) malloc(sizeof (exif_buffer));
  19. if( res == NULL)
  20. return NULL;
  21. res->data = (unsigned char *) malloc(size);
  22. if( res->data == NULL){
  23. free(res);
  24. return NULL;
  25. }
  26. memcpy ((void *) res->data, (void *) data, size);
  27. res->size = size;
  28. return res;
  29. }
  30. void exif_entry_set_string (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, const char *s)
  31. {
  32. ExifEntry *pE;
  33. pE = exif_entry_new ();
  34. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  35. exif_entry_initialize (pE, eEtag);
  36. if (pE->data)
  37. free (pE->data);
  38. pE->components = strlen (s) + 1;
  39. pE->size = sizeof (char) * pE->components;
  40. pE->data = (unsigned char *) malloc (pE->size);
  41. if (!pE->data) {
  42. printf ("Cannot allocate %d bytes.\nTerminating.\n", (int) pE->size);
  43. exit (1);
  44. }
  45. strcpy ((char *) pE->data, (char *) s);
  46. exif_entry_fix (pE);
  47. exif_entry_unref (pE);
  48. }
  49. void exif_entry_set_undefined (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  50. exif_buffer * buf)
  51. {
  52. ExifEntry *pE;
  53. pE = exif_entry_new ();
  54. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  55. exif_entry_initialize (pE, eEtag);
  56. if (buf != NULL) {
  57. if (pE->data)
  58. free (pE->data);
  59. pE->components = buf->size;
  60. pE->size = buf->size;
  61. pE->data = (unsigned char *) malloc (pE->size);
  62. if (!pE->data) {
  63. printf ("Cannot allocate %d bytes.\nTerminating.\n", (int) pE->size);
  64. exit (1);
  65. }
  66. memcpy ((void *) pE->data, (void *) buf->data, buf->size);
  67. }
  68. exif_entry_fix (pE);
  69. exif_entry_unref (pE);
  70. }
  71. void exif_entry_set_byte(ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  72. ExifByte n)
  73. {
  74. ExifEntry *pE;
  75. unsigned char *pData;
  76. pE = exif_entry_new ();
  77. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  78. exif_entry_initialize (pE, eEtag);
  79. pData = (unsigned char *) (pE->data);
  80. if (pData) {
  81. *pData = n;
  82. } else {
  83. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  84. }
  85. exif_entry_fix (pE);
  86. exif_entry_unref (pE);
  87. }
  88. void exif_entry_set_short (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  89. ExifShort n)
  90. {
  91. ExifEntry *pE;
  92. ExifByteOrder eO;
  93. pE = exif_entry_new ();
  94. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  95. exif_entry_initialize (pE, eEtag);
  96. eO = exif_data_get_byte_order (pE->parent->parent);
  97. if (pE->data) {
  98. exif_set_short (pE->data, eO, n);
  99. } else {
  100. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  101. }
  102. exif_entry_fix (pE);
  103. exif_entry_unref (pE);
  104. }
  105. void exif_entry_set_long (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  106. ExifLong n)
  107. {
  108. ExifEntry *pE;
  109. ExifByteOrder eO;
  110. pE = exif_entry_new ();
  111. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  112. exif_entry_initialize (pE, eEtag);
  113. eO = exif_data_get_byte_order (pE->parent->parent);
  114. if (pE->data) {
  115. exif_set_long (pE->data, eO, n);
  116. } else {
  117. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  118. }
  119. exif_entry_fix (pE);
  120. exif_entry_unref (pE);
  121. }
  122. void exif_entry_set_rational (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  123. ExifRational r)
  124. {
  125. ExifEntry *pE;
  126. ExifByteOrder eO;
  127. pE = exif_entry_new ();
  128. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  129. exif_entry_initialize (pE, eEtag);
  130. eO = exif_data_get_byte_order (pE->parent->parent);
  131. if (pE->data) {
  132. exif_set_rational (pE->data, eO, r);
  133. } else {
  134. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  135. }
  136. exif_entry_fix (pE);
  137. exif_entry_unref (pE);
  138. }
  139. void exif_entry_set_sbyte (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  140. ExifSByte n)
  141. {
  142. ExifEntry *pE;
  143. char *pData;
  144. pE = exif_entry_new ();
  145. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  146. exif_entry_initialize (pE, eEtag);
  147. pData = (char *) (pE->data);
  148. if (pData) {
  149. *pData = n;
  150. } else {
  151. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  152. }
  153. exif_entry_fix (pE);
  154. exif_entry_unref (pE);
  155. }
  156. void exif_entry_set_sshort (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  157. ExifSShort n)
  158. {
  159. ExifEntry *pE;
  160. ExifByteOrder eO;
  161. pE = exif_entry_new ();
  162. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  163. exif_entry_initialize (pE, eEtag);
  164. eO = exif_data_get_byte_order (pE->parent->parent);
  165. if (pE->data) {
  166. exif_set_sshort (pE->data, eO, n);
  167. } else {
  168. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  169. }
  170. exif_entry_fix (pE);
  171. exif_entry_unref (pE);
  172. }
  173. void exif_entry_set_slong (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  174. ExifSLong n)
  175. {
  176. ExifEntry *pE;
  177. ExifByteOrder eO;
  178. pE = exif_entry_new ();
  179. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  180. exif_entry_initialize (pE, eEtag);
  181. eO = exif_data_get_byte_order (pE->parent->parent);
  182. if (pE->data) {
  183. exif_set_slong (pE->data, eO, n);
  184. } else {
  185. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  186. }
  187. exif_entry_fix (pE);
  188. exif_entry_unref (pE);
  189. }
  190. void exif_entry_set_srational (ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  191. ExifSRational r)
  192. {
  193. ExifEntry *pE;
  194. ExifByteOrder eO;
  195. pE = exif_entry_new ();
  196. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  197. exif_entry_initialize (pE, eEtag);
  198. eO = exif_data_get_byte_order (pE->parent->parent);
  199. if (pE->data) {
  200. exif_set_srational (pE->data, eO, r);
  201. } else {
  202. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  203. }
  204. exif_entry_fix (pE);
  205. exif_entry_unref (pE);
  206. }
  207. void exif_entry_set_gps_coord(ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
  208. ExifRational r1, ExifRational r2, ExifRational r3)
  209. {
  210. ExifEntry *pE;
  211. ExifByteOrder eO;
  212. pE = exif_entry_new ();
  213. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  214. exif_entry_gps_initialize(pE, eEtag);
  215. eO = exif_data_get_byte_order (pE->parent->parent);
  216. if (pE->data) {
  217. exif_set_rational (pE->data, eO, r1);
  218. exif_set_rational (pE->data + exif_format_get_size (pE->format), eO, r2);
  219. exif_set_rational (pE->data + 2 * exif_format_get_size (pE->format), eO,
  220. r3);
  221. } else {
  222. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  223. }
  224. exif_entry_fix (pE);
  225. exif_entry_unref (pE);
  226. }
  227. void exif_entry_set_gps_altitude(ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifRational r1)
  228. {
  229. ExifEntry *pE;
  230. ExifByteOrder eO;
  231. pE = exif_entry_new ();
  232. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  233. exif_entry_gps_initialize(pE, eEtag);
  234. eO = exif_data_get_byte_order (pE->parent->parent);
  235. if (pE->data) {
  236. exif_set_rational (pE->data, eO, r1);
  237. } else {
  238. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  239. }
  240. exif_entry_fix (pE);
  241. exif_entry_unref (pE);
  242. }
  243. void exif_entry_set_gps_version(ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag, ExifByte r1, ExifByte r2, ExifByte r3, ExifByte r4)
  244. {
  245. ExifEntry *pE;
  246. ExifByteOrder eO;
  247. pE = exif_entry_new ();
  248. exif_content_add_entry (pEdata->ifd[eEifd], pE);
  249. exif_entry_gps_initialize(pE, eEtag);
  250. eO = exif_data_get_byte_order (pE->parent->parent);
  251. if (pE->data) {
  252. pE->data[0] = r1;
  253. pE->data[1] = r2;
  254. pE->data[2] = r3;
  255. pE->data[3] = r4;
  256. } else {
  257. printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
  258. }
  259. exif_entry_fix (pE);
  260. exif_entry_unref (pE);
  261. }
  262. exif_buffer *get_exif_buffer(void *params, void *gpsLocation)
  263. {
  264. ExifData *pEd;
  265. exif_buffer *sEb;
  266. ExifRational sR;
  267. struct timeval sTv;
  268. struct tm *sTime;
  269. char *TimeStr = NULL;
  270. int res;
  271. exif_params *par;
  272. if ( NULL == params)
  273. return NULL;
  274. par = (exif_params *) params;
  275. sEb = (exif_buffer *) malloc (sizeof (exif_buffer));
  276. pEd = exif_data_new ();
  277. if(pEd == NULL)
  278. goto EXIT;
  279. exif_entry_set_string (pEd, EXIF_IFD_0, EXIF_TAG_MAKE, "Zoom");
  280. exif_entry_set_string (pEd, EXIF_IFD_0, EXIF_TAG_MODEL, "SONY IU046");
  281. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, par->width);
  282. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, par->height);
  283. switch( par->rotation ) {
  284. case 0:
  285. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_ORIENTATION, 1);
  286. break;
  287. case 90:
  288. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_ORIENTATION, 6);
  289. break;
  290. case 180:
  291. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_ORIENTATION, 3);
  292. break;
  293. case 270:
  294. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_ORIENTATION, 8);
  295. break;
  296. };
  297. sR.numerator = 4*100+68;
  298. sR.denominator = 100;
  299. exif_entry_set_rational(pEd, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, sR);
  300. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_FLASH, 0);
  301. switch( par->metering_mode ) {
  302. case EXIF_CENTER:
  303. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE, 1);
  304. break;
  305. case EXIF_AVERAGE:
  306. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE, 2);
  307. break;
  308. };
  309. switch( par->iso ) {
  310. case EXIF_ISO_AUTO:
  311. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 0);
  312. break;
  313. case EXIF_ISO_100:
  314. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 100);
  315. break;
  316. case EXIF_ISO_200:
  317. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 200);
  318. break;
  319. case EXIF_ISO_400:
  320. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 400);
  321. break;
  322. case EXIF_ISO_800:
  323. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 800);
  324. break;
  325. case EXIF_ISO_1000:
  326. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 1000);
  327. break;
  328. case EXIF_ISO_1200:
  329. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 1200);
  330. break;
  331. case EXIF_ISO_1600:
  332. exif_entry_set_short(pEd, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, 1600);
  333. break;
  334. };
  335. sR.numerator = par->zoom*100;
  336. sR.denominator = 100;
  337. exif_entry_set_rational (pEd, EXIF_IFD_EXIF, EXIF_TAG_DIGITAL_ZOOM_RATIO, sR);
  338. if ( EXIF_WB_AUTO == par->wb )
  339. exif_entry_set_short (pEd, EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE, 0);
  340. else
  341. exif_entry_set_short (pEd, EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE, 1);
  342. sR.numerator = par->exposure;
  343. sR.denominator = 1000000;
  344. exif_entry_set_rational (pEd, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME, sR);
  345. /* resolution */
  346. sR.numerator = 72;
  347. sR.denominator = 1;
  348. exif_entry_set_rational (pEd, EXIF_IFD_0, EXIF_TAG_X_RESOLUTION, sR);
  349. exif_entry_set_rational (pEd, EXIF_IFD_0, EXIF_TAG_Y_RESOLUTION, sR);
  350. exif_entry_set_short (pEd, EXIF_IFD_0, EXIF_TAG_RESOLUTION_UNIT, 2); /* inches */
  351. exif_entry_set_short (pEd, EXIF_IFD_0, EXIF_TAG_YCBCR_POSITIONING, 1); /* centered */
  352. exif_entry_set_short(pEd, EXIF_IFD_0, EXIF_TAG_YCBCR_SUB_SAMPLING, 0);
  353. /* Exif version */
  354. exif_entry_set_undefined (pEd, EXIF_IFD_EXIF, EXIF_TAG_EXIF_VERSION, NULL);
  355. /* flashpix version */
  356. exif_entry_set_undefined(pEd, EXIF_IFD_EXIF, EXIF_TAG_FLASH_PIX_VERSION, NULL);
  357. /* file source */
  358. exif_entry_set_undefined(pEd, EXIF_IFD_EXIF, EXIF_TAG_FILE_SOURCE, NULL);
  359. /* file name */
  360. exif_entry_set_undefined(pEd, EXIF_IFD_EXIF, EXIF_TAG_DOCUMENT_NAME, NULL);
  361. /* scene type */
  362. exif_entry_set_undefined(pEd, EXIF_IFD_EXIF, EXIF_TAG_SCENE_TYPE, NULL);
  363. /* Color Components */
  364. exif_entry_set_undefined(pEd, EXIF_IFD_EXIF, EXIF_TAG_COMPONENTS_CONFIGURATION, NULL);
  365. /* Bits per sample */
  366. exif_entry_set_undefined (pEd, EXIF_IFD_0, EXIF_TAG_BITS_PER_SAMPLE, NULL);
  367. /* Color space */
  368. exif_entry_set_short (pEd, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE, 1);
  369. /* Interoperability index */
  370. exif_entry_set_string(pEd, EXIF_IFD_INTEROPERABILITY, EXIF_TAG_INTEROPERABILITY_INDEX, "R98");
  371. /* time */
  372. /* this sould be last resort */
  373. res = gettimeofday (&sTv, NULL);
  374. sTime = localtime (&sTv.tv_sec);
  375. if (res == 0 && sTime != NULL) {
  376. TimeStr = (char *) malloc(20);/* No data for secondary sensor */
  377. if (TimeStr != NULL) {
  378. snprintf(TimeStr, 20, "%04d:%02d:%02d %02d:%02d:%02d",
  379. sTime->tm_year + 1900,
  380. sTime->tm_mon + 1,
  381. sTime->tm_mday,
  382. sTime->tm_hour,
  383. sTime->tm_min,
  384. sTime->tm_sec
  385. );
  386. exif_entry_set_string (pEd, EXIF_IFD_0, EXIF_TAG_DATE_TIME, TimeStr);
  387. exif_entry_set_string (pEd, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, TimeStr);
  388. exif_entry_set_string (pEd, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, TimeStr);
  389. snprintf(TimeStr, 20, "%06d", (int) sTv.tv_usec);
  390. exif_entry_set_string (pEd, EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME, TimeStr);
  391. exif_entry_set_string (pEd, EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME_ORIGINAL, TimeStr);
  392. exif_entry_set_string (pEd, EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME_DIGITIZED, TimeStr);
  393. free (TimeStr);
  394. TimeStr = NULL;
  395. } else {
  396. printf ("%s():%d:!!!!!ERROR: malloc Failed.\n",__FUNCTION__,__LINE__);
  397. }
  398. } else {
  399. printf ("Error in time recognition. res: %d sTime: %p\n%s\n", res, sTime, strerror(errno));
  400. }
  401. exif_entry_set_short (pEd, EXIF_IFD_1, EXIF_TAG_COMPRESSION, 6); /* JPEG */
  402. exif_entry_set_long (pEd, EXIF_IFD_1, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, 0xFFFFFFFF);
  403. exif_entry_set_long (pEd, EXIF_IFD_1, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 0xFFFFFFFF);
  404. if ( NULL != gpsLocation ) {
  405. ExifRational r1, r2, r3;
  406. gps_data *gps = (gps_data *) gpsLocation;
  407. /* gps data */
  408. r1.denominator = 1;
  409. r2.denominator = 1;
  410. r3.denominator = 1;
  411. r1.numerator = gps->longDeg;
  412. r2.numerator = gps->longMin;
  413. r3.numerator = gps->longSec;
  414. exif_entry_set_gps_coord(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_LONGITUDE, r1, r2, r3);
  415. r1.numerator = gps->latDeg;
  416. r2.numerator = gps->latMin;
  417. r3.numerator = gps->latSec;
  418. exif_entry_set_gps_coord(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_LATITUDE, r1, r2, r3);
  419. r1.numerator = gps->altitude;
  420. exif_entry_set_gps_altitude(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_ALTITUDE, r1);
  421. sTime = localtime ((const time_t*) &gps->timestamp);
  422. if ( NULL != sTime ) {
  423. r1.numerator = sTime->tm_hour;
  424. r2.numerator = sTime->tm_min;
  425. r3.numerator = sTime->tm_sec;
  426. exif_entry_set_gps_coord(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_TIME_STAMP, r1, r2, r3);
  427. }
  428. exif_entry_set_byte(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_ALTITUDE_REF, (ExifByte) gps->altitudeRef);
  429. if( NULL != gps->latRef )
  430. exif_entry_set_string (pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_LATITUDE_REF, gps->latRef);
  431. if( NULL != gps->longRef )
  432. exif_entry_set_string (pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_LONGITUDE_REF, gps->longRef);
  433. if( NULL != gps->procMethod )
  434. {
  435. //using strlen since i don't want the terminating null
  436. unsigned char* data = (unsigned char*)malloc(strlen(gps->procMethod) + sizeof(ExifAsciiPrefix));
  437. exif_buffer buffer;
  438. if(data != NULL)
  439. {
  440. memcpy(data, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
  441. memcpy(data+sizeof(ExifAsciiPrefix), gps->procMethod, strlen(gps->procMethod));
  442. buffer.data = data;
  443. buffer.size = strlen(gps->procMethod)+sizeof(ExifAsciiPrefix);
  444. exif_entry_set_undefined (pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_PROCESSING_METHOD, &buffer);
  445. free(data);
  446. }
  447. }
  448. if( NULL != gps->mapdatum )
  449. exif_entry_set_string (pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_MAP_DATUM, gps->mapdatum);
  450. if( strlen(gps->datestamp) == 10)
  451. exif_entry_set_string (pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_DATE_STAMP, gps->datestamp);
  452. if( NULL != gps->versionId )
  453. exif_entry_set_gps_version(pEd, EXIF_IFD_GPS, (ExifTag) EXIF_TAG_GPS_VERSION_ID, gps->versionId[0], gps->versionId[1], gps->versionId[2], gps->versionId[3]);
  454. }
  455. /* copy data to our buffer */
  456. exif_data_save_data (pEd, &sEb->data, &sEb->size);
  457. /* destroy exif structure */
  458. exif_data_unref(pEd);
  459. return sEb;
  460. EXIT:
  461. if(sEb != NULL)
  462. free(sEb);
  463. return NULL;
  464. }