~ubuntu-branches/ubuntu/precise/spatialite/precise

« back to all changes in this revision

Viewing changes to spatialite-tools/exif_loader.c

  • Committer: Package Import Robot
  • Author(s): David Paleino, Francesco Paolo Lovergine, David Paleino
  • Date: 2011-11-21 12:10:43 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20111121121043-0g14o2uf0r343a82
Tags: 3.0.0~beta20110817-3
[ Francesco Paolo Lovergine ]
* Fixed linking order for sqlite3 in debian patch 00-systemlibs.patch.
  (closes: #638929)

[ David Paleino ]
* Conditionally disable full EPSG initialization (for srs_init.c)
  on powerpc, and document what projections are available on that
  architecture (Closes: #649302)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
/ exif_loader
 
3
/
 
4
/ a tool for uploading JPEG/EXIF photos into a DB 
 
5
/ preserving full Exif metadata and building Geometry from GPS tags [if present]
 
6
/
 
7
/ version 1.0, 2008 October 13
 
8
/
 
9
/ Author: Sandro Furieri a.furieri@lqt.it
 
10
/
 
11
/ Copyright (C) 2008  Alessandro Furieri
 
12
/
 
13
/    This program is free software: you can redistribute it and/or modify
 
14
/    it under the terms of the GNU General Public License as published by
 
15
/    the Free Software Foundation, either version 3 of the License, or
 
16
/    (at your option) any later version.
 
17
/
 
18
/    This program is distributed in the hope that it will be useful,
 
19
/    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
/    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
/    GNU General Public License for more details.
 
22
/
 
23
/    You should have received a copy of the GNU General Public License
 
24
/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
25
/
 
26
*/
 
27
 
 
28
#include <stdlib.h>
 
29
#include <stdio.h>
 
30
#include <string.h>
 
31
#include <math.h>
 
32
#include <float.h>
 
33
#include <errno.h>
 
34
#include <sys/types.h>
 
35
 
 
36
#if defined(_WIN32) && !defined(__MINGW32__)
 
37
#include <io.h>
 
38
#include <direct.h>
 
39
#else
 
40
#include <dirent.h>
 
41
#endif
 
42
 
 
43
#ifdef SPATIALITE_AMALGAMATION
 
44
#include <spatialite/sqlite3.h>
 
45
#else
 
46
#include <sqlite3.h>
 
47
#endif
 
48
 
 
49
#include <spatialite/gaiaexif.h>
 
50
#include <spatialite/gaiageo.h>
 
51
#include <spatialite.h>
 
52
 
 
53
#define ARG_NONE                        0
 
54
#define ARG_DB_PATH                     1
 
55
#define ARG_DIR                         2
 
56
#define ARG_FILE                        3
 
57
 
 
58
#if defined(_WIN32) && !defined(__MINGW32__)
 
59
#define strcasecmp      _stricmp
 
60
#endif /* not WIN32 */
 
61
 
 
62
static sqlite3_int64
 
63
getPixelX (gaiaExifTagListPtr tag_list, int *ok)
 
64
{
 
65
/* trying to retrieve the ExifImageWidth */
 
66
    gaiaExifTagPtr tag;
 
67
    *ok = 0;
 
68
    if (!tag_list)
 
69
        return 0;
 
70
    tag = tag_list->First;
 
71
    while (tag)
 
72
      {
 
73
          if (tag->TagId == 0xA002)
 
74
            {
 
75
                /* ok, this one is the ExifImageWidth tag */
 
76
                if (tag->Type == 3 && tag->Count == 1)
 
77
                  {
 
78
                      *ok = 1;
 
79
                      return *(tag->ShortValues + 0);
 
80
                  }
 
81
                else if (tag->Type == 4 && tag->Count == 1)
 
82
                  {
 
83
                      *ok = 1;
 
84
                      return *(tag->LongValues + 0);
 
85
                  }
 
86
            }
 
87
          tag = tag->Next;
 
88
      }
 
89
    return 0;
 
90
}
 
91
 
 
92
static sqlite3_int64
 
93
getPixelY (gaiaExifTagListPtr tag_list, int *ok)
 
94
{
 
95
/* trying to retrieve the ExifImageLength */
 
96
    gaiaExifTagPtr tag;
 
97
    *ok = 0;
 
98
    if (!tag_list)
 
99
        return 0;
 
100
    tag = tag_list->First;
 
101
    while (tag)
 
102
      {
 
103
          if (tag->TagId == 0xA003)
 
104
            {
 
105
                /* ok, this one is the ExifImageLength tag */
 
106
                if (tag->Type == 3 && tag->Count == 1)
 
107
                  {
 
108
                      *ok = 1;
 
109
                      return *(tag->ShortValues + 0);
 
110
                  }
 
111
                else if (tag->Type == 4 && tag->Count == 1)
 
112
                  {
 
113
                      *ok = 1;
 
114
                      return *(tag->LongValues + 0);
 
115
                  }
 
116
            }
 
117
          tag = tag->Next;
 
118
      }
 
119
    return 0;
 
120
}
 
121
 
 
122
static void
 
123
getMake (gaiaExifTagListPtr tag_list, char *str, int len, int *ok)
 
124
{
 
125
/* trying to retrieve the Make */
 
126
    gaiaExifTagPtr tag;
 
127
    int l;
 
128
    *ok = 0;
 
129
    if (!tag_list)
 
130
        return;
 
131
    tag = tag_list->First;
 
132
    while (tag)
 
133
      {
 
134
          if (tag->TagId == 0x010F)
 
135
            {
 
136
                /* ok, this one is the Make tag */
 
137
                if (tag->Type == 2)
 
138
                  {
 
139
                      *ok = 1;
 
140
                      l = strlen (tag->StringValue);
 
141
                      if (len > l)
 
142
                          strcpy (str, tag->StringValue);
 
143
                      else
 
144
                        {
 
145
                            memset (str, '\0', len);
 
146
                            memcpy (str, tag->StringValue, len - 1);
 
147
                        }
 
148
                      return;
 
149
                  }
 
150
            }
 
151
          tag = tag->Next;
 
152
      }
 
153
    return;
 
154
}
 
155
 
 
156
static void
 
157
getModel (gaiaExifTagListPtr tag_list, char *str, int len, int *ok)
 
158
{
 
159
/* trying to retrieve the Model */
 
160
    gaiaExifTagPtr tag;
 
161
    int l;
 
162
    *ok = 0;
 
163
    if (!tag_list)
 
164
        return;
 
165
    tag = tag_list->First;
 
166
    while (tag)
 
167
      {
 
168
          if (tag->TagId == 0x0110)
 
169
            {
 
170
                /* ok, this one is the Model tag */
 
171
                if (tag->Type == 2)
 
172
                  {
 
173
                      *ok = 1;
 
174
                      l = strlen (tag->StringValue);
 
175
                      if (len > l)
 
176
                          strcpy (str, tag->StringValue);
 
177
                      else
 
178
                        {
 
179
                            memset (str, '\0', len);
 
180
                            memcpy (str, tag->StringValue, len - 1);
 
181
                        }
 
182
                      return;
 
183
                  }
 
184
            }
 
185
          tag = tag->Next;
 
186
      }
 
187
    return;
 
188
}
 
189
 
 
190
static void
 
191
getDate (gaiaExifTagListPtr tag_list, char *str, int len, int *ok)
 
192
{
 
193
/* trying to retrieve the Date */
 
194
    gaiaExifTagPtr tag;
 
195
    int l;
 
196
    *ok = 0;
 
197
    if (!tag_list)
 
198
        return;
 
199
    tag = tag_list->First;
 
200
    while (tag)
 
201
      {
 
202
          if (tag->TagId == 0x9003)
 
203
            {
 
204
                /* ok, this one is the DateTimeOriginal tag */
 
205
                if (tag->Type == 2)
 
206
                  {
 
207
                      *ok = 1;
 
208
                      l = strlen (tag->StringValue);
 
209
                      if (len > l)
 
210
                          strcpy (str, tag->StringValue);
 
211
                      else
 
212
                        {
 
213
                            memset (str, '\0', len);
 
214
                            memcpy (str, tag->StringValue, len - 1);
 
215
                        }
 
216
                      if (len > 19)
 
217
                        {
 
218
                            str[4] = '-';
 
219
                            str[7] = '-';
 
220
                        }
 
221
                      return;
 
222
                  }
 
223
            }
 
224
          tag = tag->Next;
 
225
      }
 
226
    return;
 
227
}
 
228
 
 
229
static void
 
230
getGpsCoords (gaiaExifTagListPtr tag_list, double *longitude, double *latitude,
 
231
              int *ok)
 
232
{
 
233
/* trying to retrieve the GPS coordinates */
 
234
    gaiaExifTagPtr tag;
 
235
    char lat_ref = '\0';
 
236
    char long_ref = '\0';
 
237
    double lat_degs = -DBL_MAX;
 
238
    double lat_mins = -DBL_MAX;
 
239
    double lat_secs = -DBL_MAX;
 
240
    double long_degs = -DBL_MAX;
 
241
    double long_mins = -DBL_MAX;
 
242
    double long_secs = -DBL_MAX;
 
243
    double dblval;
 
244
    double sign;
 
245
    int xok;
 
246
    *ok = 0;
 
247
    if (!tag_list)
 
248
        return;
 
249
    tag = tag_list->First;
 
250
    while (tag)
 
251
      {
 
252
          if (tag->Gps && tag->TagId == 0x01)
 
253
            {
 
254
                /* ok, this one is the GPSLatitudeRef tag */
 
255
                if (tag->Type == 2)
 
256
                    lat_ref = *(tag->StringValue);
 
257
            }
 
258
          if (tag->Gps && tag->TagId == 0x03)
 
259
            {
 
260
                /* ok, this one is the GPSLongitudeRef tag */
 
261
                if (tag->Type == 2)
 
262
                    long_ref = *(tag->StringValue);
 
263
            }
 
264
          if (tag->Gps && tag->TagId == 0x02)
 
265
            {
 
266
                /* ok, this one is the GPSLatitude tag */
 
267
                if (tag->Type == 5 && tag->Count == 3)
 
268
                  {
 
269
                      dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
 
270
                      if (xok)
 
271
                          lat_degs = dblval;
 
272
                      dblval = gaiaExifTagGetRationalValue (tag, 1, &xok);
 
273
                      if (xok)
 
274
                          lat_mins = dblval;
 
275
                      dblval = gaiaExifTagGetRationalValue (tag, 2, &xok);
 
276
                      if (xok)
 
277
                          lat_secs = dblval;
 
278
                  }
 
279
            }
 
280
          if (tag->Gps && tag->TagId == 0x04)
 
281
            {
 
282
                /* ok, this one is the GPSLongitude tag */
 
283
                if (tag->Type == 5 && tag->Count == 3)
 
284
                  {
 
285
                      dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
 
286
                      if (xok)
 
287
                          long_degs = dblval;
 
288
                      dblval = gaiaExifTagGetRationalValue (tag, 1, &xok);
 
289
                      if (xok)
 
290
                          long_mins = dblval;
 
291
                      dblval = gaiaExifTagGetRationalValue (tag, 2, &xok);
 
292
                      if (xok)
 
293
                          long_secs = dblval;
 
294
                  }
 
295
            }
 
296
          tag = tag->Next;
 
297
      }
 
298
    if ((lat_ref == 'N' || lat_ref == 'S' || long_ref == 'E' || long_ref == 'W')
 
299
        && lat_degs != -DBL_MAX && lat_mins != -DBL_MAX && lat_secs != -DBL_MAX
 
300
        && long_degs != -DBL_MAX && long_mins != -DBL_MAX
 
301
        && long_secs != -DBL_MAX)
 
302
      {
 
303
          *ok = 1;
 
304
          if (lat_ref == 'S')
 
305
              sign = -1.0;
 
306
          else
 
307
              sign = 1.0;
 
308
          lat_degs = math_round (lat_degs * 1000000.0);
 
309
          lat_mins = math_round (lat_mins * 1000000.0);
 
310
          lat_secs = math_round (lat_secs * 1000000.0);
 
311
          dblval =
 
312
              math_round (lat_degs + (lat_mins / 60.0) +
 
313
                          (lat_secs / 3600.0)) * (sign / 1000000.0);
 
314
          *latitude = dblval;
 
315
          if (long_ref == 'W')
 
316
              sign = -1.0;
 
317
          else
 
318
              sign = 1.0;
 
319
          long_degs = math_round (long_degs * 1000000.0);
 
320
          long_mins = math_round (long_mins * 1000000.0);
 
321
          long_secs = math_round (long_secs * 1000000.0);
 
322
          dblval =
 
323
              math_round (long_degs + (long_mins / 60.0) +
 
324
                          (long_secs / 3600.0)) * (sign / 1000000.0);
 
325
          *longitude = dblval;
 
326
      }
 
327
    return;
 
328
}
 
329
 
 
330
static void
 
331
getGpsSatellites (gaiaExifTagListPtr tag_list, char *str, int len, int *ok)
 
332
{
 
333
/* trying to retrieve the GPSSatellites */
 
334
    gaiaExifTagPtr tag;
 
335
    int l;
 
336
    *ok = 0;
 
337
    if (!tag_list)
 
338
        return;
 
339
    tag = tag_list->First;
 
340
    while (tag)
 
341
      {
 
342
          if (tag->Gps && tag->TagId == 0x08)
 
343
            {
 
344
                /* ok, this one is the GPSSatellites tag */
 
345
                if (tag->Type == 2)
 
346
                  {
 
347
                      *ok = 1;
 
348
                      l = strlen (tag->StringValue);
 
349
                      if (len > l)
 
350
                          strcpy (str, tag->StringValue);
 
351
                      else
 
352
                        {
 
353
                            memset (str, '\0', len);
 
354
                            memcpy (str, tag->StringValue, len - 1);
 
355
                        }
 
356
                      return;
 
357
                  }
 
358
            }
 
359
          tag = tag->Next;
 
360
      }
 
361
    return;
 
362
}
 
363
 
 
364
static double
 
365
getGpsDirection (gaiaExifTagListPtr tag_list, int *ok)
 
366
{
 
367
/* trying to retrieve the GPS direction */
 
368
    gaiaExifTagPtr tag;
 
369
    char dir_ref = '\0';
 
370
    double direction = -DBL_MAX;
 
371
    double dblval;
 
372
    int xok;
 
373
    *ok = 0;
 
374
    if (!tag_list)
 
375
        return direction;
 
376
    tag = tag_list->First;
 
377
    while (tag)
 
378
      {
 
379
          if (tag->Gps && tag->TagId == 0x10)
 
380
            {
 
381
                /* ok, this one is the GPSDirectionRef tag */
 
382
                if (tag->Type == 2)
 
383
                    dir_ref = *(tag->StringValue);
 
384
            }
 
385
          if (tag->Gps && tag->TagId == 0x11)
 
386
            {
 
387
                /* ok, this one is the GPSDirection tag */
 
388
                if (tag->Type == 5 && tag->Count == 1)
 
389
                  {
 
390
                      dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
 
391
                      if (xok)
 
392
                          direction = dblval;
 
393
                  }
 
394
            }
 
395
          tag = tag->Next;
 
396
      }
 
397
    if ((dir_ref == 'T' || dir_ref == 'M') && direction != -DBL_MAX)
 
398
        *ok = 1;
 
399
    return direction;
 
400
}
 
401
 
 
402
static void
 
403
getGpsTimestamp (gaiaExifTagListPtr tag_list, char *str, int len, int *ok)
 
404
{
 
405
/* trying to retrieve the GPS Timestamp */
 
406
    gaiaExifTagPtr tag;
 
407
    char date[16];
 
408
    char timestamp[32];
 
409
    double hours = -DBL_MAX;
 
410
    double mins = -DBL_MAX;
 
411
    double secs = -DBL_MAX;
 
412
    double dblval;
 
413
    int xok;
 
414
    int hh;
 
415
    int mm;
 
416
    int ss;
 
417
    int millis;
 
418
    int l;
 
419
    *ok = 0;
 
420
    if (!tag_list)
 
421
        return;
 
422
    strcpy (date, "0000-00-00");
 
423
    tag = tag_list->First;
 
424
    while (tag)
 
425
      {
 
426
          if (tag->Gps && tag->TagId == 0x1D)
 
427
            {
 
428
                /* ok, this one is the GPSDateStamp tag */
 
429
                if (tag->Type == 2)
 
430
                  {
 
431
                      strcpy (date, tag->StringValue);
 
432
                      date[4] = '-';
 
433
                      date[7] = '-';
 
434
                  }
 
435
            }
 
436
          if (tag->Gps && tag->TagId == 0x07)
 
437
            {
 
438
                /* ok, this one is the GPSTimeStamp tag */
 
439
                if (tag->Type == 5 && tag->Count == 3)
 
440
                  {
 
441
                      dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
 
442
                      if (xok)
 
443
                          hours = dblval;
 
444
                      dblval = gaiaExifTagGetRationalValue (tag, 1, &xok);
 
445
                      if (xok)
 
446
                          mins = dblval;
 
447
                      dblval = gaiaExifTagGetRationalValue (tag, 2, &xok);
 
448
                      if (xok)
 
449
                          secs = dblval;
 
450
                  }
 
451
            }
 
452
          tag = tag->Next;
 
453
      }
 
454
    if (hours != -DBL_MAX && mins != -DBL_MAX && secs != -DBL_MAX)
 
455
      {
 
456
          *ok = 1;
 
457
          hh = (int) floor (hours);
 
458
          mm = (int) floor (mins);
 
459
          ss = (int) floor (secs);
 
460
          millis = (int) ((secs - ss) * 1000);
 
461
          sprintf (timestamp, "%s %02d:%02d:%02d.%03d", date, hh, mm, ss,
 
462
                   millis);
 
463
          l = strlen (timestamp);
 
464
          if (len > l)
 
465
              strcpy (str, timestamp);
 
466
          else
 
467
            {
 
468
                memset (str, '\0', len);
 
469
                memcpy (str, timestamp, len - 1);
 
470
            }
 
471
      }
 
472
    return;
 
473
}
 
474
 
 
475
static int
 
476
isExifGps (gaiaExifTagListPtr tag_list)
 
477
{
 
478
/* checks if this one is a GPS-tagged EXIF */
 
479
    int gps_lat = 0;
 
480
    int gps_long = 0;
 
481
    gaiaExifTagPtr pT = tag_list->First;
 
482
    while (pT)
 
483
      {
 
484
          if (pT->Gps && pT->TagId == 0x04)
 
485
              gps_long = 1;
 
486
          if (pT->Gps && pT->TagId == 0x02)
 
487
              gps_lat = 1;
 
488
          if (gps_long && gps_lat)
 
489
              return 1;
 
490
          pT = pT->Next;
 
491
      }
 
492
    return 0;
 
493
}
 
494
 
 
495
static int
 
496
updateExifTables (sqlite3 * handle, const unsigned char *blob, int sz,
 
497
                  gaiaExifTagListPtr tag_list, int metadata, const char *path)
 
498
{
 
499
/* inserting an EXIF photo into the DB */
 
500
    int i;
 
501
    int iv;
 
502
    int ok;
 
503
    int ok_human;
 
504
    char tag_name[128];
 
505
    gaiaExifTagPtr pT;
 
506
    int ret;
 
507
    char sql[1024];
 
508
    char human[1024];
 
509
    char make[1024];
 
510
    char model[1024];
 
511
    char satellites[1024];
 
512
    char date[32];
 
513
    char timestamp[32];
 
514
    char *err_msg = NULL;
 
515
    sqlite3_stmt *stmt;
 
516
    sqlite3_int64 pk = 0;
 
517
    sqlite3_int64 val64;
 
518
    double dblval;
 
519
    char *type_desc;
 
520
    double longitude;
 
521
    double latitude;
 
522
    gaiaGeomCollPtr geom;
 
523
    unsigned char *geoblob;
 
524
    int geosize;
 
525
/* starts a transaction */
 
526
    strcpy (sql, "BEGIN");
 
527
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
528
    if (ret != SQLITE_OK)
 
529
      {
 
530
          printf ("BEGIN error: %s\n", err_msg);
 
531
          sqlite3_free (err_msg);
 
532
          goto abort;
 
533
      }
 
534
/* feeding the ExifPhoto table; preparing the SQL statement*/
 
535
    strcpy (sql,
 
536
            "INSERT INTO ExifPhoto (PhotoId, Photo, PixelX, PixelY, CameraMake, CameraModel, ");
 
537
    strcat (sql,
 
538
            "ShotDateTime, GpsGeometry, GpsDirection, GpsSatellites, GpsTimestamp, FromPath) ");
 
539
    strcat (sql,
 
540
            "VALUES (NULL, ?, ?, ?, ?, ?, JulianDay(?), ?, ?, ?, JulianDay(?), ?)");
 
541
    ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
 
542
    if (ret != SQLITE_OK)
 
543
      {
 
544
          printf ("INSERT INTO ExifPhoto error: %s\n", sqlite3_errmsg (handle));
 
545
          goto abort;
 
546
      }
 
547
    sqlite3_bind_blob (stmt, 1, blob, sz, SQLITE_STATIC);
 
548
    val64 = getPixelX (tag_list, &ok);
 
549
    if (ok)
 
550
        sqlite3_bind_int64 (stmt, 2, val64);
 
551
    else
 
552
        sqlite3_bind_null (stmt, 2);
 
553
    val64 = getPixelY (tag_list, &ok);
 
554
    if (ok)
 
555
        sqlite3_bind_int64 (stmt, 3, val64);
 
556
    else
 
557
        sqlite3_bind_null (stmt, 3);
 
558
    getMake (tag_list, make, 1024, &ok);
 
559
    if (ok)
 
560
        sqlite3_bind_text (stmt, 4, make, strlen (make), SQLITE_STATIC);
 
561
    else
 
562
        sqlite3_bind_null (stmt, 4);
 
563
    getModel (tag_list, model, 1024, &ok);
 
564
    if (ok)
 
565
        sqlite3_bind_text (stmt, 5, model, strlen (model), SQLITE_STATIC);
 
566
    else
 
567
        sqlite3_bind_null (stmt, 5);
 
568
    getDate (tag_list, date, 32, &ok);
 
569
    if (ok)
 
570
        sqlite3_bind_text (stmt, 6, date, strlen (date), SQLITE_STATIC);
 
571
    else
 
572
        sqlite3_bind_text (stmt, 6, "0000-00-00 00:00:00", 19, SQLITE_STATIC);
 
573
    getGpsCoords (tag_list, &longitude, &latitude, &ok);
 
574
    if (ok)
 
575
      {
 
576
          geom = gaiaAllocGeomColl ();
 
577
          geom->Srid = 4326;
 
578
          gaiaAddPointToGeomColl (geom, longitude, latitude);
 
579
          gaiaToSpatiaLiteBlobWkb (geom, &geoblob, &geosize);
 
580
          gaiaFreeGeomColl (geom);
 
581
          sqlite3_bind_blob (stmt, 7, geoblob, geosize, SQLITE_TRANSIENT);
 
582
          free (geoblob);
 
583
      }
 
584
    else
 
585
        sqlite3_bind_null (stmt, 7);
 
586
    dblval = getGpsDirection (tag_list, &ok);
 
587
    if (ok)
 
588
        sqlite3_bind_double (stmt, 8, dblval);
 
589
    else
 
590
        sqlite3_bind_null (stmt, 8);
 
591
    getGpsSatellites (tag_list, satellites, 1024, &ok);
 
592
    if (ok)
 
593
        sqlite3_bind_text (stmt, 9, satellites, strlen (satellites),
 
594
                           SQLITE_STATIC);
 
595
    else
 
596
        sqlite3_bind_null (stmt, 9);
 
597
    getGpsTimestamp (tag_list, timestamp, 32, &ok);
 
598
    if (ok)
 
599
        sqlite3_bind_text (stmt, 10, timestamp, strlen (timestamp),
 
600
                           SQLITE_STATIC);
 
601
    else
 
602
        sqlite3_bind_text (stmt, 10, "0000-00-00 00:00:00", 19, SQLITE_STATIC);
 
603
    sqlite3_bind_text (stmt, 11, path, strlen (path), SQLITE_STATIC);
 
604
    ret = sqlite3_step (stmt);
 
605
    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 
606
        ;
 
607
    else
 
608
      {
 
609
          printf ("sqlite3_step() error: %s\n", sqlite3_errmsg (handle));
 
610
          sqlite3_finalize (stmt);
 
611
          goto abort;
 
612
      }
 
613
    sqlite3_finalize (stmt);
 
614
    pk = sqlite3_last_insert_rowid (handle);
 
615
    if (metadata)
 
616
      {
 
617
          /* feeding the ExifTags table; preparing the SQL statement */
 
618
          strcpy (sql,
 
619
                  "INSERT OR IGNORE INTO ExifTags (PhotoId, TagId, TagName, GpsTag, ValueType, ");
 
620
          strcat (sql, "TypeName, CountValues) VALUES (?, ?, ?, ?, ?, ?, ?)");
 
621
          ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
 
622
          if (ret != SQLITE_OK)
 
623
            {
 
624
                printf ("INSERT INTO ExifTags error: %s\n",
 
625
                        sqlite3_errmsg (handle));
 
626
                goto abort;
 
627
            }
 
628
          for (i = 0; i < gaiaGetExifTagsCount (tag_list); i++)
 
629
            {
 
630
                pT = gaiaGetExifTagByPos (tag_list, i);
 
631
                if (pT)
 
632
                  {
 
633
                      gaiaExifTagGetName (pT, tag_name, 128);
 
634
                      switch (gaiaExifTagGetValueType (pT))
 
635
                        {
 
636
                        case 1:
 
637
                            type_desc = "BYTE";
 
638
                            break;
 
639
                        case 2:
 
640
                            type_desc = "STRING";
 
641
                            break;
 
642
                        case 3:
 
643
                            type_desc = "SHORT";
 
644
                            break;
 
645
                        case 4:
 
646
                            type_desc = "LONG";
 
647
                            break;
 
648
                        case 5:
 
649
                            type_desc = "RATIONAL";
 
650
                            break;
 
651
                        case 6:
 
652
                            type_desc = "SBYTE";
 
653
                            break;
 
654
                        case 7:
 
655
                            type_desc = "UNDEFINED";
 
656
                            break;
 
657
                        case 8:
 
658
                            type_desc = "SSHORT";
 
659
                            break;
 
660
                        case 9:
 
661
                            type_desc = "SLONG";
 
662
                            break;
 
663
                        case 10:
 
664
                            type_desc = "SRATIONAL";
 
665
                            break;
 
666
                        case 11:
 
667
                            type_desc = "FLOAT";
 
668
                            break;
 
669
                        case 12:
 
670
                            type_desc = "DOUBLE";
 
671
                            break;
 
672
                        default:
 
673
                            type_desc = "UNKNOWN";
 
674
                            break;
 
675
                        };
 
676
                      /* INSERTing an Exif Tag */
 
677
                      sqlite3_reset (stmt);
 
678
                      sqlite3_clear_bindings (stmt);
 
679
                      sqlite3_bind_int64 (stmt, 1, pk);
 
680
                      sqlite3_bind_int (stmt, 2, gaiaExifTagGetId (pT));
 
681
                      sqlite3_bind_text (stmt, 3, tag_name, strlen (tag_name),
 
682
                                         SQLITE_STATIC);
 
683
                      sqlite3_bind_int (stmt, 4, gaiaIsExifGpsTag (pT));
 
684
                      sqlite3_bind_int (stmt, 5, gaiaExifTagGetValueType (pT));
 
685
                      sqlite3_bind_text (stmt, 6, type_desc, strlen (type_desc),
 
686
                                         SQLITE_STATIC);
 
687
                      sqlite3_bind_int (stmt, 7, gaiaExifTagGetNumValues (pT));
 
688
                      ret = sqlite3_step (stmt);
 
689
                      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 
690
                          ;
 
691
                      else
 
692
                        {
 
693
                            printf ("sqlite3_step() error: %s\n",
 
694
                                    sqlite3_errmsg (handle));
 
695
                            sqlite3_finalize (stmt);
 
696
                            goto abort;
 
697
                        }
 
698
                  }
 
699
            }
 
700
          sqlite3_finalize (stmt);
 
701
          /* feeding the ExifValues table; preparing the SQL statement */
 
702
          strcpy (sql,
 
703
                  "INSERT OR IGNORE INTO ExifValues (PhotoId, TagId, ValueIndex, ByteValue, ");
 
704
          strcat (sql,
 
705
                  "StringValue, NumValue, NumValueBis, DoubleValue, HumanReadable) VALUES ");
 
706
          strcat (sql, "(?, ?, ?, ?, ?, ?, ?, ?, ?)");
 
707
          ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
 
708
          if (ret != SQLITE_OK)
 
709
            {
 
710
                printf ("INSERT INTO ExifValues error: %s\n",
 
711
                        sqlite3_errmsg (handle));
 
712
                goto abort;
 
713
            }
 
714
          for (i = 0; i < gaiaGetExifTagsCount (tag_list); i++)
 
715
            {
 
716
                pT = gaiaGetExifTagByPos (tag_list, i);
 
717
                if (pT)
 
718
                  {
 
719
                      gaiaExifTagGetHumanReadable (pT, human, 1024, &ok_human);
 
720
                      for (iv = 0; iv < gaiaExifTagGetNumValues (pT); iv++)
 
721
                        {
 
722
                            /* INSERTing an Exif Tag */
 
723
                            sqlite3_reset (stmt);
 
724
                            sqlite3_clear_bindings (stmt);
 
725
                            sqlite3_bind_int64 (stmt, 1, pk);
 
726
                            sqlite3_bind_int (stmt, 2, gaiaExifTagGetId (pT));
 
727
                            sqlite3_bind_int (stmt, 3, iv);
 
728
                            if (gaiaExifTagGetValueType (pT) == 1
 
729
                                || gaiaExifTagGetValueType (pT) == 6
 
730
                                || gaiaExifTagGetValueType (pT) == 7)
 
731
                              {
 
732
                                  sqlite3_bind_blob (stmt, 4, pT->ByteValue,
 
733
                                                     pT->Count, SQLITE_STATIC);
 
734
                                  sqlite3_bind_null (stmt, 5);
 
735
                                  sqlite3_bind_null (stmt, 6);
 
736
                                  sqlite3_bind_null (stmt, 7);
 
737
                                  sqlite3_bind_null (stmt, 8);
 
738
                              }
 
739
                            if (gaiaExifTagGetValueType (pT) == 2)
 
740
                              {
 
741
                                  sqlite3_bind_null (stmt, 4);
 
742
                                  sqlite3_bind_text (stmt, 5, pT->StringValue,
 
743
                                                     strlen (pT->StringValue),
 
744
                                                     SQLITE_STATIC);
 
745
                                  sqlite3_bind_null (stmt, 6);
 
746
                                  sqlite3_bind_null (stmt, 7);
 
747
                                  sqlite3_bind_null (stmt, 8);
 
748
                              }
 
749
                            if (gaiaExifTagGetValueType (pT) == 3)
 
750
                              {
 
751
                                  sqlite3_bind_null (stmt, 4);
 
752
                                  sqlite3_bind_null (stmt, 5);
 
753
                                  val64 =
 
754
                                      gaiaExifTagGetShortValue (pT, iv, &ok);
 
755
                                  if (!ok)
 
756
                                      sqlite3_bind_null (stmt, 6);
 
757
                                  else
 
758
                                      sqlite3_bind_int64 (stmt, 6, val64);
 
759
                                  sqlite3_bind_null (stmt, 7);
 
760
                                  sqlite3_bind_null (stmt, 8);
 
761
                              }
 
762
                            if (gaiaExifTagGetValueType (pT) == 4)
 
763
                              {
 
764
                                  sqlite3_bind_null (stmt, 4);
 
765
                                  sqlite3_bind_null (stmt, 5);
 
766
                                  val64 = gaiaExifTagGetLongValue (pT, iv, &ok);
 
767
                                  if (!ok)
 
768
                                      sqlite3_bind_null (stmt, 6);
 
769
                                  else
 
770
                                      sqlite3_bind_int64 (stmt, 6, val64);
 
771
                                  sqlite3_bind_null (stmt, 7);
 
772
                                  sqlite3_bind_null (stmt, 8);
 
773
                              }
 
774
                            if (gaiaExifTagGetValueType (pT) == 5)
 
775
                              {
 
776
                                  sqlite3_bind_null (stmt, 4);
 
777
                                  sqlite3_bind_null (stmt, 5);
 
778
                                  val64 =
 
779
                                      gaiaExifTagGetRational1Value (pT, iv,
 
780
                                                                    &ok);
 
781
                                  if (!ok)
 
782
                                      sqlite3_bind_null (stmt, 6);
 
783
                                  else
 
784
                                      sqlite3_bind_int64 (stmt, 6, val64);
 
785
                                  val64 =
 
786
                                      gaiaExifTagGetRational2Value (pT, iv,
 
787
                                                                    &ok);
 
788
                                  if (!ok)
 
789
                                      sqlite3_bind_null (stmt, 7);
 
790
                                  else
 
791
                                      sqlite3_bind_int64 (stmt, 7, val64);
 
792
                                  dblval =
 
793
                                      gaiaExifTagGetRationalValue (pT, iv, &ok);
 
794
                                  if (!ok)
 
795
                                      sqlite3_bind_null (stmt, 8);
 
796
                                  else
 
797
                                      sqlite3_bind_double (stmt, 8, dblval);
 
798
                              }
 
799
                            if (gaiaExifTagGetValueType (pT) == 9)
 
800
                              {
 
801
                                  sqlite3_bind_null (stmt, 4);
 
802
                                  sqlite3_bind_null (stmt, 5);
 
803
                                  val64 =
 
804
                                      gaiaExifTagGetSignedLongValue (pT, iv,
 
805
                                                                     &ok);
 
806
                                  if (!ok)
 
807
                                      sqlite3_bind_null (stmt, 6);
 
808
                                  else
 
809
                                      sqlite3_bind_int64 (stmt, 6, val64);
 
810
                                  sqlite3_bind_null (stmt, 7);
 
811
                                  sqlite3_bind_null (stmt, 8);
 
812
                              }
 
813
                            if (gaiaExifTagGetValueType (pT) == 10)
 
814
                              {
 
815
                                  sqlite3_bind_null (stmt, 4);
 
816
                                  sqlite3_bind_null (stmt, 5);
 
817
                                  val64 =
 
818
                                      gaiaExifTagGetSignedRational1Value (pT,
 
819
                                                                          iv,
 
820
                                                                          &ok);
 
821
                                  if (!ok)
 
822
                                      sqlite3_bind_null (stmt, 6);
 
823
                                  else
 
824
                                      sqlite3_bind_int64 (stmt, 6, val64);
 
825
                                  val64 =
 
826
                                      gaiaExifTagGetSignedRational2Value (pT,
 
827
                                                                          iv,
 
828
                                                                          &ok);
 
829
                                  if (!ok)
 
830
                                      sqlite3_bind_null (stmt, 7);
 
831
                                  else
 
832
                                      sqlite3_bind_int64 (stmt, 7, val64);
 
833
                                  dblval =
 
834
                                      gaiaExifTagGetSignedRationalValue (pT, iv,
 
835
                                                                         &ok);
 
836
                                  if (!ok)
 
837
                                      sqlite3_bind_null (stmt, 8);
 
838
                                  else
 
839
                                      sqlite3_bind_double (stmt, 8, dblval);
 
840
                              }
 
841
                            if (gaiaExifTagGetValueType (pT) == 11)
 
842
                              {
 
843
                                  sqlite3_bind_null (stmt, 4);
 
844
                                  sqlite3_bind_null (stmt, 5);
 
845
                                  sqlite3_bind_null (stmt, 6);
 
846
                                  sqlite3_bind_null (stmt, 7);
 
847
                                  dblval =
 
848
                                      gaiaExifTagGetFloatValue (pT, iv, &ok);
 
849
                                  if (!ok)
 
850
                                      sqlite3_bind_null (stmt, 8);
 
851
                                  else
 
852
                                      sqlite3_bind_double (stmt, 8, dblval);
 
853
                              }
 
854
                            if (gaiaExifTagGetValueType (pT) == 12)
 
855
                              {
 
856
                                  sqlite3_bind_null (stmt, 4);
 
857
                                  sqlite3_bind_null (stmt, 5);
 
858
                                  sqlite3_bind_null (stmt, 6);
 
859
                                  sqlite3_bind_null (stmt, 7);
 
860
                                  dblval =
 
861
                                      gaiaExifTagGetDoubleValue (pT, iv, &ok);
 
862
                                  if (!ok)
 
863
                                      sqlite3_bind_null (stmt, 8);
 
864
                                  else
 
865
                                      sqlite3_bind_double (stmt, 8, dblval);
 
866
                              }
 
867
                            if (!ok_human)
 
868
                                sqlite3_bind_null (stmt, 9);
 
869
                            else
 
870
                                sqlite3_bind_text (stmt, 9, human,
 
871
                                                   strlen (human),
 
872
                                                   SQLITE_STATIC);
 
873
                            ret = sqlite3_step (stmt);
 
874
                            if (ret == SQLITE_DONE || ret == SQLITE_ROW)
 
875
                                ;
 
876
                            else
 
877
                              {
 
878
                                  printf ("sqlite3_step() error: %s\n",
 
879
                                          sqlite3_errmsg (handle));
 
880
                                  sqlite3_finalize (stmt);
 
881
                                  goto abort;
 
882
                              }
 
883
                            if (gaiaExifTagGetValueType (pT) == 1
 
884
                                || gaiaExifTagGetValueType (pT) == 2
 
885
                                || gaiaExifTagGetValueType (pT) == 6
 
886
                                || gaiaExifTagGetValueType (pT) == 7)
 
887
                                break;
 
888
                            ok_human = 0;
 
889
                        }
 
890
                  }
 
891
            }
 
892
          sqlite3_finalize (stmt);
 
893
      }
 
894
/* commits the transaction */
 
895
    strcpy (sql, "COMMIT");
 
896
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
897
    if (ret != SQLITE_OK)
 
898
      {
 
899
          printf ("COMMIT error: %s\n", err_msg);
 
900
          sqlite3_free (err_msg);
 
901
      }
 
902
    return 1;
 
903
  abort:
 
904
/* rolling back the transaction */
 
905
    strcpy (sql, "ROLLBACK");
 
906
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
907
    if (ret != SQLITE_OK)
 
908
      {
 
909
          printf ("ROLLBACK error: %s\n", err_msg);
 
910
          sqlite3_free (err_msg);
 
911
      }
 
912
    return 0;
 
913
}
 
914
 
 
915
static int
 
916
load_file (sqlite3 * handle, const char *file_path, int gps_only, int metadata)
 
917
{
 
918
/* importing a single EXIF file */
 
919
    FILE *fl;
 
920
    char msg[256];
 
921
    int sz = 0;
 
922
    int rd;
 
923
    int ok_exif = 0;
 
924
    int loaded = 0;
 
925
    int gps_skip = 0;
 
926
    unsigned char *blob = NULL;
 
927
    gaiaExifTagListPtr tag_list = NULL;
 
928
    fl = fopen (file_path, "rb");
 
929
    if (!fl)
 
930
      {
 
931
          sprintf (msg, "exif_loader: cannot open file '%s'", file_path);
 
932
          perror (msg);
 
933
          return 0;
 
934
      }
 
935
    if (fseek (fl, 0, SEEK_END) == 0)
 
936
        sz = ftell (fl);
 
937
    if (sz > 14)
 
938
      {
 
939
          blob = malloc (sz);
 
940
          rewind (fl);
 
941
          rd = fread (blob, 1, sz, fl);
 
942
          if (rd == sz)
 
943
            {
 
944
                tag_list = gaiaGetExifTags (blob, sz);
 
945
                if (tag_list)
 
946
                  {
 
947
                      ok_exif = 1;
 
948
                      if (gps_only && !isExifGps (tag_list))
 
949
                        {
 
950
                            gps_skip = 1;
 
951
                            goto stop;
 
952
                        }
 
953
                      if (!updateExifTables
 
954
                          (handle, blob, sz, tag_list, metadata, file_path))
 
955
                          goto stop;
 
956
                      loaded = 1;
 
957
                  }
 
958
            }
 
959
      }
 
960
  stop:
 
961
    if (!ok_exif)
 
962
        printf ("file '%s' doesn't seems to be a valid EXIF\n", file_path);
 
963
    else if (!loaded)
 
964
      {
 
965
          if (gps_skip)
 
966
              printf
 
967
                  ("file '%s' is a valid EXIF, but doesn't contains any GPS info\n",
 
968
                   file_path);
 
969
          else
 
970
              printf ("SQL error(s): file '%s' was not loaded\n", file_path);
 
971
      }
 
972
    else
 
973
        printf ("file '%s' successfully loaded\n", file_path);
 
974
    if (blob)
 
975
        free (blob);
 
976
    if (tag_list)
 
977
        gaiaExifTagsFree (tag_list);
 
978
    fclose (fl);
 
979
    return loaded;
 
980
}
 
981
 
 
982
static int
 
983
load_dir (sqlite3 * handle, const char *dir_path, int gps_only, int metadata)
 
984
{
 
985
/* importing EXIF files from a whole DIRECTORY */
 
986
#if defined(_WIN32) && !defined(__MINGW32__)
 
987
/* Visual Studio .NET */
 
988
    struct _finddata_t c_file;
 
989
    intptr_t hFile;
 
990
    int cnt = 0;
 
991
    char file_path[1024];
 
992
    if (_chdir (dir_path) < 0)
 
993
      {
 
994
          fprintf (stderr, "exif_loader: cannot access dir '%s'", dir_path);
 
995
          return 0;
 
996
      }
 
997
    if ((hFile = _findfirst ("*.*", &c_file)) == -1L)
 
998
        fprintf (stderr, "exif_loader: cannot access dir '%s' [or empty dir]\n",
 
999
                 dir_path);
 
1000
    else
 
1001
      {
 
1002
          while (1)
 
1003
            {
 
1004
                if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
 
1005
                    || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
 
1006
                  {
 
1007
                      sprintf (file_path, "%s\\%s", dir_path, c_file.name);
 
1008
                      cnt += load_file (handle, file_path, gps_only, metadata);
 
1009
                  }
 
1010
                if (_findnext (hFile, &c_file) != 0)
 
1011
                    break;
 
1012
            };
 
1013
          _findclose (hFile);
 
1014
      }
 
1015
    return cnt;
 
1016
#else
 
1017
/* not Visual Studio .NET */
 
1018
    int cnt = 0;
 
1019
    char file_path[4096];
 
1020
    char msg[256];
 
1021
    struct dirent *entry;
 
1022
    DIR *dir = opendir (dir_path);
 
1023
    if (!dir)
 
1024
      {
 
1025
          sprintf (msg, "exif_loader: cannot access dir '%s'", dir_path);
 
1026
          perror (msg);
 
1027
          return 0;
 
1028
      }
 
1029
    while (1)
 
1030
      {
 
1031
          /* scanning dir-entries */
 
1032
          entry = readdir (dir);
 
1033
          if (!entry)
 
1034
              break;
 
1035
          sprintf (file_path, "%s/%s", dir_path, entry->d_name);
 
1036
          cnt += load_file (handle, file_path, gps_only, metadata);
 
1037
      }
 
1038
    closedir (dir);
 
1039
    return cnt;
 
1040
#endif
 
1041
}
 
1042
 
 
1043
static int
 
1044
checkExifTables (sqlite3 * handle)
 
1045
{
 
1046
/* creates the EXIF DB tables / or checks existing ones for validity */
 
1047
    int ret;
 
1048
    char sql[1024];
 
1049
    char *err_msg = NULL;
 
1050
    int ok_photoId;
 
1051
    int ok_photo;
 
1052
    int ok_pixelX;
 
1053
    int ok_pixelY;
 
1054
    int ok_cameraMake;
 
1055
    int ok_cameraModel;
 
1056
    int ok_shotDateTime;
 
1057
    int ok_gpsGeometry;
 
1058
    int ok_gpsDirection;
 
1059
    int ok_gpsSatellites;
 
1060
    int ok_gpsTimestamp;
 
1061
    int ok_fromPath;
 
1062
    int ok_tagId;
 
1063
    int ok_tagName;
 
1064
    int ok_gpsTag;
 
1065
    int ok_valueType;
 
1066
    int ok_typeName;
 
1067
    int ok_countValues;
 
1068
    int ok_valueIndex;
 
1069
    int ok_byteValue;
 
1070
    int ok_stringValue;
 
1071
    int ok_numValue;
 
1072
    int ok_numValueBis;
 
1073
    int ok_doubleValue;
 
1074
    int ok_humanReadable;
 
1075
    int err_pk;
 
1076
    int ok_photoIdPk;
 
1077
    int ok_tagIdPk;
 
1078
    int ok_valueIndexPk;
 
1079
    int pKey;
 
1080
    const char *name;
 
1081
    int i;
 
1082
    char **results;
 
1083
    int rows;
 
1084
    int columns;
 
1085
/* creating the ExifPhoto table */
 
1086
    strcpy (sql, "CREATE TABLE IF NOT EXISTS ExifPhoto (\n");
 
1087
    strcat (sql, "PhotoId INTEGER PRIMARY KEY AUTOINCREMENT,\n");
 
1088
    strcat (sql, "Photo BLOB NOT NULL,\n");
 
1089
    strcat (sql, "PixelX INTEGER,\n");
 
1090
    strcat (sql, "PixelY INTEGER,\n");
 
1091
    strcat (sql, "CameraMake TEXT,\n");
 
1092
    strcat (sql, "CameraModel TEXT,\n");
 
1093
    strcat (sql, "ShotDateTime DOUBLE,\n");
 
1094
    strcat (sql, "GpsGeometry BLOB, ");
 
1095
    strcat (sql, "GpsDirection DOUBLE, ");
 
1096
    strcat (sql, "GpsSatellites TEXT,\n");
 
1097
    strcat (sql, "GpsTimestamp DOUBLE, ");
 
1098
    strcat (sql, "FromPath TEXT");
 
1099
    strcat (sql, ")");
 
1100
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
1101
    if (ret != SQLITE_OK)
 
1102
      {
 
1103
          printf ("CREATE TABLE ExifPhoto error: %s\n", err_msg);
 
1104
          sqlite3_free (err_msg);
 
1105
          goto abort;
 
1106
      }
 
1107
/* checking the ExifPhoto table for sanity */
 
1108
    ok_photoId = 0;
 
1109
    ok_photo = 0;
 
1110
    ok_pixelX = 0;
 
1111
    ok_pixelY = 0;
 
1112
    ok_cameraMake = 0;
 
1113
    ok_cameraModel = 0;
 
1114
    ok_shotDateTime = 0;
 
1115
    ok_gpsGeometry = 0;
 
1116
    ok_gpsDirection = 0;
 
1117
    ok_gpsSatellites = 0;
 
1118
    ok_gpsTimestamp = 0;
 
1119
    ok_fromPath = 0;
 
1120
    ok_photoIdPk = 0;
 
1121
    err_pk = 0;
 
1122
    strcpy (sql, "PRAGMA table_info(\"ExifPhoto\")");
 
1123
    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, &err_msg);
 
1124
    if (ret != SQLITE_OK)
 
1125
      {
 
1126
          printf ("PRAGMA table_info(\"ExifPhoto\") error: %s\n", err_msg);
 
1127
          sqlite3_free (err_msg);
 
1128
          goto abort;
 
1129
      }
 
1130
    if (rows < 1)
 
1131
        ;
 
1132
    else
 
1133
      {
 
1134
          for (i = 1; i <= rows; i++)
 
1135
            {
 
1136
                name = results[(i * columns) + 1];
 
1137
                if (atoi (results[(i * columns) + 5]) == 0)
 
1138
                    pKey = 0;
 
1139
                else
 
1140
                    pKey = 1;
 
1141
                if (strcasecmp (name, "PhotoId") == 0)
 
1142
                    ok_photoId = 1;
 
1143
                if (strcasecmp (name, "Photo") == 0)
 
1144
                    ok_photo = 1;
 
1145
                if (strcasecmp (name, "PixelX") == 0)
 
1146
                    ok_pixelX = 1;
 
1147
                if (strcasecmp (name, "PixelY") == 0)
 
1148
                    ok_pixelY = 1;
 
1149
                if (strcasecmp (name, "CameraMake") == 0)
 
1150
                    ok_cameraMake = 1;
 
1151
                if (strcasecmp (name, "CameraModel") == 0)
 
1152
                    ok_cameraModel = 1;
 
1153
                if (strcasecmp (name, "ShotDateTime") == 0)
 
1154
                    ok_shotDateTime = 1;
 
1155
                if (strcasecmp (name, "GpsGeometry") == 0)
 
1156
                    ok_gpsGeometry = 1;
 
1157
                if (strcasecmp (name, "GpsDirection") == 0)
 
1158
                    ok_gpsDirection = 1;
 
1159
                if (strcasecmp (name, "GpsTimestamp") == 0)
 
1160
                    ok_gpsTimestamp = 1;
 
1161
                if (strcasecmp (name, "FromPath") == 0)
 
1162
                    ok_fromPath = 1;
 
1163
                if (pKey)
 
1164
                  {
 
1165
                      if (strcasecmp (name, "PhotoId") == 0)
 
1166
                          ok_photoIdPk = 1;
 
1167
                      else
 
1168
                          err_pk = 1;
 
1169
                  }
 
1170
            }
 
1171
      }
 
1172
    sqlite3_free_table (results);
 
1173
    if (ok_photoId && ok_photo && ok_pixelX && ok_pixelY && ok_cameraMake
 
1174
        && ok_cameraModel && ok_shotDateTime && ok_gpsGeometry
 
1175
        && ok_gpsDirection && ok_gpsTimestamp && ok_fromPath && ok_photoIdPk
 
1176
        && !err_pk)
 
1177
        ;
 
1178
    else
 
1179
      {
 
1180
          printf
 
1181
              ("ERROR: table 'ExifPhoto' already exists, but has incompatible columns\n");
 
1182
          goto abort;
 
1183
      }
 
1184
/* creating the ExifTags table */
 
1185
    strcpy (sql, "CREATE TABLE IF NOT EXISTS ExifTags (\n");
 
1186
    strcat (sql, "PhotoId INTEGER NOT NULL,\n");
 
1187
    strcat (sql, "TagId INTEGER NOT NULL,\n");
 
1188
    strcat (sql, "TagName TEXT NOT NULL,\n");
 
1189
    strcat (sql, "GpsTag INTEGER NOT NULL CHECK (GpsTag IN (0, 1)),\n");
 
1190
    strcat (sql,
 
1191
            "ValueType INTEGER NOT NULL CHECK (ValueType IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)),\n");
 
1192
    strcat (sql, "TypeName TEXT NOT NULL,\n");
 
1193
    strcat (sql, "CountValues INTEGER NOT NULL,\n");
 
1194
    strcat (sql, "PRIMARY KEY (PhotoId, TagId)");
 
1195
    strcat (sql, ")");
 
1196
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
1197
    if (ret != SQLITE_OK)
 
1198
      {
 
1199
          printf ("CREATE TABLE ExifTags error: %s\n", err_msg);
 
1200
          sqlite3_free (err_msg);
 
1201
          goto abort;
 
1202
      }
 
1203
/* checking the ExifTags table for sanity */
 
1204
    ok_photoId = 0;
 
1205
    ok_tagId = 0;
 
1206
    ok_tagName = 0;
 
1207
    ok_gpsTag = 0;
 
1208
    ok_valueType = 0;
 
1209
    ok_typeName = 0;
 
1210
    ok_countValues = 0;
 
1211
    ok_photoIdPk = 0;
 
1212
    ok_tagIdPk = 0;
 
1213
    err_pk = 0;
 
1214
    strcpy (sql, "PRAGMA table_info(\"ExifTags\")");
 
1215
    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, &err_msg);
 
1216
    if (ret != SQLITE_OK)
 
1217
      {
 
1218
          printf ("PRAGMA table_info(\"ExifTags\") error: %s\n", err_msg);
 
1219
          sqlite3_free (err_msg);
 
1220
          goto abort;
 
1221
      }
 
1222
    if (rows < 1)
 
1223
        ;
 
1224
    else
 
1225
      {
 
1226
          for (i = 1; i <= rows; i++)
 
1227
            {
 
1228
                name = results[(i * columns) + 1];
 
1229
                if (atoi (results[(i * columns) + 5]) == 0)
 
1230
                    pKey = 0;
 
1231
                else
 
1232
                    pKey = 1;
 
1233
                if (strcasecmp (name, "PhotoId") == 0)
 
1234
                    ok_photoId = 1;
 
1235
                if (strcasecmp (name, "TagId") == 0)
 
1236
                    ok_tagId = 1;
 
1237
                if (strcasecmp (name, "TagName") == 0)
 
1238
                    ok_tagName = 1;
 
1239
                if (strcasecmp (name, "GpsTag") == 0)
 
1240
                    ok_gpsTag = 1;
 
1241
                if (strcasecmp (name, "ValueType") == 0)
 
1242
                    ok_valueType = 1;
 
1243
                if (strcasecmp (name, "TypeName") == 0)
 
1244
                    ok_typeName = 1;
 
1245
                if (strcasecmp (name, "CountValues") == 0)
 
1246
                    ok_countValues = 1;
 
1247
                if (pKey)
 
1248
                  {
 
1249
                      if (strcasecmp (name, "PhotoId") == 0)
 
1250
                          ok_photoIdPk = 1;
 
1251
                      else if (strcasecmp (name, "TagId") == 0)
 
1252
                          ok_tagIdPk = 1;
 
1253
                      else
 
1254
                          err_pk = 1;
 
1255
                  }
 
1256
            }
 
1257
      }
 
1258
    sqlite3_free_table (results);
 
1259
    if (ok_photoId && ok_tagId && ok_tagName && ok_gpsTag && ok_valueType
 
1260
        && ok_typeName && ok_countValues && ok_photoIdPk && ok_tagIdPk
 
1261
        && !err_pk)
 
1262
        ;
 
1263
    else
 
1264
      {
 
1265
          printf
 
1266
              ("ERROR: table 'ExifTags' already exists, but has incompatible columns\n");
 
1267
          goto abort;
 
1268
      }
 
1269
/* creating the ExifValues table */
 
1270
    strcpy (sql, "CREATE TABLE IF NOT EXISTS ExifValues (\n");
 
1271
    strcat (sql, "PhotoId INTEGER NOT NULL,\n");
 
1272
    strcat (sql, "TagId INTEGER NOT NULL,\n");
 
1273
    strcat (sql, "ValueIndex INTEGER NOT NULL,\n");
 
1274
    strcat (sql, "ByteValue BLOB,\n");
 
1275
    strcat (sql, "StringValue TEXT,\n");
 
1276
    strcat (sql, "NumValue INTEGER,\n");
 
1277
    strcat (sql, "NumValueBis INTEGER,\n");
 
1278
    strcat (sql, "DoubleValue DOUBLE,\n");
 
1279
    strcat (sql, "HumanReadable TEXT,\n");
 
1280
    strcat (sql, "PRIMARY KEY (PhotoId, TagId, ValueIndex)");
 
1281
    strcat (sql, ")");
 
1282
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
1283
    if (ret != SQLITE_OK)
 
1284
      {
 
1285
          printf ("CREATE TABLE ExifValues error: %s\n", err_msg);
 
1286
          sqlite3_free (err_msg);
 
1287
          goto abort;
 
1288
      }
 
1289
/* checking the ExifValues table for sanity */
 
1290
    ok_photoId = 0;
 
1291
    ok_tagId = 0;
 
1292
    ok_valueIndex = 0;
 
1293
    ok_byteValue = 0;
 
1294
    ok_stringValue = 0;
 
1295
    ok_numValue = 0;
 
1296
    ok_numValueBis = 0;
 
1297
    ok_doubleValue = 0;
 
1298
    ok_humanReadable = 0;
 
1299
    ok_photoIdPk = 0;
 
1300
    ok_tagIdPk = 0;
 
1301
    ok_valueIndexPk = 0;
 
1302
    err_pk = 0;
 
1303
    strcpy (sql, "PRAGMA table_info(\"ExifValues\")");
 
1304
    ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, &err_msg);
 
1305
    if (ret != SQLITE_OK)
 
1306
      {
 
1307
          printf ("PRAGMA table_info(\"ExifValues\") error: %s\n", err_msg);
 
1308
          sqlite3_free (err_msg);
 
1309
          goto abort;
 
1310
      }
 
1311
    if (rows < 1)
 
1312
        ;
 
1313
    else
 
1314
      {
 
1315
          for (i = 1; i <= rows; i++)
 
1316
            {
 
1317
                name = results[(i * columns) + 1];
 
1318
                if (atoi (results[(i * columns) + 5]) == 0)
 
1319
                    pKey = 0;
 
1320
                else
 
1321
                    pKey = 1;
 
1322
                if (strcasecmp (name, "PhotoId") == 0)
 
1323
                    ok_photoId = 1;
 
1324
                if (strcasecmp (name, "TagId") == 0)
 
1325
                    ok_tagId = 1;
 
1326
                if (strcasecmp (name, "ValueIndex") == 0)
 
1327
                    ok_valueIndex = 1;
 
1328
                if (strcasecmp (name, "ByteValue") == 0)
 
1329
                    ok_byteValue = 1;
 
1330
                if (strcasecmp (name, "StringValue") == 0)
 
1331
                    ok_stringValue = 1;
 
1332
                if (strcasecmp (name, "NumValue") == 0)
 
1333
                    ok_numValue = 1;
 
1334
                if (strcasecmp (name, "NumValueBis") == 0)
 
1335
                    ok_numValueBis = 1;
 
1336
                if (strcasecmp (name, "DoubleValue") == 0)
 
1337
                    ok_doubleValue = 1;
 
1338
                if (strcasecmp (name, "HumanReadable") == 0)
 
1339
                    ok_humanReadable = 1;
 
1340
                if (pKey)
 
1341
                  {
 
1342
                      if (strcasecmp (name, "PhotoId") == 0)
 
1343
                          ok_photoIdPk = 1;
 
1344
                      else if (strcasecmp (name, "TagId") == 0)
 
1345
                          ok_tagIdPk = 1;
 
1346
                      else if (strcasecmp (name, "ValueIndex") == 0)
 
1347
                          ok_valueIndexPk = 1;
 
1348
                      else
 
1349
                          err_pk = 1;
 
1350
                  }
 
1351
            }
 
1352
      }
 
1353
    sqlite3_free_table (results);
 
1354
    if (ok_photoId && ok_tagId && ok_valueIndex && ok_byteValue
 
1355
        && ok_stringValue && ok_numValue && ok_numValueBis && ok_doubleValue
 
1356
        && ok_humanReadable && ok_photoIdPk && ok_tagIdPk && ok_valueIndexPk
 
1357
        && !err_pk)
 
1358
        ;
 
1359
    else
 
1360
      {
 
1361
          printf
 
1362
              ("ERROR: table 'ExifValues' already exists, but has incompatible columns\n");
 
1363
          goto abort;
 
1364
      }
 
1365
/* creating the ExifView view */
 
1366
    strcpy (sql, "CREATE VIEW IF NOT EXISTS \"ExifMetadata\" AS\n");
 
1367
    strcat (sql, "SELECT p.\"PhotoId\" AS 'PhotoId', ");
 
1368
    strcat (sql, "t.\"TagId\" AS 'TagId', ");
 
1369
    strcat (sql, "t.\"TagName\" AS 'TagName',");
 
1370
    strcat (sql, "t.\"GpsTag\" AS 'GpsTag',\n");
 
1371
    strcat (sql, "t.\"ValueType\" AS 'ValueType',");
 
1372
    strcat (sql, "t.\"TypeName\" AS 'TypeName', ");
 
1373
    strcat (sql, "t.\"CountValues\" AS 'CountValues', ");
 
1374
    strcat (sql, "v.\"ValueIndex\" AS 'ValueIndex',\n");
 
1375
    strcat (sql, "v.\"ByteValue\" AS 'ByteValue', ");
 
1376
    strcat (sql, "v.\"StringValue\" AS 'StringValue', ");
 
1377
    strcat (sql, "v.\"NumValue\" AS 'NumValue', ");
 
1378
    strcat (sql, "v.\"NumValueBis\" AS 'NumValueBis',\n");
 
1379
    strcat (sql, "v.\"DoubleValue\" AS 'DoubleValue', ");
 
1380
    strcat (sql, "v.\"HumanReadable\" AS 'HumanReadable'\n");
 
1381
    strcat (sql,
 
1382
            "FROM \"ExifPhoto\" AS p, \"ExifTags\" AS t, \"ExifValues\" AS v\n");
 
1383
    strcat (sql,
 
1384
            "WHERE t.\"PhotoId\" = p.\"PhotoId\" AND v.\"PhotoId\" = t.\"PhotoId\" AND v.\"TagId\" = t.\"TagId\"");
 
1385
    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
 
1386
    if (ret != SQLITE_OK)
 
1387
      {
 
1388
          printf ("CREATE VIEW ExifMetadata error: %s\n", err_msg);
 
1389
          sqlite3_free (err_msg);
 
1390
          goto abort;
 
1391
      }
 
1392
    return 1;
 
1393
  abort:
 
1394
    return 0;
 
1395
}
 
1396
 
 
1397
static void
 
1398
spatialite_autocreate (sqlite3 * db)
 
1399
{
 
1400
/* attempting to perform self-initialization for a newly created DB */
 
1401
    int ret;
 
1402
    char sql[1024];
 
1403
    char *err_msg = NULL;
 
1404
    int count;
 
1405
    int i;
 
1406
    char **results;
 
1407
    int rows;
 
1408
    int columns;
 
1409
 
 
1410
/* checking if this DB is really empty */
 
1411
    strcpy (sql, "SELECT Count(*) from sqlite_master");
 
1412
    ret = sqlite3_get_table (db, sql, &results, &rows, &columns, NULL);
 
1413
    if (ret != SQLITE_OK)
 
1414
        return;
 
1415
    if (rows < 1)
 
1416
        ;
 
1417
    else
 
1418
      {
 
1419
          for (i = 1; i <= rows; i++)
 
1420
              count = atoi (results[(i * columns) + 0]);
 
1421
      }
 
1422
    sqlite3_free_table (results);
 
1423
 
 
1424
    if (count > 0)
 
1425
        return;
 
1426
 
 
1427
/* all right, it's empty: proceding to initialize */
 
1428
    strcpy (sql, "SELECT InitSpatialMetadata()");
 
1429
    ret = sqlite3_exec (db, sql, NULL, NULL, &err_msg);
 
1430
    if (ret != SQLITE_OK)
 
1431
      {
 
1432
          fprintf (stderr, "InitSpatialMetadata() error: %s\n", err_msg);
 
1433
          sqlite3_free (err_msg);
 
1434
          return;
 
1435
      }
 
1436
}
 
1437
 
 
1438
static void
 
1439
do_help ()
 
1440
{
 
1441
/* printing the argument list */
 
1442
    fprintf (stderr, "\n\nusage: exif_loader ARGLIST\n");
 
1443
    fprintf (stderr,
 
1444
             "==============================================================\n");
 
1445
    fprintf (stderr,
 
1446
             "-h or --help                      print this help message\n");
 
1447
    fprintf (stderr,
 
1448
             "-d or --db-path pathname          the SpatiaLite db path\n");
 
1449
    fprintf (stderr,
 
1450
             "-D or --dir     dir_path          the DIR path containing EXIF files\n");
 
1451
    fprintf (stderr, "-f or --file    file_name         a single EXIF file\n");
 
1452
    fprintf (stderr, "you can specify the following options as well\n");
 
1453
    fprintf (stderr, "--any-exif                 *default*\n");
 
1454
    fprintf (stderr, "--gps-exif-only\n\n");
 
1455
    fprintf (stderr, "--metadata                 *default*\n");
 
1456
    fprintf (stderr, "--no-metadata\n\n");
 
1457
}
 
1458
 
 
1459
int
 
1460
main (int argc, char *argv[])
 
1461
{
 
1462
/* the MAIN function simply perform arguments checking */
 
1463
    int i;
 
1464
    int next_arg = ARG_NONE;
 
1465
    char *path = NULL;
 
1466
    char *dir_path = NULL;
 
1467
    char *file_path = NULL;
 
1468
    int gps_only = 0;
 
1469
    int metadata = 1;
 
1470
    int error = 0;
 
1471
    sqlite3 *handle;
 
1472
    int ret;
 
1473
    int cnt = 0;
 
1474
    for (i = 1; i < argc; i++)
 
1475
      {
 
1476
          /* parsing the invocation arguments */
 
1477
          if (next_arg != ARG_NONE)
 
1478
            {
 
1479
                switch (next_arg)
 
1480
                  {
 
1481
                  case ARG_DB_PATH:
 
1482
                      path = argv[i];
 
1483
                      break;
 
1484
                  case ARG_DIR:
 
1485
                      dir_path = argv[i];
 
1486
                      break;
 
1487
                  case ARG_FILE:
 
1488
                      file_path = argv[i];
 
1489
                      break;
 
1490
                  };
 
1491
                next_arg = ARG_NONE;
 
1492
                continue;
 
1493
            }
 
1494
          if (strcasecmp (argv[i], "--help") == 0
 
1495
              || strcmp (argv[i], "-h") == 0)
 
1496
            {
 
1497
                do_help ();
 
1498
                return -1;
 
1499
            }
 
1500
          if (strcasecmp (argv[i], "--db-path") == 0)
 
1501
            {
 
1502
                next_arg = ARG_DB_PATH;
 
1503
                continue;
 
1504
            }
 
1505
          if (strcmp (argv[i], "-d") == 0)
 
1506
            {
 
1507
                next_arg = ARG_DB_PATH;
 
1508
                continue;
 
1509
            }
 
1510
          if (strcasecmp (argv[i], "--dir-path") == 0)
 
1511
            {
 
1512
                next_arg = ARG_DIR;
 
1513
                continue;
 
1514
            }
 
1515
          if (strcmp (argv[i], "-D") == 0)
 
1516
            {
 
1517
                next_arg = ARG_DIR;
 
1518
                continue;
 
1519
            }
 
1520
          if (strcasecmp (argv[i], "--file-path") == 0)
 
1521
            {
 
1522
                next_arg = ARG_FILE;
 
1523
                continue;
 
1524
            }
 
1525
          if (strcmp (argv[i], "-f") == 0)
 
1526
            {
 
1527
                next_arg = ARG_FILE;
 
1528
                continue;
 
1529
            }
 
1530
          if (strcasecmp (argv[i], "--any-exif") == 0)
 
1531
            {
 
1532
                gps_only = 0;
 
1533
                continue;
 
1534
            }
 
1535
          if (strcasecmp (argv[i], "--gps-exif-only") == 0)
 
1536
            {
 
1537
                gps_only = 1;
 
1538
                continue;
 
1539
            }
 
1540
          if (strcasecmp (argv[i], "--metatada") == 0)
 
1541
            {
 
1542
                metadata = 1;
 
1543
                continue;
 
1544
            }
 
1545
          if (strcasecmp (argv[i], "--no-metadata") == 0)
 
1546
            {
 
1547
                metadata = 0;
 
1548
                continue;
 
1549
            }
 
1550
          fprintf (stderr, "unknown argument: %s\n", argv[i]);
 
1551
          error = 1;
 
1552
      }
 
1553
    if (error)
 
1554
      {
 
1555
          do_help ();
 
1556
          return -1;
 
1557
      }
 
1558
/* checking the arguments */
 
1559
    if (!path)
 
1560
      {
 
1561
          fprintf (stderr, "did you forget setting the --db-path argument ?\n");
 
1562
          error = 1;
 
1563
      }
 
1564
    if (!dir_path && !file_path)
 
1565
      {
 
1566
          fprintf (stderr,
 
1567
                   "did you forget setting the --dir_path OR --file_path argument ?\n");
 
1568
          error = 1;
 
1569
      }
 
1570
    if (dir_path && file_path)
 
1571
      {
 
1572
          fprintf (stderr,
 
1573
                   "--dir_path AND --file_path argument are mutually exclusive\n");
 
1574
          error = 1;
 
1575
      }
 
1576
    if (error)
 
1577
      {
 
1578
          do_help ();
 
1579
          return -1;
 
1580
      }
 
1581
/* trying to connect the SpatiaLite DB  */
 
1582
    ret =
 
1583
        sqlite3_open_v2 (path, &handle,
 
1584
                         SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
 
1585
    if (ret != SQLITE_OK)
 
1586
      {
 
1587
          fprintf (stderr, "cannot open '%s': %s\n", path,
 
1588
                   sqlite3_errmsg (handle));
 
1589
          sqlite3_close (handle);
 
1590
          return -1;
 
1591
      }
 
1592
    spatialite_autocreate (handle);
 
1593
    if (!checkExifTables (handle))
 
1594
      {
 
1595
          fprintf (stderr,
 
1596
                   "An EXIF table is already defined, but has incompatibles columns\n\nSorry ...\n");
 
1597
          sqlite3_close (handle);
 
1598
          return -1;
 
1599
      }
 
1600
    if (dir_path)
 
1601
        cnt = load_dir (handle, dir_path, gps_only, metadata);
 
1602
    else
 
1603
        cnt = load_file (handle, file_path, gps_only, metadata);
 
1604
    ret = sqlite3_close (handle);
 
1605
    if (ret != SQLITE_OK)
 
1606
        fprintf (stderr, "sqlite3_close() error: %s\n",
 
1607
                 sqlite3_errmsg (handle));
 
1608
    if (cnt)
 
1609
        fprintf (stderr,
 
1610
                 "\n\n***   %d EXIF photo%s successfully inserted into the DB\n",
 
1611
                 cnt, (cnt > 1) ? "s where" : " was");
 
1612
    return 0;
 
1613
}