From 8d2d73759dfe0c193c29b7e1f0b90a0873c3b9e7 Mon Sep 17 00:00:00 2001 From: Johannes Hofmann Date: Tue, 7 Apr 2009 14:30:26 +0200 Subject: switch ImageMetadata to exiv2 (mostly by Konrad Golling) --- configure.ac | 4 + src/ImageMetaData.cxx | 323 +++++++++++++++++++++++--------------------------- 2 files changed, 155 insertions(+), 172 deletions(-) diff --git a/configure.ac b/configure.ac index de7e818..e9cf00e 100644 --- a/configure.ac +++ b/configure.ac @@ -60,5 +60,9 @@ LIBS="`$GSLCONFIG --libs` $LIBS" AC_CHECK_HEADERS([tiffio.h], [], [echo "Error: tiffio.h not found."; exit 1;]) AC_CHECK_LIB([tiff], [TIFFOpen], [], [echo "Error: libtiff.so not found."; exit 1;]) +# Check for exiv2 +AC_CHECK_HEADERS([exiv2/exif.hpp], [], [echo "Error: exiv2/exif.hpp not found."; exit 1;]) +LIBS="$LIBS -lexiv2" + AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT diff --git a/src/ImageMetaData.cxx b/src/ImageMetaData.cxx index f22a641..1c3b2f5 100644 --- a/src/ImageMetaData.cxx +++ b/src/ImageMetaData.cxx @@ -12,12 +12,14 @@ #include #include #include +#include #include #include -#include #include -#include "util.h" +#include +#include + #include "ImageMetaData.H" ImageMetaData::ImageMetaData() { @@ -65,87 +67,89 @@ ImageMetaData::save_image(char *in_img, char *out_img) { return save_image_jpgcom(in_img, out_img); } -static double -degminsecstr2double(char *val) { - double ret, dv; - - ret = 0.0; - for (dv=1.0; dv <= 3600.0; dv = dv * 60.0) { - ret = ret + atof(val) / dv; - val = strchr(val, ','); - if (!val || val[1] == '\0') { - break; - } else { - val++; +int +ImageMetaData::load_image_exif(char *name) { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(name); + assert(image.get() != 0); + image->readMetadata(); + Exiv2::ExifData &exifData = image->exifData(); + if (exifData.empty()) + { + fprintf(stderr, "%s: No Exif data found in the file", name); + return 0; } - } - return ret; -} + Exiv2::ExifData::iterator pos = exifData.end(); + + if (!_manufacturer ) + { + Exiv2::ExifKey key("Exif.Image.Make"); // tag auch wirklich vorhanden? + pos = exifData.findKey(key); + if (pos != exifData.end() && pos->size() ) + _manufacturer = strdup(pos->toString().c_str()); + } -#define EXIF_MANUFACTURER 0x010f -#define EXIF_MODEL 0x0110 -#define EXIF_FOCAL_LENGTH 0x920a -#define EXIF_FOCAL_LENGTH_IN_35MM_FILM 0xa405 -#define EXIF_GPS_LATIITUDE 0x0002 -#define EXIF_GPS_LONGITUDE 0x0004 -#define EXIF_GPS_ALTITUDE 0x0006 + if(!_model) + { + Exiv2::ExifKey key("Exif.Image.Model"); + pos = exifData.findKey(key); + if (pos != exifData.end() && pos->size() ) + _model = strdup(pos->toString().c_str()); + } -int -ImageMetaData::load_image_exif(char *name) { - const char * args[32]; - FILE *p; - pid_t pid; - int status; - char buf[1024]; - char val[1024]; - int id; - - args[0] = "exif"; - args[1] = "-i"; - args[2] = "-m"; - args[3] = name; - args[4] = NULL; - - p = pexecvp(args[0], const_cast(args), &pid, "r"); - - if (p) { - while (fgets(buf, sizeof(buf), p) != NULL) { - if (sscanf(buf, "%x\t%[^\n]\n", &id, val) != 2) { - continue; + if (isnan(_focal_length)) + { + Exiv2::ExifKey key("Exif.Photo.FocalLength"); + pos = exifData.findKey(key); + if (pos != exifData.end() && pos->toFloat() >= 0) + _focal_length = pos->toFloat(); + } + + if (isnan(_focal_length_35mm)) + { + Exiv2::ExifKey key("Exif.Photo.FocalLengthIn35mmFilm"); + pos = exifData.findKey(key); + if (pos != exifData.end() && pos->toFloat() >= 0) + _focal_length_35mm = pos->toFloat(); + } + + if (isnan(_longitude)) + { + Exiv2::ExifKey key("Exif.GPSInfo.GPSLongitude"); + pos = exifData.findKey(key); + if (pos != exifData.end()) + { + if ( pos->toFloat() >= 0) + _longitude = pos->toFloat(); + if ( pos->toFloat(1) >= 0) + _longitude += pos->toFloat(1)/60; + if ( pos->toFloat(2) >= 0) + _longitude += pos->toFloat(2)/3600; } + } - switch(id) { - case EXIF_MANUFACTURER: - if (!_manufacturer) _manufacturer = strdup(val); - break; - case EXIF_MODEL: - if (!_model) _model = strdup(val); - break; - case EXIF_FOCAL_LENGTH: - if (isnan(_focal_length)) _focal_length = atof(val); - break; - case EXIF_FOCAL_LENGTH_IN_35MM_FILM: - if (isnan(_focal_length_35mm)) _focal_length_35mm = atof(val); - break; - case EXIF_GPS_LONGITUDE: - if (isnan(_longitude)) _longitude = degminsecstr2double(val); - break; - case EXIF_GPS_LATIITUDE: - if (isnan(_latitude)) _latitude = degminsecstr2double(val); - break; - case EXIF_GPS_ALTITUDE: - if (isnan(_height)) _height = atof(val); - break; + if (isnan(_latitude)) + { + Exiv2::ExifKey key("Exif.GPSInfo.GPSLatitude"); + pos = exifData.findKey(key); + if (pos != exifData.end()) + { + if ( pos->toFloat() >= 0) + _latitude = pos->toFloat(); + if ( pos->toFloat(1) >= 0) + _latitude += pos->toFloat(1)/60; + if ( pos->toFloat(2) >= 0) + _latitude += pos->toFloat(2)/3600; } } - } - fclose(p); - waitpid(pid, &status, 0); - if (WEXITSTATUS(status) == 127 || WEXITSTATUS(status) == 126) { - fprintf(stderr, "%s not found\n", args[0]); - } + if (isnan(_height)) + { + Exiv2::ExifKey key("Exif.GPSInfo.GPSAltitude"); + pos = exifData.findKey(key); + if (pos != exifData.end() && pos->toFloat() >= 0) + _height = pos->toFloat(); + } return 0; } @@ -155,76 +159,74 @@ ImageMetaData::load_image_exif(char *name) { int ImageMetaData::load_image_jpgcom(char *name) { - const char * args[32]; - FILE *p; - pid_t pid; - int status; - char buf[1024]; double lo, la, he, dir, ni, ti, fr, k0, k1, x0 = 0.0; int pt = 0; int n, ret = 1; - args[0] = "rdjpgcom"; - args[1] = name; - args[2] = NULL; - - p = pexecvp(args[0], const_cast(args), &pid, "r"); - - if (p) { - while (fgets(buf, sizeof(buf), p) != NULL) { - if ((n = sscanf(buf, GIPFEL_FORMAT_2, - &lo, &la, &he, &dir, &ni, &ti, &fr, &pt, &k0, &k1, &x0)) >= 8) { - - _longitude = lo; - _latitude = la; - _height = he; - _direction = dir; - _nick = ni; - _tilt = ti; - _focal_length_35mm = fr; - _projection_type = pt; - - if (n >= 10) { - _k0 = k0; - _k1 = k1; - _x0 = x0; - } - - ret = 0; - - break; + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(name); + assert (image.get() != 0); + image->readMetadata(); + const char *com = image->comment().c_str(); + + if ((n = sscanf(com, GIPFEL_FORMAT_2, + &lo, &la, &he, &dir, &ni, &ti, &fr, &pt, &k0, &k1, &x0)) >= 8) + { + _longitude = lo; + _latitude = la; + _height = he; + _direction = dir; + _nick = ni; + _tilt = ti; + _focal_length_35mm = fr; + _projection_type = pt; + + if (n >= 10) + { + _k0 = k0; + _k1 = k1; + _x0 = x0; } + ret = 0; } - - fclose(p); - waitpid(pid, &status, 0); - if (WEXITSTATUS(status) == 127 || WEXITSTATUS(status) == 126) { - fprintf(stderr, "%s not found\n", args[0]); - } - } - return ret; } int ImageMetaData::save_image_jpgcom(char *in_img, char *out_img) { - const char * args[32]; - FILE *p; - pid_t pid; char buf[1024], tmpname[MAXPATHLEN]; - int status, err = 0; - ssize_t n; - int tmp_fd; - char *dirbuf; - - dirbuf = strdup(out_img); - snprintf(tmpname, sizeof(tmpname), "%s/.gipfelXXXXXX", dirname(dirbuf)); - free(dirbuf); - tmp_fd = mkstemp(tmpname); - if (tmp_fd < 0) { - perror("mkstemp"); - return 1; - } + int n, err = 0; + + char* dirbuf = strdup(out_img); + snprintf(tmpname, sizeof(tmpname), "%s/.gipfelXXXXXX", dirname(dirbuf)); + free(dirbuf); + + int in_fd = open(in_img, O_RDONLY); + if (in_fd == -1) { + perror("open"); + return 1; + } + + int out_fd = open(tmpname, O_WRONLY | O_TRUNC | O_CREAT); + if (out_fd == -1) { + perror("open"); + close(in_fd); + return 1; + } + + while ((n = read(in_fd, buf, sizeof(buf))) != 0) { + if (write(out_fd, buf, n) != n) { + perror("write"); + err++; + break; + } + } + + close(in_fd); + + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(tmpname); + assert (image.get() != 0); + image->readMetadata(); + image->clearComment(); snprintf(buf, sizeof(buf), GIPFEL_FORMAT_2, _longitude, @@ -235,49 +237,26 @@ ImageMetaData::save_image_jpgcom(char *in_img, char *out_img) { _tilt, _focal_length_35mm, _projection_type, - _k0, _k1, _x0); - - // try to save gipfel data in JPEG comment section - args[0] = "wrjpgcom"; - args[1] = "-replace"; - args[2] = "-comment"; - args[3] = buf; - args[4] = in_img; - args[5] = NULL; - - p = pexecvp(args[0], const_cast(args), &pid, "r"); - - if (p) { - while ((n = fread(buf, 1, sizeof(buf), p)) != 0) { - if (write(tmp_fd, buf, n) != n) { - perror("write"); - err++; - break; - } - } - fclose(p); - waitpid(pid, &status, 0); - if (WEXITSTATUS(status) != 0) - err++; - if (WEXITSTATUS(status) == 127 || WEXITSTATUS(status) == 126) - fprintf(stderr, "%s not found\n", args[0]); - } else { - perror("pexecvp"); - err++; - } + _k0, _k1, _x0); - fsync(tmp_fd); /* make sure data is on disk before replacing orig file */ - close(tmp_fd); - if (!err) { - if (rename(tmpname, out_img) != 0) { - perror("rename"); - err++; - unlink(tmpname); - } - } + image->setComment(buf); + image->writeMetadata(); + + fsync(out_fd); /* make sure data is on disk before replacing orig file */ + close(out_fd); + + struct stat stFileInfo; + if (! stat(out_img,&stFileInfo) ) + unlink(out_img); + if (rename(tmpname, out_img) != 0) + { + perror("rename"); + err++; + unlink(tmpname); + } - return err != 0; + return (err != 0); } void -- cgit v1.2.3