// // Copyright 2006-2009 Johannes Hofmann // // This software may be used and distributed according to the terms // of the GNU General Public License, incorporated herein by reference. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ImageMetaData.H" ImageMetaData::ImageMetaData() { _manufacturer = NULL; _model = NULL; clear(); } ImageMetaData::~ImageMetaData() { if (_manufacturer) free(_manufacturer); if (_model) free(_model); } void ImageMetaData::clear() { if (_manufacturer) free(_manufacturer); _manufacturer = NULL; if (_model) free(_model); _model = NULL; _longitude = NAN; _latitude = NAN; _height = NAN; _direction = NAN; _nick = NAN; _tilt = NAN; _k0 = NAN; _k1 = NAN; _x0 = NAN; _focal_length = NAN; _focal_length_35mm = NAN; _scale = NAN; _projection_type = 0; } int ImageMetaData::load_image(char *name) { clear(); load_image_jpgcom(name); load_image_exif(name); // fill missing values from exif data return 0; } int ImageMetaData::save_image(char *in_img, char *out_img) { return save_image_jpgcom(in_img, out_img); } 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; } 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()); } if(!_model) { Exiv2::ExifKey key("Exif.Image.Model"); pos = exifData.findKey(key); if (pos != exifData.end() && pos->size() ) _model = strdup(pos->toString().c_str()); } 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; } } 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; } } 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; } #define GIPFEL_FORMAT_2 "gipfel: longitude %lf, latitude %lf, height %lf, direction %lf, nick %lf, tilt %lf, focal_length_35mm %lf, projection type %d, k0 %lf, k1 %lf, x0 %lf" int ImageMetaData::load_image_jpgcom(char *name) { double lo, la, he, dir, ni, ti, fr, k0, k1, x0 = 0.0; int pt = 0; int n, ret = 1; 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; } return ret; } int ImageMetaData::save_image_jpgcom(char *in_img, char *out_img) { char buf[1024], tmpname[MAXPATHLEN]; 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, _latitude, _height, _direction, _nick, _tilt, _focal_length_35mm, _projection_type, _k0, _k1, _x0); 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); } void ImageMetaData::distortion_params(double *k0, double *k1, double *x0) { *k0 = _k0; *k1 = _k1; *x0 = _x0; } void ImageMetaData::distortion_params(double k0, double k1, double x0) { _k0 = k0; _k1 = k1; _x0 = x0; }