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