You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
4.8 KiB
C++
228 lines
4.8 KiB
C++
// ***************************************************************** -*- C++ -*-
|
|
// geotag.cpp, $Rev: 2286 $
|
|
// Sample program to read gpx files and update the images with GPS tags
|
|
// Work in progress - doesn't do anything yet!
|
|
|
|
#include <exiv2/exiv2.hpp>
|
|
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <cassert>
|
|
|
|
#include <sys/types.h>
|
|
#include <stdio.h>
|
|
#include "expat.h"
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
typedef std::vector<std::string> strings_t ;
|
|
|
|
#ifndef lengthof
|
|
#define lengthof(x) (sizeof(*x)/sizeof(x))
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <windows.h>
|
|
#if _MSC_VER < 1400
|
|
#define strcpy_s(d,l,s) strcpy(d,s)
|
|
#define strcat_s(d,l,s) strcat(d,s)
|
|
#endif
|
|
|
|
#else
|
|
#include <dirent.h>
|
|
#endif
|
|
|
|
enum
|
|
{ typeUnknown = 0
|
|
, typeDirectory = 1
|
|
, typeImage = 2
|
|
, typeXML = 3
|
|
, typeFile = 4
|
|
};
|
|
static const char* types[] = { "unknown" , "directory" , "image" , "xml" ,"file" };
|
|
|
|
class UserData
|
|
{
|
|
public:
|
|
UserData() : indent(0),count(0) {};
|
|
virtual ~UserData() {} ;
|
|
|
|
// public data members
|
|
int indent;
|
|
size_t count ;
|
|
};
|
|
|
|
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->count++ ;
|
|
me->indent++ ;
|
|
}
|
|
static void endElement(void* userData, const char* name)
|
|
{
|
|
UserData* me = (UserData*) userData;
|
|
me->indent-- ;
|
|
for ( int i = 0 ; i < me->indent ; i++ ) printf(" ");
|
|
printf("end %s\n",name);
|
|
}
|
|
|
|
|
|
bool readDir(char* path,strings_t& paths)
|
|
{
|
|
paths.empty();
|
|
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 <DIR>\n"), ffd.cFileName);
|
|
}
|
|
else
|
|
{
|
|
paths.push_back( std::string(ffd.cFileName));
|
|
printf("-> %s\n",ffd.cFileName);
|
|
}
|
|
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)
|
|
{
|
|
printf ("%s\n", ent->d_name);
|
|
paths.push_back(std::string(ent->d_name)) ;
|
|
}
|
|
closedir (dir);
|
|
}
|
|
#endif
|
|
return bResult ;
|
|
}
|
|
|
|
bool readXML(char* path,size_t& count)
|
|
{
|
|
FILE* f = fopen(path,"r");
|
|
XML_Parser parser = XML_ParserCreate(NULL);
|
|
bool bResult = f && parser ;
|
|
if ( bResult ) {
|
|
char buffer[8*1024];
|
|
UserData me ;
|
|
|
|
XML_SetUserData(parser, &me);
|
|
XML_SetElementHandler(parser, startElement, endElement);
|
|
|
|
// a little sip at the data
|
|
size_t len = fread(buffer,1,sizeof(buffer),f);
|
|
const char* lead = "<?xml" ;
|
|
bResult = strncmp(lead,buffer,strlen(lead))==0;
|
|
|
|
// swallow it
|
|
if ( bResult ) {
|
|
bResult = XML_Parse(parser, buffer,(int)len, len == 0 ) == XML_STATUS_OK;
|
|
}
|
|
|
|
// drink the rest of the file
|
|
while ( bResult && !feof(f) ) {
|
|
len = fread(buffer,1,sizeof(buffer),f);
|
|
bResult = XML_Parse(parser, buffer,(int)len, len == 0 ) == XML_STATUS_OK;
|
|
};
|
|
count = me.count ;
|
|
}
|
|
|
|
if ( f ) fclose(f);
|
|
if ( parser ) XML_ParserFree(parser);
|
|
|
|
return bResult ;
|
|
}
|
|
|
|
bool readFile(char* path,size_t& count)
|
|
{
|
|
FILE* f = fopen(path,"r");
|
|
bool bResult = f ? true : false;
|
|
if ( bResult ) {
|
|
fseek(f,0L,SEEK_END);
|
|
count = ftell(f);
|
|
}
|
|
if ( f ) fclose(f) ;
|
|
|
|
return bResult ;
|
|
}
|
|
|
|
|
|
int main(int argc, char* const argv[])
|
|
{
|
|
if ( argc < 2 ) {
|
|
std::cout << "Usage: " << argv[0] << " arg+\n";
|
|
return 1;
|
|
}
|
|
|
|
for ( int i = 1 ; i < argc ; i++ ) {
|
|
char* arg = argv[i];
|
|
size_t count = 0 ;
|
|
int fileType = typeUnknown ;
|
|
|
|
if ( fileType == typeUnknown ) {
|
|
if ( readXML(arg,count) ) {
|
|
if ( count ) fileType = typeXML ;
|
|
}
|
|
}
|
|
|
|
if ( fileType == typeUnknown ) {
|
|
strings_t files ;
|
|
if ( readDir(arg,files) ) {
|
|
fileType = typeDirectory ;
|
|
count = files.size();
|
|
}
|
|
}
|
|
|
|
if ( fileType == typeUnknown ) try {
|
|
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(arg);
|
|
if ( image.get() ) {
|
|
Exiv2::ExifData &exifData = image->exifData();
|
|
image->readMetadata();
|
|
if ( !exifData.empty() ) {
|
|
fileType = typeImage ;
|
|
count = exifData.count();
|
|
}
|
|
}
|
|
} catch (Exiv2::Error& ) {};
|
|
|
|
if ( fileType == typeUnknown ) {
|
|
if ( readFile(arg,count) ) {
|
|
if ( count ) fileType = typeFile ;
|
|
}
|
|
}
|
|
|
|
printf("arg:%s type:%s count:%d\n",arg,types[fileType],count); ;
|
|
}
|
|
|
|
return 0;
|
|
}
|