|
Packit |
01d647 |
// ***************************************************************** -*- C++ -*-
|
|
Packit |
01d647 |
// geotag.cpp
|
|
Packit |
01d647 |
// Sample program to read gpx files and update images with GPS tags
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// g++ geotag.cpp -o geotag -lexiv2 -lexpat
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <exiv2/exiv2.hpp>
|
|
Packit |
01d647 |
#include "unused.h"
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <iostream>
|
|
Packit |
01d647 |
#include <iomanip>
|
|
Packit |
01d647 |
#include <cassert>
|
|
Packit |
01d647 |
#include <algorithm>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <stdio.h>
|
|
Packit |
01d647 |
#include <cstdlib>
|
|
Packit |
01d647 |
#include <time.h>
|
|
Packit |
01d647 |
#include <string.h>
|
|
Packit |
01d647 |
#include <sys/stat.h>
|
|
Packit |
01d647 |
#include <sys/types.h>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <expat.h>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include <vector>
|
|
Packit |
01d647 |
#include <string>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#if defined(__MINGW32__) || defined(__MINGW64__)
|
|
Packit |
01d647 |
# ifndef __MINGW__
|
|
Packit |
01d647 |
# define __MINGW__
|
|
Packit |
01d647 |
# endif
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
using namespace std;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifndef lengthof
|
|
Packit |
01d647 |
#define lengthof(x) (sizeof(*x)/sizeof(x))
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#if defined(_MSC_VER) || defined(__MINGW__)
|
|
Packit |
01d647 |
#include <windows.h>
|
|
Packit |
01d647 |
char* realpath(const char* file,char* path);
|
|
Packit |
01d647 |
#define lstat _stat
|
|
Packit |
01d647 |
#define stat _stat
|
|
Packit |
01d647 |
#if _MSC_VER < 1400
|
|
Packit |
01d647 |
#define strcpy_s(d,l,s) strcpy(d,s)
|
|
Packit |
01d647 |
#define strcat_s(d,l,s) strcat(d,s)
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#if ! defined(_MSC_VER)
|
|
Packit |
01d647 |
#include <dirent.h>
|
|
Packit |
01d647 |
#include <unistd.h>
|
|
Packit |
01d647 |
#include <sys/param.h>
|
|
Packit |
01d647 |
#define stricmp strcasecmp
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifndef _MAX_PATH
|
|
Packit |
01d647 |
#define _MAX_PATH 1024
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// prototypes
|
|
Packit |
01d647 |
class Options;
|
|
Packit |
01d647 |
int getFileType(const char* path ,Options& options);
|
|
Packit |
01d647 |
int getFileType(std::string& path,Options& options);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
string getExifTime(const time_t t);
|
|
Packit |
01d647 |
time_t parseTime(const char* ,bool bAdjust=false);
|
|
Packit |
01d647 |
int timeZoneAdjust();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// platform specific code
|
|
Packit |
01d647 |
#if defined(_MSC_VER) || defined(__MINGW__)
|
|
Packit |
01d647 |
char* realpath(const char* file,char* path)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char* result = (char*) malloc(_MAX_PATH);
|
|
Packit |
01d647 |
if (result) GetFullPathName(file,_MAX_PATH,result,NULL);
|
|
Packit |
01d647 |
return result ;
|
|
Packit |
01d647 |
UNUSED(path);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Command-line parser
|
|
Packit |
01d647 |
class Options {
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
bool verbose;
|
|
Packit |
01d647 |
bool help;
|
|
Packit |
01d647 |
bool version;
|
|
Packit |
01d647 |
bool dst;
|
|
Packit |
01d647 |
bool dryrun;
|
|
Packit |
01d647 |
bool ascii;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Options()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
verbose = false;
|
|
Packit |
01d647 |
help = false;
|
|
Packit |
01d647 |
version = false;
|
|
Packit |
01d647 |
dst = false;
|
|
Packit |
01d647 |
dryrun = false;
|
|
Packit |
01d647 |
ascii = false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
virtual ~Options() {} ;
|
|
Packit |
01d647 |
} ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
enum
|
|
Packit |
01d647 |
{ resultOK=0
|
|
Packit |
01d647 |
, resultSyntaxError
|
|
Packit |
01d647 |
, resultSelectFailed
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
enum // keyword indices
|
|
Packit |
01d647 |
{ kwHELP = 0
|
|
Packit |
01d647 |
, kwVERSION
|
|
Packit |
01d647 |
, kwDST
|
|
Packit |
01d647 |
, kwDRYRUN
|
|
Packit |
01d647 |
, kwASCII
|
|
Packit |
01d647 |
, kwVERBOSE
|
|
Packit |
01d647 |
, kwADJUST
|
|
Packit |
01d647 |
, kwTZ
|
|
Packit |
01d647 |
, kwDELTA
|
|
Packit |
01d647 |
, kwMAX // manages keyword array
|
|
Packit |
01d647 |
, kwNEEDVALUE // bogus keywords for error reporting
|
|
Packit |
01d647 |
, kwSYNTAX // -- ditto --
|
|
Packit |
01d647 |
, kwNOVALUE = -kwVERBOSE // keywords <= kwNOVALUE are flags (no value needed)
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// file types supported
|
|
Packit |
01d647 |
enum
|
|
Packit |
01d647 |
{ typeUnknown = 0
|
|
Packit |
01d647 |
, typeDirectory = 1
|
|
Packit |
01d647 |
, typeImage = 2
|
|
Packit |
01d647 |
, typeXML = 3
|
|
Packit |
01d647 |
, typeFile = 4
|
|
Packit |
01d647 |
, typeDoc = 5
|
|
Packit |
01d647 |
, typeCode = 6
|
|
Packit |
01d647 |
, typeMax = 7
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// forward declaration
|
|
Packit |
01d647 |
class Position;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// globals
|
|
Packit |
01d647 |
typedef std::map<time_t,Position> TimeDict_t;
|
|
Packit |
01d647 |
typedef std::map<time_t,Position>::iterator TimeDict_i;
|
|
Packit |
01d647 |
typedef std::vector<std::string> strings_t;
|
|
Packit |
01d647 |
const char* gDeg = NULL ; // string "°" or "deg"
|
|
Packit |
01d647 |
TimeDict_t gTimeDict ;
|
|
Packit |
01d647 |
strings_t gFiles;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Position (from gpx file)
|
|
Packit |
01d647 |
class Position
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
Position(time_t time, double lat, double lon, double ele) :
|
|
Packit |
01d647 |
time_(time)
|
|
Packit |
01d647 |
, lon_(lon)
|
|
Packit |
01d647 |
, lat_(lat)
|
|
Packit |
01d647 |
, ele_(ele)
|
|
Packit |
01d647 |
, delta_(0)
|
|
Packit |
01d647 |
{}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Position():
|
|
Packit |
01d647 |
time_(0)
|
|
Packit |
01d647 |
, lon_(0.0)
|
|
Packit |
01d647 |
, lat_(0.0)
|
|
Packit |
01d647 |
, ele_(0.0)
|
|
Packit |
01d647 |
, delta_(0)
|
|
Packit |
01d647 |
{ }
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
virtual ~Position() {}
|
|
Packit |
01d647 |
// copy constructor
|
|
Packit |
01d647 |
Position(const Position& o) :
|
|
Packit |
01d647 |
time_(o.time_)
|
|
Packit |
01d647 |
, lon_(o.lon_)
|
|
Packit |
01d647 |
, lat_(o.lat_)
|
|
Packit |
01d647 |
, ele_(o.ele_)
|
|
Packit |
01d647 |
, delta_(o.delta_)
|
|
Packit |
01d647 |
{}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// instance methods
|
|
Packit |
01d647 |
bool good() { return time_ || lon_ || lat_ || ele_ ; }
|
|
Packit |
01d647 |
std::string getTimeString() { if ( times_.empty() ) times_ = getExifTime(time_) ; return times_; }
|
|
Packit |
01d647 |
time_t getTime() { return time_ ; }
|
|
Packit |
01d647 |
std::string toString();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// getters/setters
|
|
Packit |
01d647 |
double lat() {return lat_ ;}
|
|
Packit |
01d647 |
double lon() {return lon_ ;}
|
|
Packit |
01d647 |
double ele() {return ele_ ;}
|
|
Packit |
01d647 |
int delta() {return delta_ ;}
|
|
Packit |
01d647 |
void delta(int delta) {delta_=delta ;}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// data
|
|
Packit |
01d647 |
private:
|
|
Packit |
01d647 |
time_t time_;
|
|
Packit |
01d647 |
double lon_ ;
|
|
Packit |
01d647 |
double lat_ ;
|
|
Packit |
01d647 |
double ele_ ;
|
|
Packit |
01d647 |
std::string times_;
|
|
Packit |
01d647 |
int delta_;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// public static data
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
static int adjust_ ;
|
|
Packit |
01d647 |
static int tz_ ;
|
|
Packit |
01d647 |
static int dst_ ;
|
|
Packit |
01d647 |
static time_t deltaMax_;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// public static member functions
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
static int Adjust() {return Position::adjust_ + Position::tz_ + Position::dst_ ;}
|
|
Packit |
01d647 |
static int tz() {return tz_ ;}
|
|
Packit |
01d647 |
static int dst() {return dst_ ;}
|
|
Packit |
01d647 |
static int adjust() {return adjust_;}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
static std::string toExifString(double d,bool bRational,bool bLat);
|
|
Packit |
01d647 |
static std::string toExifString(double d);
|
|
Packit |
01d647 |
static std::string toExifTimeStamp(std::string& t);
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Position::toExifTimeStamp(std::string& t)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char result[200];
|
|
Packit |
01d647 |
const char* arg = t.c_str();
|
|
Packit |
01d647 |
int HH = 0 ;
|
|
Packit |
01d647 |
int mm = 0 ;
|
|
Packit |
01d647 |
int SS = 0 ;
|
|
Packit |
01d647 |
if ( strstr(arg,":") || strstr(arg,"-") ) {
|
|
Packit |
01d647 |
int YY,MM,DD ;
|
|
Packit |
01d647 |
char a,b,c,d,e ;
|
|
Packit |
01d647 |
sscanf(arg,"%d%c%d%c%d%c%d%c%d%c%d",&YY,&a,&MM,&b,&DD,&c,&HH,&d,&mm,&e,&SS;;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
sprintf(result,"%d/1 %d/1 %d/1",HH,mm,SS);
|
|
Packit |
01d647 |
return std::string(result);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Position::toExifString(double d)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char result[200];
|
|
Packit |
01d647 |
d *= 100;
|
|
Packit |
01d647 |
sprintf(result,"%d/100",abs((int)d));
|
|
Packit |
01d647 |
return std::string(result);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Position::toExifString(double d,bool bRational,bool bLat)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const char* NS = d>=0.0?"N":"S";
|
|
Packit |
01d647 |
const char* EW = d>=0.0?"E":"W";
|
|
Packit |
01d647 |
const char* NSEW = bLat ? NS: EW;
|
|
Packit |
01d647 |
if ( d < 0 ) d = -d;
|
|
Packit |
01d647 |
int deg = (int) d;
|
|
Packit |
01d647 |
d -= deg;
|
|
Packit |
01d647 |
d *= 60;
|
|
Packit |
01d647 |
int min = (int) d ;
|
|
Packit |
01d647 |
d -= min;
|
|
Packit |
01d647 |
d *= 60;
|
|
Packit |
01d647 |
int sec = (int)d;
|
|
Packit |
01d647 |
char result[200];
|
|
Packit |
01d647 |
if ( bRational )
|
|
Packit |
01d647 |
sprintf(result,"%d/1 %d/1 %d/1" ,deg,min,sec);
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
sprintf(result,"%03d%s%02d'%02d\"%s" ,deg,gDeg,min,sec,NSEW);
|
|
Packit |
01d647 |
return std::string(result);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Position::toString()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
char result[200];
|
|
Packit |
01d647 |
std::string sLat = Position::toExifString(lat_,false,true );
|
|
Packit |
01d647 |
std::string sLon = Position::toExifString(lon_,false,false);
|
|
Packit |
01d647 |
sprintf(result,"%s %s %-8.3f",sLon.c_str(),sLat.c_str(),ele_);
|
|
Packit |
01d647 |
return std::string(result);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// defaults
|
|
Packit |
01d647 |
int Position::adjust_ = 0;
|
|
Packit |
01d647 |
int Position::tz_ = timeZoneAdjust();
|
|
Packit |
01d647 |
int Position::dst_ = 0;
|
|
Packit |
01d647 |
time_t Position::deltaMax_ = 60 ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
///////////////////////////////////////////////////////////
|
|
Packit |
01d647 |
// UserData - used by XML Parser
|
|
Packit |
01d647 |
class UserData
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
explicit UserData(Options& options):
|
|
Packit |
01d647 |
indent(0)
|
|
Packit |
01d647 |
, count(0)
|
|
Packit |
01d647 |
, nTrkpt(0)
|
|
Packit |
01d647 |
, bTime(false)
|
|
Packit |
01d647 |
, bEle(false)
|
|
Packit |
01d647 |
, ele(0.0)
|
|
Packit |
01d647 |
, lat(0.0)
|
|
Packit |
01d647 |
, lon(0.0)
|
|
Packit |
01d647 |
, options_(options)
|
|
Packit |
01d647 |
{}
|
|
Packit |
01d647 |
virtual ~UserData() {}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// public data members
|
|
Packit |
01d647 |
int indent;
|
|
Packit |
01d647 |
size_t count ;
|
|
Packit |
01d647 |
Position now ;
|
|
Packit |
01d647 |
Position prev;
|
|
Packit |
01d647 |
int nTrkpt;
|
|
Packit |
01d647 |
bool bTime ;
|
|
Packit |
01d647 |
bool bEle ;
|
|
Packit |
01d647 |
double ele;
|
|
Packit |
01d647 |
double lat;
|
|
Packit |
01d647 |
double lon;
|
|
Packit |
01d647 |
std::string xmlt;
|
|
Packit |
01d647 |
std::string exift;
|
|
Packit |
01d647 |
time_t time;
|
|
Packit |
01d647 |
Options& options_;
|
|
Packit |
01d647 |
// static public data memembers
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// XML Parser Callbacks
|
|
Packit |
01d647 |
static void startElement(void* userData, const char* name, const char** atts )
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
UserData* me = (UserData*) userData;
|
|
Packit |
01d647 |
//for ( int i = 0 ; i < me->indent ; i++ ) printf(" ");
|
|
Packit |
01d647 |
//printf("begin %s\n",name);
|
|
Packit |
01d647 |
me->bTime = strcmp(name,"time")==0;
|
|
Packit |
01d647 |
me->bEle = strcmp(name,"ele")==0;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( strcmp(name,"trkpt")==0 ) {
|
|
Packit |
01d647 |
me->nTrkpt++;
|
|
Packit |
01d647 |
while ( *atts ) {
|
|
Packit |
01d647 |
const char* a=atts[0];
|
|
Packit |
01d647 |
const char* v=atts[1];
|
|
Packit |
01d647 |
if ( !strcmp(a,"lat") ) me->lat = atof(v);
|
|
Packit |
01d647 |
if ( !strcmp(a,"lon") ) me->lon = atof(v);
|
|
Packit |
01d647 |
atts += 2 ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
me->count++ ;
|
|
Packit |
01d647 |
me->indent++ ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
static void endElement(void* userData, const char* name)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
UserData* me = (UserData*) userData;
|
|
Packit |
01d647 |
me->indent-- ;
|
|
Packit |
01d647 |
if ( strcmp(name,"trkpt")==0 ) {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
me->nTrkpt--;
|
|
Packit |
01d647 |
me->now = Position(me->time,me->lat,me->lon,me->ele) ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( !me->prev.good() && me->options_.verbose ) {
|
|
Packit |
01d647 |
printf("trkseg %s begin ",me->now.getTimeString().c_str());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// remember our location and put it in gTimeDict
|
|
Packit |
01d647 |
gTimeDict[me->time] = me->now ;
|
|
Packit |
01d647 |
me->prev = me->now ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( strcmp(name,"trkseg")==0 && me->options_.verbose ) {
|
|
Packit |
01d647 |
printf("%s end\n",me->now.getTimeString().c_str());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void charHandler(void* userData,const char* s,int len)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
UserData* me = (UserData*) userData;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( me->nTrkpt == 1 ) {
|
|
Packit |
01d647 |
char buffer[100];
|
|
Packit |
01d647 |
int l_max = 98 ; // lengthof(buffer) -2 ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( me->bTime && len > 5 ) {
|
|
Packit |
01d647 |
if ( len < l_max ) {
|
|
Packit |
01d647 |
memcpy(buffer,s,len);
|
|
Packit |
01d647 |
buffer[len]=0;
|
|
Packit |
01d647 |
char* b = buffer ;
|
|
Packit |
01d647 |
while ( *b == ' ' && b < buffer+len ) b++ ;
|
|
Packit |
01d647 |
me->xmlt = b ;
|
|
Packit |
01d647 |
me->time = parseTime(me->xmlt.c_str());
|
|
Packit |
01d647 |
me->exift = getExifTime(me->time);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
me->bTime=false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( me->bEle && len > 2 ) {
|
|
Packit |
01d647 |
if ( len < l_max ) {
|
|
Packit |
01d647 |
memcpy(buffer,s,len);
|
|
Packit |
01d647 |
buffer[len]=0;
|
|
Packit |
01d647 |
char* b = buffer ;
|
|
Packit |
01d647 |
while ( *b == ' ' && b < buffer+len ) b++ ;
|
|
Packit |
01d647 |
me->ele = atof(b);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
me->bEle=false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
///////////////////////////////////////////////////////////
|
|
Packit |
01d647 |
// Time Functions
|
|
Packit |
01d647 |
time_t parseTime(const char* arg,bool bAdjust)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
time_t result = 0 ;
|
|
Packit |
01d647 |
try {
|
|
Packit |
01d647 |
//559 rmills@rmills-imac:~/bin $ exiv2 -pa ~/R.jpg | grep -i date
|
|
Packit |
01d647 |
//Exif.Image.DateTime Ascii 20 2009:08:03 08:58:57
|
|
Packit |
01d647 |
//Exif.Photo.DateTimeOriginal Ascii 20 2009:08:03 08:58:57
|
|
Packit |
01d647 |
//Exif.Photo.DateTimeDigitized Ascii 20 2009:08:03 08:58:57
|
|
Packit |
01d647 |
//Exif.GPSInfo.GPSDateStamp Ascii 21 2009-08-03T15:58:57Z
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// <time>2012-07-14T17:33:16Z</time>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( strstr(arg,":") || strstr(arg,"-") ) {
|
|
Packit |
01d647 |
int YY,MM,DD,HH,mm,SS ;
|
|
Packit |
01d647 |
char a,b,c,d,e ;
|
|
Packit |
01d647 |
sscanf(arg,"%d%c%d%c%d%c%d%c%d%c%d",&YY,&a,&MM,&b,&DD,&c,&HH,&d,&mm,&e,&SS;;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
struct tm T;
|
|
Packit |
01d647 |
memset(&T,0,sizeof(T));
|
|
Packit |
01d647 |
T.tm_min = mm ;
|
|
Packit |
01d647 |
T.tm_hour = HH ;
|
|
Packit |
01d647 |
T.tm_sec = SS ;
|
|
Packit |
01d647 |
if ( bAdjust ) T.tm_sec -= Position::Adjust();
|
|
Packit |
01d647 |
T.tm_year = YY -1900 ;
|
|
Packit |
01d647 |
T.tm_mon = MM -1 ;
|
|
Packit |
01d647 |
T.tm_mday = DD ;
|
|
Packit |
01d647 |
T.tm_isdst = -1 ; // determine value automatically (otherwise hour may shift)
|
|
Packit |
01d647 |
result = mktime(&T);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
} catch ( ... ) {};
|
|
Packit |
01d647 |
return result ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// West of GMT is negative (PDT = Pacific Daylight = -07:00 == -25200 seconds
|
|
Packit |
01d647 |
int timeZoneAdjust()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
time_t now = time(NULL);
|
|
Packit |
01d647 |
int offset;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#if defined(_MSC_VER) || defined(__MINGW__)
|
|
Packit |
01d647 |
TIME_ZONE_INFORMATION TimeZoneInfo;
|
|
Packit |
01d647 |
GetTimeZoneInformation( &TimeZoneInfo );
|
|
Packit |
01d647 |
offset = - (((int)TimeZoneInfo.Bias + (int)TimeZoneInfo.DaylightBias) * 60);
|
|
Packit |
01d647 |
UNUSED(now);
|
|
Packit |
01d647 |
#elif defined(__CYGWIN__)
|
|
Packit |
01d647 |
struct tm lcopy = *localtime(&now;;
|
|
Packit |
01d647 |
time_t gmt = timegm(&lcopy) ; // timegm modifies lcopy
|
|
Packit |
01d647 |
offset = (int) ( ((long signed int) gmt) - ((long signed int) now) ) ;
|
|
Packit |
01d647 |
#elif defined(OS_SOLARIS)
|
|
Packit |
01d647 |
struct tm local = *localtime(&now) ;
|
|
Packit |
01d647 |
time_t local_tt = (int) mktime(&local);
|
|
Packit |
01d647 |
time_t time_gmt = (int) mktime(gmtime(&now));
|
|
Packit |
01d647 |
offset = time_gmt - local_tt;
|
|
Packit |
01d647 |
#else
|
|
Packit |
01d647 |
struct tm local = *localtime(&now) ;
|
|
Packit |
01d647 |
offset = local.tm_gmtoff ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#if EXIV2_DEBUG_MESSAGES
|
|
Packit |
01d647 |
struct tm utc = *gmtime(&now;;
|
|
Packit |
01d647 |
printf("utc : offset = %6d dst = %d time = %s", 0 ,utc .tm_isdst, asctime(&utc ));
|
|
Packit |
01d647 |
printf("local: offset = %6d dst = %d time = %s", offset,local.tm_isdst, asctime(&local));
|
|
Packit |
01d647 |
printf("timeZoneAdjust = %6d\n",offset);
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
return offset ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
string getExifTime(const time_t t)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
static char result[100];
|
|
Packit |
01d647 |
strftime(result,sizeof(result),"%Y-%m-%d %H:%M:%S",localtime(&t);;
|
|
Packit |
01d647 |
return result ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string makePath(const std::string& dir, const std::string& file)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return dir + std::string(EXV_SEPARATOR_STR) + file ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* makePath(const char* dir,const char* file)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
static char result[_MAX_PATH] ;
|
|
Packit |
01d647 |
std::string r = makePath(std::string(dir),std::string(file));
|
|
Packit |
01d647 |
strcpy(result,r.c_str());
|
|
Packit |
01d647 |
return result;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// file utilities
|
|
Packit |
01d647 |
bool readDir(const char* path,Options& options)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
bool bResult = false;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef _MSC_VER
|
|
Packit |
01d647 |
DWORD attrs = GetFileAttributes(path);
|
|
Packit |
01d647 |
bool bOKAttrs = attrs != INVALID_FILE_ATTRIBUTES;
|
|
Packit |
01d647 |
bool bIsDir = (attrs & FILE_ATTRIBUTE_DIRECTORY) ? true : false ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if( bOKAttrs && bIsDir ) {
|
|
Packit |
01d647 |
bResult = true ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
char search[_MAX_PATH+10];
|
|
Packit |
01d647 |
strcpy_s(search,_MAX_PATH,path);
|
|
Packit |
01d647 |
strcat_s(search,_MAX_PATH,"\\*");
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
WIN32_FIND_DATA ffd;
|
|
Packit |
01d647 |
HANDLE hFind = FindFirstFile(search, &ffd;;
|
|
Packit |
01d647 |
BOOL bGo = hFind != INVALID_HANDLE_VALUE;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( bGo ) {
|
|
Packit |
01d647 |
while ( bGo ) {
|
|
Packit |
01d647 |
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// _tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string pathName = makePath(path,std::string(ffd.cFileName));
|
|
Packit |
01d647 |
if ( getFileType(pathName,options) == typeImage ) {
|
|
Packit |
01d647 |
gFiles.push_back( pathName );
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
bGo = FindNextFile(hFind, &ffd) != 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
// CloseHandle(hFind);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#else
|
|
Packit |
01d647 |
DIR* dir = opendir (path);
|
|
Packit |
01d647 |
if (dir != NULL)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
bResult = true;
|
|
Packit |
01d647 |
struct dirent* ent;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// print all the files and directories within directory
|
|
Packit |
01d647 |
while ((ent = readdir (dir)) != NULL)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string pathName = makePath(path,ent->d_name);
|
|
Packit |
01d647 |
struct stat buf ;
|
|
Packit |
01d647 |
lstat(path, &buf );
|
|
Packit |
01d647 |
if ( ent->d_name[0] != '.' ) {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// printf("reading %s => %s\n",ent->d_name,pathName.c_str());
|
|
Packit |
01d647 |
if ( getFileType(pathName,options) == typeImage ) {
|
|
Packit |
01d647 |
gFiles.push_back( pathName );
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
closedir (dir);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
return bResult ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
inline size_t sip(FILE* f,char* buffer,size_t max_len,size_t len)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
while ( !feof(f) && len < max_len && buffer[len-1] != '>')
|
|
Packit |
01d647 |
buffer[len++] = fgetc(f);
|
|
Packit |
01d647 |
return len;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool readXML(const char* path,Options& options)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
FILE* f = fopen(path,"r");
|
|
Packit |
01d647 |
XML_Parser parser = XML_ParserCreate(NULL);
|
|
Packit |
01d647 |
bool bResult = f && parser ;
|
|
Packit |
01d647 |
if ( bResult ) {
|
|
Packit |
01d647 |
char buffer[8*1024];
|
|
Packit |
01d647 |
UserData me(options) ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
XML_SetUserData (parser, &me);
|
|
Packit |
01d647 |
XML_SetElementHandler (parser, startElement, endElement);
|
|
Packit |
01d647 |
XML_SetCharacterDataHandler(parser,charHandler);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// a little sip at the data
|
|
Packit |
01d647 |
size_t len = fread(buffer,1,sizeof(buffer)-100,f);
|
|
Packit |
01d647 |
const char* lead = "
|
|
Packit |
01d647 |
bResult = strncmp(lead,buffer,strlen(lead))==0;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// swallow it
|
|
Packit |
01d647 |
if ( bResult ) {
|
|
Packit |
01d647 |
len = sip(f,buffer,sizeof buffer,len);
|
|
Packit |
01d647 |
bResult = XML_Parse(parser, buffer,(int)len, len == 0 ) == XML_STATUS_OK;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// drink the rest of the file
|
|
Packit |
01d647 |
while ( bResult && len != 0 ) {
|
|
Packit |
01d647 |
len = fread(buffer,1,sizeof(buffer)-100,f);
|
|
Packit |
01d647 |
len = sip(f,buffer,sizeof buffer,len);
|
|
Packit |
01d647 |
bResult = XML_Parse(parser, buffer,(int)len, len == 0 ) == XML_STATUS_OK;
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( f ) fclose(f);
|
|
Packit |
01d647 |
if ( parser ) XML_ParserFree(parser);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return bResult ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool readImage(const char* path,Options& /* options */)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
using namespace Exiv2;
|
|
Packit |
01d647 |
bool bResult = false ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
try {
|
|
Packit |
01d647 |
Image::AutoPtr image = ImageFactory::open(path);
|
|
Packit |
01d647 |
if ( image.get() ) {
|
|
Packit |
01d647 |
image->readMetadata();
|
|
Packit |
01d647 |
ExifData &exifData = image->exifData();
|
|
Packit |
01d647 |
bResult = !exifData.empty();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
} catch ( ... ) {};
|
|
Packit |
01d647 |
return bResult ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
time_t readImageTime(const std::string& path,std::string* pS=NULL)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
using namespace Exiv2;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
time_t result = 0 ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* dateStrings[] =
|
|
Packit |
01d647 |
{ "Exif.Photo.DateTimeOriginal"
|
|
Packit |
01d647 |
, "Exif.Photo.DateTimeDigitized"
|
|
Packit |
01d647 |
, "Exif.Image.DateTime"
|
|
Packit |
01d647 |
, NULL
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
const char* dateString = dateStrings[0] ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
do {
|
|
Packit |
01d647 |
try {
|
|
Packit |
01d647 |
Image::AutoPtr image = ImageFactory::open(path);
|
|
Packit |
01d647 |
if ( image.get() ) {
|
|
Packit |
01d647 |
image->readMetadata();
|
|
Packit |
01d647 |
ExifData &exifData = image->exifData();
|
|
Packit |
01d647 |
// printf("%s => %s\n",dateString, exifData[dateString].toString().c_str());
|
|
Packit |
01d647 |
result = parseTime(exifData[dateString].toString().c_str(),true);
|
|
Packit |
01d647 |
if ( result && pS ) *pS = exifData[dateString].toString();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
} catch ( ... ) {};
|
|
Packit |
01d647 |
} while ( !result && ++dateString );
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return result ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool sina(const char* s,const char** a)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
bool bResult = false ;
|
|
Packit |
01d647 |
int i = 0 ;
|
|
Packit |
01d647 |
while ( *s == '-' ) s++;
|
|
Packit |
01d647 |
while ( !bResult && a[i]) {
|
|
Packit |
01d647 |
const char* A = a[i] ;
|
|
Packit |
01d647 |
while ( *A == '-' ) A++ ;
|
|
Packit |
01d647 |
bResult = stricmp(s,A)==0;
|
|
Packit |
01d647 |
i++;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return bResult;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int readFile(const char* path,Options /* options */)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
FILE* f = fopen(path,"r");
|
|
Packit |
01d647 |
int nResult = f ? typeFile : typeUnknown;
|
|
Packit |
01d647 |
if ( f ) {
|
|
Packit |
01d647 |
const char* ext = strstr(path,".");
|
|
Packit |
01d647 |
if ( ext ) {
|
|
Packit |
01d647 |
const char* docs[] = { ".doc",".txt", NULL };
|
|
Packit |
01d647 |
const char* code[] = { ".cpp",".h" ,".pl" ,".py" ,".pyc", NULL };
|
|
Packit |
01d647 |
if ( sina(ext,docs) )
|
|
Packit |
01d647 |
nResult = typeDoc;
|
|
Packit |
01d647 |
if ( sina(ext,code) )
|
|
Packit |
01d647 |
nResult = typeCode;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( f ) fclose(f) ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return nResult ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Position* searchTimeDict(TimeDict_t& td, const time_t& time,long long delta)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Position* result = NULL;
|
|
Packit |
01d647 |
for ( int t = 0 ; !result && t < delta ; t++ ) {
|
|
Packit |
01d647 |
for ( int x = 0 ; !result && x < 2 ; x++ ) {
|
|
Packit |
01d647 |
int T = t * ((x==0)?-1:1);
|
|
Packit |
01d647 |
if ( td.count(time+T) ) {
|
|
Packit |
01d647 |
result = &td[time+T];
|
|
Packit |
01d647 |
result->delta(T);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return result;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int getFileType(std::string& path,Options& options) { return getFileType(path.c_str(),options); }
|
|
Packit |
01d647 |
int getFileType(const char* path,Options& options)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return readXML (path,options) ? typeXML
|
|
Packit |
01d647 |
: readDir (path,options) ? typeDirectory
|
|
Packit |
01d647 |
: readImage(path,options) ? typeImage
|
|
Packit |
01d647 |
: readFile (path,options)
|
|
Packit |
01d647 |
;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int version(const char* program)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
printf("%s: %s %s\n",program,__DATE__,__TIME__);
|
|
Packit |
01d647 |
return 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int help(const char* program,char const* words[],int nWords,bool /*bVerbose*/)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
printf("usage: %s ",program);
|
|
Packit |
01d647 |
for ( int i = 0 ; i < nWords ; i++ ) {
|
|
Packit |
01d647 |
if ( words[i] )
|
|
Packit |
01d647 |
printf("%c-%s%s",i?'|':'{',words[i],i>(-kwNOVALUE)?" value":"");
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
printf("}+ path+\n");
|
|
Packit |
01d647 |
return 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int compare(const char* a,const char* b)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int result=*a && *b;
|
|
Packit |
01d647 |
while ( result && *a && *b) {
|
|
Packit |
01d647 |
char A=*a++;
|
|
Packit |
01d647 |
char B=*b++;
|
|
Packit |
01d647 |
result=tolower(A)==tolower(B);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return result;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int find(const char* arg,char const* words[],int nWords)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if ( arg[0] != '-' ) return kwSYNTAX;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int result=0;
|
|
Packit |
01d647 |
int count =0;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for ( int i = 0 ; i < nWords ; i++) {
|
|
Packit |
01d647 |
int j = 0 ;
|
|
Packit |
01d647 |
while ( arg[j] == '-' ) j++;
|
|
Packit |
01d647 |
if ( ::compare(arg+j,words[i]) ) {
|
|
Packit |
01d647 |
result = i ;
|
|
Packit |
01d647 |
count++;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return count==1?result:kwSYNTAX;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int parseTZ(const char* adjust)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int h=0;
|
|
Packit |
01d647 |
int m=0;
|
|
Packit |
01d647 |
char c ;
|
|
Packit |
01d647 |
try {
|
|
Packit |
01d647 |
sscanf(adjust,"%d%c%d",&h,&c,&m);
|
|
Packit |
01d647 |
} catch ( ... ) {} ;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return (3600*h)+(60*m);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool mySort(const std::string& a, const std::string& b)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
time_t A = readImageTime(a);
|
|
Packit |
01d647 |
time_t B = readImageTime(b);
|
|
Packit |
01d647 |
return (A
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int main(int argc,const char* argv[])
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int result=0;
|
|
Packit |
01d647 |
const char* program = argv[0];
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* types[typeMax];
|
|
Packit |
01d647 |
types[typeUnknown ] = "unknown";
|
|
Packit |
01d647 |
types[typeDirectory] = "directory";
|
|
Packit |
01d647 |
types[typeImage ] = "image";
|
|
Packit |
01d647 |
types[typeXML ] = "xml";
|
|
Packit |
01d647 |
types[typeDoc ] = "doc";
|
|
Packit |
01d647 |
types[typeCode ] = "code";
|
|
Packit |
01d647 |
types[typeFile ] = "file";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
char const* keywords[kwMAX];
|
|
Packit |
01d647 |
memset(keywords,0,sizeof(keywords));
|
|
Packit |
01d647 |
keywords[kwHELP ] = "help";
|
|
Packit |
01d647 |
keywords[kwVERSION ] = "version";
|
|
Packit |
01d647 |
keywords[kwVERBOSE ] = "verbose";
|
|
Packit |
01d647 |
keywords[kwDRYRUN ] = "dryrun";
|
|
Packit |
01d647 |
keywords[kwASCII ] = "ascii";
|
|
Packit |
01d647 |
keywords[kwDST ] = "dst";
|
|
Packit |
01d647 |
keywords[kwADJUST ] = "adjust";
|
|
Packit |
01d647 |
keywords[kwTZ ] = "tz";
|
|
Packit |
01d647 |
keywords[kwDELTA ] = "delta";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
map<std::string,string> shorts;
|
|
Packit |
01d647 |
shorts["-?"] = "-help";
|
|
Packit |
01d647 |
shorts["-h"] = "-help";
|
|
Packit |
01d647 |
shorts["-v"] = "-verbose";
|
|
Packit |
01d647 |
shorts["-V"] = "-version";
|
|
Packit |
01d647 |
shorts["-d"] = "-dst";
|
|
Packit |
01d647 |
shorts["-a"] = "-adjust";
|
|
Packit |
01d647 |
shorts["-t"] = "-tz";
|
|
Packit |
01d647 |
shorts["-D"] = "-delta";
|
|
Packit |
01d647 |
shorts["-s"] = "-delta";
|
|
Packit |
01d647 |
shorts["-X"] = "-dryrun";
|
|
Packit |
01d647 |
shorts["-a"] = "-ascii";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Options options ;
|
|
Packit |
01d647 |
options.help = sina(keywords[kwHELP ],argv) || argc < 2;
|
|
Packit |
01d647 |
options.verbose = sina(keywords[kwVERBOSE],argv);
|
|
Packit |
01d647 |
options.dryrun = sina(keywords[kwDRYRUN ],argv);
|
|
Packit |
01d647 |
options.version = sina(keywords[kwVERSION],argv);
|
|
Packit |
01d647 |
options.dst = sina(keywords[kwDST ],argv);
|
|
Packit |
01d647 |
options.ascii = sina(keywords[kwASCII ],argv);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for ( int i = 1 ; !result && i < argc ; i++ ) {
|
|
Packit |
01d647 |
const char* arg = argv[i++];
|
|
Packit |
01d647 |
if ( shorts.count(arg) ) arg = shorts[arg].c_str();
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* value = argv[i ];
|
|
Packit |
01d647 |
int ivalue = ::atoi(value?value:"0");
|
|
Packit |
01d647 |
int key = ::find(arg,keywords,kwMAX);
|
|
Packit |
01d647 |
int needv = key < kwMAX && key > (-kwNOVALUE);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (!needv ) i--;
|
|
Packit |
01d647 |
if ( needv && !value) key = kwNEEDVALUE;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
switch ( key ) {
|
|
Packit |
01d647 |
case kwDST : options.dst = true ; break;
|
|
Packit |
01d647 |
case kwHELP : options.help = true ; break;
|
|
Packit |
01d647 |
case kwVERSION : options.version = true ; break;
|
|
Packit |
01d647 |
case kwDRYRUN : options.dryrun = true ; break;
|
|
Packit |
01d647 |
case kwVERBOSE : options.verbose = true ; break;
|
|
Packit |
01d647 |
case kwASCII : options.ascii = true ; break;
|
|
Packit |
01d647 |
case kwTZ : Position::tz_ = parseTZ(value);break;
|
|
Packit |
01d647 |
case kwADJUST : Position::adjust_ = ivalue;break;
|
|
Packit |
01d647 |
case kwDELTA : Position::deltaMax_ = ivalue;break;
|
|
Packit |
01d647 |
case kwNEEDVALUE: fprintf(stderr,"error: %s requires a value\n",arg); result = resultSyntaxError ; break ;
|
|
Packit |
01d647 |
case kwSYNTAX : default:
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int type = getFileType(arg,options) ;
|
|
Packit |
01d647 |
if ( options.verbose ) printf("%s %s ",arg,types[type]) ;
|
|
Packit |
01d647 |
if ( type == typeImage ) {
|
|
Packit |
01d647 |
time_t t = readImageTime(std::string(arg)) ;
|
|
Packit |
01d647 |
#ifdef __APPLE__
|
|
Packit |
01d647 |
char buffer[1024];
|
|
Packit |
01d647 |
#else
|
|
Packit |
01d647 |
char* buffer = NULL;
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
char* path = realpath(arg,buffer);
|
|
Packit |
01d647 |
if ( t && path ) {
|
|
Packit |
01d647 |
if ( options.verbose) printf("%s %ld %s",path,(long int)t,asctime(localtime(&t)));
|
|
Packit |
01d647 |
gFiles.push_back(path);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( path && path != buffer ) ::free((void*) path);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( type == typeUnknown ) {
|
|
Packit |
01d647 |
fprintf(stderr,"error: illegal syntax %s\n",arg);
|
|
Packit |
01d647 |
result = resultSyntaxError ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
} break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( options.help ) ::help(program,keywords,kwMAX,options.verbose);
|
|
Packit |
01d647 |
if ( options.version ) ::version(program);
|
|
Packit |
01d647 |
gDeg = options.ascii ? "deg" : "°";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if ( !result ) {
|
|
Packit |
01d647 |
sort(gFiles.begin(),gFiles.end(),mySort);
|
|
Packit |
01d647 |
if ( options.dst ) Position::dst_ = 3600;
|
|
Packit |
01d647 |
if ( options.verbose ) {
|
|
Packit |
01d647 |
int t = Position::tz();
|
|
Packit |
01d647 |
int d = Position::dst();
|
|
Packit |
01d647 |
int a = Position::adjust();
|
|
Packit |
01d647 |
int A = Position::Adjust();
|
|
Packit |
01d647 |
int s = A ;
|
|
Packit |
01d647 |
int h = s/3600;
|
|
Packit |
01d647 |
s-= h*3600;
|
|
Packit |
01d647 |
s = abs(s);
|
|
Packit |
01d647 |
int m = s/60 ;
|
|
Packit |
01d647 |
s-= m*60 ;
|
|
Packit |
01d647 |
printf("tz,dst,adjust = %d,%d,%d total = %dsecs (= %d:%d:%d)\n",t,d,a,A,h,m,s);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
/*
|
|
Packit |
01d647 |
if ( options.verbose ) {
|
|
Packit |
01d647 |
printf("Time Dictionary\n");
|
|
Packit |
01d647 |
for ( TimeDict_i it = gTimeDict.begin() ; it != gTimeDict.end() ; it++ ) {
|
|
Packit |
01d647 |
std::string sTime = getExifTime(it->first);
|
|
Packit |
01d647 |
Position* pPos = &it->second;
|
|
Packit |
01d647 |
std::string sPos = Position::toExifString(pPos->lat(),false,true)
|
|
Packit |
01d647 |
+ " "
|
|
Packit |
01d647 |
+ Position::toExifString(pPos->lon(),false,true)
|
|
Packit |
01d647 |
;
|
|
Packit |
01d647 |
printf("%s %s\n",sTime.c_str(), sPos.c_str());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
for ( size_t p = 0 ; p < gFiles.size() ; p++ ) {
|
|
Packit |
01d647 |
std::string path = gFiles[p] ;
|
|
Packit |
01d647 |
std::string stamp ;
|
|
Packit |
01d647 |
try {
|
|
Packit |
01d647 |
time_t t = readImageTime(path,&stamp) ;
|
|
Packit |
01d647 |
Position* pPos = searchTimeDict(gTimeDict,t,Position::deltaMax_);
|
|
Packit |
01d647 |
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
|
|
Packit |
01d647 |
if ( image.get() ) {
|
|
Packit |
01d647 |
image->readMetadata();
|
|
Packit |
01d647 |
Exiv2::ExifData& exifData = image->exifData();
|
|
Packit |
01d647 |
if ( pPos ) {
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSProcessingMethod" ] = "65 83 67 73 73 0 0 0 72 89 66 82 73 68 45 70 73 88"; // ASCII HYBRID-FIX
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSVersionID" ] = "2 2 0 0";
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSMapDatum" ] = "WGS-84";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSLatitude" ] = Position::toExifString(pPos->lat(),true,true);
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSLongitude" ] = Position::toExifString(pPos->lon(),true,false);
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSAltitude" ] = Position::toExifString(pPos->ele());
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSAltitudeRef" ] = pPos->ele()<0.0?"1":"0";
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSLatitudeRef" ] = pPos->lat()>0?"N":"S";
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSLongitudeRef" ] = pPos->lon()>0?"E":"W";
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSDateStamp" ] = stamp;
|
|
Packit |
01d647 |
exifData["Exif.GPSInfo.GPSTimeStamp" ] = Position::toExifTimeStamp(stamp);
|
|
Packit |
01d647 |
exifData["Exif.Image.GPSTag" ] = 4908;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
printf("%s %s % 2d\n",path.c_str(),pPos->toString().c_str(),pPos->delta());
|
|
Packit |
01d647 |
} else {
|
|
Packit |
01d647 |
printf("%s *** not in time dict ***\n",path.c_str());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if ( !options.dryrun ) image->writeMetadata();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
} catch ( ... ) {};
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return result ;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// That's all Folks!
|
|
Packit |
01d647 |
////
|