You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

exif.cc 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570
  1. /*
  2. Support for embedded (JPEG) Exif-GPS information.
  3. Copyright (C) 2008 Olaf Klein, o.b.klein@gpsbabel.org
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. /*
  17. * Exif specifications can be found at
  18. * 2012, version 2.3: http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2012_E.pdf
  19. * 2010, version 2.3: http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf
  20. * 2002, version 2.2: http://www.exif.org/Exif2-2.PDF
  21. * 1998, version 2.1: http://www.exif.org/Exif2-1.PDF
  22. */
  23. #include "defs.h"
  24. #include "garmin_tables.h"
  25. #include "jeeps/gpsmath.h"
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <math.h>
  29. #include <QtCore/QFile>
  30. #define MYNAME "exif"
  31. // #define EXIF_DBG
  32. #define UNKNOWN_TIMESTAMP 999999999
  33. #define IFD0 0
  34. #define IFD1 1
  35. #define EXIF_IFD 2 /* dummy index */
  36. #define GPS_IFD 3 /* dummy index */
  37. #define INTER_IFD 4 /* dummy index */
  38. #define EXIF_TYPE_BYTE 1
  39. #define EXIF_TYPE_ASCII 2
  40. #define EXIF_TYPE_SHORT 3
  41. #define EXIF_TYPE_LONG 4
  42. #define EXIF_TYPE_RAT 5
  43. /* TIFF 6.0 */
  44. #define EXIF_TYPE_SBYTE 6
  45. #define EXIF_TYPE_UNK 7
  46. #define EXIF_TYPE_SSHORT 8
  47. #define EXIF_TYPE_SLONG 9
  48. #define EXIF_TYPE_SRAT 10
  49. #define EXIF_TYPE_FLOAT 11
  50. #define EXIF_TYPE_DOUBLE 12
  51. #define EXIF_TYPE_IFD 13
  52. #define EXIF_TYPE_UNICODE 14
  53. #define EXIF_TYPE_COMPLEX 15
  54. #define EXIF_TYPE_LONG8 16
  55. #define EXIF_TYPE_SLONG8 17
  56. #define EXIF_TYPE_IFD8 18
  57. #define BYTE_TYPE(a) ( (a==EXIF_TYPE_BYTE) || (a==EXIF_TYPE_ASCII) || (a==EXIF_TYPE_UNK) )
  58. #define WORD_TYPE(a) ( (a==EXIF_TYPE_SHORT) || (a==EXIF_TYPE_SSHORT) )
  59. #define LONG_TYPE(a) ( (a==EXIF_TYPE_LONG) || (a==EXIF_TYPE_SLONG) || (a==EXIF_TYPE_IFD) )
  60. #define IFD0_TAG_EXIF_IFD_OFFS 0x8769
  61. #define IFD0_TAG_GPS_IFD_OFFS 0x8825
  62. #define IFD1_TAG_STRIP_OFFS 0x0111
  63. #define IFD1_TAG_JPEG_OFFS 0x0201
  64. #define IFD1_TAG_JPEG_SIZE 0x0202
  65. #define EXIF_IFD_TAG_USER_CMT 0x9286
  66. #define EXIF_IFD_TAG_INTER_IFD_OFFS 0xA005
  67. #define GPS_IFD_TAG_VERSION 0x0000
  68. #define GPS_IFD_TAG_LATREF 0x0001
  69. #define GPS_IFD_TAG_LAT 0x0002
  70. #define GPS_IFD_TAG_LONREF 0x0003
  71. #define GPS_IFD_TAG_LON 0x0004
  72. #define GPS_IFD_TAG_ALTREF 0x0005
  73. #define GPS_IFD_TAG_ALT 0x0006
  74. #define GPS_IFD_TAG_TIMESTAMP 0x0007
  75. #define GPS_IFD_TAG_SAT 0x0008
  76. #define GPS_IFD_TAG_MODE 0x000A
  77. #define GPS_IFD_TAG_DOP 0x000B
  78. #define GPS_IFD_TAG_SPEEDREF 0x000C
  79. #define GPS_IFD_TAG_SPEED 0x000D
  80. #define GPS_IFD_TAG_DATUM 0x0012
  81. #define GPS_IFD_TAG_DATESTAMP 0x001D
  82. typedef struct exif_tag_s {
  83. queue Q;
  84. uint16_t id;
  85. uint16_t type;
  86. uint32_t count;
  87. uint32_t value;
  88. uint32_t origin;
  89. uint32_t size;
  90. #ifdef EXIF_DBG
  91. uint32_t offs;
  92. #endif
  93. unsigned char data_is_dynamic:1;
  94. void* data;
  95. } exif_tag_t;
  96. typedef struct exif_ifd_s {
  97. queue Q;
  98. uint32_t next_ifd;
  99. uint16_t nr;
  100. uint16_t count;
  101. queue tags;
  102. } exif_ifd_t, *exif_ifd_p;
  103. typedef struct exif_app_s {
  104. queue Q;
  105. uint16_t marker;
  106. gbsize_t len;
  107. gbfile* fcache;
  108. gbfile* fexif;
  109. queue ifds;
  110. } exif_app_t;
  111. static gbfile* fin, *fout;
  112. static queue exif_apps;
  113. static exif_app_t* exif_app;
  114. const Waypoint* exif_wpt_ref;
  115. time_t exif_time_ref;
  116. static char exif_success;
  117. static QString exif_fout_name;
  118. static char* opt_filename, *opt_overwrite, *opt_frame, *opt_name;
  119. static uint8_t writer_gps_tag_version[4] = {2, 0, 0, 0};
  120. arglist_t exif_args[] = {
  121. { "filename", &opt_filename, "Set waypoint name to source filename", "Y", ARGTYPE_BOOL, ARG_NOMINMAX },
  122. { "frame", &opt_frame, "Time-frame (in seconds)", "10", ARGTYPE_INT, "0", NULL },
  123. { "name", &opt_name, "Locate waypoint for tagging by this name", NULL, ARGTYPE_STRING, ARG_NOMINMAX },
  124. { "overwrite", &opt_overwrite, "!OVERWRITE! the original file. Default=N", "N", ARGTYPE_BOOL, ARG_NOMINMAX },
  125. ARG_TERMINATOR
  126. };
  127. #ifdef EXIF_DBG
  128. static void
  129. print_buff(const char* buf, int sz, const char* cmt)
  130. {
  131. int i;
  132. printf("%s: ", cmt);
  133. for (i = 0; i < sz; i++) {
  134. printf("%02x ", buf[i] & 0xFF);
  135. }
  136. for (i = 0; i < sz; i++) {
  137. char c = buf[i];
  138. if (isspace(c)) {
  139. c = ' ';
  140. } else if (! isprint(c)) {
  141. c = '.';
  142. }
  143. printf("%c", c);
  144. }
  145. }
  146. #endif
  147. static uint16_t
  148. exif_type_size(const uint16_t type)
  149. {
  150. uint16_t size;
  151. switch (type) {
  152. case EXIF_TYPE_BYTE:
  153. case EXIF_TYPE_ASCII:
  154. case EXIF_TYPE_UNK:
  155. size = 1;
  156. break;
  157. case EXIF_TYPE_SHORT:
  158. case EXIF_TYPE_SSHORT:
  159. case EXIF_TYPE_UNICODE:
  160. size = 2;
  161. break;
  162. case EXIF_TYPE_IFD:
  163. case EXIF_TYPE_LONG:
  164. case EXIF_TYPE_SLONG:
  165. case EXIF_TYPE_FLOAT:
  166. size = 4;
  167. break;
  168. case EXIF_TYPE_RAT:
  169. case EXIF_TYPE_SRAT:
  170. case EXIF_TYPE_DOUBLE:
  171. case EXIF_TYPE_LONG8:
  172. case EXIF_TYPE_SLONG8:
  173. case EXIF_TYPE_IFD8:
  174. size = 8;
  175. break;
  176. default:
  177. fatal(MYNAME ": Unknown data type %d! Please report.\n", type);
  178. }
  179. return size;
  180. }
  181. // TODO: If this were actually ever used (!?!?!) it could probably be
  182. // replaced by return QDateTime(time).toString("yyyy/MM/dd, hh:mm:ss);
  183. static QString
  184. exif_time_str(const time_t time)
  185. {
  186. struct tm tm;
  187. tm = *localtime(&time);
  188. tm.tm_year += 1900;
  189. tm.tm_mon += 1;
  190. return QString().sprintf("%04d/%02d/%02d, %02d:%02d:%02d",
  191. tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  192. }
  193. static char*
  194. exif_read_str(exif_tag_t* tag)
  195. {
  196. // Panasonic DMC-TZ10 stores datum with trailing spaces.
  197. char* buf = xstrndup((char*)tag->data, tag->size);
  198. rtrim(buf);
  199. return buf;
  200. }
  201. static double
  202. exif_read_double(const exif_tag_t* tag, const int index)
  203. {
  204. unsigned int num, den;
  205. int32_t* data = (int32_t*)tag->data;
  206. num = data[index * 2];
  207. den = data[(index * 2) + 1];
  208. if (den == 0) {
  209. den = 1;
  210. }
  211. return (double)num / (double)den;
  212. }
  213. static double
  214. exif_read_coord(const exif_tag_t* tag)
  215. {
  216. double res, min, sec;
  217. res = exif_read_double(tag, 0);
  218. if (tag->count == 1) {
  219. return res;
  220. }
  221. min = exif_read_double(tag, 1);
  222. res += (min / 60);
  223. if (tag->count == 2) {
  224. return res;
  225. }
  226. sec = exif_read_double(tag, 2);
  227. res += (sec / 3600);
  228. return res;
  229. }
  230. static time_t
  231. exif_read_timestamp(const exif_tag_t* tag)
  232. {
  233. double hour, min, sec;
  234. hour = exif_read_double(tag, 0);
  235. min = exif_read_double(tag, 1);
  236. sec = exif_read_double(tag, 2);
  237. return ((int)hour * SECONDS_PER_HOUR) + ((int)min * 60) + (int)sec;
  238. }
  239. static time_t
  240. exif_read_datestamp(const exif_tag_t* tag)
  241. {
  242. struct tm tm;
  243. char* str;
  244. memset(&tm, 0, sizeof(tm));
  245. str = xstrndup((char*)tag->data, tag->size);
  246. sscanf(str, "%d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
  247. xfree(str);
  248. tm.tm_year -= 1900;
  249. tm.tm_mon -= 1;
  250. return mkgmtime(&tm);
  251. }
  252. static void
  253. exif_release_tag(exif_tag_t* tag)
  254. {
  255. dequeue(&tag->Q);
  256. if (tag->data_is_dynamic) {
  257. xfree(tag->data);
  258. }
  259. xfree(tag);
  260. }
  261. static void
  262. exif_release_ifd(exif_ifd_t* ifd)
  263. {
  264. if (ifd != NULL) {
  265. queue* elem, *tmp;
  266. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  267. exif_release_tag((exif_tag_t*)elem);
  268. }
  269. xfree(ifd);
  270. }
  271. }
  272. static void
  273. exif_release_apps(void)
  274. {
  275. queue* e0, *t0;
  276. QUEUE_FOR_EACH(&exif_apps, e0, t0) {
  277. queue* e1, *t1;
  278. exif_app_t* app = (exif_app_t*)dequeue(e0);
  279. if (app->fcache) {
  280. gbfclose(app->fcache);
  281. }
  282. if (app->fexif) {
  283. gbfclose(app->fexif);
  284. }
  285. QUEUE_FOR_EACH(&app->ifds, e1, t1) {
  286. exif_ifd_t* ifd = (exif_ifd_t*)dequeue(e1);
  287. exif_release_ifd(ifd);
  288. }
  289. xfree(app);
  290. }
  291. }
  292. static uint32_t
  293. exif_ifd_size(exif_ifd_t* ifd)
  294. {
  295. queue* elem, *tmp;
  296. uint32_t res = 6; /* nr of tags + next_ifd */
  297. res += (ifd->count * 12);
  298. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  299. exif_tag_t* tag = (exif_tag_t*)elem;
  300. if (tag->size > 4) {
  301. uint32_t size = tag->size;
  302. if (size & 1) {
  303. size++;
  304. }
  305. res += size;
  306. }
  307. }
  308. return res;
  309. }
  310. static exif_app_t*
  311. exif_load_apps(void)
  312. {
  313. exif_app_t* exif_app = NULL;
  314. while (! gbfeof(fin)) {
  315. exif_app_t* app = (exif_app_t*) xcalloc(sizeof(*app), 1);
  316. ENQUEUE_TAIL(&exif_apps, &app->Q);
  317. QUEUE_INIT(&app->ifds);
  318. app->fcache = gbfopen(NULL, "wb", MYNAME);
  319. app->marker = gbfgetuint16(fin);
  320. app->len = gbfgetuint16(fin);
  321. #ifdef EXIF_DBG
  322. printf(MYNAME ": api = %02X, len = %d (0x%04x), offs = 0x%08X\n", app->marker & 0xFF, app->len, app->len, gbftell(fin));
  323. #endif
  324. if (exif_app || (app->marker == 0xFFDA)) /* compressed data */ {
  325. gbfcopyfrom(app->fcache, fin, 0x7FFFFFFF);
  326. #ifdef EXIF_DBG
  327. printf(MYNAME ": compressed data size = %d\n", gbftell(app->fcache));
  328. #endif
  329. } else {
  330. gbfcopyfrom(app->fcache, fin, app->len - 2);
  331. if (app->marker == 0xFFE1) {
  332. exif_app = app;
  333. }
  334. }
  335. }
  336. return exif_app;
  337. }
  338. static exif_ifd_t*
  339. exif_read_ifd(exif_app_t* app, const uint16_t ifd_nr, gbsize_t offs,
  340. uint32_t* exif_ifd_ofs, uint32_t* gps_ifd_ofs, uint32_t* inter_ifd_ofs)
  341. {
  342. queue* elem, *tmp;
  343. uint16_t i;
  344. exif_ifd_t* ifd;
  345. gbfile* fin = app->fexif;
  346. ifd = (exif_ifd_t*) xcalloc(sizeof(*ifd), 1);
  347. QUEUE_INIT(&ifd->tags);
  348. ENQUEUE_TAIL(&app->ifds, &ifd->Q);
  349. ifd->nr = ifd_nr;
  350. gbfseek(fin, offs, SEEK_SET);
  351. ifd->count = gbfgetuint16(fin);
  352. #ifdef EXIF_DBG
  353. {
  354. const char* name;
  355. switch (ifd_nr) {
  356. case IFD0:
  357. name = "IFD0";
  358. break;
  359. case IFD1:
  360. name = "IFD1";
  361. break;
  362. case GPS_IFD:
  363. name = "GPS";
  364. break;
  365. case EXIF_IFD:
  366. name = "EXIF";
  367. break;
  368. case INTER_IFD:
  369. name = "INTER";
  370. break;
  371. default:
  372. name = "private";
  373. break;
  374. }
  375. printf(MYNAME "-offs 0x%08X: Number of items in IFD%d \"%s\" = %d (0x%04x)\n",
  376. offs, ifd_nr, name, ifd->count, ifd->count);
  377. }
  378. #endif
  379. if (ifd->count == 0) {
  380. return ifd;
  381. }
  382. for (i = 0; i < ifd->count; i++) {
  383. exif_tag_t* tag;
  384. tag = (exif_tag_t*) xcalloc(sizeof(*tag), 1);
  385. #ifdef EXIF_DBG
  386. offs = gbftell(fin);
  387. tag->offs = offs;
  388. #endif
  389. ENQUEUE_TAIL(&ifd->tags, &tag->Q);
  390. tag->id = gbfgetuint16(fin);
  391. tag->type = gbfgetuint16(fin);
  392. tag->count = gbfgetuint32(fin);
  393. tag->size = exif_type_size(tag->type) * tag->count;
  394. tag->data = &tag->value;
  395. if (BYTE_TYPE(tag->type) && (tag->count <= 4)) {
  396. gbfread(tag->data, 4, 1, fin);
  397. } else {
  398. tag->value = gbfgetuint32(fin);
  399. tag->origin = tag->value;
  400. }
  401. if (ifd_nr == IFD0) {
  402. if (tag->id == IFD0_TAG_EXIF_IFD_OFFS) {
  403. *exif_ifd_ofs = tag->value;
  404. } else if (tag->id == IFD0_TAG_GPS_IFD_OFFS) {
  405. *gps_ifd_ofs = tag->value;
  406. }
  407. } else if (ifd_nr == EXIF_IFD) {
  408. if (tag->id == EXIF_IFD_TAG_INTER_IFD_OFFS) {
  409. *inter_ifd_ofs = tag->value;
  410. }
  411. }
  412. }
  413. #ifdef EXIF_DBG
  414. gbsize_t next_ifd_offs = gbftell(fin);
  415. #endif
  416. ifd->next_ifd = gbfgetuint32(fin);
  417. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  418. exif_tag_t* tag = (exif_tag_t*)elem;
  419. if ((tag->size > 4) && (tag->value)) {
  420. uint16_t i;
  421. char* ptr;
  422. tag->data = xmalloc(tag->size);
  423. tag->data_is_dynamic = 1;
  424. ptr = (char*) tag->data;
  425. gbfseek(fin, tag->value, SEEK_SET);
  426. if (BYTE_TYPE(tag->type)) {
  427. gbfread(ptr, tag->count, 1, fin);
  428. } else for (i = 0; i < tag->count; i++) {
  429. switch (tag->type) {
  430. case EXIF_TYPE_SHORT:
  431. case EXIF_TYPE_SSHORT:
  432. *(int16_t*)ptr = gbfgetuint16(fin);
  433. break;
  434. case EXIF_TYPE_IFD:
  435. case EXIF_TYPE_LONG:
  436. case EXIF_TYPE_SLONG:
  437. *(int32_t*)ptr = gbfgetuint32(fin);
  438. break;
  439. case EXIF_TYPE_RAT:
  440. case EXIF_TYPE_SRAT:
  441. *(int32_t*)ptr = gbfgetuint32(fin);
  442. *(int32_t*)(ptr+4) = gbfgetuint32(fin);
  443. break;
  444. case EXIF_TYPE_FLOAT:
  445. *(float*)ptr = gbfgetflt(fin);
  446. break;
  447. case EXIF_TYPE_DOUBLE:
  448. *(double*)ptr = gbfgetdbl(fin);
  449. break;
  450. default:
  451. gbfread(ptr, 1, 1, fin);
  452. break;
  453. }
  454. ptr += (tag->size / tag->count);
  455. }
  456. }
  457. #ifdef EXIF_DBG
  458. printf(MYNAME "-offs 0x%08X: ifd=%d id=0x%04X t=0x%04X c=%4d s=%4d v=0x%08X",
  459. tag->offs, ifd->nr, tag->id, tag->type, tag->count, tag->size, tag->value);
  460. if (tag->type == EXIF_TYPE_ASCII) {
  461. printf(" \"%s\"", exif_read_str(tag));
  462. }
  463. printf("\n");
  464. #endif
  465. }
  466. #ifdef EXIF_DBG
  467. printf(MYNAME "-offs 0x%08X: Next IFD=0x%08X\n", next_ifd_offs, ifd->next_ifd);
  468. #endif
  469. return ifd;
  470. }
  471. static void
  472. exif_read_app(exif_app_t* app)
  473. {
  474. gbsize_t offs;
  475. uint32_t exif_ifd_ofs, gps_ifd_ofs, inter_ifd_ofs;
  476. exif_ifd_t* ifd;
  477. gbfile* fin = app->fexif;
  478. #ifdef EXIF_DBG
  479. printf(MYNAME ": read_app...\n");
  480. print_buff((const char*)fin->handle.mem, 8, MYNAME "-offs 0x00000000: Image File Header");
  481. printf("\n");
  482. #endif
  483. exif_ifd_ofs = gps_ifd_ofs = inter_ifd_ofs = 0;
  484. gbfseek(fin, 4, SEEK_SET);
  485. offs = gbfgetuint32(fin);
  486. ifd = exif_read_ifd(app, IFD0, offs, &exif_ifd_ofs, &gps_ifd_ofs, &inter_ifd_ofs);
  487. if (ifd == NULL) {
  488. return;
  489. }
  490. if (ifd->next_ifd) {
  491. ifd = exif_read_ifd(app, IFD1, ifd->next_ifd, &exif_ifd_ofs, &gps_ifd_ofs, &inter_ifd_ofs);
  492. }
  493. if (exif_ifd_ofs) {
  494. ifd = exif_read_ifd(app, EXIF_IFD, exif_ifd_ofs, NULL, NULL, &inter_ifd_ofs);
  495. }
  496. if (gps_ifd_ofs) {
  497. ifd = exif_read_ifd(app, 3, gps_ifd_ofs, NULL, NULL, NULL);
  498. }
  499. if (inter_ifd_ofs) {
  500. ifd = exif_read_ifd(app, 4, inter_ifd_ofs, NULL, NULL, NULL);
  501. }
  502. // The return values of exif_read_ifd above aren't actually used.
  503. // Warning hush.
  504. (void) ifd;
  505. }
  506. static void
  507. exif_examine_app(exif_app_t* app)
  508. {
  509. uint16_t endianess;
  510. uint32_t ident;
  511. gbfile* ftmp = exif_app->fcache;
  512. gbfrewind(ftmp);
  513. ident = gbfgetuint32(ftmp);
  514. is_fatal(ident != 0x66697845, MYNAME ": Invalid EXIF header magic.");
  515. is_fatal(gbfgetint16(ftmp) != 0, MYNAME ": Error in EXIF header.");
  516. endianess = gbfgetint16(ftmp);
  517. #ifdef EXIF_DBG
  518. printf(MYNAME ": endianess = 0x%04X\n", endianess);
  519. #endif
  520. if (endianess == 0x4949) {
  521. ftmp->big_endian = 0;
  522. } else if (endianess == 0x4D4D) {
  523. ftmp->big_endian = 1;
  524. } else {
  525. fatal(MYNAME ": Invalid endianess identifier 0x%04X!\n", endianess);
  526. }
  527. gbfseek(ftmp, 6, SEEK_SET);
  528. app->fexif = gbfopen(NULL, "wb", MYNAME);
  529. app->fexif->big_endian = ftmp->big_endian;
  530. gbfcopyfrom(app->fexif, ftmp, 0x7FFFFFFF);
  531. exif_read_app(exif_app);
  532. }
  533. static exif_ifd_t*
  534. exif_find_ifd(exif_app_t* app, const uint16_t ifd_nr)
  535. {
  536. queue* e0, *t0;
  537. QUEUE_FOR_EACH(&app->ifds, e0, t0) {
  538. exif_ifd_t* ifd = (exif_ifd_t*)e0;
  539. if (ifd->nr == ifd_nr) {
  540. return ifd;
  541. }
  542. }
  543. return NULL;
  544. }
  545. static exif_tag_t*
  546. exif_find_tag(exif_app_t* app, const uint16_t ifd_nr, const uint16_t tag_id)
  547. {
  548. exif_ifd_t* ifd = exif_find_ifd(app, ifd_nr);
  549. if (ifd != NULL) {
  550. queue* elem, *tmp;
  551. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  552. exif_tag_t* tag = (exif_tag_t*)elem;
  553. if (tag->id == tag_id) {
  554. return tag;
  555. }
  556. }
  557. }
  558. return NULL;
  559. }
  560. static time_t
  561. exif_get_exif_time(exif_app_t* app)
  562. {
  563. QDateTime res;
  564. exif_tag_t* tag;
  565. tag = exif_find_tag(app, EXIF_IFD, 0x9003); /* DateTimeOriginal from EXIF */
  566. if (! tag) {
  567. tag = exif_find_tag(app, IFD0, 0x0132); /* DateTime from IFD0 */
  568. }
  569. if (! tag) {
  570. tag = exif_find_tag(app, EXIF_IFD, 0x9004); /* DateTimeDigitized from EXIF */
  571. }
  572. if (tag) {
  573. char* str;
  574. str = exif_read_str(tag);
  575. res = QDateTime::fromString(str, "yyyy:MM:dd hh:mm:ss");
  576. xfree(str);
  577. }
  578. return res.toTime_t();
  579. }
  580. static Waypoint*
  581. exif_waypt_from_exif_app(exif_app_t* app)
  582. {
  583. Waypoint* wpt;
  584. queue* elem, *tmp;
  585. exif_ifd_t* ifd;
  586. exif_tag_t* tag;
  587. char lat_ref = '\0';
  588. char lon_ref = '\0';
  589. char alt_ref = 0;
  590. char speed_ref = 'K';
  591. char* datum = NULL;
  592. char mode = '\0';
  593. double gpsdop = unknown_alt;
  594. double alt = unknown_alt;
  595. time_t timestamp = UNKNOWN_TIMESTAMP;
  596. time_t datestamp = UNKNOWN_TIMESTAMP;
  597. ifd = exif_find_ifd(app, GPS_IFD);
  598. if (ifd == NULL) {
  599. return NULL;
  600. }
  601. wpt = new Waypoint;
  602. wpt->latitude = unknown_alt;
  603. wpt->longitude = unknown_alt;
  604. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  605. tag = (exif_tag_t*)elem;
  606. switch (tag->id) {
  607. case GPS_IFD_TAG_VERSION:
  608. break;
  609. case GPS_IFD_TAG_LATREF:
  610. lat_ref = *(char*)tag->data;
  611. break;
  612. case GPS_IFD_TAG_LAT:
  613. wpt->latitude = exif_read_coord(tag);
  614. break;
  615. case GPS_IFD_TAG_LONREF:
  616. lon_ref = *(char*)tag->data;
  617. break;
  618. case GPS_IFD_TAG_LON:
  619. wpt->longitude = exif_read_coord(tag);
  620. break;
  621. case GPS_IFD_TAG_ALTREF:
  622. alt_ref = *(char*)tag->data;
  623. break;
  624. case GPS_IFD_TAG_ALT:
  625. alt = exif_read_double(tag, 0);
  626. break;
  627. case GPS_IFD_TAG_TIMESTAMP:
  628. timestamp = exif_read_timestamp(tag);
  629. break;
  630. case GPS_IFD_TAG_SAT:
  631. wpt->sat = atoi((char*)tag->data);
  632. break;
  633. case GPS_IFD_TAG_MODE:
  634. mode = *(char*)tag->data;
  635. break;
  636. case GPS_IFD_TAG_DOP:
  637. gpsdop = exif_read_double(tag, 0);
  638. break;
  639. case GPS_IFD_TAG_SPEEDREF:
  640. speed_ref = *(char*)tag->data;
  641. break;
  642. case GPS_IFD_TAG_SPEED:
  643. WAYPT_SET(wpt, speed, exif_read_double(tag, 0));
  644. break;
  645. case GPS_IFD_TAG_DATUM:
  646. datum = exif_read_str(tag);
  647. break;
  648. case GPS_IFD_TAG_DATESTAMP:
  649. datestamp = exif_read_datestamp(tag);
  650. break;
  651. }
  652. }
  653. if ((wpt->latitude == unknown_alt) || (wpt->longitude == unknown_alt)) {
  654. fatal(MYNAME ": Missing GPSLatitude and/or GPSLongitude!\n");
  655. }
  656. if (lat_ref == 'S') {
  657. wpt->latitude *= -1;
  658. } else if (lat_ref != 'N') {
  659. warning(MYNAME ": GPSLatitudeRef not set! Using N(orth).\n");
  660. }
  661. if (lon_ref == 'W') {
  662. wpt->longitude *= -1;
  663. } else if (lon_ref != 'E') {
  664. warning(MYNAME ": GPSLongitudeRef not set! Using E(east).\n");
  665. }
  666. #ifdef EXIF_DBG
  667. printf(MYNAME "-GPSLatitude = %12.7f\n", wpt->latitude);
  668. printf(MYNAME "-GPSLongitude = %12.7f\n", wpt->longitude);
  669. #endif
  670. if (datum) {
  671. int idatum = gt_lookup_datum_index(datum, MYNAME);
  672. if (idatum < 0) {
  673. fatal(MYNAME ": Unknown GPSMapDatum \"%s\"!\n", datum);
  674. }
  675. if (idatum != DATUM_WGS84) {
  676. double alt;
  677. GPS_Math_WGS84_To_Known_Datum_M(wpt->latitude, wpt->longitude, 0.0,
  678. &wpt->latitude, &wpt->longitude, &alt, idatum);
  679. }
  680. xfree(datum);
  681. }
  682. if (alt != unknown_alt) {
  683. double sign;
  684. switch (alt_ref) {
  685. case 0:
  686. sign = 1.0;
  687. break;
  688. case 1:
  689. sign = -1.0;
  690. break;
  691. default:
  692. warning(MYNAME ": Invalid GPSAltitudeRef (%d)! Using default value 0 (= Sea level).\n", alt_ref);
  693. sign = 1.0;
  694. }
  695. wpt->altitude = sign * alt;
  696. #ifdef EXIF_DBG
  697. printf(MYNAME "-GPSAltitude = %12.7f m\n", wpt->altitude);
  698. #endif
  699. }
  700. if WAYPT_HAS(wpt, speed) {
  701. switch (speed_ref) {
  702. case 'K':
  703. wpt->speed = KPH_TO_MPS(wpt->speed);
  704. break;
  705. case 'M':
  706. wpt->speed = MPH_TO_MPS(wpt->speed);
  707. break;
  708. case 'N':
  709. wpt->speed = KNOTS_TO_MPS(wpt->speed);
  710. break;
  711. default:
  712. wpt->speed = 0;
  713. WAYPT_UNSET(wpt, speed);
  714. warning(MYNAME ": Unknown GPSSpeedRef unit %c (0x%02x)!\n", speed_ref, speed_ref);
  715. }
  716. #ifdef EXIF_DBG
  717. if WAYPT_HAS(wpt, speed) {
  718. printf(MYNAME "-GPSSpeed = %12.2f m/s\n", wpt->speed);
  719. }
  720. #endif
  721. }
  722. if (mode == '2') {
  723. wpt->fix = fix_2d;
  724. if (gpsdop != unknown_alt) {
  725. wpt->hdop = gpsdop;
  726. }
  727. } else if (mode == '3') {
  728. wpt->fix = fix_3d;
  729. if (gpsdop != unknown_alt) {
  730. wpt->pdop = gpsdop;
  731. }
  732. }
  733. if (timestamp != UNKNOWN_TIMESTAMP) {
  734. if (datestamp != UNKNOWN_TIMESTAMP) {
  735. timestamp += datestamp;
  736. }
  737. } else {
  738. timestamp = datestamp;
  739. }
  740. if (timestamp != UNKNOWN_TIMESTAMP) {
  741. #ifdef EXIF_DBG
  742. QString str = QDateTime::fromTime_t(timestamp).toUTC().toString(Qt::ISODate);
  743. printf(MYNAME "-GPSTimeStamp = %s\n", qPrintable(str));
  744. #endif
  745. wpt->SetCreationTime(timestamp);
  746. } else {
  747. wpt->SetCreationTime(exif_get_exif_time(app));
  748. }
  749. tag = exif_find_tag(app, EXIF_IFD, EXIF_IFD_TAG_USER_CMT); /* UserComment */
  750. if (tag && (tag->size > 8)) {
  751. QString str;
  752. if (memcmp(tag->data, "ASCII\0\0\0", 8) == 0) {
  753. wpt->notes = QString::fromLatin1((char*) tag->data + 8, tag->size - 8);
  754. } else if (memcmp(tag->data, "UNICODE\0", 8) == 0) {
  755. // I'm not at all sure that casting alignment away like this is a good
  756. // idea in light of arches that don't allow unaligned loads, but in the
  757. // absence of test data that captures it and the grubbiness of the code
  758. // that was here before, I'm going to do this and then come back to it
  759. // if it's a problem.
  760. wpt->notes = QString::fromUtf16((const uint16_t*)((char*) tag->data + 8), tag->size - 8);
  761. }
  762. }
  763. if (opt_filename) {
  764. char* c, *cx;
  765. char* str = xstrdup(fin->name);
  766. cx = str;
  767. if ((c = strrchr(cx, ':'))) {
  768. cx = c + 1;
  769. }
  770. if ((c = strrchr(cx, '\\'))) {
  771. cx = c + 1;
  772. }
  773. if ((c = strrchr(cx, '/'))) {
  774. cx = c + 1;
  775. }
  776. if (((c = strchr(cx, '.'))) && (c != cx)) {
  777. *c = '\0';
  778. }
  779. wpt->shortname = cx;
  780. xfree(str);
  781. }
  782. return wpt;
  783. }
  784. static void
  785. exif_dec2frac(double val, int32_t* num, int32_t* den)
  786. {
  787. char sval[16], snum[16];
  788. char dot = 0;
  789. int den1 = 1;
  790. int num1, num2, den2, rem;
  791. char* cx;
  792. double vx;
  793. if (val < 0.000000001) {
  794. val = 0.0;
  795. } else if (val > 999999999.0) {
  796. fatal(MYNAME ": Value (%f) to big for a rational representation!\n", val);
  797. }
  798. num1 = 0;
  799. vx = fabs(val);
  800. while (vx > 1) {
  801. num1++;
  802. vx = vx / 10;
  803. }
  804. snprintf(sval, sizeof(sval), "%*.*f", 9, 9 - num1, fabs(val));
  805. snum[0] = '\0';
  806. cx = sval;
  807. while (*cx) {
  808. if (dot) {
  809. den1 *= 10;
  810. }
  811. if (*cx == '.') {
  812. dot = 1;
  813. } else {
  814. strncat(snum, cx, 1);
  815. }
  816. cx++;
  817. }
  818. num1 = atoi(snum);
  819. if (den1 == 1) {
  820. *num = num1;
  821. *den = den1;
  822. }
  823. num2 = num1;
  824. den2 = den1;
  825. rem = 1;
  826. /* Euclid's Algorithm to find the gcd */
  827. while (num2 % den2) {
  828. rem = num2 % den2;
  829. num2 = den2;
  830. den2 = rem;
  831. }
  832. if (den2 != den1) {
  833. rem = den2;
  834. }
  835. *num = num1 / rem;
  836. *den = den1 / rem;
  837. }
  838. static exif_tag_t*
  839. exif_put_value(const int ifd_nr, const uint16_t tag_id, const uint16_t type, const uint32_t count, const int index, const void* data)
  840. {
  841. exif_tag_t* tag = NULL;
  842. exif_ifd_t* ifd;
  843. uint16_t item_size, size;
  844. ifd = exif_find_ifd(exif_app, ifd_nr);
  845. if (ifd == NULL) {
  846. ifd = (exif_ifd_t*) xcalloc(sizeof(*ifd), 1);
  847. ifd->nr = ifd_nr;
  848. QUEUE_INIT(&ifd->tags);
  849. ENQUEUE_TAIL(&exif_app->ifds, &ifd->Q);
  850. } else {
  851. tag = exif_find_tag(exif_app, ifd_nr, tag_id);
  852. }
  853. item_size = exif_type_size(type);
  854. if ((data == NULL) || (count < 1) || (index < 0)) {
  855. size = 0;
  856. } else {
  857. size = (index + count) * item_size;
  858. }
  859. if (tag == NULL) {
  860. if (size == 0) {
  861. return NULL;
  862. }
  863. tag = (exif_tag_t*) xcalloc(sizeof(*tag), 1);
  864. tag->id = tag_id;
  865. tag->type = type;
  866. tag->count = index + count;
  867. tag->size = size;
  868. tag->data = xcalloc((size < 4) ? 4 : size, 1);
  869. tag->data_is_dynamic = 1;
  870. ifd->count++;
  871. ENQUEUE_TAIL(&ifd->tags, &tag->Q);
  872. } else {
  873. if (size == 0) { /* remove this element */
  874. ifd->count--;
  875. exif_release_tag(tag);
  876. return NULL;
  877. }
  878. if (tag->count < (index + count)) {
  879. if (! tag->data_is_dynamic) {
  880. void* tmp = xmalloc(tag->size < 4 ? 4 : tag->size);
  881. memcpy(tmp, tag->data, tag->size);
  882. tag->data = tmp;
  883. tag->data_is_dynamic = 1;
  884. }
  885. tag->size = size;
  886. tag->count = index + count;
  887. tag->data = xrealloc(tag->data, size < 4 ? 4 : size);
  888. }
  889. }
  890. switch (type) {
  891. case EXIF_TYPE_RAT:
  892. case EXIF_TYPE_SRAT: {
  893. double val = *(double*)data;
  894. uint32_t* dest = (uint32_t*) tag->data;
  895. if ((int)val == val) {
  896. dest[index * 2] = (int)val;
  897. dest[(index * 2) + 1] = 1;
  898. } else {
  899. int32_t Nom, Den;
  900. exif_dec2frac(val, &Nom, &Den);
  901. if ((type == EXIF_TYPE_SRAT) && (val < 0.0)) {
  902. Nom *= -1;
  903. }
  904. dest[index * 2] = Nom;
  905. dest[(index * 2) + 1] = Den;
  906. }
  907. }
  908. break;
  909. default: {
  910. char* dest = (char*) tag->data;
  911. memcpy(&dest[index * item_size], data, count * item_size);
  912. }
  913. }
  914. return tag;
  915. }
  916. static void
  917. exif_put_double(const int ifd_nr, const int tag_id, const int index, const double val)
  918. {
  919. double d = fabs(val);
  920. exif_put_value(ifd_nr, tag_id, EXIF_TYPE_RAT, 1, index, &d);
  921. }
  922. static void
  923. exif_put_str(const int ifd_nr, const int tag_id, const char* val)
  924. {
  925. int len = (val) ? strlen(val) + 1 : 0;
  926. exif_put_value(ifd_nr, tag_id, EXIF_TYPE_ASCII, len, 0, val);
  927. }
  928. static void
  929. exif_put_coord(const int ifd_nr, const int tag_id, const double val)
  930. {
  931. double vmin, vsec;
  932. int vint;
  933. vint = abs((int) val);
  934. vmin = 60.0 * (fabs(val) - vint);
  935. vsec = 60.0 * (vmin - floor(vmin));
  936. vmin = floor(vmin);
  937. exif_put_double(ifd_nr, tag_id, 0, (double)vint);
  938. exif_put_double(ifd_nr, tag_id, 1, (double)vmin);
  939. exif_put_double(ifd_nr, tag_id, 2, (double)vsec);
  940. }
  941. static void
  942. exif_put_long(const int ifd_nr, const int tag_id, const int index, const int32_t val)
  943. {
  944. exif_put_value(ifd_nr, tag_id, EXIF_TYPE_LONG, 1, index, &val);
  945. }
  946. static void
  947. exif_remove_tag(const int ifd_nr, const int tag_id)
  948. {
  949. exif_put_value(ifd_nr, tag_id, EXIF_TYPE_BYTE, 0, 0, NULL);
  950. }
  951. static void
  952. exif_find_wpt_by_time(const Waypoint* wpt)
  953. {
  954. if (!wpt->creation_time.isValid()) {
  955. return;
  956. }
  957. if (exif_wpt_ref == NULL) {
  958. exif_wpt_ref = wpt;
  959. } else if (labs(exif_time_ref - wpt->creation_time.toTime_t()) < labs(exif_time_ref - exif_wpt_ref->creation_time.toTime_t())) {
  960. exif_wpt_ref = wpt;
  961. }
  962. }
  963. static void
  964. exif_find_wpt_by_name(const Waypoint* wpt)
  965. {
  966. if (exif_wpt_ref != NULL) {
  967. return;
  968. } else if ((wpt->shortname != NULL) && (case_ignore_strcmp(wpt->shortname, opt_name) == 0)) {
  969. exif_wpt_ref = wpt;
  970. }
  971. }
  972. static int
  973. exif_sort_tags_cb(const queue* A, const queue* B)
  974. {
  975. exif_tag_t* ta = (exif_tag_t*)A;
  976. exif_tag_t* tb = (exif_tag_t*)B;
  977. return ta->id - tb->id;
  978. }
  979. static int
  980. exif_sort_ifds_cb(const queue* A, const queue* B)
  981. {
  982. exif_ifd_t* ia = (exif_ifd_t*)A;
  983. exif_ifd_t* ib = (exif_ifd_t*)B;
  984. return ia->nr - ib->nr;
  985. }
  986. static void
  987. exif_write_value(exif_tag_t* tag, gbfile* fout)
  988. {
  989. if (tag->size > 4) {
  990. gbfputuint32(tag->value, fout); /* offset to data */
  991. } else {
  992. char* data = (char*) tag->data;
  993. if BYTE_TYPE(tag->type) {
  994. gbfwrite(data, 4, 1, fout);
  995. } else if WORD_TYPE(tag->type) {
  996. gbfputuint16(*(uint16_t*)data, fout);
  997. gbfputuint16(*(uint16_t*)(data+2), fout);
  998. } else if LONG_TYPE(tag->type) {
  999. gbfputuint32(*(uint32_t*)data, fout);
  1000. } else if (tag->type == EXIF_TYPE_FLOAT) {
  1001. gbfputflt(*(float*)data, fout);
  1002. } else {
  1003. fatal(MYNAME ": Unknown data type %d!\n", tag->type);
  1004. }
  1005. }
  1006. }
  1007. static void
  1008. exif_write_ifd(const exif_ifd_t* ifd, const char next, gbfile* fout)
  1009. {
  1010. gbsize_t offs;
  1011. queue* elem, *tmp;
  1012. gbfputuint16(ifd->count, fout);
  1013. offs = gbftell(fout) + (ifd->count * 12) + 4;
  1014. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  1015. exif_tag_t* tag = (exif_tag_t*)elem;
  1016. gbfputuint16(tag->id, fout);
  1017. gbfputuint16(tag->type, fout);
  1018. gbfputuint32(tag->count, fout);
  1019. if (tag->size > 4) {
  1020. tag->value = offs;
  1021. offs += tag->size;
  1022. if (offs & 1) {
  1023. offs++;
  1024. }
  1025. gbfputuint32(tag->value, fout);
  1026. } else {
  1027. exif_write_value(tag, fout);
  1028. }
  1029. }
  1030. if (next) {
  1031. gbfputuint32(offs, fout);
  1032. } else {
  1033. gbfputuint32(0, fout);
  1034. }
  1035. QUEUE_FOR_EACH(&ifd->tags, elem, tmp) {
  1036. exif_tag_t* tag = (exif_tag_t*)elem;
  1037. if (tag->size > 4) {
  1038. uint16_t i;
  1039. char* ptr = (char*) tag->data;
  1040. if BYTE_TYPE(tag->type) {
  1041. gbfwrite(tag->data, tag->size, 1, fout);
  1042. } else for (i = 0; i < tag->count; i++) {
  1043. switch (tag->type) {
  1044. case EXIF_TYPE_SHORT:
  1045. case EXIF_TYPE_SSHORT:
  1046. gbfputuint16(*(int16_t*)ptr, fout);
  1047. break;
  1048. case EXIF_TYPE_LONG:
  1049. case EXIF_TYPE_SLONG:
  1050. case EXIF_TYPE_IFD:
  1051. gbfputuint32(*(int32_t*)ptr, fout);
  1052. break;
  1053. case EXIF_TYPE_RAT:
  1054. case EXIF_TYPE_SRAT:
  1055. gbfputuint32(*(int32_t*)ptr, fout);
  1056. gbfputuint32(*(int32_t*)(ptr+4), fout);
  1057. break;
  1058. case EXIF_TYPE_FLOAT:
  1059. gbfputflt(*(float*)ptr, fout);
  1060. break;
  1061. case EXIF_TYPE_DOUBLE:
  1062. gbfputdbl(*(double*)ptr, fout);
  1063. break;
  1064. default:
  1065. gbfwrite(ptr, exif_type_size(tag->type), 1, fin);
  1066. break;
  1067. }
  1068. ptr += (tag->size / tag->count);
  1069. }
  1070. if (gbftell(fout) & 1) {
  1071. gbfputc(0, fout);
  1072. }
  1073. }
  1074. }
  1075. }
  1076. static void
  1077. exif_write_apps(void)
  1078. {
  1079. queue* e0, *t0;
  1080. gbfputuint16(0xFFD8, fout);
  1081. QUEUE_FOR_EACH(&exif_apps, e0, t0) {
  1082. exif_app_t* app = (exif_app_t*)e0;
  1083. gbfputuint16(app->marker, fout);
  1084. if (app == exif_app) {
  1085. queue* e1, *t1;
  1086. uint16_t len = 8;
  1087. gbfile* ftmp;
  1088. exif_tag_t* tag;
  1089. exif_put_long(IFD0, IFD0_TAG_GPS_IFD_OFFS, 0, 0);
  1090. exif_put_value(GPS_IFD, GPS_IFD_TAG_VERSION, EXIF_TYPE_BYTE, 4, 0, writer_gps_tag_version);
  1091. sortqueue(&exif_app->ifds, exif_sort_ifds_cb);
  1092. QUEUE_FOR_EACH(&app->ifds, e1, t1) {
  1093. exif_ifd_t* ifd = (exif_ifd_t*)e1;
  1094. if (ifd->nr == GPS_IFD) {
  1095. exif_put_long(IFD0, IFD0_TAG_GPS_IFD_OFFS, 0, len);
  1096. } else if (ifd->nr == EXIF_IFD) {
  1097. exif_put_long(IFD0, IFD0_TAG_EXIF_IFD_OFFS, 0, len);
  1098. } else if (ifd->nr == INTER_IFD) {
  1099. exif_put_long(EXIF_IFD, EXIF_IFD_TAG_INTER_IFD_OFFS, 0, len);
  1100. }
  1101. len += exif_ifd_size(ifd);
  1102. }
  1103. len += 4; /* DWORD(0) after last ifd */
  1104. if ((exif_find_tag(app, IFD1, IFD1_TAG_JPEG_OFFS))) {
  1105. exif_put_long(IFD1, IFD1_TAG_JPEG_OFFS, 0, len);
  1106. }
  1107. QUEUE_FOR_EACH(&app->ifds, e1, t1) {
  1108. exif_ifd_t* ifd = (exif_ifd_t*)e1;
  1109. sortqueue(&ifd->tags, exif_sort_tags_cb);
  1110. }
  1111. ftmp = gbfopen_be(NULL, "wb", MYNAME);
  1112. ftmp->big_endian = app->fcache->big_endian;
  1113. gbfwrite((ftmp->big_endian) ? "MM" : "II", 2, 1, ftmp);
  1114. gbfputuint16(0x2A, ftmp);
  1115. gbfputuint32(0x08, ftmp); /* offset to first IFD */
  1116. QUEUE_FOR_EACH(&app->ifds, e1, t1) {
  1117. exif_ifd_t* ifd = (exif_ifd_t*)e1;
  1118. exif_ifd_t* ifd_next = (exif_ifd_t*)t1;
  1119. char next;
  1120. if ((ifd->nr == IFD0) && (ifd_next->nr == IFD1)) {
  1121. next = 1;
  1122. } else {
  1123. next = 0;
  1124. }
  1125. exif_write_ifd(ifd, next, ftmp);
  1126. len = gbftell(ftmp);
  1127. }
  1128. gbfputuint32(0, ftmp); /* DWORD(0) after last ifd */
  1129. if ((tag = exif_find_tag(app, IFD1, IFD1_TAG_JPEG_OFFS))) {
  1130. gbsize_t offs = tag->origin;
  1131. if ((tag = exif_find_tag(app, IFD1, IFD1_TAG_JPEG_SIZE))) {
  1132. gbfseek(app->fexif, offs, SEEK_SET);
  1133. gbfcopyfrom(ftmp, app->fexif, tag->value);
  1134. }
  1135. }
  1136. len = gbftell(ftmp);
  1137. gbfrewind(ftmp);
  1138. gbfputuint16(len + 8, fout);
  1139. gbfwrite("Exif\0\0", 6, 1, fout);
  1140. gbfcopyfrom(fout, ftmp, len);
  1141. gbfclose(ftmp);
  1142. } else {
  1143. gbfputuint16(app->len, fout);
  1144. gbfrewind(app->fcache);
  1145. gbfcopyfrom(fout, app->fcache, 0x7FFFFFFF);
  1146. }
  1147. }
  1148. }
  1149. /*******************************************************************************
  1150. * %%% global callbacks called by gpsbabel main process %%% *
  1151. *******************************************************************************/
  1152. static void
  1153. exif_rd_init(const QString& fname)
  1154. {
  1155. fin = gbfopen_be(fname, "rb", MYNAME);
  1156. QUEUE_INIT(&exif_apps);
  1157. }
  1158. static void
  1159. exif_rd_deinit(void)
  1160. {
  1161. exif_release_apps();
  1162. gbfclose(fin);
  1163. }
  1164. static void
  1165. exif_read(void)
  1166. {
  1167. uint16_t soi;
  1168. Waypoint* wpt;
  1169. soi = gbfgetuint16(fin);
  1170. is_fatal(soi != 0xFFD8, MYNAME ": Unknown image file."); /* only jpeg for now */
  1171. exif_app = exif_load_apps();
  1172. is_fatal(exif_app == NULL, MYNAME ": No EXIF header in source file \"%s\".", fin->name);
  1173. exif_examine_app(exif_app);
  1174. wpt = exif_waypt_from_exif_app(exif_app);
  1175. if (wpt) {
  1176. waypt_add(wpt);
  1177. }
  1178. }
  1179. static void
  1180. exif_wr_init(const QString& fname)
  1181. {
  1182. uint16_t soi;
  1183. exif_success = 0;
  1184. exif_fout_name = fname;
  1185. QUEUE_INIT(&exif_apps);
  1186. fin = gbfopen_be(fname, "rb", MYNAME);
  1187. is_fatal(fin->is_pipe, MYNAME ": Sorry, this format cannot be used with pipes!");
  1188. soi = gbfgetuint16(fin);
  1189. is_fatal(soi != 0xFFD8, MYNAME ": Unknown image file.");
  1190. exif_app = exif_load_apps();
  1191. is_fatal(exif_app == NULL, MYNAME ": No EXIF header found in source file \"%s\".", fin->name);
  1192. exif_examine_app(exif_app);
  1193. gbfclose(fin);
  1194. exif_time_ref = exif_get_exif_time(exif_app);
  1195. if (exif_time_ref == 0) {
  1196. fatal(MYNAME ": No valid timestamp found in picture!\n");
  1197. }
  1198. QString filename(fname);
  1199. filename += ".jpg";
  1200. fout = gbfopen_be(filename, "wb", MYNAME);
  1201. }
  1202. static void
  1203. exif_wr_deinit(void)
  1204. {
  1205. exif_release_apps();
  1206. QString tmpname = QString::fromLocal8Bit(fout->name);
  1207. gbfclose(fout);
  1208. if (exif_success) {
  1209. if (*opt_overwrite == '1') {
  1210. QFile::remove(exif_fout_name);
  1211. QFile::rename(tmpname, exif_fout_name);
  1212. }
  1213. } else {
  1214. QFile::remove(tmpname);
  1215. }
  1216. exif_fout_name.clear();
  1217. }
  1218. static void
  1219. exif_write(void)
  1220. {
  1221. time_t frame;
  1222. exif_wpt_ref = NULL;
  1223. if (opt_name) {
  1224. waypt_disp_all(exif_find_wpt_by_name);
  1225. if (exif_wpt_ref == NULL) {
  1226. route_disp_all(NULL, NULL, exif_find_wpt_by_name);
  1227. }
  1228. if (exif_wpt_ref == NULL) {
  1229. track_disp_all(NULL, NULL, exif_find_wpt_by_name);
  1230. }
  1231. if (exif_wpt_ref == NULL) {
  1232. warning(MYNAME ": No matching point with name \"%s\" found.\n", opt_name);
  1233. }
  1234. } else {
  1235. QString str = exif_time_str(exif_time_ref);
  1236. track_disp_all(NULL, NULL, exif_find_wpt_by_time);
  1237. route_disp_all(NULL, NULL, exif_find_wpt_by_time);
  1238. waypt_disp_all(exif_find_wpt_by_time);
  1239. frame = atoi(opt_frame);
  1240. if (exif_wpt_ref == NULL) {
  1241. warning(MYNAME ": No point with a valid timestamp found.\n");
  1242. } else if (labs(exif_time_ref - exif_wpt_ref->creation_time.toTime_t()) > frame) {
  1243. warning(MYNAME ": No matching point found for image date %s!\n", qPrintable(str));
  1244. if (exif_wpt_ref != NULL) {
  1245. QString str = exif_time_str(exif_wpt_ref->creation_time.toTime_t());
  1246. warning(MYNAME ": Best is from %s, %ld second(s) away.\n",
  1247. qPrintable(str), labs(exif_time_ref - exif_wpt_ref->creation_time.toTime_t()));
  1248. }
  1249. exif_wpt_ref = NULL;
  1250. }
  1251. }
  1252. if (exif_wpt_ref != NULL) {
  1253. const Waypoint* wpt = exif_wpt_ref;
  1254. exif_put_long(IFD0, IFD0_TAG_GPS_IFD_OFFS, 0, 0);
  1255. exif_put_value(GPS_IFD, GPS_IFD_TAG_VERSION, EXIF_TYPE_BYTE, 4, 0, writer_gps_tag_version);
  1256. exif_put_str(GPS_IFD, GPS_IFD_TAG_DATUM, "WGS-84");
  1257. exif_put_str(GPS_IFD, GPS_IFD_TAG_LATREF, wpt->latitude < 0 ? "S" : "N");
  1258. exif_put_coord(GPS_IFD, GPS_IFD_TAG_LAT, fabs(wpt->latitude));
  1259. exif_put_str(GPS_IFD, GPS_IFD_TAG_LONREF, wpt->longitude < 0 ? "W" : "E");
  1260. exif_put_coord(GPS_IFD, GPS_IFD_TAG_LON, fabs(wpt->longitude));
  1261. if (wpt->altitude == unknown_alt) {
  1262. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_ALT);
  1263. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_ALTREF);
  1264. } else {
  1265. uint8_t alt_ref;
  1266. if (wpt->altitude >= 0.0) {
  1267. alt_ref = 0;
  1268. } else {
  1269. alt_ref = 1;
  1270. }
  1271. exif_put_value(GPS_IFD, GPS_IFD_TAG_ALTREF, EXIF_TYPE_BYTE, 1, 0, &alt_ref);
  1272. exif_put_double(GPS_IFD, GPS_IFD_TAG_ALT, 0, wpt->altitude);
  1273. }
  1274. if (wpt->creation_time.isValid()) {
  1275. struct tm tm;
  1276. char buf[32];
  1277. const time_t tt = wpt->GetCreationTime().toTime_t();
  1278. tm = *gmtime(&tt);
  1279. tm.tm_year += 1900;
  1280. tm.tm_mon += 1;
  1281. exif_put_double(GPS_IFD, GPS_IFD_TAG_TIMESTAMP, 0, tm.tm_hour);
  1282. exif_put_double(GPS_IFD, GPS_IFD_TAG_TIMESTAMP, 1, tm.tm_min);
  1283. exif_put_double(GPS_IFD, GPS_IFD_TAG_TIMESTAMP, 2, tm.tm_sec);
  1284. snprintf(buf, sizeof(buf), "%04d:%02d:%02d", tm.tm_year, tm.tm_mon, tm.tm_mday);
  1285. exif_put_str(GPS_IFD, GPS_IFD_TAG_DATESTAMP, buf);
  1286. } else {
  1287. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_TIMESTAMP);
  1288. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_DATESTAMP);
  1289. }
  1290. if (wpt->sat > 0) {
  1291. char buf[16];
  1292. snprintf(buf, sizeof(buf), "%d", wpt->sat);
  1293. exif_put_str(GPS_IFD, GPS_IFD_TAG_SAT, buf);
  1294. } else {
  1295. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_SAT);
  1296. }
  1297. if (wpt->fix == fix_2d) {
  1298. exif_put_str(GPS_IFD, GPS_IFD_TAG_MODE, "2");
  1299. } else if (wpt->fix == fix_3d) {
  1300. exif_put_str(GPS_IFD, GPS_IFD_TAG_MODE, "3");
  1301. } else {
  1302. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_MODE);
  1303. }
  1304. if (wpt->hdop > 0) {
  1305. exif_put_double(GPS_IFD, GPS_IFD_TAG_DOP, 0, wpt->hdop);
  1306. } else {
  1307. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_DOP);
  1308. }
  1309. if WAYPT_HAS(wpt, speed) {
  1310. exif_put_str(GPS_IFD, GPS_IFD_TAG_SPEEDREF, "K");
  1311. exif_put_double(GPS_IFD, GPS_IFD_TAG_SPEED, 0, MPS_TO_KPH(wpt->speed));
  1312. } else {
  1313. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_SPEEDREF);
  1314. exif_remove_tag(GPS_IFD, GPS_IFD_TAG_SPEED);
  1315. }
  1316. exif_write_apps(); /* Success, write the new file */
  1317. exif_success = 1;
  1318. }
  1319. }
  1320. /**************************************************************************/
  1321. ff_vecs_t exif_vecs = {
  1322. ff_type_file,
  1323. {
  1324. (ff_cap)(ff_cap_read | ff_cap_write) /* waypoints */,
  1325. ff_cap_none /* tracks */,
  1326. ff_cap_none /* routes */
  1327. },
  1328. exif_rd_init,
  1329. exif_wr_init,
  1330. exif_rd_deinit,
  1331. exif_wr_deinit,
  1332. exif_read,
  1333. exif_write,
  1334. NULL,
  1335. exif_args,
  1336. CET_CHARSET_UTF8, 0
  1337. };
  1338. /**************************************************************************/