Changed option -eX to write XMP sidecar file (corresponding insert not done yet).
This commit is contained in:
+29
-21
@@ -44,6 +44,7 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
#include "exiv2.hpp"
|
||||
#include "image.hpp"
|
||||
#include "jpgimage.hpp"
|
||||
#include "xmpsidecar.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "types.hpp"
|
||||
#include "exif.hpp"
|
||||
@@ -1020,10 +1021,11 @@ namespace Action {
|
||||
if (Params::instance().target_ & Params::ctThumb) {
|
||||
rc = writeThumbnail();
|
||||
}
|
||||
if (Params::instance().target_ & Params::ctXmpPacket) {
|
||||
rc = writeXmp();
|
||||
if (Params::instance().target_ & Params::ctXmpSidecar) {
|
||||
rc = writeXmpSidecar();
|
||||
}
|
||||
if (Params::instance().target_ & ~Params::ctThumb & ~Params::ctXmpPacket) {
|
||||
if ( !(Params::instance().target_ & Params::ctXmpSidecar)
|
||||
&& !(Params::instance().target_ & Params::ctThumb)) {
|
||||
std::string exvPath = newFilePath(path_, ".exv");
|
||||
if (dontOverwrite(exvPath)) return 0;
|
||||
rc = metacopy(path_, exvPath, false);
|
||||
@@ -1037,7 +1039,7 @@ namespace Action {
|
||||
return 1;
|
||||
} // Extract::run
|
||||
|
||||
int Extract::writeXmp() const
|
||||
int Extract::writeXmpSidecar() const
|
||||
{
|
||||
if (!Exiv2::fileExists(path_, true)) {
|
||||
std::cerr << path_
|
||||
@@ -1047,26 +1049,32 @@ namespace Action {
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
|
||||
assert(image.get() != 0);
|
||||
image->readMetadata();
|
||||
const std::string& xmpPacket = image->xmpPacket();
|
||||
if (xmpPacket.empty()) {
|
||||
return -3;
|
||||
}
|
||||
std::string xmpPath = newFilePath(path_, ".xmp");
|
||||
if (dontOverwrite(xmpPath)) return 0;
|
||||
|
||||
std::string sidecarPath = newFilePath(path_, ".xmp");
|
||||
if (dontOverwrite(sidecarPath)) return 0;
|
||||
|
||||
// Apply any modification commands to the source image on-the-fly
|
||||
Action::Modify::applyCommands(image.get());
|
||||
|
||||
Exiv2::Image::AutoPtr xmpSidecar =
|
||||
Exiv2::ImageFactory::create(Exiv2::ImageType::xmp, sidecarPath);
|
||||
assert(xmpSidecar.get() != 0);
|
||||
if (Params::instance().verbose_) {
|
||||
std::cout << _("Writing XMP packet from") << " " << path_
|
||||
<< " " << _("to") << " " << xmpPath << std::endl;
|
||||
std::cout << _("Writing XMP sidecar file ") << " "
|
||||
<< sidecarPath << std::endl;
|
||||
}
|
||||
std::ofstream file(xmpPath.c_str());
|
||||
if (!file) {
|
||||
std::cerr << Params::instance().progname() << ": "
|
||||
<< _("Failed to open file ") << " " << xmpPath << ": "
|
||||
<< Exiv2::strError() << "\n";
|
||||
return 1;
|
||||
if (Params::instance().target_ & Params::ctExif) {
|
||||
xmpSidecar->setExifData(image->exifData());
|
||||
}
|
||||
file << xmpPacket;
|
||||
if (Params::instance().target_ & Params::ctIptc) {
|
||||
xmpSidecar->setIptcData(image->iptcData());
|
||||
}
|
||||
if (Params::instance().target_ & Params::ctXmp) {
|
||||
xmpSidecar->setXmpData(image->xmpData());
|
||||
}
|
||||
xmpSidecar->writeMetadata();
|
||||
return 0;
|
||||
} // Extract::writeXmp
|
||||
} // Extract::writeXmpSidecar
|
||||
|
||||
int Extract::writeThumbnail() const
|
||||
{
|
||||
@@ -1143,7 +1151,7 @@ namespace Action {
|
||||
std::string exvPath = newFilePath(path, suffix);
|
||||
rc = metacopy(exvPath, path, true);
|
||||
}
|
||||
if (0 == rc && Params::instance().target_ & Params::ctXmpPacket) {
|
||||
if (0 == rc && Params::instance().target_ & Params::ctXmpSidecar) {
|
||||
rc = insertXmpPacket(path);
|
||||
}
|
||||
if (Params::instance().preserve_) {
|
||||
|
||||
+2
-2
@@ -278,8 +278,8 @@ namespace Action {
|
||||
on the format of the Exif thumbnail image.
|
||||
*/
|
||||
int writeThumbnail() const;
|
||||
//! Write the XMP packet to a file.
|
||||
int writeXmp() const;
|
||||
//! Write an XMP sidecar file.
|
||||
int writeXmpSidecar() const;
|
||||
|
||||
private:
|
||||
virtual Extract* clone_() const;
|
||||
|
||||
+1
-1
@@ -840,9 +840,9 @@ namespace {
|
||||
case 'e': target |= Params::ctExif; break;
|
||||
case 'i': target |= Params::ctIptc; break;
|
||||
case 'x': target |= Params::ctXmp; break;
|
||||
case 'X': target |= Params::ctXmpPacket; break;
|
||||
case 'c': target |= Params::ctComment; break;
|
||||
case 't': target |= Params::ctThumb; break;
|
||||
case 'X': target |= Params::ctXmpSidecar; // fall-through
|
||||
case 'a': target |= Params::ctExif
|
||||
| Params::ctIptc
|
||||
| Params::ctComment
|
||||
|
||||
+9
-1
@@ -141,7 +141,15 @@ public:
|
||||
};
|
||||
|
||||
//! Enumerates common targets, bitmap
|
||||
enum CommonTarget { ctExif = 1, ctIptc = 2, ctComment = 4, ctThumb = 8, ctXmp = 16, ctXmpPacket = 32 };
|
||||
enum CommonTarget {
|
||||
ctExif = 1,
|
||||
ctIptc = 2,
|
||||
ctComment = 4,
|
||||
ctThumb = 8,
|
||||
ctXmp = 16,
|
||||
ctXmpSidecar = 32
|
||||
};
|
||||
|
||||
//! Enumerates the policies to handle existing files in rename action
|
||||
enum FileExistsPolicy { overwritePolicy, renamePolicy, askPolicy };
|
||||
|
||||
|
||||
+20
-17
@@ -43,6 +43,7 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
#include "error.hpp"
|
||||
#include "xmp.hpp"
|
||||
#include "futils.hpp"
|
||||
#include "convert.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
@@ -53,23 +54,20 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
// class member definitions
|
||||
namespace Exiv2 {
|
||||
|
||||
XmpSidecar::XmpSidecar(BasicIo::AutoPtr io)
|
||||
const char* XmpSidecar::xmlHeader_ = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
const long XmpSidecar::xmlHdrCnt_ = 39;
|
||||
|
||||
XmpSidecar::XmpSidecar(BasicIo::AutoPtr io, bool create)
|
||||
: Image(ImageType::xmp, mdXmp, io)
|
||||
{
|
||||
if (create) {
|
||||
if (io_->open() == 0) {
|
||||
IoCloser closer(*io_);
|
||||
io_->write(reinterpret_cast<const byte*>(xmlHeader_), xmlHdrCnt_);
|
||||
}
|
||||
}
|
||||
} // XmpSidecar::XmpSidecar
|
||||
|
||||
void XmpSidecar::setExifData(const ExifData& /*exifData*/)
|
||||
{
|
||||
// Todo: implement me!
|
||||
throw(Error(32, "Exif metadata", "XMP"));
|
||||
}
|
||||
|
||||
void XmpSidecar::setIptcData(const IptcData& /*iptcData*/)
|
||||
{
|
||||
// Todo: implement me!
|
||||
throw(Error(32, "IPTC metadata", "XMP"));
|
||||
}
|
||||
|
||||
void XmpSidecar::setComment(const std::string& /*comment*/)
|
||||
{
|
||||
// not supported
|
||||
@@ -106,6 +104,8 @@ namespace Exiv2 {
|
||||
std::cerr << "Warning: Failed to decode XMP metadata.\n";
|
||||
#endif
|
||||
}
|
||||
copyXmpToIptc(xmpData_, iptcData_);
|
||||
copyXmpToExif(xmpData_, exifData_);
|
||||
} // XmpSidecar::readMetadata
|
||||
|
||||
void XmpSidecar::writeMetadata()
|
||||
@@ -116,7 +116,10 @@ namespace Exiv2 {
|
||||
IoCloser closer(*io_);
|
||||
|
||||
if (writeXmpFromPacket() == false) {
|
||||
if (XmpParser::encode(xmpPacket_, xmpData_, XmpParser::omitPacketWrapper|XmpParser::useCompactFormat)) {
|
||||
copyExifToXmp(exifData_, xmpData_);
|
||||
copyIptcToXmp(iptcData_, xmpData_);
|
||||
if (XmpParser::encode(xmpPacket_, xmpData_,
|
||||
XmpParser::omitPacketWrapper|XmpParser::useCompactFormat)) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: Failed to encode XMP metadata.\n";
|
||||
#endif
|
||||
@@ -124,7 +127,7 @@ namespace Exiv2 {
|
||||
}
|
||||
if (xmpPacket_.size() > 0) {
|
||||
if (xmpPacket_.substr(0, 5) != "<?xml") {
|
||||
xmpPacket_ = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xmpPacket_;
|
||||
xmpPacket_ = xmlHeader_ + xmpPacket_;
|
||||
}
|
||||
BasicIo::AutoPtr tempIo(io_->temporary()); // may throw
|
||||
assert(tempIo.get() != 0);
|
||||
@@ -140,9 +143,9 @@ namespace Exiv2 {
|
||||
|
||||
// *************************************************************************
|
||||
// free functions
|
||||
Image::AutoPtr newXmpInstance(BasicIo::AutoPtr io, bool /*create*/)
|
||||
Image::AutoPtr newXmpInstance(BasicIo::AutoPtr io, bool create)
|
||||
{
|
||||
Image::AutoPtr image(new XmpSidecar(io));
|
||||
Image::AutoPtr image(new XmpSidecar(io, create));
|
||||
if (!image->good()) {
|
||||
image.reset();
|
||||
}
|
||||
|
||||
+7
-11
@@ -66,24 +66,16 @@ namespace Exiv2 {
|
||||
auto-pointer. Callers should not continue to use the BasicIo
|
||||
instance after it is passed to this method. Use the Image::io()
|
||||
method to get a temporary reference.
|
||||
@param create Specifies if an existing image should be read (false)
|
||||
or if a new image should be created (true).
|
||||
*/
|
||||
XmpSidecar(BasicIo::AutoPtr io);
|
||||
XmpSidecar(BasicIo::AutoPtr io, bool create);
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
void readMetadata();
|
||||
void writeMetadata();
|
||||
/*!
|
||||
@brief Todo: Not supported yet, requires conversion from Exif to XMP.
|
||||
Calling this function will throw an instance of Error(32).
|
||||
*/
|
||||
void setExifData(const ExifData& exifData);
|
||||
/*!
|
||||
@brief Todo: Not supported yet, requires conversion from IPTC to XMP.
|
||||
Calling this function will throw an instance of Error(32).
|
||||
*/
|
||||
void setIptcData(const IptcData& iptcData);
|
||||
/*!
|
||||
@brief Not supported. XMP sidecar files do not contain a comment.
|
||||
Calling this function will throw an instance of Error(32).
|
||||
@@ -105,6 +97,10 @@ namespace Exiv2 {
|
||||
XmpSidecar& operator=(const XmpSidecar& rhs);
|
||||
//@}
|
||||
|
||||
// DATA
|
||||
static const char* xmlHeader_;
|
||||
static const long xmlHdrCnt_;
|
||||
|
||||
}; // class XmpSidecar
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user