diff --git a/src/xmp.cpp b/src/xmp.cpp index 941491e9..c03acd3e 100644 --- a/src/xmp.cpp +++ b/src/xmp.cpp @@ -74,7 +74,7 @@ namespace { Exiv2::XmpValue::XmpStruct xmpStruct(const XMP_OptionBits& opt); //! Convert Value::XmpStruct to XMP Toolkit array option bits - XMP_OptionBits xmpOptionBits(Exiv2::XmpValue::XmpStruct xs); + XMP_OptionBits xmpArrayOptionBits(Exiv2::XmpValue::XmpStruct xs); //! Convert XMP Toolkit array option bits to array TypeId Exiv2::TypeId arrayValueTypeId(const XMP_OptionBits& opt); @@ -83,7 +83,10 @@ namespace { Exiv2::XmpValue::XmpArrayType xmpArrayType(const XMP_OptionBits& opt); //! Convert Value::XmpArrayType to XMP Toolkit array option bits - XMP_OptionBits xmpOptionBits(Exiv2::XmpValue::XmpArrayType xat); + XMP_OptionBits xmpArrayOptionBits(Exiv2::XmpValue::XmpArrayType xat); + + //! Convert XmpFormatFlags to XMP Toolkit format option bits + XMP_OptionBits xmpFormatOptionBits(Exiv2::XmpParser::XmpFormatFlags flags); # ifdef DEBUG //! Print information about a parsed XMP node @@ -564,7 +567,9 @@ namespace Exiv2 { #ifdef EXV_HAVE_XMP_TOOLKIT int XmpParser::encode( std::string& xmpPacket, - const XmpData& xmpData) + const XmpData& xmpData, + uint16_t formatFlags, + uint32_t padding) { try { if (xmpData.empty()) return 0; @@ -609,8 +614,8 @@ namespace Exiv2 { // Todo: Xmpdatum should have an XmpValue, not a Value const XmpValue* val = dynamic_cast(&i->value()); assert(val); - options = xmpOptionBits(val->xmpArrayType()) - | xmpOptionBits(val->xmpStruct()); + options = xmpArrayOptionBits(val->xmpArrayType()) + | xmpArrayOptionBits(val->xmpStruct()); if ( i->typeId() == xmpBag || i->typeId() == xmpSeq || i->typeId() == xmpAlt) { @@ -646,7 +651,7 @@ namespace Exiv2 { throw Error(38, i->tagName(), TypeInfo::typeName(i->typeId())); } std::string tmpPacket; - meta.SerializeToBuffer(&tmpPacket, kXMP_UseCompactFormat); // throws + meta.SerializeToBuffer(&tmpPacket, xmpFormatOptionBits(static_cast(formatFlags)), padding); // throws xmpPacket = tmpPacket; return 0; @@ -686,7 +691,7 @@ namespace { return var; } - XMP_OptionBits xmpOptionBits(Exiv2::XmpValue::XmpStruct xs) + XMP_OptionBits xmpArrayOptionBits(Exiv2::XmpValue::XmpStruct xs) { XMP_OptionBits var(0); switch (xs) { @@ -715,7 +720,7 @@ namespace { return Exiv2::XmpValue::xmpArrayType(arrayValueTypeId(opt)); } - XMP_OptionBits xmpOptionBits(Exiv2::XmpValue::XmpArrayType xat) + XMP_OptionBits xmpArrayOptionBits(Exiv2::XmpValue::XmpArrayType xat) { XMP_OptionBits var(0); switch (xat) { @@ -736,6 +741,19 @@ namespace { return var; } + XMP_OptionBits xmpFormatOptionBits(Exiv2::XmpParser::XmpFormatFlags flags) + { + XMP_OptionBits var(0); + if (flags & Exiv2::XmpParser::omitPacketWrapper) var |= kXMP_OmitPacketWrapper; + if (flags & Exiv2::XmpParser::readOnlyPacket) var |= kXMP_ReadOnlyPacket; + if (flags & Exiv2::XmpParser::useCompactFormat) var |= kXMP_UseCompactFormat; + if (flags & Exiv2::XmpParser::includeThumbnailPad) var |= kXMP_IncludeThumbnailPad; + if (flags & Exiv2::XmpParser::exactPacketLength) var |= kXMP_ExactPacketLength; + if (flags & Exiv2::XmpParser::writeAliasComments) var |= kXMP_WriteAliasComments; + if (flags & Exiv2::XmpParser::omitAllFormatting) var |= kXMP_OmitAllFormatting; + return var; + } + #ifdef DEBUG void printNode(const std::string& schemaNs, const std::string& propPath, diff --git a/src/xmp.hpp b/src/xmp.hpp index 14c37448..4594626b 100644 --- a/src/xmp.hpp +++ b/src/xmp.hpp @@ -254,6 +254,16 @@ namespace Exiv2 { friend void XmpProperties::registerNs(const std::string&, const std::string&); friend void XmpProperties::unregisterNs(const std::string&); public: + //! Options to control the format of the serialized XMP packet. + enum XmpFormatFlags { + omitPacketWrapper = 0x0010UL, //!< Omit the XML packet wrapper. + readOnlyPacket = 0x0020UL, //!< Default is a writeable packet. + useCompactFormat = 0x0040UL, //!< Use a compact form of RDF. + includeThumbnailPad = 0x0100UL, //!< Include a padding allowance for a thumbnail image. + exactPacketLength = 0x0200UL, //!< The padding parameter is the overall packet length. + writeAliasComments = 0x0400UL, //!< Show aliases as XML comments. + omitAllFormatting = 0x0800UL //!< Omit all formatting whitespace. + }; /*! @brief Decode XMP metadata from an XMP packet \em xmpPacket into \em xmpData. The format of the XMP packet must follow the @@ -275,16 +285,21 @@ namespace Exiv2 { follows the XMP specification. This method only modifies \em xmpPacket if the operations succeeds (return code 0). - @param xmpPacket Reference to a string to hold the encoded XMP - packet. - @param xmpData XMP properties to encode. + @param xmpPacket Reference to a string to hold the encoded XMP + packet. + @param xmpData XMP properties to encode. + @param formatFlags Flags that control the format of the XMP packet, + see enum XmpFormatFlags. + @param padding Padding length. @return 0 if successful;
1 if XMP support has not been compiled-in;
2 if the XMP toolkit failed to initialize;
3 if the XMP toolkit failed and raised an XMP_Error */ static int encode( std::string& xmpPacket, - const XmpData& xmpData); + const XmpData& xmpData, + uint16_t formatFlags =useCompactFormat, + uint32_t padding =0); /*! @brief Initialize the XMP Toolkit. diff --git a/src/xmpsidecar.cpp b/src/xmpsidecar.cpp index 8d234e14..e40a80a2 100644 --- a/src/xmpsidecar.cpp +++ b/src/xmpsidecar.cpp @@ -116,13 +116,16 @@ namespace Exiv2 { IoCloser closer(*io_); if (writeXmpFromPacket() == false) { - if (XmpParser::encode(xmpPacket_, xmpData_)) { + if (XmpParser::encode(xmpPacket_, xmpData_, XmpParser::omitPacketWrapper|XmpParser::useCompactFormat)) { #ifndef SUPPRESS_WARNINGS std::cerr << "Error: Failed to encode XMP metadata.\n"; #endif } } if (xmpPacket_.size() > 0) { + if (xmpPacket_.substr(0, 5) != "\n" + xmpPacket_; + } BasicIo::AutoPtr tempIo(io_->temporary()); // may throw assert(tempIo.get() != 0); // Write XMP packet