Overhauled exception handling. The new class Error has a list of error messages, which is selected based on the error code provided in the constructor.
Image::read/writeMetadata and ImageFactory::open now throw Error in case of failure. Applications therefore now need an exception handler for the error handling of such function calls. This should result in shorter and simpler application code.
This commit is contained in:
+5
-4
@@ -48,12 +48,13 @@ include $(top_srcdir)/config/config.mk
|
||||
# Source files
|
||||
|
||||
# Add standalone C++ header files to this list
|
||||
CCHDR = exv_conf.h exv_msvc.h error.hpp rcsid.hpp
|
||||
CCHDR = exv_conf.h exv_msvc.h rcsid.hpp
|
||||
|
||||
# Add library C++ source files to this list
|
||||
CCSRC = basicio.cpp canonmn.cpp datasets.cpp exif.cpp fujimn.cpp ifd.cpp \
|
||||
image.cpp iptc.cpp jpgimage.cpp makernote.cpp metadatum.cpp nikonmn.cpp \
|
||||
olympusmn.cpp sigmamn.cpp tags.cpp types.cpp value.cpp
|
||||
CCSRC = basicio.cpp canonmn.cpp datasets.cpp error.cpp exif.cpp futils.cpp \
|
||||
fujimn.cpp ifd.cpp image.cpp iptc.cpp jpgimage.cpp makernote.cpp \
|
||||
metadatum.cpp nikonmn.cpp olympusmn.cpp sigmamn.cpp tags.cpp types.cpp \
|
||||
value.cpp
|
||||
|
||||
# Add source files of simple applications to this list
|
||||
BINSRC = addmoddel.cpp dataarea-test.cpp exifcomment.cpp exifdata-test.cpp \
|
||||
|
||||
+91
-206
@@ -44,6 +44,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include "exif.hpp"
|
||||
#include "canonmn.hpp"
|
||||
#include "iptc.hpp"
|
||||
#include "futils.hpp"
|
||||
#ifndef EXV_HAVE_TIMEGM
|
||||
# include "timegm.h"
|
||||
#endif
|
||||
@@ -158,30 +159,22 @@ namespace Action {
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
catch(const Exiv2::Error& e) {
|
||||
std::cerr << "Exif exception in print action for file "
|
||||
catch(const Exiv2::AnyError& e) {
|
||||
std::cerr << "Exiv2 exception in print action for file "
|
||||
<< path << ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Print::run
|
||||
|
||||
int Print::printSummary()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -445,22 +438,14 @@ namespace Action {
|
||||
|
||||
int Print::printInterpreted()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -483,22 +468,14 @@ namespace Action {
|
||||
|
||||
int Print::printValues()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -528,22 +505,14 @@ namespace Action {
|
||||
|
||||
int Print::printIptc()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::IptcData &iptcData = image->iptcData();
|
||||
if (iptcData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -573,22 +542,14 @@ namespace Action {
|
||||
|
||||
int Print::printHexdump()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -621,23 +582,14 @@ namespace Action {
|
||||
|
||||
int Print::printComment()
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << path_
|
||||
<< ": Could not read metadata\n";
|
||||
return 1;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
if (Params::instance().verbose_) {
|
||||
std::cout << "Jpeg comment: ";
|
||||
}
|
||||
@@ -657,22 +609,14 @@ namespace Action {
|
||||
|
||||
int Rename::run(const std::string& path)
|
||||
try {
|
||||
if (!Util::fileExists(path, true)) {
|
||||
if (!Exiv2::fileExists(path, true)) {
|
||||
std::cerr << path
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path
|
||||
@@ -719,7 +663,7 @@ namespace Action {
|
||||
if (Params::instance().verbose_) {
|
||||
std::cout << "Renaming file to " << newPath << std::endl;
|
||||
}
|
||||
if (!Params::instance().force_ && Util::fileExists(newPath)) {
|
||||
if (!Params::instance().force_ && Exiv2::fileExists(newPath)) {
|
||||
std::cout << Params::instance().progname()
|
||||
<< ": Overwrite `" << newPath << "'? ";
|
||||
std::string s;
|
||||
@@ -732,14 +676,14 @@ namespace Action {
|
||||
std::cerr << Params::instance().progname()
|
||||
<< ": Failed to rename "
|
||||
<< path << " to " << newPath << ": "
|
||||
<< Util::strError() << "\n";
|
||||
<< Exiv2::strError() << "\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in rename action for file " << path
|
||||
std::cerr << "Exiv2 exception in rename action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Rename::run
|
||||
@@ -758,24 +702,17 @@ namespace Action {
|
||||
try {
|
||||
path_ = path;
|
||||
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image
|
||||
= Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::ExifData::strError(rc, path_) << "\n";
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
// Thumbnail must be before Exif
|
||||
if (0 == rc && Params::instance().target_ & Params::ctThumb) {
|
||||
int rc = 0;
|
||||
if (Params::instance().target_ & Params::ctThumb) {
|
||||
rc = eraseThumbnail(image.get());
|
||||
}
|
||||
if (0 == rc && Params::instance().target_ & Params::ctExif) {
|
||||
@@ -788,17 +725,14 @@ namespace Action {
|
||||
rc = eraseComment(image.get());
|
||||
}
|
||||
if (0 == rc) {
|
||||
rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
}
|
||||
image->writeMetadata();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in erase action for file " << path
|
||||
std::cerr << "Exiv2 exception in erase action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Erase::run
|
||||
@@ -867,7 +801,7 @@ namespace Action {
|
||||
if (directory.empty()) directory = Util::dirname(path_);
|
||||
std::string exvPath = directory + EXV_SEPERATOR_STR
|
||||
+ Util::basename(path_, true) + ".exv";
|
||||
if (!Params::instance().force_ && Util::fileExists(exvPath)) {
|
||||
if (!Params::instance().force_ && Exiv2::fileExists(exvPath)) {
|
||||
std::cout << Params::instance().progname()
|
||||
<< ": Overwrite `" << exvPath << "'? ";
|
||||
std::string s;
|
||||
@@ -878,31 +812,23 @@ namespace Action {
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in extract action for file " << path
|
||||
std::cerr << "Exiv2 exception in extract action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Extract::run
|
||||
|
||||
int Extract::writeThumbnail() const
|
||||
{
|
||||
if (!Util::fileExists(path_, true)) {
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path_
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path_) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path_
|
||||
@@ -915,6 +841,7 @@ namespace Action {
|
||||
std::string thumb = directory + EXV_SEPERATOR_STR
|
||||
+ Util::basename(path_, true) + "-thumb";
|
||||
std::string thumbExt = exifData.thumbnailExtension();
|
||||
int rc = 0;
|
||||
if (thumbExt.empty()) {
|
||||
std::cerr << path_ << ": Image does not contain an Exif thumbnail\n";
|
||||
}
|
||||
@@ -926,7 +853,7 @@ namespace Action {
|
||||
<< buf.size_ << " Bytes) to file "
|
||||
<< thumb << thumbExt << std::endl;
|
||||
}
|
||||
if (!Params::instance().force_ && Util::fileExists(thumb + thumbExt)) {
|
||||
if (!Params::instance().force_ && Exiv2::fileExists(thumb + thumbExt)) {
|
||||
std::cout << Params::instance().progname()
|
||||
<< ": Overwrite `" << thumb + thumbExt << "'? ";
|
||||
std::string s;
|
||||
@@ -935,7 +862,7 @@ namespace Action {
|
||||
}
|
||||
rc = exifData.writeThumbnail(thumb);
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::ExifData::strError(rc, thumb) << "\n";
|
||||
std::cerr << thumb << ": Exif data doesn't contain a thumbnail\n";
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -953,7 +880,7 @@ namespace Action {
|
||||
|
||||
int Insert::run(const std::string& path)
|
||||
try {
|
||||
if (!Util::fileExists(path, true)) {
|
||||
if (!Exiv2::fileExists(path, true)) {
|
||||
std::cerr << path
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
@@ -974,9 +901,9 @@ namespace Action {
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in insert action for file " << path
|
||||
std::cerr << "Exiv2 exception in insert action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Insert::run
|
||||
@@ -987,32 +914,24 @@ namespace Action {
|
||||
if (directory.empty()) directory = Util::dirname(path);
|
||||
std::string thumbPath = directory + EXV_SEPERATOR_STR
|
||||
+ Util::basename(path, true) + "-thumb.jpg";
|
||||
if (!Util::fileExists(thumbPath, true)) {
|
||||
if (!Exiv2::fileExists(thumbPath, true)) {
|
||||
std::cerr << thumbPath
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
if (!Util::fileExists(path, true)) {
|
||||
if (!Exiv2::fileExists(path, true)) {
|
||||
std::cerr << path
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
return rc;
|
||||
}
|
||||
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
exifData.setJpegThumbnail(thumbPath);
|
||||
return image->writeMetadata();
|
||||
|
||||
image->writeMetadata();
|
||||
|
||||
return 0;
|
||||
} // Insert::insertThumbnail
|
||||
|
||||
Insert::AutoPtr Insert::clone() const
|
||||
@@ -1027,22 +946,14 @@ namespace Action {
|
||||
|
||||
int Modify::run(const std::string& path)
|
||||
try {
|
||||
if (!Util::fileExists(path, true)) {
|
||||
if (!Exiv2::fileExists(path, true)) {
|
||||
std::cerr << path
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
image_ = Exiv2::ImageFactory::open(path);
|
||||
if (image_.get() == 0) {
|
||||
std::cerr << path
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image_->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image_.get() != 0);
|
||||
image_->readMetadata();
|
||||
|
||||
// loop through command table and apply each command
|
||||
ModifyCmds& modifyCmds = Params::instance().modifyCmds_;
|
||||
@@ -1066,15 +977,13 @@ namespace Action {
|
||||
}
|
||||
|
||||
// Save both exif and iptc metadata
|
||||
rc = image_->writeMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
}
|
||||
return rc;
|
||||
image_->writeMetadata();
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in modify action for file " << path
|
||||
std::cerr << "Exiv2 exception in modify action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Modify::run
|
||||
@@ -1161,41 +1070,30 @@ namespace Action {
|
||||
try {
|
||||
adjustment_ = Params::instance().adjustment_;
|
||||
|
||||
if (!Util::fileExists(path, true)) {
|
||||
if (!Exiv2::fileExists(path, true)) {
|
||||
std::cerr << path
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path);
|
||||
if (image.get() == 0) {
|
||||
std::cerr << path
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
}
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
return rc;
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::cerr << path
|
||||
<< ": No Exif data found in the file\n";
|
||||
return -3;
|
||||
}
|
||||
rc = adjustDateTime(exifData, "Exif.Image.DateTime", path);
|
||||
int rc = adjustDateTime(exifData, "Exif.Image.DateTime", path);
|
||||
rc += adjustDateTime(exifData, "Exif.Photo.DateTimeOriginal", path);
|
||||
rc += adjustDateTime(exifData, "Exif.Photo.DateTimeDigitized", path);
|
||||
if (rc) return 1;
|
||||
rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::cerr << Exiv2::Image::strError(rc, path) << "\n";
|
||||
}
|
||||
image->writeMetadata();
|
||||
return rc;
|
||||
}
|
||||
catch(const Exiv2::Error& e)
|
||||
catch(const Exiv2::AnyError& e)
|
||||
{
|
||||
std::cerr << "Exif exception in adjust action for file " << path
|
||||
std::cerr << "Exiv2 exception in adjust action for file " << path
|
||||
<< ":\n" << e << "\n";
|
||||
return 1;
|
||||
} // Adjust::run
|
||||
@@ -1307,41 +1205,25 @@ namespace {
|
||||
const std::string& target,
|
||||
bool preserve)
|
||||
{
|
||||
if (!Util::fileExists(source, true)) {
|
||||
if (!Exiv2::fileExists(source, true)) {
|
||||
std::cerr << source
|
||||
<< ": Failed to open the file\n";
|
||||
return -1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr sourceImage
|
||||
= Exiv2::ImageFactory::open(source);
|
||||
if (sourceImage.get() == 0) {
|
||||
std::cerr << source
|
||||
<< ": The file contains data of an unknown image type\n";
|
||||
return -2;
|
||||
Exiv2::Image::AutoPtr sourceImage = Exiv2::ImageFactory::open(source);
|
||||
assert(sourceImage.get() != 0);
|
||||
sourceImage->readMetadata();
|
||||
|
||||
Exiv2::Image::AutoPtr targetImage;
|
||||
if (Exiv2::fileExists(target)) {
|
||||
targetImage = Exiv2::ImageFactory::open(target);
|
||||
assert(targetImage.get() != 0);
|
||||
if (preserve) targetImage->readMetadata();
|
||||
}
|
||||
int rc = sourceImage->readMetadata();
|
||||
if (rc) {
|
||||
std::cerr << source
|
||||
<< ": Could not read metadata\n";
|
||||
return 1;
|
||||
}
|
||||
Exiv2::Image::AutoPtr targetImage
|
||||
= Exiv2::ImageFactory::open(target);
|
||||
if (preserve && targetImage.get() != 0) {
|
||||
if (targetImage->readMetadata()) {
|
||||
std::cerr << target
|
||||
<< ": Could not read metadata\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (targetImage.get() == 0) {
|
||||
else {
|
||||
targetImage
|
||||
= Exiv2::ImageFactory::create(Exiv2::Image::exv, target);
|
||||
}
|
||||
if (targetImage.get() == 0) {
|
||||
std::cerr << target
|
||||
<< ": Could not open nor create the file\n";
|
||||
return 2;
|
||||
assert(targetImage.get() != 0);
|
||||
}
|
||||
if ( Params::instance().target_ & Params::ctExif
|
||||
&& !sourceImage->exifData().empty()) {
|
||||
@@ -1367,11 +1249,14 @@ namespace {
|
||||
}
|
||||
targetImage->setComment(sourceImage->comment());
|
||||
}
|
||||
rc = targetImage->writeMetadata();
|
||||
if (rc) {
|
||||
std::cerr << target <<
|
||||
": Could not write metadata to file, rc = " << rc << "\n";
|
||||
try {
|
||||
targetImage->writeMetadata();
|
||||
}
|
||||
return rc;
|
||||
catch (const Exiv2::AnyError& e) {
|
||||
std::cerr << target <<
|
||||
": Could not write metadata to file: " << e << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // metacopy
|
||||
}
|
||||
|
||||
+7
-14
@@ -6,6 +6,7 @@
|
||||
#include "exif.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
try {
|
||||
@@ -68,12 +69,12 @@ try {
|
||||
// Alternatively, we can use findKey()
|
||||
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
|
||||
Exiv2::ExifData::iterator pos = exifData.findKey(key);
|
||||
if (pos == exifData.end()) throw Exiv2::Error("Key not found");
|
||||
if (pos == exifData.end()) throw Exiv2::Error(1, "Key not found");
|
||||
// Get a pointer to a copy of the value
|
||||
v = pos->getValue();
|
||||
// Downcast the Value pointer to its actual type
|
||||
Exiv2::URationalValue* prv = dynamic_cast<Exiv2::URationalValue*>(v.release());
|
||||
if (prv == 0) throw Exiv2::Error("Downcast failed");
|
||||
if (prv == 0) throw Exiv2::Error(1, "Downcast failed");
|
||||
rv = Exiv2::URationalValue::AutoPtr(prv);
|
||||
// Modify the value directly through the interface of URationalValue
|
||||
rv->value_[2] = std::make_pair(88,77);
|
||||
@@ -88,29 +89,21 @@ try {
|
||||
// Delete the metadatum at iterator position pos
|
||||
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
|
||||
pos = exifData.findKey(key);
|
||||
if (pos == exifData.end()) throw Exiv2::Error("Key not found");
|
||||
if (pos == exifData.end()) throw Exiv2::Error(1, "Key not found");
|
||||
exifData.erase(pos);
|
||||
std::cout << "Deleted key \"" << key << "\"\n";
|
||||
|
||||
// *************************************************************************
|
||||
// Finally, write the remaining Exif data to the image file
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
|
||||
image->setExifData(exifData);
|
||||
int rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
+34
-21
@@ -40,10 +40,13 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#endif
|
||||
|
||||
#include "basicio.hpp"
|
||||
#include "futils.hpp"
|
||||
#include "types.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <cassert>
|
||||
#include <cstdio> // for remove()
|
||||
#include <sys/types.h> // for stat()
|
||||
#include <sys/stat.h> // for stat()
|
||||
#ifdef EXV_HAVE_PROCESS_H
|
||||
@@ -75,21 +78,19 @@ namespace Exiv2 {
|
||||
int ret = stat(path_.c_str(), &buf);
|
||||
|
||||
// If file is > 1MB then use a file, otherwise use memory buffer
|
||||
if (buf.st_size > 1048576 || ret != 0) {
|
||||
if (ret != 0 || buf.st_size > 1048576) {
|
||||
pid_t pid = getpid();
|
||||
std::string tmpname = path_ + toString(pid);
|
||||
FileIo *fileIo = new FileIo(tmpname);
|
||||
if (fileIo->open("w+b") != 0 ) {
|
||||
delete fileIo;
|
||||
}
|
||||
else {
|
||||
basicIo.reset(fileIo);
|
||||
std::auto_ptr<FileIo> fileIo(new FileIo(tmpname));
|
||||
if (fileIo->open("w+b") != 0) {
|
||||
throw Error(10, path_, "w+b", strError());
|
||||
}
|
||||
basicIo = fileIo;
|
||||
}
|
||||
else {
|
||||
basicIo.reset(new MemIo);
|
||||
}
|
||||
|
||||
|
||||
return basicIo;
|
||||
}
|
||||
|
||||
@@ -137,7 +138,7 @@ namespace Exiv2 {
|
||||
return writeTotal;
|
||||
}
|
||||
|
||||
int FileIo::transfer(BasicIo& src)
|
||||
void FileIo::transfer(BasicIo& src)
|
||||
{
|
||||
const bool wasOpen = (fp_ != 0);
|
||||
const std::string lastMode(openMode_);
|
||||
@@ -148,22 +149,34 @@ namespace Exiv2 {
|
||||
close();
|
||||
fileIo->close();
|
||||
// MSVCRT rename that does not overwrite existing files
|
||||
if (remove(path_.c_str()) != 0) return -4;
|
||||
if (rename(fileIo->path_.c_str(), path_.c_str()) == -1) return -4;
|
||||
if (remove(path_.c_str()) != 0) {
|
||||
throw Error(2, path_, strError(), "::remove");
|
||||
}
|
||||
if (rename(fileIo->path_.c_str(), path_.c_str()) == -1) {
|
||||
throw Error(17, fileIo->path_, path_, strError());
|
||||
}
|
||||
remove(fileIo->path_.c_str());
|
||||
}
|
||||
else{
|
||||
// Generic handling, reopen both to reset to start
|
||||
open("w+b");
|
||||
if (src.open() !=0) return 1;
|
||||
if (open("w+b") != 0) {
|
||||
throw Error(10, path_, "w+b", strError());
|
||||
}
|
||||
if (src.open() != 0) {
|
||||
throw Error(9, strError());
|
||||
}
|
||||
write(src);
|
||||
src.close();
|
||||
src.close();
|
||||
}
|
||||
|
||||
if (wasOpen) {
|
||||
if (open(lastMode) != 0) {
|
||||
throw Error(10, path_, lastMode, strError());
|
||||
}
|
||||
}
|
||||
|
||||
if (wasOpen) open(lastMode);
|
||||
else close();
|
||||
|
||||
return error() || src.error();
|
||||
if (error() || src.error()) throw Error(18, path_, strError());
|
||||
}
|
||||
|
||||
int FileIo::putb(byte data)
|
||||
@@ -315,7 +328,7 @@ namespace Exiv2 {
|
||||
}
|
||||
}
|
||||
|
||||
long MemIo::write(const byte* data, long wcount )
|
||||
long MemIo::write(const byte* data, long wcount)
|
||||
{
|
||||
checkSize(wcount);
|
||||
// According to Josuttis 6.2.3 this is safe
|
||||
@@ -324,7 +337,7 @@ namespace Exiv2 {
|
||||
return wcount;
|
||||
}
|
||||
|
||||
int MemIo::transfer(BasicIo& src)
|
||||
void MemIo::transfer(BasicIo& src)
|
||||
{
|
||||
MemIo *memIo = dynamic_cast<MemIo*>(&src);
|
||||
if (memIo) {
|
||||
@@ -336,11 +349,11 @@ namespace Exiv2 {
|
||||
// Generic reopen to reset position to start
|
||||
data_.clear();
|
||||
idx_ = 0;
|
||||
if (src.open() != 0) return 1;
|
||||
if (src.open() != 0) throw Error(9, strError());
|
||||
write(src);
|
||||
src.close();
|
||||
}
|
||||
return error() || src.error();
|
||||
if (error() || src.error()) throw Error(19, strError());
|
||||
}
|
||||
|
||||
long MemIo::write(BasicIo& src)
|
||||
|
||||
+36
-40
@@ -32,7 +32,6 @@
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include "types.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
@@ -49,9 +48,9 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief An interface for simple binary IO.
|
||||
|
||||
Designed to have semantics
|
||||
and names similar to those of C style FILE* operations. Subclasses
|
||||
should all behave the same so that they can be interchanged.
|
||||
Designed to have semantics and names similar to those of C style FILE*
|
||||
operations. Subclasses should all behave the same so that they can be
|
||||
interchanged.
|
||||
*/
|
||||
class BasicIo
|
||||
{
|
||||
@@ -80,7 +79,7 @@ namespace Exiv2 {
|
||||
opening IO sources differently.
|
||||
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
Nonzero if failure.
|
||||
*/
|
||||
virtual int open() = 0;
|
||||
/*!
|
||||
@@ -88,7 +87,7 @@ namespace Exiv2 {
|
||||
be read or written. Closing flushes any unwritten data. It is
|
||||
safe to call close on a closed instance.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
Nonzero if failure.
|
||||
*/
|
||||
virtual int close() = 0;
|
||||
/*!
|
||||
@@ -98,7 +97,7 @@ namespace Exiv2 {
|
||||
bytes long
|
||||
@param wcount Number of bytes to be written.
|
||||
@return Number of bytes written to IO source successfully;<BR>
|
||||
0 if failure;
|
||||
0 if failure;
|
||||
*/
|
||||
virtual long write(const byte* data, long wcount) = 0;
|
||||
/*!
|
||||
@@ -108,7 +107,7 @@ namespace Exiv2 {
|
||||
@param src Reference to another BasicIo instance. Reading start
|
||||
at the source's current IO position
|
||||
@return Number of bytes written to IO source successfully;<BR>
|
||||
0 if failure;
|
||||
0 if failure;
|
||||
*/
|
||||
virtual long write(BasicIo& src) = 0;
|
||||
/*!
|
||||
@@ -116,7 +115,7 @@ namespace Exiv2 {
|
||||
advanced by one byte.
|
||||
@param data The single byte to be written.
|
||||
@return The value of the byte written if successful;<BR>
|
||||
EOF if failure;
|
||||
EOF if failure;
|
||||
*/
|
||||
virtual int putb(byte data) = 0;
|
||||
/*!
|
||||
@@ -126,8 +125,8 @@ namespace Exiv2 {
|
||||
@param rcount Maximum number of bytes to read. Fewer bytes may be
|
||||
read if \em rcount bytes are not available.
|
||||
@return DataBuf instance containing the bytes read. Use the
|
||||
DataBuf::size_ member to find the number of bytes read.
|
||||
DataBuf::size_ will be 0 on failure.
|
||||
DataBuf::size_ member to find the number of bytes read.
|
||||
DataBuf::size_ will be 0 on failure.
|
||||
*/
|
||||
virtual DataBuf read(long rcount) = 0;
|
||||
/*!
|
||||
@@ -140,14 +139,14 @@ namespace Exiv2 {
|
||||
@param rcount Maximum number of bytes to read. Fewer bytes may be
|
||||
read if \em rcount bytes are not available.
|
||||
@return Number of bytes read from IO source successfully;<BR>
|
||||
0 if failure;
|
||||
0 if failure;
|
||||
*/
|
||||
virtual long read(byte *buf, long rcount) = 0;
|
||||
/*!
|
||||
@brief Read one byte from the IO source. Current IO position is
|
||||
advanced by one byte.
|
||||
@return The byte read from the IO source if successful;<BR>
|
||||
EOF if failure;
|
||||
EOF if failure;
|
||||
*/
|
||||
virtual int getb() = 0;
|
||||
/*!
|
||||
@@ -161,17 +160,16 @@ namespace Exiv2 {
|
||||
@param src Reference to another BasicIo instance. The entire contents
|
||||
of src are transferred to this object. The \em src object is
|
||||
invalidated by the method.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
@throw Error In case of failure
|
||||
*/
|
||||
virtual int transfer(BasicIo& src) = 0;
|
||||
virtual void transfer(BasicIo& src) = 0;
|
||||
/*!
|
||||
@brief Move the current IO position.
|
||||
@param offset Number of bytes to move the position relative
|
||||
to the starting position specified by \em pos
|
||||
@param pos Position from which the seek should start
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
Nonzero if failure;
|
||||
*/
|
||||
virtual int seek(long offset, Position pos) = 0;
|
||||
//@}
|
||||
@@ -181,13 +179,13 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Get the current IO position.
|
||||
@return Offset from the start of IO if successful;<BR>
|
||||
-l if failure;
|
||||
-1 if failure;
|
||||
*/
|
||||
virtual long tell() const = 0;
|
||||
/*!
|
||||
@brief Get the current size of the IO source in bytes.
|
||||
@return Size of the IO source in bytes;<BR>
|
||||
-l if failure;
|
||||
-1 if failure;
|
||||
*/
|
||||
virtual long size() const = 0;
|
||||
//!Returns true if the IO source is open, otherwise false.
|
||||
@@ -206,8 +204,8 @@ namespace Exiv2 {
|
||||
replace the original IO source with the modified version. Subclasses
|
||||
are free to return any class that derives from BasicIo.
|
||||
|
||||
@return An instance of BasicIo on success;<BR>
|
||||
Null pointer on failure;
|
||||
@return An instance of BasicIo on success
|
||||
@throw Error In case of failure
|
||||
*/
|
||||
virtual BasicIo::AutoPtr temporary() const = 0;
|
||||
//@}
|
||||
@@ -287,15 +285,15 @@ namespace Exiv2 {
|
||||
@param mode Specified that type of access allowed on the file.
|
||||
Valid values match those of the C fopen command exactly.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
*/
|
||||
int open( const std::string& mode);
|
||||
Nonzero if failure.
|
||||
*/
|
||||
int open(const std::string& mode);
|
||||
/*!
|
||||
@brief Open the file using using the default access mode of "r+b".
|
||||
This method can also be used to "reopen" a file which will flush
|
||||
any unwritten data and reset the IO position to the start.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
Nonzero if failure.
|
||||
*/
|
||||
virtual int open();
|
||||
/*!
|
||||
@@ -377,10 +375,9 @@ namespace Exiv2 {
|
||||
@param src Reference to another BasicIo instance. The entire contents
|
||||
of src are transferred to this object. The \em src object is
|
||||
invalidated by the method.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
@throw Error In case of failure
|
||||
*/
|
||||
virtual int transfer(BasicIo& src);
|
||||
virtual void transfer(BasicIo& src);
|
||||
/*!
|
||||
@brief Move the current file position.
|
||||
@param offset Number of bytes to move the file position
|
||||
@@ -397,14 +394,14 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Get the current file position.
|
||||
@return Offset from the start of the file if successful;<BR>
|
||||
-l if failure;
|
||||
-1 if failure;
|
||||
*/
|
||||
virtual long tell() const;
|
||||
/*!
|
||||
@brief Flush any buffered writes and get the current file size
|
||||
in bytes.
|
||||
@return Size of the file in bytes;<BR>
|
||||
-l if failure;
|
||||
-1 if failure;
|
||||
*/
|
||||
virtual long size() const;
|
||||
//!Returns true if the file is open, otherwise false.
|
||||
@@ -419,8 +416,8 @@ namespace Exiv2 {
|
||||
object. For small files, a MemIo is returned while for large files
|
||||
a FileIo is returned. Callers should not rely on this behavior,
|
||||
however, since it may change.
|
||||
@return An instance of BasicIo on success;<BR>
|
||||
Null pointer on failure;
|
||||
@return An instance of BasicIo on success
|
||||
@throw Error If opening the temporary file fails
|
||||
*/
|
||||
virtual BasicIo::AutoPtr temporary() const;
|
||||
//@}
|
||||
@@ -476,8 +473,9 @@ namespace Exiv2 {
|
||||
//@{
|
||||
/*!
|
||||
@brief Memory IO is always open for reading and writing. This method
|
||||
therefore only resets the IO position to the start.
|
||||
@return 0
|
||||
therefore only resets the IO position to the start.
|
||||
|
||||
@return 0
|
||||
*/
|
||||
virtual int open();
|
||||
/*!
|
||||
@@ -559,10 +557,9 @@ namespace Exiv2 {
|
||||
@param src Reference to another BasicIo instance. The entire contents
|
||||
of src are transferred to this object. The \em src object is
|
||||
invalidated by the method.
|
||||
@return 0 if successful;<BR>
|
||||
Nonzero if failure;
|
||||
@throw Error In case of failure
|
||||
*/
|
||||
virtual int transfer(BasicIo& src);
|
||||
virtual void transfer(BasicIo& src);
|
||||
/*!
|
||||
@brief Move the current IO position.
|
||||
@param offset Number of bytes to move the IO position
|
||||
@@ -584,7 +581,7 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Get the current memory buffer size in bytes.
|
||||
@return Size of the in memory data in bytes;<BR>
|
||||
-l if failure;
|
||||
-1 if failure;
|
||||
*/
|
||||
virtual long size() const;
|
||||
//!Always returns true
|
||||
@@ -597,8 +594,7 @@ namespace Exiv2 {
|
||||
@brief Returns a temporary data storage location. Currently returns
|
||||
an empty MemIo object, but callers should not rely on this
|
||||
behavior since it may change.
|
||||
@return An instance of BasicIo on success;<BR>
|
||||
Null pointer on failure;
|
||||
@return An instance of BasicIo
|
||||
*/
|
||||
virtual BasicIo::AutoPtr temporary() const;
|
||||
//@}
|
||||
|
||||
+6
-17
@@ -71,7 +71,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -83,24 +83,14 @@ void write(const std::string& file, Exiv2::ExifData& ed)
|
||||
assert(image.get() != 0);
|
||||
|
||||
image->setExifData(ed);
|
||||
int rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
}
|
||||
|
||||
void print(const std::string& file)
|
||||
{
|
||||
Image::AutoPtr image = ImageFactory::open(file);
|
||||
assert(image.get() != 0);
|
||||
|
||||
// Load existing metadata
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->readMetadata();
|
||||
|
||||
Exiv2::ExifData &ed = image->exifData();
|
||||
Exiv2::ExifData::const_iterator end = ed.end();
|
||||
@@ -125,16 +115,15 @@ int read(const std::string& path)
|
||||
{
|
||||
Image::AutoPtr image = ImageFactory::open(path);
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
int rc = image->readMetadata();
|
||||
if (rc) return rc;
|
||||
if (image->exifData().count() > 0) {
|
||||
if (!image->exifData().empty()) {
|
||||
DataBuf exifData = image->exifData().copy();
|
||||
long size = exifData.size_;
|
||||
|
||||
// Read the TIFF header
|
||||
TiffHeader tiffHeader;
|
||||
rc = tiffHeader.read(exifData.pData_);
|
||||
int rc = tiffHeader.read(exifData.pData_);
|
||||
if (rc) return rc;
|
||||
|
||||
// Read IFD0
|
||||
|
||||
+7
-7
@@ -239,7 +239,7 @@ namespace Exiv2 {
|
||||
dataSet = records_[recordId][idx].number_;
|
||||
}
|
||||
else {
|
||||
if (!isHex(dataSetName, 4, "0x")) throw Error("Invalid dataset name");
|
||||
if (!isHex(dataSetName, 4, "0x")) throw Error(4, dataSetName);
|
||||
std::istringstream is(dataSetName);
|
||||
is >> std::hex >> dataSet;
|
||||
}
|
||||
@@ -273,7 +273,7 @@ namespace Exiv2 {
|
||||
if (recordInfo_[i].name_ == recordName) break;
|
||||
}
|
||||
if (i == 0) {
|
||||
if (!isHex(recordName, 4, "0x")) throw Error("Invalid record name");
|
||||
if (!isHex(recordName, 4, "0x")) throw Error(5, recordName);
|
||||
std::istringstream is(recordName);
|
||||
is >> std::hex >> i;
|
||||
}
|
||||
@@ -334,18 +334,18 @@ namespace Exiv2 {
|
||||
{
|
||||
// Get the family name, record name and dataSet name parts of the key
|
||||
std::string::size_type pos1 = key_.find('.');
|
||||
if (pos1 == std::string::npos) throw Error("Invalid key");
|
||||
if (pos1 == std::string::npos) throw Error(6, key_);
|
||||
std::string familyName = key_.substr(0, pos1);
|
||||
if (familyName != std::string(familyName_)) {
|
||||
throw Error("Invalid key");
|
||||
throw Error(6, key_);
|
||||
}
|
||||
std::string::size_type pos0 = pos1 + 1;
|
||||
pos1 = key_.find('.', pos0);
|
||||
if (pos1 == std::string::npos) throw Error("Invalid key");
|
||||
if (pos1 == std::string::npos) throw Error(6, key_);
|
||||
std::string recordName = key_.substr(pos0, pos1 - pos0);
|
||||
if (recordName == "") throw Error("Invalid key");
|
||||
if (recordName == "") throw Error(6, key_);
|
||||
std::string dataSetName = key_.substr(pos1 + 1);
|
||||
if (dataSetName == "") throw Error("Invalid key");
|
||||
if (dataSetName == "") throw Error(6, key_);
|
||||
|
||||
// Use the parts of the key to find dataSet and recordId
|
||||
uint16_t recId = IptcDataSets::recordId(recordName);
|
||||
|
||||
+26
-26
@@ -70,18 +70,16 @@ namespace Exiv2 {
|
||||
uint16_t recordId,
|
||||
const char* photoshop
|
||||
);
|
||||
//@{
|
||||
uint16_t number_;
|
||||
const char* name_;
|
||||
const char* desc_;
|
||||
bool mandatory_;
|
||||
bool repeatable_;
|
||||
uint32_t minbytes_;
|
||||
uint32_t maxbytes_;
|
||||
TypeId type_;
|
||||
uint16_t recordId_;
|
||||
const char* photoshop_;
|
||||
//@}
|
||||
uint16_t number_; //!< Dataset number
|
||||
const char* name_; //!< Dataset name
|
||||
const char* desc_; //!< Dataset description
|
||||
bool mandatory_; //!< True if dataset is mandatory
|
||||
bool repeatable_; //!< True if dataset is repeatable
|
||||
uint32_t minbytes_; //!< Minimum number of bytes
|
||||
uint32_t maxbytes_; //!< Maximum number of bytes
|
||||
TypeId type_; //!< Exiv2 default type
|
||||
uint16_t recordId_; //!< Record id
|
||||
const char* photoshop_; //!< Photoshop string
|
||||
}; // struct DataSet
|
||||
|
||||
//! Container for Iptc dataset information. Implemented as a static class.
|
||||
@@ -197,8 +195,6 @@ namespace Exiv2 {
|
||||
@param number The dataset number
|
||||
@param recordId The Iptc record Id
|
||||
@return The description of the dataset
|
||||
@throw Error ("No dataset for recordId") if there is no dataset info
|
||||
for the given record id in the lookup tables.
|
||||
*/
|
||||
static const char* dataSetDesc(uint16_t number, uint16_t recordId);
|
||||
/*!
|
||||
@@ -206,9 +202,7 @@ namespace Exiv2 {
|
||||
@param number The dataset number
|
||||
@param recordId The Iptc record Id
|
||||
@return The name used by photoshop for a dataset or an empty
|
||||
string if photoshop does not use the dataset.
|
||||
@throw Error ("No dataset for recordId") if there is no dataset info
|
||||
for the given record id in the lookup tables.
|
||||
string if photoshop does not use the dataset.
|
||||
*/
|
||||
static const char* dataSetPsName(uint16_t number, uint16_t recordId);
|
||||
/*!
|
||||
@@ -216,11 +210,18 @@ namespace Exiv2 {
|
||||
@param number The dataset number
|
||||
@param recordId The Iptc record Id
|
||||
@return true if the given dataset is repeatable otherwise false
|
||||
@throw Error ("No dataset for recordId") if there is no dataset info
|
||||
for the given record id in the lookup tables.
|
||||
*/
|
||||
static bool dataSetRepeatable(uint16_t number, uint16_t recordId);
|
||||
//! Return the dataSet number for dataset name and record id
|
||||
/*!
|
||||
@brief Return the dataSet number for dataset name and record id
|
||||
|
||||
@param dataSetName dataSet name
|
||||
@param recordId recordId
|
||||
|
||||
@return dataSet number
|
||||
|
||||
@throw Error if the \em dataSetName or \em recordId are invalid
|
||||
*/
|
||||
static uint16_t dataSet(const std::string& dataSetName, uint16_t recordId);
|
||||
//! Return the type for dataSet number and Record id
|
||||
static TypeId dataSetType(uint16_t number, uint16_t recordId);
|
||||
@@ -236,14 +237,13 @@ namespace Exiv2 {
|
||||
@brief Return the description of a record
|
||||
@param recordId Record Id number
|
||||
@return the description of the Record
|
||||
@throw Error("Unknown record");
|
||||
*/
|
||||
static const char* recordDesc(uint16_t recordId);
|
||||
/*!
|
||||
@brief Return the Id number of a record
|
||||
@param recordName Name of a record type
|
||||
@return the Id number of a Record
|
||||
@throw Error("Unknown record");
|
||||
@throw Error if the record is not known;
|
||||
*/
|
||||
static uint16_t recordId(const std::string& recordName);
|
||||
//! Print a list of all dataSets to output stream
|
||||
@@ -272,8 +272,8 @@ namespace Exiv2 {
|
||||
@brief Constructor to create an Iptc key from a key string.
|
||||
|
||||
@param key The key string.
|
||||
@throw Error ("Invalid key") if the first part of the key is not
|
||||
'Iptc' or the remaining parts of the key cannot be parsed and
|
||||
@throw Error if the first part of the key is not '<b>Iptc</b>' or
|
||||
the remaining parts of the key cannot be parsed and
|
||||
converted to a record name and a dataset name.
|
||||
*/
|
||||
explicit IptcKey(const std::string& key);
|
||||
@@ -327,9 +327,9 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Parse and convert the key string into dataset and record id.
|
||||
Updates data members if the string can be decomposed, or throws
|
||||
Error ("Invalid key").
|
||||
\em Error.
|
||||
|
||||
@throw Error ("Invalid key") if the key cannot be decomposed.
|
||||
@throw Error if the key cannot be decomposed.
|
||||
*/
|
||||
void decomposeKey();
|
||||
//@}
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2005 Andreas Huggel <ahuggel@gmx.net>
|
||||
*
|
||||
* This program is part of the Exiv2 distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*
|
||||
File: error.cpp
|
||||
Version: $Rev$
|
||||
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
||||
History: 02-Apr-05, ahu: created
|
||||
*/
|
||||
// *****************************************************************************
|
||||
#include "rcsid.hpp"
|
||||
EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include "error.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
|
||||
// *****************************************************************************
|
||||
// class member definitions
|
||||
namespace Exiv2 {
|
||||
|
||||
const ErrMsg Error::errMsg_[] = {
|
||||
ErrMsg( -1, "Error %0: arg1=%1, arg2=%2, arg3=%3."),
|
||||
ErrMsg( 0, "Success"),
|
||||
ErrMsg( 1, "%1"), // %1=error message
|
||||
|
||||
ErrMsg( 2, "%1: %2 (%3)"), // %1=path, %2=strerror, %3=function that failed
|
||||
// ErrMsg( 3, ""),
|
||||
|
||||
ErrMsg( 4, "Invalid dataset name `%1'"), // %1=dataset name
|
||||
ErrMsg( 5, "Invalid record name `%1'"), // %1=record name
|
||||
ErrMsg( 6, "Invalid key `%1'"), // %1=key
|
||||
ErrMsg( 7, "Invalid tag name or ifdId `%1', ifdId %2"), // %1=tag name, %2=ifdId
|
||||
ErrMsg( 8, "Value not set"),
|
||||
ErrMsg( 9, "Failed to open the data source: %1"), // %1=strerror
|
||||
ErrMsg( 10, "%1: Failed to open file (%2): %3"), // %1=path, %2=mode, %3=strerror
|
||||
ErrMsg( 11, "%1: The file contains data of an unknown image type"), // %1=path
|
||||
ErrMsg( 12, "The memory contains data of an unknown image type"),
|
||||
ErrMsg( 13, "Image type %1 is not supported"), // %1=image type
|
||||
ErrMsg( 14, "Failed to read image data"),
|
||||
ErrMsg( 15, "This does not look like a JPEG image"),
|
||||
ErrMsg( 16, "MakerTagInfo registry full"),
|
||||
ErrMsg( 17, "%1: Failed to rename file to %2: %3"), // %1=old path, %2=new path, %3=strerror
|
||||
ErrMsg( 18, "%1: Transfer failed: %2"), // %1=path, %2=strerror
|
||||
ErrMsg( 19, "Memory transfer failed: %1"), // %1=strerror
|
||||
ErrMsg( 20, "Failed to read input data"),
|
||||
ErrMsg( 21, "Failed to write image"),
|
||||
ErrMsg( 22, "Input data does not contain a valid image"),
|
||||
ErrMsg( 23, "Failed to create Makernote for ifdId %1"), // %1=ifdId
|
||||
ErrMsg( 24, "Entry::setValue: Value too large (tag=%1, size=%2, requested=%3)"), // %1=tag, %2=dataSize, %3=required size
|
||||
ErrMsg( 25, "Entry::setDataArea: Value too large (tag=%1, size=%2, requested=%3)"), // %1=tag, %2=dataAreaSize, %3=required size
|
||||
ErrMsg( 26, "Offset out of range"),
|
||||
ErrMsg( 27, "Unsupported data area offset type"),
|
||||
ErrMsg( 28, "Invalid charset: `%1'"), // %1=charset name
|
||||
ErrMsg( 29, "Unsupported date format"),
|
||||
ErrMsg( 30, "Unsupported time format"),
|
||||
|
||||
// Last error message (message is not used)
|
||||
ErrMsg( -2, "(Unknown Error)")
|
||||
};
|
||||
|
||||
int Error::errorIdx(int code)
|
||||
{
|
||||
int idx;
|
||||
for (idx = 0; errMsg_[idx].code_ != code; ++idx) {
|
||||
if (errMsg_[idx].code_ == -2) return 0;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
std::string Error::what() const
|
||||
{
|
||||
int idx = errorIdx(code_);
|
||||
std::string msg = std::string(errMsg_[idx].message_);
|
||||
std::string::size_type pos;
|
||||
pos = msg.find("%0");
|
||||
if (pos != std::string::npos) {
|
||||
msg.replace(pos, 2, toString(code_));
|
||||
}
|
||||
if (count_ > 0) {
|
||||
pos = msg.find("%1");
|
||||
if (pos != std::string::npos) {
|
||||
msg.replace(pos, 2, arg1_);
|
||||
}
|
||||
}
|
||||
if (count_ > 1) {
|
||||
pos = msg.find("%2");
|
||||
if (pos != std::string::npos) {
|
||||
msg.replace(pos, 2, arg2_);
|
||||
}
|
||||
}
|
||||
if (count_ > 2) {
|
||||
pos = msg.find("%3");
|
||||
if (pos != std::string::npos) {
|
||||
msg.replace(pos, 2, arg3_);
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
+94
-19
@@ -32,6 +32,7 @@
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#include "types.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
@@ -44,30 +45,104 @@ namespace Exiv2 {
|
||||
// *****************************************************************************
|
||||
// class definitions
|
||||
|
||||
/*!
|
||||
@brief Very simple error class used for exceptions. It contains just an
|
||||
error message. An output operator is provided to print
|
||||
errors to a stream.
|
||||
*/
|
||||
class Error {
|
||||
public:
|
||||
//! Constructor taking a (short) error message as argument
|
||||
Error(const std::string& message) : message_(message) {}
|
||||
/*!
|
||||
@brief Return the error message. Consider using the output operator
|
||||
operator<<(std::ostream &os, const Error& error) instead.
|
||||
*/
|
||||
std::string message() const { return message_; }
|
||||
private:
|
||||
std::string message_;
|
||||
//! Helper structure defining an error message
|
||||
struct ErrMsg {
|
||||
//! Constructor
|
||||
ErrMsg(int code, const char* message)
|
||||
: code_(code), message_(message)
|
||||
{
|
||||
}
|
||||
int code_; //!< Error code
|
||||
const char* message_; //!< Error message
|
||||
};
|
||||
|
||||
//! %Error output operator
|
||||
inline std::ostream& operator<<(std::ostream& os, const Error& error)
|
||||
/*!
|
||||
@brief Error class interface. Allows the definition and use of a hierarchy
|
||||
of error classes which can all be handled in one catch block.
|
||||
*/
|
||||
class AnyError {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Virtual destructor.
|
||||
virtual ~AnyError()
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Return the error code.
|
||||
virtual int code() const =0;
|
||||
/*!
|
||||
@brief Return the error message. Consider using the output operator
|
||||
operator<<(std::ostream &os, const AnyError& error) instead.
|
||||
@note Unlike std::exception::what(), this function returns an
|
||||
std::string.
|
||||
*/
|
||||
virtual std::string what() const =0;
|
||||
}; // AnyError
|
||||
|
||||
//! %AnyBase output operator
|
||||
inline std::ostream& operator<<(std::ostream& os, const AnyError& error)
|
||||
{
|
||||
return os << error.message();
|
||||
return os << error.what();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Simple error class used for exceptions. An output operator is
|
||||
provided to print errors to a stream.
|
||||
*/
|
||||
class Error : public AnyError {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor taking only an error code
|
||||
explicit Error(int code)
|
||||
: code_(code), count_(0)
|
||||
{
|
||||
}
|
||||
//! Constructor taking an error code and one argument
|
||||
template<typename A>
|
||||
Error(int code, const A& arg1)
|
||||
: code_(code), count_(1), arg1_(toString(arg1))
|
||||
{
|
||||
}
|
||||
//! Constructor taking an error code and two arguments
|
||||
template<typename A, typename B>
|
||||
Error(int code, const A& arg1, const B& arg2)
|
||||
: code_(code), count_(2),
|
||||
arg1_(toString(arg1)), arg2_(toString(arg2))
|
||||
{
|
||||
}
|
||||
//! Constructor taking an error code and three arguments
|
||||
template<typename A, typename B, typename C>
|
||||
Error(int code, const A& arg1, const B& arg2, const C& arg3)
|
||||
: code_(code), count_(3),
|
||||
arg1_(toString(arg1)), arg2_(toString(arg2)), arg3_(toString(arg3))
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual int code() const { return code_; }
|
||||
virtual std::string what() const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
static int errorIdx(int code);
|
||||
|
||||
// DATA
|
||||
int code_; //!< Error code
|
||||
int count_; //!< Number of arguments
|
||||
std::string arg1_; //!< First argument
|
||||
std::string arg2_; //!< Second argument
|
||||
std::string arg3_; //!< Third argument
|
||||
|
||||
static const ErrMsg errMsg_[]; //!< List of error messages
|
||||
}; // class Error
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef ERROR_HPP_
|
||||
|
||||
+19
-56
@@ -50,6 +50,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include "tags.hpp"
|
||||
#include "jpgimage.hpp"
|
||||
#include "makernote.hpp"
|
||||
#include "futils.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <iostream>
|
||||
@@ -739,7 +740,8 @@ namespace Exiv2 {
|
||||
if (pMakerNote_ == 0) {
|
||||
MakerNoteFactory& mnf = MakerNoteFactory::instance();
|
||||
pMakerNote_ = mnf.create(exifdatum.ifdId()).release();
|
||||
}
|
||||
}
|
||||
if (pMakerNote_ == 0) throw Error(23, exifdatum.ifdId());
|
||||
}
|
||||
// allow duplicates
|
||||
exifMetadata_.push_back(exifdatum);
|
||||
@@ -804,14 +806,14 @@ namespace Exiv2 {
|
||||
|
||||
void ExifData::setJpegThumbnail(const std::string& path)
|
||||
{
|
||||
DataBuf thumb = readFile(path);
|
||||
DataBuf thumb = readFile(path); // may throw
|
||||
setJpegThumbnail(thumb.pData_, thumb.size_);
|
||||
}
|
||||
|
||||
void ExifData::setJpegThumbnail(const std::string& path,
|
||||
URational xres, URational yres, uint16_t unit)
|
||||
{
|
||||
DataBuf thumb = readFile(path);
|
||||
DataBuf thumb = readFile(path); // may throw
|
||||
setJpegThumbnail(thumb.pData_, thumb.size_, xres, yres, unit);
|
||||
}
|
||||
|
||||
@@ -901,12 +903,15 @@ namespace Exiv2 {
|
||||
|
||||
std::string name = path + thumbnail->extension();
|
||||
FileIo file(name);
|
||||
if (file.open("wb") != 0) return -1;
|
||||
if (file.open("wb") != 0) {
|
||||
throw Error(10, name, "wb", strError());
|
||||
}
|
||||
|
||||
DataBuf buf(thumbnail->copy(*this));
|
||||
if (file.write(buf.pData_, buf.size_) != buf.size_) {
|
||||
return 4;
|
||||
throw Error(2, name, strError(), "FileIo::write");
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // ExifData::writeThumbnail
|
||||
|
||||
@@ -1106,51 +1111,6 @@ namespace Exiv2 {
|
||||
return ifd;
|
||||
} // ExifData::getIfd
|
||||
|
||||
std::string ExifData::strError(int rc, const std::string& path)
|
||||
{
|
||||
std::string error = path + ": ";
|
||||
switch (rc) {
|
||||
case -1:
|
||||
error += "Failed to open the file";
|
||||
break;
|
||||
case -2:
|
||||
error += "The file contains data of an unknown image type";
|
||||
break;
|
||||
case -3:
|
||||
error += "Couldn't open temporary file";
|
||||
break;
|
||||
case -4:
|
||||
error += "Renaming temporary file failed";
|
||||
break;
|
||||
case 1:
|
||||
error += "Couldn't read from the input stream";
|
||||
break;
|
||||
case 2:
|
||||
error += "This does not look like a JPEG image";
|
||||
break;
|
||||
case 3:
|
||||
error += "No Exif data found in the file";
|
||||
break;
|
||||
case 4:
|
||||
error += "Writing to the output stream failed";
|
||||
break;
|
||||
case 5:
|
||||
error += "No JFIF APP0 or Exif APP1 segment found in the file";
|
||||
break;
|
||||
case 6:
|
||||
error += "Exif data contains a broken IFD";
|
||||
break;
|
||||
case 7:
|
||||
error += "Unsupported Exif or GPS data found in IFD1";
|
||||
break;
|
||||
|
||||
default:
|
||||
error += "Accessing Exif data failed, rc = " + toString(rc);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
} // ExifData::strError
|
||||
|
||||
// *************************************************************************
|
||||
// free functions
|
||||
|
||||
@@ -1253,15 +1213,18 @@ namespace {
|
||||
Exiv2::DataBuf readFile(const std::string& path)
|
||||
{
|
||||
Exiv2::FileIo file(path);
|
||||
if (file.open("rb") != 0)
|
||||
throw Exiv2::Error("Couldn't open input file");
|
||||
if (file.open("rb") != 0) {
|
||||
throw Exiv2::Error(10, path, "rb", Exiv2::strError());
|
||||
}
|
||||
struct stat st;
|
||||
if (0 != stat(path.c_str(), &st))
|
||||
throw Exiv2::Error("Couldn't stat input file");
|
||||
if (0 != stat(path.c_str(), &st)) {
|
||||
throw Exiv2::Error(2, path, Exiv2::strError(), "::stat");
|
||||
}
|
||||
Exiv2::DataBuf buf(st.st_size);
|
||||
long len = file.read(buf.pData_, buf.size_);
|
||||
if (len != buf.size_)
|
||||
throw Exiv2::Error("Couldn't read input file");
|
||||
if (len != buf.size_) {
|
||||
throw Exiv2::Error(2, path, Exiv2::strError(), "FileIo::read");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
+22
-28
@@ -80,7 +80,7 @@ namespace Exiv2 {
|
||||
|
||||
@param key %ExifKey.
|
||||
@param pValue Pointer to an %Exifdatum value.
|
||||
@throw Error ("Invalid key") if the key cannot be parsed and converted.
|
||||
@throw Error if the key cannot be parsed and converted.
|
||||
*/
|
||||
explicit Exifdatum(const ExifKey& key, const Value* pValue =0);
|
||||
//! Constructor to build an %Exifdatum from an IFD entry.
|
||||
@@ -281,10 +281,10 @@ namespace Exiv2 {
|
||||
@endcode
|
||||
|
||||
@return A constant reference to the value.
|
||||
@throw Error ("Value not set") if the value is not set.
|
||||
@throw Error if the value is not set.
|
||||
*/
|
||||
const Value& value() const
|
||||
{ if (value_.get() != 0) return *value_; throw Error("Value not set"); }
|
||||
{ if (value_.get() != 0) return *value_; throw Error(8); }
|
||||
//! Return the size of the data area.
|
||||
long sizeDataArea() const
|
||||
{ return value_.get() == 0 ? 0 : value_->sizeDataArea(); }
|
||||
@@ -560,8 +560,7 @@ namespace Exiv2 {
|
||||
duplicate checks are performed, i.e., it is possible to add
|
||||
multiple metadata with the same key.
|
||||
|
||||
@throw Error ("Inconsistent MakerNote") if \em exifdatum is a MakerNote
|
||||
tag for a different %MakerNote than that of the %ExifData.
|
||||
@throw Error if the makernote cannot be created
|
||||
*/
|
||||
void add(const Exifdatum& exifdatum);
|
||||
/*!
|
||||
@@ -611,12 +610,14 @@ namespace Exiv2 {
|
||||
This results in the minimal thumbnail tags being set for a Jpeg
|
||||
thumbnail, as mandated by the Exif standard.
|
||||
|
||||
@throw Error if reading the file fails.
|
||||
|
||||
@note No checks on the file format or size are performed.
|
||||
@note Additional existing Exif thumbnail tags are not modified.
|
||||
|
||||
@throw Error ("Couldn't open input file") if fopen fails,
|
||||
@throw Error ("Couldn't stat input file") if stat fails, or
|
||||
@throw Error ("Couldn't read input file") if fread fails.
|
||||
@note The Jpeg image inserted as thumbnail image should not
|
||||
itself contain Exif data (or other metadata), as existing
|
||||
applications may have problems with that. (The preview
|
||||
application that comes with OS X for one.) - David Harvey.
|
||||
*/
|
||||
void setJpegThumbnail(const std::string& path,
|
||||
URational xres, URational yres, uint16_t unit);
|
||||
@@ -628,8 +629,14 @@ namespace Exiv2 {
|
||||
This results in the minimal thumbnail tags being set for a Jpeg
|
||||
thumbnail, as mandated by the Exif standard.
|
||||
|
||||
@throw Error if reading the file fails.
|
||||
|
||||
@note No checks on the image format or size are performed.
|
||||
@note Additional existing Exif thumbnail tags are not modified.
|
||||
@note The Jpeg image inserted as thumbnail image should not
|
||||
itself contain Exif data (or other metadata), as existing
|
||||
applications may have problems with that. (The preview
|
||||
application that comes with OS X for one.) - David Harvey.
|
||||
*/
|
||||
void setJpegThumbnail(const byte* buf, long size,
|
||||
URational xres, URational yres, uint16_t unit);
|
||||
@@ -641,12 +648,10 @@ namespace Exiv2 {
|
||||
Exif information mandatory according to the Exif standard. (But it's
|
||||
enough to work with the thumbnail.)
|
||||
|
||||
@throw Error if reading the file fails.
|
||||
|
||||
@note No checks on the file format or size are performed.
|
||||
@note Additional existing Exif thumbnail tags are not modified.
|
||||
|
||||
@throw Error ("Couldn't open input file") if fopen fails,
|
||||
@throw Error ("Couldn't stat input file") if stat fails, or
|
||||
@throw Error ("Couldn't read input file") if fread fails.
|
||||
*/
|
||||
void setJpegThumbnail(const std::string& path);
|
||||
/*!
|
||||
@@ -720,10 +725,11 @@ namespace Exiv2 {
|
||||
This will overwrite an existing file of the same name.
|
||||
|
||||
@param path Path of the filename without image type extension
|
||||
|
||||
@throw Error if writing to the file fails.
|
||||
|
||||
@return 0 if successful;<BR>
|
||||
-1 if opening the file failed;<BR>
|
||||
4 if writing to the output stream failed;<BR>
|
||||
8 if the Exif data does not contain a thumbnail
|
||||
8 if the Exif data does not contain a thumbnail.
|
||||
*/
|
||||
int writeThumbnail(const std::string& path) const;
|
||||
/*!
|
||||
@@ -749,18 +755,6 @@ namespace Exiv2 {
|
||||
Thumbnail::AutoPtr getThumbnail() const;
|
||||
//@}
|
||||
|
||||
/*!
|
||||
@brief Convert the return code \em rc from \n
|
||||
int read(const byte* buf, long len), \n
|
||||
into an error message.
|
||||
@param rc Error code.
|
||||
@param path %Image file or other identifying string.
|
||||
@return String containing error message.
|
||||
|
||||
Todo: Implement global handling of error messages
|
||||
*/
|
||||
static std::string strError(int rc, const std::string& path);
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
|
||||
+6
-20
@@ -16,6 +16,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
// *****************************************************************************
|
||||
// Main
|
||||
@@ -28,19 +29,8 @@ try {
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
|
||||
if (image.get() == 0) {
|
||||
std::string error(argv[1]);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
// Load existing metadata
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, argv[1]);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
assert (image.get() != 0);
|
||||
image->readMetadata();
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
|
||||
/*
|
||||
@@ -68,15 +58,11 @@ try {
|
||||
<< exifData["Exif.Photo.UserComment"]
|
||||
<< "' back to the image\n";
|
||||
|
||||
rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, argv[1]);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
+9
-34
@@ -15,6 +15,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
void write(const std::string& file, Exiv2::ExifData& ed);
|
||||
void print(const std::string& file);
|
||||
@@ -31,21 +32,13 @@ try {
|
||||
std::string file(argv[1]);
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert (image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
Exiv2::ExifData &ed = image->exifData();
|
||||
if (ed.empty()) {
|
||||
std::string error = file + ": No Exif data found in the file";
|
||||
throw Exiv2::Error(error);
|
||||
throw Exiv2::Error(1, error);
|
||||
}
|
||||
|
||||
std::cout << "Copy construction, non-intrusive changes\n";
|
||||
@@ -103,7 +96,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -112,34 +105,16 @@ catch (Exiv2::Error& e) {
|
||||
void write(const std::string& file, Exiv2::ExifData& ed)
|
||||
{
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
assert (image.get() != 0);
|
||||
image->setExifData(ed);
|
||||
int rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
}
|
||||
|
||||
void print(const std::string& file)
|
||||
{
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert (image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
Exiv2::ExifData &ed = image->exifData();
|
||||
Exiv2::ExifData::const_iterator end = ed.end();
|
||||
|
||||
+6
-14
@@ -6,6 +6,7 @@
|
||||
#include "exif.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
try {
|
||||
@@ -16,23 +17,14 @@ try {
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
|
||||
if (image.get() == 0) {
|
||||
std::string error(argv[1]);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
// Load existing metadata
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, argv[1]);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
Exiv2::ExifData &exifData = image->exifData();
|
||||
if (exifData.empty()) {
|
||||
std::string error(argv[1]);
|
||||
error += ": No Exif data found in the file";
|
||||
throw Exiv2::Error(error);
|
||||
throw Exiv2::Error(1, error);
|
||||
}
|
||||
Exiv2::ExifData::const_iterator end = exifData.end();
|
||||
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) {
|
||||
@@ -44,9 +36,9 @@ try {
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
+14
-14
@@ -657,7 +657,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Exiv2::Error& error) {
|
||||
catch (const Exiv2::AnyError& error) {
|
||||
std::cerr << *filename << ", line " << error << "\n";
|
||||
return false;
|
||||
}
|
||||
@@ -680,7 +680,7 @@ namespace {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const Exiv2::Error& error) {
|
||||
catch (const Exiv2::AnyError& error) {
|
||||
std::cerr << "-M option " << error << "\n";
|
||||
return false;
|
||||
}
|
||||
@@ -701,14 +701,14 @@ namespace {
|
||||
if ( cmdStart == std::string::npos
|
||||
|| cmdEnd == std::string::npos
|
||||
|| keyStart == std::string::npos) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Invalid command line");
|
||||
}
|
||||
|
||||
std::string cmd(line.substr(cmdStart, cmdEnd-cmdStart));
|
||||
CmdId cmdId = commandId(cmd);
|
||||
if (cmdId == invalidCmdId) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Invalid command `" + cmd + "'");
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ namespace {
|
||||
defaultType = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(),
|
||||
iptcKey.record());
|
||||
}
|
||||
catch (const Exiv2::Error&) {}
|
||||
catch (const Exiv2::AnyError&) {}
|
||||
if (metadataId == invalidMetadataId) {
|
||||
try {
|
||||
Exiv2::ExifKey exifKey(key);
|
||||
@@ -729,11 +729,11 @@ namespace {
|
||||
defaultType = Exiv2::ExifTags::tagType(exifKey.tag(),
|
||||
exifKey.ifdId());
|
||||
}
|
||||
catch (const Exiv2::Error&) {}
|
||||
catch (const Exiv2::AnyError&) {}
|
||||
}
|
||||
if (metadataId == invalidMetadataId) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
+ ": Invalid key `" + key + "'");
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Invalid key `" + key + "'");
|
||||
}
|
||||
|
||||
std::string value;
|
||||
@@ -751,8 +751,8 @@ namespace {
|
||||
if ( keyEnd == std::string::npos
|
||||
|| typeStart == std::string::npos
|
||||
|| valStart == std::string::npos) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
+ ": Invalid command line ");
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Invalid command line ");
|
||||
}
|
||||
|
||||
if (typeEnd != std::string::npos) {
|
||||
@@ -761,8 +761,8 @@ namespace {
|
||||
if (tmpType != Exiv2::invalidTypeId) {
|
||||
valStart = line.find_first_not_of(delim, typeEnd+1);
|
||||
if (valStart == std::string::npos) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
+ ": Invalid command line ");
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Invalid command line ");
|
||||
}
|
||||
type = tmpType;
|
||||
explicitType = true;
|
||||
@@ -773,8 +773,8 @@ namespace {
|
||||
std::string::size_type last = value.length()-1;
|
||||
if ( (value[0] == '"' || value[last] == '"')
|
||||
&& value[0] != value[last]) {
|
||||
throw Exiv2::Error(Exiv2::toString(num)
|
||||
+ ": Unbalanced quotes");
|
||||
throw Exiv2::Error(1, Exiv2::toString(num)
|
||||
+ ": Unbalanced quotes");
|
||||
}
|
||||
if (value[0] == '"') {
|
||||
value = value.substr(1, value.length()-2);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// ***************************************************************** -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2004, 2005 Andreas Huggel <ahuggel@gmx.net>
|
||||
*
|
||||
* This program is part of the Exiv2 distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*
|
||||
File: utils.cpp
|
||||
Version: $Rev$
|
||||
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
||||
History: 08-Dec-03, ahu: created
|
||||
02-Apr-05, ahu: moved to Exiv2 namespace
|
||||
*/
|
||||
// *****************************************************************************
|
||||
#include "rcsid.hpp"
|
||||
EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
#ifdef _MSC_VER
|
||||
# include "exv_msvc.h"
|
||||
#else
|
||||
# include "exv_conf.h"
|
||||
#endif
|
||||
|
||||
#include "futils.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef _MSC_VER
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#ifdef EXV_HAVE_UNISTD_H
|
||||
# include <unistd.h> // for stat()
|
||||
#endif
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace Exiv2 {
|
||||
|
||||
// *****************************************************************************
|
||||
// free functions
|
||||
|
||||
bool fileExists(const std::string& path, bool ct)
|
||||
{
|
||||
struct stat buf;
|
||||
int ret = stat(path.c_str(), &buf);
|
||||
if (0 != ret) return false;
|
||||
if (ct && !S_ISREG(buf.st_mode)) return false;
|
||||
return true;
|
||||
} // fileExists
|
||||
|
||||
std::string strError()
|
||||
{
|
||||
int error = errno;
|
||||
std::ostringstream os;
|
||||
os << strerror(error) << " (" << error << ")";
|
||||
return os.str();
|
||||
} // strError
|
||||
|
||||
} // namespace Exiv2
|
||||
@@ -0,0 +1,66 @@
|
||||
// ********************************************************* -*- C++ -*-
|
||||
/*
|
||||
* Copyright (C) 2004, 2005 Andreas Huggel <ahuggel@gmx.net>
|
||||
*
|
||||
* This program is part of the Exiv2 distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*!
|
||||
@file futils.hpp
|
||||
@brief Basic file utility functions required by Exiv2
|
||||
@version $Rev$
|
||||
@author Andreas Huggel (ahu)
|
||||
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
|
||||
@date 12-Dec-03, ahu: created<BR>
|
||||
02-Apr-05, ahu: moved to Exiv2 namespace
|
||||
*/
|
||||
#ifndef FUTILS_HPP_
|
||||
#define FUTILS_HPP_
|
||||
|
||||
// *********************************************************************
|
||||
// included header files
|
||||
// + standard includes
|
||||
#include <string>
|
||||
|
||||
// *********************************************************************
|
||||
// namespace extensions
|
||||
namespace Exiv2 {
|
||||
|
||||
// *********************************************************************
|
||||
// free functions
|
||||
|
||||
/*!
|
||||
@brief Test if a file exists.
|
||||
|
||||
@param path Name of file to verify.
|
||||
@param ct Flag to check if <i>path</i> is a regular file.
|
||||
@return true if <i>path</i> exists and, if <i>ct</i> is set,
|
||||
is a regular file, else false.
|
||||
|
||||
@note The function calls <b>stat()</b> test for <i>path</i>
|
||||
and its type, see stat(2). <b>errno</b> is left unchanged
|
||||
in case of an error.
|
||||
*/
|
||||
bool fileExists(const std::string& path, bool ct =false);
|
||||
/*!
|
||||
@brief Return a system error message and the error code (errno).
|
||||
See %strerror(3).
|
||||
*/
|
||||
std::string strError();
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef FUTILS_HPP_
|
||||
+1
-1
@@ -203,7 +203,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (const Exiv2::Error& e) {
|
||||
catch (const Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
+8
-11
@@ -137,9 +137,7 @@ namespace Exiv2 {
|
||||
{
|
||||
long dataSize = count * TypeInfo::typeSize(TypeId(type));
|
||||
// No minimum size requirement, but make sure the buffer can hold the data
|
||||
if (len < dataSize) {
|
||||
throw Error("Size too small");
|
||||
}
|
||||
if (len < dataSize) throw Error(24, tag(), dataSize, len);
|
||||
if (alloc_) {
|
||||
delete[] pData_;
|
||||
pData_ = new byte[len];
|
||||
@@ -155,7 +153,7 @@ namespace Exiv2 {
|
||||
}
|
||||
else {
|
||||
// Overwrite existing data if it fits into the buffer
|
||||
if (dataSize > size_) throw Error("Value too large");
|
||||
if (size_ < dataSize) throw Error(24, tag(), dataSize, size_);
|
||||
memset(pData_, 0x0, size_);
|
||||
memcpy(pData_, buf, dataSize);
|
||||
// do not change size_
|
||||
@@ -181,7 +179,9 @@ namespace Exiv2 {
|
||||
}
|
||||
else {
|
||||
// Overwrite existing data if it fits into the buffer
|
||||
if (len > sizeDataArea_) throw Error("Value too large");
|
||||
if (sizeDataArea_ < len) {
|
||||
throw Error(25, tag(), sizeDataArea_, len);
|
||||
}
|
||||
memset(pDataArea_, 0x0, sizeDataArea_);
|
||||
memcpy(pDataArea_, buf, len);
|
||||
// do not change sizeDataArea_
|
||||
@@ -196,9 +196,7 @@ namespace Exiv2 {
|
||||
switch(TypeId(type())) {
|
||||
case unsignedShort: {
|
||||
uint16_t d = getUShort(buf, byteOrder);
|
||||
if (d + offset > 0xffff) {
|
||||
throw Error("Offset out of range");
|
||||
}
|
||||
if (d + offset > 0xffff) throw Error(26);
|
||||
us2Data(buf, d + static_cast<uint16_t>(offset), byteOrder);
|
||||
break;
|
||||
}
|
||||
@@ -214,8 +212,7 @@ namespace Exiv2 {
|
||||
}
|
||||
case signedShort: {
|
||||
int16_t d = getShort(buf, byteOrder);
|
||||
if (d + static_cast<int32_t>(offset) > 0xffff)
|
||||
throw Error("Offset out of range");
|
||||
if (d + static_cast<int32_t>(offset) > 0xffff) throw Error(26);
|
||||
s2Data(buf, d + static_cast<int16_t>(offset), byteOrder);
|
||||
break;
|
||||
}
|
||||
@@ -231,7 +228,7 @@ namespace Exiv2 {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Error("Unsupported data area offset type");
|
||||
throw Error(27);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -121,10 +121,9 @@ namespace Exiv2 {
|
||||
@param count Number of components in the buffer.
|
||||
@param data Pointer to the data buffer.
|
||||
@param size Size of the desired data buffer in bytes.
|
||||
@throw Error ("Value too large") if no memory allocation is allowed
|
||||
@throw Error if no memory allocation is allowed
|
||||
and the size of the data buffer is larger than the existing
|
||||
data buffer of the entry.<BR>
|
||||
@throw Error ("Size too small") if size is not large enough to hold
|
||||
data buffer of the entry or if size is not large enough to hold
|
||||
count components of the given type.
|
||||
*/
|
||||
void setValue(uint16_t type, uint32_t count, const byte* data, long size);
|
||||
@@ -143,6 +142,10 @@ namespace Exiv2 {
|
||||
|
||||
@param buf Pointer to the data area.
|
||||
@param len Size of the data area.
|
||||
|
||||
@throw Error in non-alloc mode, if there already is a dataarea but the
|
||||
size of the existing dataarea is not large enough for the
|
||||
new buffer.
|
||||
*/
|
||||
void setDataArea(const byte* buf, long len);
|
||||
/*!
|
||||
@@ -153,6 +156,12 @@ namespace Exiv2 {
|
||||
offsets relative to the data area to become offsets from the start of
|
||||
the TIFF header. Usually, entries with a data area have exactly one
|
||||
unsigned long data component, which is 0.
|
||||
|
||||
@param offset Offset
|
||||
@param byteOrder Byte order
|
||||
|
||||
@throw Error if the offset is out of range for the data type of the
|
||||
tag or the data type is not supported.
|
||||
*/
|
||||
void setDataAreaOffsets(uint32_t offset, ByteOrder byteOrder);
|
||||
/*!
|
||||
|
||||
+21
-56
@@ -42,11 +42,13 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
#include "image.hpp"
|
||||
#include "error.hpp"
|
||||
#include "futils.hpp"
|
||||
|
||||
// Ensure registration with factory
|
||||
#include "jpgimage.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdio> // for rename, remove
|
||||
@@ -95,9 +97,8 @@ namespace Exiv2 {
|
||||
|
||||
Image::Type ImageFactory::getType(BasicIo& io)
|
||||
{
|
||||
if (io.open() != 0) return Image::none;
|
||||
IoCloser closer(io);
|
||||
if (io.open() != 0) return Image::none;
|
||||
|
||||
Image::Type type = Image::none;
|
||||
Registry::const_iterator b = registry_->begin();
|
||||
Registry::const_iterator e = registry_->end();
|
||||
@@ -114,21 +115,24 @@ namespace Exiv2 {
|
||||
Image::AutoPtr ImageFactory::open(const std::string& path)
|
||||
{
|
||||
BasicIo::AutoPtr io(new FileIo(path));
|
||||
return open(io);
|
||||
Image::AutoPtr image(open(io));
|
||||
if (image.get() == 0) throw Error(11, path);
|
||||
return image;
|
||||
}
|
||||
|
||||
Image::AutoPtr ImageFactory::open(const byte* data, long size)
|
||||
{
|
||||
BasicIo::AutoPtr io(new MemIo(data, size));
|
||||
return open(io);
|
||||
Image::AutoPtr image(open(io));
|
||||
if (image.get() == 0) throw Error(12);
|
||||
return image;
|
||||
}
|
||||
|
||||
Image::AutoPtr ImageFactory::open(BasicIo::AutoPtr io)
|
||||
{
|
||||
Image::AutoPtr image;
|
||||
IoCloser closer(*io);
|
||||
if (io->open() != 0) return image;
|
||||
|
||||
IoCloser closer(*io);
|
||||
Registry::const_iterator b = registry_->begin();
|
||||
Registry::const_iterator e = registry_->end();
|
||||
for (Registry::const_iterator i = b; i != e; ++i)
|
||||
@@ -141,25 +145,29 @@ namespace Exiv2 {
|
||||
return image;
|
||||
} // ImageFactory::open
|
||||
|
||||
|
||||
Image::AutoPtr ImageFactory::create(Image::Type type,
|
||||
const std::string& path)
|
||||
{
|
||||
FileIo *fileIo = new FileIo(path);
|
||||
BasicIo::AutoPtr io(fileIo);
|
||||
std::auto_ptr<FileIo> fileIo(new FileIo(path));
|
||||
// Create or overwrite the file, then close it
|
||||
if (fileIo->open("w+b") != 0) return Image::AutoPtr();
|
||||
if (fileIo->open("w+b") != 0) {
|
||||
throw Error(10, path, "w+b", strError());
|
||||
}
|
||||
fileIo->close();
|
||||
return create(type, io);
|
||||
BasicIo::AutoPtr io(fileIo);
|
||||
Image::AutoPtr image(create(type, io));
|
||||
if (image.get() == 0) throw Error(13, type);
|
||||
return image;
|
||||
}
|
||||
|
||||
Image::AutoPtr ImageFactory::create(Image::Type type)
|
||||
{
|
||||
BasicIo::AutoPtr io(new MemIo);
|
||||
return create(type, io);
|
||||
Image::AutoPtr image(create(type, io));
|
||||
if (image.get() == 0) throw Error(13, type);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
Image::AutoPtr ImageFactory::create(Image::Type type,
|
||||
BasicIo::AutoPtr io)
|
||||
{
|
||||
@@ -171,37 +179,6 @@ namespace Exiv2 {
|
||||
return Image::AutoPtr();
|
||||
} // ImageFactory::create
|
||||
|
||||
std::string Image::strError(int rc, const std::string& path)
|
||||
{
|
||||
std::string error = path + ": ";
|
||||
switch (rc) {
|
||||
case -1:
|
||||
error += "Failed to open the file";
|
||||
break;
|
||||
case -2:
|
||||
error += "The file contains data of an unknown image type";
|
||||
break;
|
||||
case -3:
|
||||
error += "Couldn't open temporary file";
|
||||
break;
|
||||
case -4:
|
||||
error += "Renaming temporary file failed";
|
||||
break;
|
||||
case 1:
|
||||
error += "Couldn't read from the input file";
|
||||
break;
|
||||
case 2:
|
||||
error += "This does not look like a JPEG image";
|
||||
break;
|
||||
default:
|
||||
error += "Accessing image data failed, rc = " + toString(rc);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
} // Image::strError
|
||||
|
||||
|
||||
|
||||
TiffHeader::TiffHeader(ByteOrder byteOrder)
|
||||
: byteOrder_(byteOrder), tag_(0x002a), offset_(0x00000008)
|
||||
{
|
||||
@@ -243,16 +220,4 @@ namespace Exiv2 {
|
||||
return size();
|
||||
} // TiffHeader::copy
|
||||
|
||||
// *****************************************************************************
|
||||
// free functions
|
||||
|
||||
bool fileExists(const std::string& path, bool ct)
|
||||
{
|
||||
struct stat buf;
|
||||
int ret = stat(path.c_str(), &buf);
|
||||
if (0 != ret) return false;
|
||||
if (ct && !S_ISREG(buf.st_mode)) return false;
|
||||
return true;
|
||||
} // fileExists
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
+19
-45
@@ -52,7 +52,6 @@ namespace Exiv2 {
|
||||
class ExifData;
|
||||
class IptcData;
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// class definitions
|
||||
/*!
|
||||
@@ -82,9 +81,9 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Read metadata from assigned image. Before this method
|
||||
is called, the various metadata types (Iptc, Exif) will be empty.
|
||||
@return 0 if successful.
|
||||
@throw Error In case of failure.
|
||||
*/
|
||||
virtual int readMetadata() =0;
|
||||
virtual void readMetadata() =0;
|
||||
/*!
|
||||
@brief Write metadata back to the image.
|
||||
|
||||
@@ -95,9 +94,9 @@ namespace Exiv2 {
|
||||
any exists section for that metadata type will be removed from the
|
||||
image.
|
||||
|
||||
@return 0 if successful.
|
||||
@throw Error if the operation fails
|
||||
*/
|
||||
virtual int writeMetadata() =0;
|
||||
virtual void writeMetadata() =0;
|
||||
/*!
|
||||
@brief Assign new exif data. The new exif data is not written
|
||||
to the image until the writeMetadata() method is called.
|
||||
@@ -220,19 +219,8 @@ namespace Exiv2 {
|
||||
method is called.
|
||||
*/
|
||||
virtual BasicIo& io() const = 0;
|
||||
/*!
|
||||
@brief Convert the return code \em rc from various methods
|
||||
in this class to string messages.
|
||||
@param rc Error code.
|
||||
@param path %Image file or other identifying string.
|
||||
@return String containing error message.
|
||||
|
||||
Todo: Implement global handling of error messages
|
||||
*/
|
||||
static std::string strError(int rc, const std::string& path);
|
||||
//@}
|
||||
|
||||
|
||||
protected:
|
||||
//! @name Creators
|
||||
//@{
|
||||
@@ -277,8 +265,8 @@ namespace Exiv2 {
|
||||
@param isType Function pointer to test for matching image types.
|
||||
*/
|
||||
static void registerImage(Image::Type type,
|
||||
NewInstanceFct newInst,
|
||||
IsThisTypeFct isType);
|
||||
NewInstanceFct newInst,
|
||||
IsThisTypeFct isType);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
@@ -286,36 +274,37 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Create an Image subclass of the appropriate type by reading
|
||||
the specified file. %Image type is derived from the file
|
||||
contents.
|
||||
contents.
|
||||
@param path %Image file. The contents of the file are tested to
|
||||
determine the image type. File extension is ignored.
|
||||
@return An auto-pointer that owns an Image instance whose type
|
||||
matches that of the file. If no image type could be determined,
|
||||
the pointer is 0.
|
||||
matches that of the file.
|
||||
@throw Error If opening the file fails or it contains data of an
|
||||
unknown image type.
|
||||
*/
|
||||
static Image::AutoPtr open(const std::string& path);
|
||||
/*!
|
||||
@brief Create an Image subclass of the appropriate type by reading
|
||||
the provided memory. %Image type is derived from the memory
|
||||
contents.
|
||||
contents.
|
||||
@param data Pointer to a data buffer containing an image. The contents
|
||||
of the memory are tested to determine the image type.
|
||||
@param size Number of bytes pointed to by \em data.
|
||||
@return An auto-pointer that owns an Image instance whose type
|
||||
matches that of the data buffer. If no image type could be
|
||||
determined, the pointer is 0.
|
||||
matches that of the data buffer.
|
||||
@throw Error If the memory contains data of an unknown image type.
|
||||
*/
|
||||
static Image::AutoPtr open(const byte* data, long size);
|
||||
/*!
|
||||
@brief Create an Image subclass of the appropriate type by reading
|
||||
the provided BasicIo instance. %Image type is derived from the
|
||||
data provided by \em io. The passed in \em io instance is
|
||||
(re)opened by this method.
|
||||
(re)opened by this method.
|
||||
@param io An auto-pointer that owns a BasicIo instance that provides
|
||||
image data. The contents of the image data are tested to determine
|
||||
the type. \b Important: This method takes ownership of the passed
|
||||
in BasicIo instance through the auto-pointer. Callers should not
|
||||
continue to use the BasicIo instance after it is passed to this method.
|
||||
continue to use the BasicIo instance after it is passed to this method.
|
||||
Use theImage::io() method to get a temporary reference.
|
||||
@return An auto-pointer that owns an Image instance whose type
|
||||
matches that of the \em io data. If no image type could be
|
||||
@@ -328,7 +317,8 @@ namespace Exiv2 {
|
||||
@param type Type of the image to be created.
|
||||
@param path %Image file to create. File extension is ignored.
|
||||
@return An auto-pointer that owns an Image instance of the requested
|
||||
type. If the image type is not supported, the pointer is 0.
|
||||
type.
|
||||
@throw Error If the image type is not supported.
|
||||
*/
|
||||
static Image::AutoPtr create(Image::Type type, const std::string& path);
|
||||
/*!
|
||||
@@ -336,7 +326,8 @@ namespace Exiv2 {
|
||||
new image in memory.
|
||||
@param type Type of the image to be created.
|
||||
@return An auto-pointer that owns an Image instance of the requested
|
||||
type. If the image type is not supported, the pointer is 0.
|
||||
type.
|
||||
@throw Error If the image type is not supported
|
||||
*/
|
||||
static Image::AutoPtr create(Image::Type type);
|
||||
/*!
|
||||
@@ -463,23 +454,6 @@ namespace Exiv2 {
|
||||
|
||||
}; // class TiffHeader
|
||||
|
||||
// *********************************************************************
|
||||
// free functions
|
||||
|
||||
/*!
|
||||
@brief Test if a file exists.
|
||||
|
||||
@param path Name of file to verify.
|
||||
@param ct Flag to check if <i>path</i> is a regular file.
|
||||
@return true if <i>path</i> exists and, if <i>ct</i> is set,
|
||||
is a regular file, else false.
|
||||
|
||||
@note The function calls <b>stat()</b> test for <i>path</i>
|
||||
and its type, see stat(2). <b>errno</b> is left unchanged
|
||||
in case of an error.
|
||||
*/
|
||||
bool fileExists(const std::string& path, bool ct =false);
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
#endif // #ifndef IMAGE_HPP_
|
||||
|
||||
+14
-18
@@ -31,6 +31,7 @@
|
||||
// included header files
|
||||
#include "types.hpp"
|
||||
#include "error.hpp"
|
||||
#include "futils.hpp"
|
||||
#include "basicio.hpp"
|
||||
#include <iostream>
|
||||
|
||||
@@ -39,6 +40,8 @@ using Exiv2::BasicIo;
|
||||
using Exiv2::MemIo;
|
||||
using Exiv2::FileIo;
|
||||
using Exiv2::IoCloser;
|
||||
using Exiv2::Error;
|
||||
using Exiv2::strError;
|
||||
|
||||
int WriteReadSeek(BasicIo &io);
|
||||
|
||||
@@ -55,16 +58,12 @@ try {
|
||||
|
||||
FileIo fileIn(argv[1]);
|
||||
if (fileIn.open() != 0) {
|
||||
std::cerr << argv[0] <<
|
||||
": Could not open input file (" << argv[1] << ")\n";
|
||||
return 1;
|
||||
throw Error(9, strError());
|
||||
}
|
||||
|
||||
FileIo fileOut1(argv[2]);
|
||||
if (fileOut1.open("w+b") != 0) {
|
||||
std::cerr << argv[0] <<
|
||||
": Could not open output file 1 (" << argv[2] << ")\n";
|
||||
return 1;
|
||||
throw Error(10, argv[2], "w+b", strError());
|
||||
}
|
||||
|
||||
MemIo memIo1;
|
||||
@@ -90,10 +89,9 @@ try {
|
||||
// Create or overwrite the file, then close it
|
||||
FileIo fileTest("iotest.txt");
|
||||
if (fileTest.open("w+b") != 0) {
|
||||
std::cerr << argv[0] <<
|
||||
": Could not create test file iotest.txt\n";
|
||||
return 1;
|
||||
throw Error(10, "iotest.txt", "w+b", strError());
|
||||
}
|
||||
|
||||
fileTest.close();
|
||||
rc = WriteReadSeek(fileTest);
|
||||
if (rc != 0) return rc;
|
||||
@@ -103,9 +101,7 @@ try {
|
||||
memIo2.seek(0, BasicIo::beg);
|
||||
FileIo fileOut2(argv[3]);
|
||||
if (fileOut2.open("w+b") != 0) {
|
||||
std::cerr << argv[0] <<
|
||||
": Could not open output file 2 (" << argv[3] << ")\n";
|
||||
return 1;
|
||||
throw Error(10, argv[3], "w+b", strError());
|
||||
}
|
||||
|
||||
long readCount = 0;
|
||||
@@ -125,7 +121,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return 20;
|
||||
}
|
||||
@@ -142,12 +138,10 @@ int WriteReadSeek(BasicIo &io)
|
||||
const long len1 = (long)strlen(tester1) + 1;
|
||||
const long len2 = (long)strlen(tester2) + 1;
|
||||
|
||||
IoCloser closer(io);
|
||||
if (io.open() != 0) {
|
||||
std::cerr << ": WRS could not open IO\n";
|
||||
return 2;
|
||||
throw Error(9, strError());
|
||||
}
|
||||
|
||||
IoCloser closer(io);
|
||||
if (io.write((byte*)tester1, len1) != len1) {
|
||||
std::cerr << ": WRS initial write failed\n";
|
||||
return 2;
|
||||
@@ -207,7 +201,9 @@ int WriteReadSeek(BasicIo &io)
|
||||
}
|
||||
|
||||
// open should seek to beginning
|
||||
io.open();
|
||||
if (io.open() != 0) {
|
||||
throw Error(9, strError());
|
||||
}
|
||||
memset(buf, -1, sizeof(buf));
|
||||
if (io.read(buf, sizeof(buf)) != insert + len2) {
|
||||
std::cerr << ": WRS something went wrong\n";
|
||||
|
||||
@@ -288,48 +288,6 @@ namespace Exiv2 {
|
||||
return iptcMetadata_.erase(pos);
|
||||
}
|
||||
|
||||
std::string IptcData::strError(int rc, const std::string& path)
|
||||
{
|
||||
std::string error = path + ": ";
|
||||
switch (rc) {
|
||||
case -1:
|
||||
error += "Failed to open the file";
|
||||
break;
|
||||
case -2:
|
||||
error += "The file contains data of an unknown image type";
|
||||
break;
|
||||
case -3:
|
||||
error += "Couldn't open temporary file";
|
||||
break;
|
||||
case -4:
|
||||
error += "Renaming temporary file failed";
|
||||
break;
|
||||
case 1:
|
||||
error += "Couldn't read from the input file";
|
||||
break;
|
||||
case 2:
|
||||
error += "This does not look like a JPEG image";
|
||||
break;
|
||||
case 3:
|
||||
error += "No Iptc data found in the file";
|
||||
break;
|
||||
case 4:
|
||||
error += "Writing to the output file failed";
|
||||
break;
|
||||
case 5:
|
||||
error += "Invalid or corrupt Iptc data";
|
||||
break;
|
||||
case 6:
|
||||
error += "Iptc dataset already exists and is not repeatable";
|
||||
break;
|
||||
|
||||
default:
|
||||
error += "Accessing Iptc data failed, rc = " + toString(rc);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
} // IptcData::strError
|
||||
|
||||
// *************************************************************************
|
||||
// free functions
|
||||
std::ostream& operator<<(std::ostream& os, const Iptcdatum& md)
|
||||
|
||||
+4
-18
@@ -65,7 +65,7 @@ namespace Exiv2 {
|
||||
|
||||
@param key The key of the %Iptcdatum.
|
||||
@param pValue Pointer to a %Iptcdatum value.
|
||||
@throw Error ("Invalid key") if the key cannot be parsed and converted
|
||||
@throw Error if the key cannot be parsed and converted
|
||||
to a tag number and record id.
|
||||
*/
|
||||
explicit Iptcdatum(const IptcKey& key,
|
||||
@@ -136,7 +136,6 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Return the name of the record
|
||||
@return record name
|
||||
@throw Error("Unknown record");
|
||||
*/
|
||||
std::string recordName() const
|
||||
{ return key_.get() == 0 ? "" : key_->recordName(); }
|
||||
@@ -149,7 +148,6 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Return the name of the tag (aka dataset)
|
||||
@return tag name
|
||||
@throw Error("No dataSet for record Id") if tag is unknown
|
||||
*/
|
||||
std::string tagName() const
|
||||
{ return key_.get() == 0 ? "" : key_->tagName(); }
|
||||
@@ -226,10 +224,10 @@ namespace Exiv2 {
|
||||
@endcode
|
||||
|
||||
@return A constant reference to the value.
|
||||
@throw Error ("Value not set") if the value is not set.
|
||||
@throw Error If the value is not set.
|
||||
*/
|
||||
const Value& value() const
|
||||
{ if (value_.get() != 0) return *value_; throw Error("Value not set"); }
|
||||
const Value& value() const
|
||||
{ if (value_.get() != 0) return *value_; throw Error(8); }
|
||||
//@}
|
||||
|
||||
private:
|
||||
@@ -394,18 +392,6 @@ namespace Exiv2 {
|
||||
long size() const;
|
||||
//@}
|
||||
|
||||
/*!
|
||||
@brief Convert the return code from \n
|
||||
int read(const byte* buf, long len), \n
|
||||
into an error message.
|
||||
@param rc Error code.
|
||||
@param path %Image file or other identifying string.
|
||||
@return String containing error message.
|
||||
|
||||
Todo: Implement global handling of error messages
|
||||
*/
|
||||
static std::string strError(int rc, const std::string& path);
|
||||
|
||||
private:
|
||||
/*!
|
||||
@brief Read a single dataset payload and create a new metadata entry
|
||||
|
||||
+7
-15
@@ -6,6 +6,7 @@
|
||||
#include "image.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
try {
|
||||
@@ -34,24 +35,15 @@ try {
|
||||
|
||||
// Open image file
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert (image.get() != 0);
|
||||
|
||||
// Read existing metdata (so that exif will be preserved)
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
// Replace Iptc data and write it back to the file
|
||||
// Set Iptc data and write it to the file
|
||||
image->setIptcData(iptcData);
|
||||
return image->writeMetadata();
|
||||
image->writeMetadata();
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
+6
-14
@@ -6,6 +6,7 @@
|
||||
#include "iptc.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
try {
|
||||
@@ -16,23 +17,14 @@ try {
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
|
||||
if (image.get() == 0) {
|
||||
std::string error(argv[1]);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert (image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
// Load existing metadata
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, argv[1]);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
Exiv2::IptcData &iptcData = image->iptcData();
|
||||
if (iptcData.empty()) {
|
||||
std::string error(argv[1]);
|
||||
error += ": No Iptc data found in the file";
|
||||
throw Exiv2::Error(error);
|
||||
throw Exiv2::Error(1, error);
|
||||
}
|
||||
|
||||
Exiv2::IptcData::iterator end = iptcData.end();
|
||||
@@ -50,9 +42,9 @@ try {
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
+12
-26
@@ -16,6 +16,7 @@
|
||||
#include "value.hpp"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cassert>
|
||||
|
||||
using namespace Exiv2;
|
||||
|
||||
@@ -37,16 +38,8 @@ int main(int argc, char* const argv[])
|
||||
}
|
||||
|
||||
Image::AutoPtr image = ImageFactory::open(argv[1]);
|
||||
if (image.get() == 0) {
|
||||
throw Error("Could not read file");
|
||||
}
|
||||
|
||||
// Load existing metadata
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Image::strError(rc, argv[1]);
|
||||
throw Error(error);
|
||||
}
|
||||
assert (image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
// Process commands
|
||||
std::string line;
|
||||
@@ -57,15 +50,11 @@ int main(int argc, char* const argv[])
|
||||
}
|
||||
|
||||
// Save any changes
|
||||
rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Image::strError(rc, argv[1]);
|
||||
throw Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
catch (Error& e) {
|
||||
catch (AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -92,7 +81,7 @@ bool processLine(const std::string& line, int num, IptcData &iptcData)
|
||||
default:
|
||||
std::ostringstream os;
|
||||
os << "Unknown command (" << line.at(0) << ") at line " << num;
|
||||
throw Error(os.str());
|
||||
throw Error(1, os.str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -108,7 +97,7 @@ void processAdd(const std::string& line, int num, IptcData &iptcData)
|
||||
dataStart == std::string::npos) {
|
||||
std::ostringstream os;
|
||||
os << "Invalid \'a\' command at line " << num;
|
||||
throw Error(os.str());
|
||||
throw Error(1, os.str());
|
||||
}
|
||||
|
||||
std::string key(line.substr(keyStart, keyEnd-keyStart));
|
||||
@@ -125,10 +114,8 @@ void processAdd(const std::string& line, int num, IptcData &iptcData)
|
||||
|
||||
int rc = iptcData.add(iptcKey, value.get());
|
||||
if (rc) {
|
||||
std::string error = IptcData::strError(rc, "Input file");
|
||||
throw Error(error);
|
||||
throw Error(1, "Iptc dataset already exists and is not repeatable");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void processRemove(const std::string& line, int num, IptcData &iptcData)
|
||||
@@ -138,7 +125,7 @@ void processRemove(const std::string& line, int num, IptcData &iptcData)
|
||||
if (keyStart == std::string::npos) {
|
||||
std::ostringstream os;
|
||||
os << "Invalid \'r\' command at line " << num;
|
||||
throw Error(os.str());
|
||||
throw Error(1, os.str());
|
||||
}
|
||||
|
||||
const std::string key( line.substr(keyStart) );
|
||||
@@ -161,7 +148,7 @@ void processModify(const std::string& line, int num, IptcData &iptcData)
|
||||
dataStart == std::string::npos) {
|
||||
std::ostringstream os;
|
||||
os << "Invalid \'m\' command at line " << num;
|
||||
throw Error(os.str());
|
||||
throw Error(1, os.str());
|
||||
}
|
||||
|
||||
std::string key(line.substr(keyStart, keyEnd-keyStart));
|
||||
@@ -183,8 +170,7 @@ void processModify(const std::string& line, int num, IptcData &iptcData)
|
||||
else {
|
||||
int rc = iptcData.add(iptcKey, value.get());
|
||||
if (rc) {
|
||||
std::string error = IptcData::strError(rc, "Input file");
|
||||
throw Error(error);
|
||||
throw Error(1, "Iptc dataset already exists and is not repeatable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+77
-80
@@ -40,6 +40,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
#include "jpgimage.hpp"
|
||||
#include "error.hpp"
|
||||
#include "futils.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <cstring>
|
||||
@@ -85,14 +86,16 @@ namespace Exiv2 {
|
||||
: io_(io)
|
||||
{
|
||||
if (create) {
|
||||
initImage(initData, dataSize);
|
||||
initImage(initData, dataSize); // may throw
|
||||
}
|
||||
}
|
||||
|
||||
int JpegBase::initImage(const byte initData[], long dataSize)
|
||||
{
|
||||
if (io_->open() != 0) {
|
||||
return 4;
|
||||
}
|
||||
IoCloser closer(*io_);
|
||||
if (io_->open() != 0) return 4;
|
||||
if (io_->write(initData, dataSize) != dataSize) {
|
||||
return 4;
|
||||
}
|
||||
@@ -101,8 +104,8 @@ namespace Exiv2 {
|
||||
|
||||
bool JpegBase::good() const
|
||||
{
|
||||
IoCloser closer(*io_);
|
||||
if (io_->open() != 0) return false;
|
||||
IoCloser closer(*io_);
|
||||
return isThisType(*io_, false);
|
||||
}
|
||||
|
||||
@@ -165,15 +168,16 @@ namespace Exiv2 {
|
||||
return c;
|
||||
}
|
||||
|
||||
int JpegBase::readMetadata()
|
||||
void JpegBase::readMetadata()
|
||||
{
|
||||
if (io_->open() != 0) {
|
||||
throw Error(9, strError());
|
||||
}
|
||||
IoCloser closer(*io_);
|
||||
if (io_->open() != 0) return 1;
|
||||
|
||||
// Ensure that this is the correct image type
|
||||
if (!isThisType(*io_, true)) {
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
return 2;
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
throw Error(15);
|
||||
}
|
||||
clearMetadata();
|
||||
int search = 3;
|
||||
@@ -183,34 +187,32 @@ namespace Exiv2 {
|
||||
|
||||
// Read section marker
|
||||
int marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(15);
|
||||
|
||||
while (marker != sos_ && marker != eoi_ && search > 0) {
|
||||
// Read size and signature (ok if this hits EOF)
|
||||
bufRead = io_->read(buf.pData_, bufMinSize);
|
||||
if (io_->error()) return 1;
|
||||
if (io_->error()) throw Error(14);
|
||||
uint16_t size = getUShort(buf.pData_, bigEndian);
|
||||
|
||||
if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
|
||||
if (size < 8) return 2;
|
||||
if (size < 8) throw Error(15);
|
||||
// Seek to begining and read the Exif data
|
||||
io_->seek(8-bufRead, BasicIo::cur);
|
||||
long sizeExifData = size - 8;
|
||||
DataBuf rawExif(sizeExifData);
|
||||
io_->read(rawExif.pData_, sizeExifData);
|
||||
if (io_->error() || io_->eof()) {
|
||||
return 1;
|
||||
}
|
||||
if (exifData_.load(rawExif.pData_, sizeExifData)) return 2;
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
if (exifData_.load(rawExif.pData_, sizeExifData)) throw Error(15);
|
||||
--search;
|
||||
}
|
||||
else if (marker == app13_ && memcmp(buf.pData_ + 2, ps3Id_, 14) == 0) {
|
||||
if (size < 16) return 2;
|
||||
if (size < 16) throw Error(15);
|
||||
// Read the rest of the APP13 segment
|
||||
// needed if bufMinSize!=16: io_->seek(16-bufRead, BasicIo::cur);
|
||||
DataBuf psData(size - 16);
|
||||
io_->read(psData.pData_, psData.size_);
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
const byte *record = 0;
|
||||
uint16_t sizeIptc = 0;
|
||||
uint16_t sizeHdr = 0;
|
||||
@@ -218,20 +220,20 @@ namespace Exiv2 {
|
||||
if (!locateIptcData(psData.pData_, psData.size_, &record,
|
||||
&sizeHdr, &sizeIptc)) {
|
||||
assert(sizeIptc);
|
||||
if (iptcData_.load(record + sizeHdr, sizeIptc)) return 2;
|
||||
if (iptcData_.load(record + sizeHdr, sizeIptc)) throw Error(15);
|
||||
}
|
||||
--search;
|
||||
}
|
||||
else if (marker == com_ && comment_.empty())
|
||||
{
|
||||
if (size < 2) return 2;
|
||||
if (size < 2) throw Error(15);
|
||||
// Jpegs can have multiple comments, but for now only read
|
||||
// the first one (most jpegs only have one anyway). Comments
|
||||
// are simple single byte ISO-8859-1 strings.
|
||||
io_->seek(2-bufRead, BasicIo::cur);
|
||||
buf.alloc(size-2);
|
||||
io_->read(buf.pData_, size-2);
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
if (io_->error() || io_->eof()) throw Error(14);
|
||||
comment_.assign(reinterpret_cast<char*>(buf.pData_), size-2);
|
||||
while ( comment_.length()
|
||||
&& comment_.at(comment_.length()-1) == '\0') {
|
||||
@@ -240,15 +242,14 @@ namespace Exiv2 {
|
||||
--search;
|
||||
}
|
||||
else {
|
||||
if (size < 2) return 2;
|
||||
if (size < 2) throw Error(15);
|
||||
// Skip the remainder of the unknown segment
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) return 2;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(15);
|
||||
}
|
||||
// Read the beginning of the next segment
|
||||
marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(15);
|
||||
}
|
||||
return 0;
|
||||
} // JpegBase::readMetadata
|
||||
|
||||
|
||||
@@ -295,30 +296,27 @@ namespace Exiv2 {
|
||||
return 3;
|
||||
} // JpegBase::locateIptcData
|
||||
|
||||
int JpegBase::writeMetadata()
|
||||
void JpegBase::writeMetadata()
|
||||
{
|
||||
if (io_->open() != 0) throw Error(9, strError());
|
||||
IoCloser closer(*io_);
|
||||
if (io_->open() != 0) return 1;
|
||||
BasicIo::AutoPtr tempIo(io_->temporary());
|
||||
if (!tempIo.get()) return -3;
|
||||
BasicIo::AutoPtr tempIo(io_->temporary()); // may throw
|
||||
assert (tempIo.get() != 0);
|
||||
|
||||
int rc = doWriteMetadata(*tempIo);
|
||||
doWriteMetadata(*tempIo); // may throw
|
||||
io_->close();
|
||||
if( rc == 0 ) {
|
||||
if (io_->transfer(*tempIo) != 0) return -3;
|
||||
}
|
||||
return rc;
|
||||
io_->transfer(*tempIo); // may throw
|
||||
} // JpegBase::writeMetadata
|
||||
|
||||
int JpegBase::doWriteMetadata(BasicIo& outIo)
|
||||
void JpegBase::doWriteMetadata(BasicIo& outIo)
|
||||
{
|
||||
if (!io_->isopen()) return 1;
|
||||
if (!outIo.isopen()) return 4;
|
||||
if (!io_->isopen()) throw Error(20);
|
||||
if (!outIo.isopen()) throw Error(21);
|
||||
|
||||
// Ensure that this is the correct image type
|
||||
if (!isThisType(*io_, true)) {
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
return 2;
|
||||
if (io_->error() || io_->eof()) throw Error(20);
|
||||
throw Error(22);
|
||||
}
|
||||
|
||||
const long bufMinSize = 16;
|
||||
@@ -334,11 +332,11 @@ namespace Exiv2 {
|
||||
DataBuf psData;
|
||||
|
||||
// Write image header
|
||||
if (writeHeader(outIo)) return 4;
|
||||
if (writeHeader(outIo)) throw Error(21);
|
||||
|
||||
// Read section marker
|
||||
int marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(22);
|
||||
|
||||
// First find segments of interest. Normally app0 is first and we want
|
||||
// to insert after it. But if app0 comes after com, app1 and app13 then
|
||||
@@ -346,44 +344,44 @@ namespace Exiv2 {
|
||||
while (marker != sos_ && marker != eoi_ && search < 3) {
|
||||
// Read size and signature (ok if this hits EOF)
|
||||
bufRead = io_->read(buf.pData_, bufMinSize);
|
||||
if (io_->error()) return 1;
|
||||
if (io_->error()) throw Error(20);
|
||||
uint16_t size = getUShort(buf.pData_, bigEndian);
|
||||
|
||||
if (marker == app0_) {
|
||||
if (size < 2) return 2;
|
||||
if (size < 2) throw Error(22);
|
||||
insertPos = count + 1;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) return 2;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
|
||||
}
|
||||
else if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) {
|
||||
if (size < 8) return 2;
|
||||
if (size < 8) throw Error(22);
|
||||
skipApp1Exif = count;
|
||||
++search;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) return 2;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
|
||||
}
|
||||
else if (marker == app13_ && memcmp(buf.pData_ + 2, ps3Id_, 14) == 0) {
|
||||
if (size < 16) return 2;
|
||||
if (size < 16) throw Error(22);
|
||||
skipApp13Ps3 = count;
|
||||
++search;
|
||||
// needed if bufMinSize!=16: io_->seek(16-bufRead, BasicIo::cur);
|
||||
psData.alloc(size - 16);
|
||||
// Load PS data now to allow reinsertion at any point
|
||||
io_->read(psData.pData_, psData.size_);
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
if (io_->error() || io_->eof()) throw Error(20);
|
||||
}
|
||||
else if (marker == com_ && skipCom == -1) {
|
||||
if (size < 2) return 2;
|
||||
if (size < 2) throw Error(22);
|
||||
// Jpegs can have multiple comments, but for now only handle
|
||||
// the first one (most jpegs only have one anyway).
|
||||
skipCom = count;
|
||||
++search;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) return 2;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
|
||||
}
|
||||
else {
|
||||
if (size < 2) return 2;
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) return 2;
|
||||
if (size < 2) throw Error(22);
|
||||
if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22);
|
||||
}
|
||||
marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(22);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -394,7 +392,7 @@ namespace Exiv2 {
|
||||
io_->seek(seek, BasicIo::beg);
|
||||
count = 0;
|
||||
marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(22);
|
||||
|
||||
// To simplify this a bit, new segments are inserts at either the start
|
||||
// or right after app0. This is standard in most jpegs, but has the
|
||||
@@ -403,7 +401,7 @@ namespace Exiv2 {
|
||||
while (marker != sos_ && search > 0) {
|
||||
// Read size and signature (ok if this hits EOF)
|
||||
bufRead = io_->read(buf.pData_, bufMinSize);
|
||||
if (io_->error()) return 1;
|
||||
if (io_->error()) throw Error(20);
|
||||
// Careful, this can be a meaningless number for empty
|
||||
// images with only an eoi_ marker
|
||||
uint16_t size = getUShort(buf.pData_, bigEndian);
|
||||
@@ -416,11 +414,11 @@ namespace Exiv2 {
|
||||
tmpBuf[1] = com_;
|
||||
us2Data(tmpBuf + 2,
|
||||
static_cast<uint16_t>(comment_.length()+3), bigEndian);
|
||||
if (outIo.write(tmpBuf, 4) != 4) return 4;
|
||||
if (outIo.write(tmpBuf, 4) != 4) throw Error(21);
|
||||
if (outIo.write((byte*)comment_.data(), (long)comment_.length())
|
||||
!= (long)comment_.length()) return 4;
|
||||
if (outIo.putb(0)==EOF) return 4;
|
||||
if (outIo.error()) return 4;
|
||||
!= (long)comment_.length()) throw Error(21);
|
||||
if (outIo.putb(0)==EOF) throw Error(21);
|
||||
if (outIo.error()) throw Error(21);
|
||||
--search;
|
||||
}
|
||||
if (exifData_.count() > 0) {
|
||||
@@ -432,10 +430,10 @@ namespace Exiv2 {
|
||||
static_cast<uint16_t>(rawExif.size_+8),
|
||||
bigEndian);
|
||||
memcpy(tmpBuf + 4, exifId_, 6);
|
||||
if (outIo.write(tmpBuf, 10) != 10) return 4;
|
||||
if (outIo.write(tmpBuf, 10) != 10) throw Error(21);
|
||||
if (outIo.write(rawExif.pData_, rawExif.size_)
|
||||
!= rawExif.size_) return 4;
|
||||
if (outIo.error()) return 4;
|
||||
!= rawExif.size_) throw Error(21);
|
||||
if (outIo.error()) throw Error(21);
|
||||
--search;
|
||||
}
|
||||
|
||||
@@ -459,13 +457,13 @@ namespace Exiv2 {
|
||||
static_cast<uint16_t>(psData.size_-sizeOldData+sizeNewData+16),
|
||||
bigEndian);
|
||||
memcpy(tmpBuf + 4, ps3Id_, 14);
|
||||
if (outIo.write(tmpBuf, 18) != 18) return 4;
|
||||
if (outIo.error()) return 4;
|
||||
if (outIo.write(tmpBuf, 18) != 18) throw Error(21);
|
||||
if (outIo.error()) throw Error(21);
|
||||
|
||||
const long sizeFront = (long)(record - psData.pData_);
|
||||
const long sizeEnd = psData.size_ - sizeFront - sizeOldData;
|
||||
// write data before old record.
|
||||
if (outIo.write(psData.pData_, sizeFront) != sizeFront) return 4;
|
||||
if (outIo.write(psData.pData_, sizeFront) != sizeFront) throw Error(21);
|
||||
|
||||
// write new iptc record if we have it
|
||||
if (iptcData_.count() > 0) {
|
||||
@@ -474,21 +472,21 @@ namespace Exiv2 {
|
||||
tmpBuf[6] = 0;
|
||||
tmpBuf[7] = 0;
|
||||
ul2Data(tmpBuf + 8, rawIptc.size_, bigEndian);
|
||||
if (outIo.write(tmpBuf, 12) != 12) return 4;
|
||||
if (outIo.write(tmpBuf, 12) != 12) throw Error(21);
|
||||
if (outIo.write(rawIptc.pData_, rawIptc.size_)
|
||||
!= rawIptc.size_) return 4;
|
||||
!= rawIptc.size_) throw Error(21);
|
||||
// data is padded to be even (but not included in size)
|
||||
if (rawIptc.size_ & 1) {
|
||||
if (outIo.putb(0)==EOF) return 4;
|
||||
if (outIo.putb(0)==EOF) throw Error(21);
|
||||
}
|
||||
if (outIo.error()) return 4;
|
||||
if (outIo.error()) throw Error(21);
|
||||
--search;
|
||||
}
|
||||
|
||||
// write existing stuff after record
|
||||
if (outIo.write(record+sizeOldData, sizeEnd)
|
||||
!= sizeEnd) return 4;
|
||||
if (outIo.error()) return 4;
|
||||
!= sizeEnd) throw Error(21);
|
||||
if (outIo.error()) throw Error(21);
|
||||
}
|
||||
}
|
||||
if (marker == eoi_) {
|
||||
@@ -499,18 +497,18 @@ namespace Exiv2 {
|
||||
io_->seek(size-bufRead, BasicIo::cur);
|
||||
}
|
||||
else {
|
||||
if (size < 2) return 2;
|
||||
if (size < 2) throw Error(22);
|
||||
buf.alloc(size+2);
|
||||
io_->seek(-bufRead-2, BasicIo::cur);
|
||||
io_->read(buf.pData_, size+2);
|
||||
if (io_->error() || io_->eof()) return 1;
|
||||
if (outIo.write(buf.pData_, size+2) != size+2) return 4;
|
||||
if (outIo.error()) return 4;
|
||||
if (io_->error() || io_->eof()) throw Error(20);
|
||||
if (outIo.write(buf.pData_, size+2) != size+2) throw Error(21);
|
||||
if (outIo.error()) throw Error(21);
|
||||
}
|
||||
|
||||
// Next marker
|
||||
marker = advanceToMarker();
|
||||
if (marker < 0) return 2;
|
||||
if (marker < 0) throw Error(22);
|
||||
++count;
|
||||
}
|
||||
|
||||
@@ -519,12 +517,11 @@ namespace Exiv2 {
|
||||
buf.alloc(4096);
|
||||
long readSize = 0;
|
||||
while ((readSize=io_->read(buf.pData_, buf.size_))) {
|
||||
if (outIo.write(buf.pData_, readSize) != readSize) return 4;
|
||||
if (outIo.write(buf.pData_, readSize) != readSize) throw Error(21);
|
||||
}
|
||||
if (outIo.error()) return 4;
|
||||
|
||||
return 0;
|
||||
}// JpegBase::doWriteMetadata
|
||||
if (outIo.error()) throw Error(21);
|
||||
|
||||
} // JpegBase::doWriteMetadata
|
||||
|
||||
|
||||
const byte JpegImage::soi_ = 0xd8;
|
||||
|
||||
+13
-24
@@ -67,15 +67,13 @@ namespace Exiv2 {
|
||||
is called, the various metadata types (Iptc, Exif) will be empty.
|
||||
|
||||
This method returns success even when no metadata is found in
|
||||
the image. Callers must therefore check the size of indivdual
|
||||
the image. Callers must therefore check the size of individual
|
||||
metadata types before accessing the data.
|
||||
|
||||
@return 0 if successful;<BR>
|
||||
1 if reading from the file failed
|
||||
(could be caused by invalid image);<BR>
|
||||
2 if the file does not contain a valid image;<BR>
|
||||
@throw Error if opening or reading of the file fails or the image
|
||||
data is not valid (does not look like JPEG data).
|
||||
*/
|
||||
int readMetadata();
|
||||
void readMetadata();
|
||||
/*!
|
||||
@brief Write metadata back to the image.
|
||||
|
||||
@@ -86,22 +84,13 @@ namespace Exiv2 {
|
||||
any exists section for that metadata type will be removed from the
|
||||
image.
|
||||
|
||||
@return 0 if successful;<br>
|
||||
1 if reading from the file failed;<BR>
|
||||
2 if the file does not contain a valid image;<BR>
|
||||
4 if the temporary output file can not be written to;<BR>
|
||||
-1 if the newly created file could not be reopened;<BR>
|
||||
-3 if the temporary output file can not be opened;<BR>
|
||||
-4 if renaming the temporary file fails;<br>
|
||||
@throw Error if the operation fails
|
||||
*/
|
||||
int writeMetadata();
|
||||
void writeMetadata();
|
||||
/*!
|
||||
@brief Assign new exif data. The new exif data is not written
|
||||
to the image until the writeMetadata() method is called.
|
||||
@param exifData An ExifData instance holding exif data to be copied
|
||||
|
||||
@throw Error ("Exif data too large") if the exif data is larger than
|
||||
65535 bytes (the maximum size of JPEG APP segments)
|
||||
*/
|
||||
void setExifData(const ExifData& exifData);
|
||||
void clearExifData();
|
||||
@@ -226,7 +215,7 @@ namespace Exiv2 {
|
||||
(may not be null).
|
||||
@return 0 if successful;<BR>
|
||||
3 if no Iptc data was found in pPsData;<BR>
|
||||
-2 if the pPsData buffer does not contain valid data;<BR>
|
||||
-2 if the pPsData buffer does not contain valid data.
|
||||
*/
|
||||
int locateIptcData(const byte *pPsData,
|
||||
long sizePsData,
|
||||
@@ -238,19 +227,19 @@ namespace Exiv2 {
|
||||
@param initData Data to be written to the associated BasicIo
|
||||
@param dataSize Size in bytes of data to be written
|
||||
@return 0 if successful;<BR>
|
||||
4 if the output file can not be written to;<BR>
|
||||
4 if the image can not be written to.
|
||||
*/
|
||||
int initImage(const byte initData[], long dataSize);
|
||||
/*!
|
||||
@brief Provides the main implementation of writeMetadata() by
|
||||
writing all buffered metadata to the provided BasicIo.
|
||||
@param oIo BasicIo instance to write to (a temporary location).
|
||||
@return 0 if successful;<br>
|
||||
1 if reading from input file failed;<BR>
|
||||
2 if the input file does not contain a valid image;<BR>
|
||||
4 if the output file can not be written to;<BR>
|
||||
|
||||
@throw Error if reading from input file failed, the output file
|
||||
can not be written to, or the input file does not contain
|
||||
a valid image.
|
||||
*/
|
||||
int doWriteMetadata(BasicIo& oIo);
|
||||
void doWriteMetadata(BasicIo& oIo);
|
||||
|
||||
// NOT Implemented
|
||||
//! Default constructor.
|
||||
|
||||
+13
-35
@@ -35,6 +35,7 @@
|
||||
#include "metacopy.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cassert>
|
||||
|
||||
// *****************************************************************************
|
||||
// Main
|
||||
@@ -55,41 +56,15 @@ try {
|
||||
// Use MemIo to increase test coverage.
|
||||
Exiv2::BasicIo::AutoPtr fileIo(new Exiv2::FileIo(params.read_));
|
||||
Exiv2::BasicIo::AutoPtr memIo(new Exiv2::MemIo);
|
||||
|
||||
if (memIo->transfer(*fileIo) != 0) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not read file (" << params.read_ << ")\n";
|
||||
return 4;
|
||||
}
|
||||
memIo->transfer(*fileIo);
|
||||
|
||||
Exiv2::Image::AutoPtr readImg
|
||||
= Exiv2::ImageFactory::open(memIo);
|
||||
if (readImg.get() == 0) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not read file (" << params.read_ << ")\n";
|
||||
return 4;
|
||||
}
|
||||
if (readImg->readMetadata()) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not read metadata from (" << params.read_ << ")\n";
|
||||
return 5;
|
||||
}
|
||||
Exiv2::Image::AutoPtr readImg = Exiv2::ImageFactory::open(memIo);
|
||||
assert(readImg.get() != 0);
|
||||
readImg->readMetadata();
|
||||
|
||||
Exiv2::Image::AutoPtr writeImg
|
||||
= Exiv2::ImageFactory::open(params.write_);
|
||||
if (writeImg.get() == 0) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not read file (" << params.write_ << ")\n";
|
||||
return 6;
|
||||
}
|
||||
|
||||
if (params.preserve_) {
|
||||
if (writeImg->readMetadata()) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not read metadata from (" << params.write_ << ")\n";
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
Exiv2::Image::AutoPtr writeImg = Exiv2::ImageFactory::open(params.write_);
|
||||
assert(writeImg.get() != 0);
|
||||
if (params.preserve_) writeImg->readMetadata();
|
||||
if (params.iptc_) {
|
||||
writeImg->setIptcData(readImg->iptcData());
|
||||
}
|
||||
@@ -100,7 +75,10 @@ try {
|
||||
writeImg->setComment(readImg->comment());
|
||||
}
|
||||
|
||||
if (writeImg->writeMetadata()) {
|
||||
try {
|
||||
writeImg->writeMetadata();
|
||||
}
|
||||
catch (const Exiv2::AnyError&) {
|
||||
std::cerr << params.progname() <<
|
||||
": Could not write metadata to (" << params.write_ << ")\n";
|
||||
return 8;
|
||||
@@ -108,7 +86,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return 10;
|
||||
}
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ namespace Exiv2 {
|
||||
@endcode
|
||||
|
||||
@return A constant reference to the value.
|
||||
@throw Error ("Value not set") if the value is not set.
|
||||
@throw Error if the value is not set.
|
||||
*/
|
||||
virtual const Value& value() const =0;
|
||||
//@}
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ try {
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
catch (Error& e) {
|
||||
std::cout << "Caught Exif exception '" << e << "'\n";
|
||||
catch (AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
+10
-12
@@ -301,7 +301,7 @@ namespace Exiv2 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_MAKER_TAG_INFOS) throw Error("MakerTagInfo registry full");
|
||||
if (i == MAX_MAKER_TAG_INFOS) throw Error(16);
|
||||
} // ExifTags::registerMakerTagInfo
|
||||
|
||||
int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
|
||||
@@ -429,9 +429,7 @@ namespace Exiv2 {
|
||||
if (tagInfo != 0) tag = tagInfo->tag_;
|
||||
}
|
||||
if (tag == 0xffff) {
|
||||
if (!isHex(tagName, 4, "0x")) {
|
||||
throw Error("Invalid tag name " + tagName + ", " + toString(ifdId));
|
||||
}
|
||||
if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId);
|
||||
std::istringstream is(tagName);
|
||||
is >> std::hex >> tag;
|
||||
}
|
||||
@@ -548,7 +546,7 @@ namespace Exiv2 {
|
||||
if (ExifTags::isMakerIfd(ifdId)) {
|
||||
MakerNote::AutoPtr makerNote
|
||||
= MakerNoteFactory::instance().create(ifdId);
|
||||
if (makerNote.get() == 0) throw Error("Invalid key");
|
||||
if (makerNote.get() == 0) throw Error(23, ifdId);
|
||||
}
|
||||
tag_ = tag;
|
||||
ifdId_ = ifdId;
|
||||
@@ -610,26 +608,26 @@ namespace Exiv2 {
|
||||
{
|
||||
// Get the family name, IFD name and tag name parts of the key
|
||||
std::string::size_type pos1 = key_.find('.');
|
||||
if (pos1 == std::string::npos) throw Error("Invalid key");
|
||||
if (pos1 == std::string::npos) throw Error(6, key_);
|
||||
std::string familyName = key_.substr(0, pos1);
|
||||
if (familyName != std::string(familyName_)) {
|
||||
throw Error("Invalid key");
|
||||
throw Error(6, key_);
|
||||
}
|
||||
std::string::size_type pos0 = pos1 + 1;
|
||||
pos1 = key_.find('.', pos0);
|
||||
if (pos1 == std::string::npos) throw Error("Invalid key");
|
||||
if (pos1 == std::string::npos) throw Error(6, key_);
|
||||
std::string ifdItem = key_.substr(pos0, pos1 - pos0);
|
||||
if (ifdItem == "") throw Error("Invalid key");
|
||||
if (ifdItem == "") throw Error(6, key_);
|
||||
std::string tagName = key_.substr(pos1 + 1);
|
||||
if (tagName == "") throw Error("Invalid key");
|
||||
if (tagName == "") throw Error(6, key_);
|
||||
|
||||
// Find IfdId
|
||||
IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem);
|
||||
if (ifdId == ifdIdNotSet) throw Error("Invalid key");
|
||||
if (ifdId == ifdIdNotSet) throw Error(6, key_);
|
||||
if (ExifTags::isMakerIfd(ifdId)) {
|
||||
MakerNote::AutoPtr makerNote
|
||||
= MakerNoteFactory::instance().create(ifdId);
|
||||
if (makerNote.get() == 0) throw Error("Invalid key");
|
||||
if (makerNote.get() == 0) throw Error(6, key_);
|
||||
}
|
||||
// Convert tag
|
||||
uint16_t tag = ExifTags::tag(tagName, ifdId);
|
||||
|
||||
+14
-13
@@ -137,14 +137,14 @@ namespace Exiv2 {
|
||||
@param ifdId IFD id
|
||||
@return The description of the tag or a string indicating that
|
||||
the tag is unknown.
|
||||
@throw Error ("No taginfo for IFD") if there is no tag info
|
||||
data for the given IFD id in the lookup tables.
|
||||
*/
|
||||
static const char* tagDesc(uint16_t tag, IfdId ifdId);
|
||||
/*!
|
||||
@brief Return the tag for one combination of IFD id and tagName.
|
||||
If the tagName is not known, it expects tag names in the
|
||||
form "0x01ff" and converts them to unsigned integer.
|
||||
|
||||
@throw Error if the tagname or ifdId is invalid
|
||||
*/
|
||||
static uint16_t tag(const std::string& tagName, IfdId ifdId);
|
||||
//! Return the IFD id for an IFD item
|
||||
@@ -162,8 +162,6 @@ namespace Exiv2 {
|
||||
@param ifdId IFD id
|
||||
@return The name of the section or a string indicating that the
|
||||
section or the tag is unknown.
|
||||
@throw Error ("No taginfo for IFD") if there is no tag info
|
||||
data for the given IFD id in the lookup tables.
|
||||
*/
|
||||
static const char* sectionName(uint16_t tag, IfdId ifdId);
|
||||
/*!
|
||||
@@ -173,8 +171,6 @@ namespace Exiv2 {
|
||||
@param ifdId IFD id
|
||||
@return The description of the section or a string indicating that
|
||||
the section or the tag is unknown.
|
||||
@throw Error ("No taginfo for IFD") if there is no tag info
|
||||
data for the given IFD id in the lookup tables.
|
||||
*/
|
||||
static const char* sectionDesc(uint16_t tag, IfdId ifdId);
|
||||
//! Return the section id for a section name
|
||||
@@ -192,7 +188,11 @@ namespace Exiv2 {
|
||||
static void makerTaglist(std::ostream& os, IfdId ifdId);
|
||||
//! Register an %IfdId with the base IFD %TagInfo list for a makernote
|
||||
static void registerBaseTagInfo(IfdId ifdId);
|
||||
//! Register an %IfdId and %TagInfo list for a makernote
|
||||
/*!
|
||||
@brief Register an %IfdId and %TagInfo list for a makernote
|
||||
|
||||
@throw Error if the MakerTagInfo registry is full
|
||||
*/
|
||||
static void registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo);
|
||||
/*!
|
||||
@brief Return true if \em ifdId is an %Ifd Id which is registered
|
||||
@@ -232,8 +232,9 @@ namespace Exiv2 {
|
||||
@brief Constructor to create an Exif key from a key string.
|
||||
|
||||
@param key The key string.
|
||||
@throw Error ("Invalid key") if the key cannot be parsed into three
|
||||
parts or the first part of the key is not '<b>Exif</b>'.
|
||||
@throw Error if the first part of the key is not '<b>Exif</b>' or
|
||||
the remainin parts of the key cannot be parsed and
|
||||
converted to an ifd-item and tag name.
|
||||
*/
|
||||
explicit ExifKey(const std::string& key);
|
||||
/*!
|
||||
@@ -242,8 +243,8 @@ namespace Exiv2 {
|
||||
@param tag The tag value
|
||||
@param ifdItem The IFD string. For MakerNote tags, this must be the
|
||||
IFD item of the specific MakerNote. "MakerNote" is not allowed.
|
||||
@throw Error ("Invalid key") if the key cannot be constructed from
|
||||
the tag and IFD item parameters.
|
||||
@throw Error if the key cannot be constructed from the tag and IFD
|
||||
item parameters.
|
||||
*/
|
||||
ExifKey(uint16_t tag, const std::string& ifdItem);
|
||||
//! Constructor to build an ExifKey from an IFD entry.
|
||||
@@ -297,9 +298,9 @@ namespace Exiv2 {
|
||||
/*!
|
||||
@brief Parse and convert the key string into tag and IFD Id.
|
||||
Updates data members if the string can be decomposed,
|
||||
or throws Error ("Invalid key").
|
||||
or throws \em Error .
|
||||
|
||||
@throw Error ("Invalid key") if the key cannot be decomposed.
|
||||
@throw Error if the key cannot be decomposed.
|
||||
*/
|
||||
void decomposeKey();
|
||||
//@}
|
||||
|
||||
+1
-18
@@ -48,8 +48,8 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#ifdef EXV_HAVE_UNISTD_H
|
||||
# include <unistd.h> // for getopt(), stat()
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -78,23 +78,6 @@ int Getopt::getopt(int argc, char* const argv[], const std::string& optstring)
|
||||
// *****************************************************************************
|
||||
// free functions
|
||||
|
||||
bool fileExists(const std::string& path, bool ct)
|
||||
{
|
||||
struct stat buf;
|
||||
int ret = ::stat(path.c_str(), &buf);
|
||||
if (0 != ret) return false;
|
||||
if (ct && !S_ISREG(buf.st_mode)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string strError()
|
||||
{
|
||||
int error = errno;
|
||||
std::ostringstream os;
|
||||
os << ::strerror(error) << " (errno = " << error << ")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string dirname(const std::string& path)
|
||||
{
|
||||
if (path == "") return ".";
|
||||
|
||||
@@ -127,23 +127,6 @@ private:
|
||||
// *********************************************************************
|
||||
// free functions
|
||||
|
||||
/*!
|
||||
@brief Test if a file exists.
|
||||
|
||||
@param path Name of file to verify.
|
||||
@param ct Flag to check if <i>path</i> is a regular file.
|
||||
@return true if <i>path</i> exists and, if <i>ct</i> is set,
|
||||
is a regular file, else false.
|
||||
|
||||
@note The function calls <b>stat()</b> test for <i>path</i>
|
||||
and its type, see stat(2). <b>errno</b>
|
||||
is left unchanged in case of an error.
|
||||
*/
|
||||
bool fileExists(const std::string& path, bool ct =false);
|
||||
|
||||
//! Get a system error message and the error code. See %strerror(2).
|
||||
std::string strError();
|
||||
|
||||
/*!
|
||||
@brief Get the directory component from the \em path string.
|
||||
See %dirname(3).
|
||||
|
||||
@@ -57,18 +57,6 @@ void testStrtol()
|
||||
std::cout << "s = `" << s << "' rc = " << rc << " n = " << n << "\n";
|
||||
}
|
||||
|
||||
void testStrError()
|
||||
{
|
||||
std::string oldname = "/tmp/foo";
|
||||
std::string newname = "/tmp/bar";
|
||||
|
||||
if (::rename(oldname.c_str(), newname.c_str()) == -1) {
|
||||
std::cerr << "failed to rename "
|
||||
<< oldname << " to " << newname << ": ";
|
||||
std::cerr << Util::strError() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void testPaths()
|
||||
{
|
||||
std::string path;
|
||||
|
||||
+9
-9
@@ -313,7 +313,7 @@ namespace Exiv2 {
|
||||
if (name[0] == '"') name = name.substr(1);
|
||||
if (name[name.length()-1] == '"') name = name.substr(0, name.length()-1);
|
||||
charsetId = CharsetInfo::charsetIdByName(name);
|
||||
if (charsetId == invalidCharsetId) throw Error("Invalid charset");
|
||||
if (charsetId == invalidCharsetId) throw Error(28, name);
|
||||
c.clear();
|
||||
if (pos != std::string::npos) c = comment.substr(pos+1);
|
||||
}
|
||||
@@ -373,22 +373,22 @@ namespace Exiv2 {
|
||||
{
|
||||
// byteOrder not needed
|
||||
// Hard coded to read Iptc style dates
|
||||
if (len != 8) throw Error("Unsupported date format");
|
||||
if (len != 8) throw Error(29);
|
||||
int scanned = sscanf(reinterpret_cast<const char*>(buf),
|
||||
"%4d%2d%2d",
|
||||
&date_.year, &date_.month, &date_.day);
|
||||
if (scanned != 3) throw Error("Unsupported date format");
|
||||
if (scanned != 3) throw Error(29);
|
||||
}
|
||||
|
||||
void DateValue::read(const std::string& buf)
|
||||
{
|
||||
// byteOrder not needed
|
||||
// Hard coded to read Iptc style dates
|
||||
if (buf.length() < 8) throw Error("Unsupported date format");
|
||||
if (buf.length() < 8) throw Error(29);
|
||||
int scanned = sscanf(buf.data(),
|
||||
"%4d-%d-%d",
|
||||
&date_.year, &date_.month, &date_.day);
|
||||
if (scanned != 3) throw Error("Unsupported date format");
|
||||
if (scanned != 3) throw Error(29);
|
||||
}
|
||||
|
||||
void DateValue::setDate( const Date& src )
|
||||
@@ -464,14 +464,14 @@ namespace Exiv2 {
|
||||
{
|
||||
// byteOrder not needed
|
||||
// Hard coded to read Iptc style times
|
||||
if (len != 11) throw Error("Unsupported time format");
|
||||
if (len != 11) throw Error(30);
|
||||
char plusMinus;
|
||||
int scanned = sscanf(reinterpret_cast<const char*>(buf),
|
||||
"%2d%2d%2d%1c%2d%2d",
|
||||
&time_.hour, &time_.minute, &time_.second,
|
||||
&plusMinus, &time_.tzHour, &time_.tzMinute );
|
||||
|
||||
if (scanned != 6) throw Error("Unsupported time format");
|
||||
if (scanned != 6) throw Error(30);
|
||||
if (plusMinus == '-') {
|
||||
time_.tzHour *= -1;
|
||||
time_.tzMinute *= -1;
|
||||
@@ -482,14 +482,14 @@ namespace Exiv2 {
|
||||
{
|
||||
// byteOrder not needed
|
||||
// Hard coded to read Iptc style times
|
||||
if (buf.length() < 9) throw Error("Unsupported time format");
|
||||
if (buf.length() < 9) throw Error(30);
|
||||
char plusMinus;
|
||||
int scanned = sscanf(buf.data(),
|
||||
"%d:%d:%d%1c%d:%d",
|
||||
&time_.hour, &time_.minute, &time_.second,
|
||||
&plusMinus, &time_.tzHour, &time_.tzMinute );
|
||||
|
||||
if (scanned != 6) throw Error("Unsupported time format");
|
||||
if (scanned != 6) throw Error(30);
|
||||
if (plusMinus == '-') {
|
||||
time_.tzHour *= -1;
|
||||
time_.tzMinute *= -1;
|
||||
|
||||
+13
-2
@@ -568,8 +568,7 @@ namespace Exiv2 {
|
||||
<BR>
|
||||
The default charset is Undefined.
|
||||
|
||||
@throw Error ("Invalid charset") if an invalid character set is
|
||||
encountered
|
||||
@throw Error if an invalid character set is encountered
|
||||
*/
|
||||
void read(const std::string& comment);
|
||||
//@}
|
||||
@@ -636,12 +635,18 @@ namespace Exiv2 {
|
||||
@param buf Pointer to the data buffer to read from
|
||||
@param len Number of bytes in the data buffer
|
||||
@param byteOrder Byte order. Not needed.
|
||||
|
||||
@throw Error in case of an unsupported date format
|
||||
*/
|
||||
virtual void read(const byte* buf,
|
||||
long len,
|
||||
ByteOrder byteOrder =invalidByteOrder);
|
||||
/*!
|
||||
@brief Set the value to that of the string buf.
|
||||
|
||||
@param buf String containing the date
|
||||
|
||||
@throw Error in case of an unsupported date format
|
||||
*/
|
||||
virtual void read(const std::string& buf);
|
||||
//! Set the date
|
||||
@@ -736,12 +741,18 @@ namespace Exiv2 {
|
||||
@param buf Pointer to the data buffer to read from
|
||||
@param len Number of bytes in the data buffer
|
||||
@param byteOrder Byte order. Not needed.
|
||||
|
||||
@throw Error in case of an unsupported time format
|
||||
*/
|
||||
virtual void read(const byte* buf,
|
||||
long len,
|
||||
ByteOrder byteOrder =invalidByteOrder);
|
||||
/*!
|
||||
@brief Set the value to that of the string buf.
|
||||
|
||||
@param buf String containing the time.
|
||||
|
||||
@throw Error in case of an unsupported time format
|
||||
*/
|
||||
virtual void read(const std::string& buf);
|
||||
//! Set the time
|
||||
|
||||
+9
-28
@@ -24,6 +24,7 @@
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
// *****************************************************************************
|
||||
// local declarations
|
||||
@@ -147,8 +148,8 @@ try {
|
||||
|
||||
return rc;
|
||||
}
|
||||
catch (Error& e) {
|
||||
std::cerr << "Caught Exif exception '" << e << "'\n";
|
||||
catch (AnyError& e) {
|
||||
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -164,51 +165,31 @@ void testCase(const std::string& file1,
|
||||
|
||||
//Open first image
|
||||
Image::AutoPtr image1 = ImageFactory::open(file1);
|
||||
if (image1.get() == 0) {
|
||||
std::string error(file1);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image1.get() != 0);
|
||||
|
||||
// Load existing metadata
|
||||
std::cerr << "---> Reading file " << file1 << "\n";
|
||||
int rc = image1->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file1);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image1->readMetadata();
|
||||
|
||||
Exiv2::ExifData &ed1 = image1->exifData();
|
||||
std::cerr << "---> Modifying Exif data\n";
|
||||
Exiv2::ExifData::iterator pos = ed1.findKey(ek);
|
||||
if (pos == ed1.end()) {
|
||||
throw Error("Metadatum with key = " + ek.key() + " not found");
|
||||
throw Error(1, "Metadatum with key = " + ek.key() + " not found");
|
||||
}
|
||||
pos->setValue(value);
|
||||
|
||||
// Open second image
|
||||
Image::AutoPtr image2 = ImageFactory::open(file2);
|
||||
if (image2.get() == 0) {
|
||||
std::string error(file2);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image2.get() != 0);
|
||||
|
||||
image2->setExifData(image1->exifData());
|
||||
|
||||
std::cerr << "---> Writing Exif data to file " << file2 << "\n";
|
||||
rc = image2->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Image::strError(rc, file2.c_str());
|
||||
throw Error(error);
|
||||
}
|
||||
image2->writeMetadata();
|
||||
|
||||
std::cerr << "---> Reading file " << file2 << "\n";
|
||||
rc = image2->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file2);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image2->readMetadata();
|
||||
|
||||
Exiv2::ExifData &ed2 = image2->exifData();
|
||||
exifPrint(ed2);
|
||||
|
||||
+9
-37
@@ -15,6 +15,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
void write(const std::string& file, Exiv2::ExifData& ed);
|
||||
void print(const std::string& file);
|
||||
@@ -72,25 +73,13 @@ try {
|
||||
|
||||
std::cout <<"\n----- Non-intrusive writing of special Canon MakerNote tags\n";
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
Exiv2::ExifData& rEd = image->exifData();
|
||||
rEd["Exif.CanonCs1.0x0001"] = uint16_t(88);
|
||||
rEd["Exif.CanonCs2.0x0004"] = uint16_t(99);
|
||||
rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
print(file);
|
||||
|
||||
std::cout <<"\n----- One Fujifilm MakerNote tag\n";
|
||||
@@ -169,7 +158,7 @@ try {
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (Exiv2::Error& e) {
|
||||
catch (Exiv2::AnyError& e) {
|
||||
std::cout << "Caught Exiv2 exception '" << e << "'\n";
|
||||
return -1;
|
||||
}
|
||||
@@ -178,34 +167,17 @@ catch (Exiv2::Error& e) {
|
||||
void write(const std::string& file, Exiv2::ExifData& ed)
|
||||
{
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
|
||||
image->setExifData(ed);
|
||||
int rc = image->writeMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
image->writeMetadata();
|
||||
}
|
||||
|
||||
void print(const std::string& file)
|
||||
{
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
|
||||
if (image.get() == 0) {
|
||||
std::string error(file);
|
||||
error += " : Could not read file or unknown image type";
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
|
||||
int rc = image->readMetadata();
|
||||
if (rc) {
|
||||
std::string error = Exiv2::Image::strError(rc, file);
|
||||
throw Exiv2::Error(error);
|
||||
}
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
|
||||
Exiv2::ExifData &ed = image->exifData();
|
||||
Exiv2::ExifData::const_iterator end = ed.end();
|
||||
|
||||
Reference in New Issue
Block a user