Added parseXmp() to parse Xmp metadata.

main
Robin Mills 4 years ago
parent ca180e08cc
commit ea1c91874f

@ -74,7 +74,7 @@ namespace Exiv2
//@{
/*!
@brief parse embedded tiff file
@brief parse embedded tiff file (Exif metadata)
@param root_tag root of parse tree Tag::root, Tag::cmt2 etc.
@param length tiff block length
@param start offset in file (default, io_->tell())
@ -84,6 +84,16 @@ namespace Exiv2
void parseTiff(uint32_t root_tag, uint32_t length,uint32_t start);
//@}
//@{
/*!
@brief parse embedded xmp/xml
@param length xmp block length
@param start offset in file
@
*/
void parseXmp(uint32_t length,uint32_t start);
//@}
//! @name Manipulators
//@{
void readMetadata() /* override */;
@ -116,6 +126,7 @@ namespace Exiv2
uint64_t visits_max_;
uint16_t unknownID_; // 0xffff
uint16_t exifID_;
uint16_t xmpID_;
std::map<uint32_t, Iloc> ilocs_;
//@}

@ -265,12 +265,17 @@ namespace Exiv2
uint16_t ID = getShort(data.pData_ + skip, bigEndian);
skip += 2;
/* getShort(data.pData_+skip,bigEndian) ; */ skip += 2; // protection
std::string id;
std::string name((const char*)data.pData_ + skip);
if (name.find("Exif") == 0) { // "Exif" or "ExifExif"
if ( !name.find("Exif") ) { // "Exif" or "ExifExif"
exifID_ = ID;
id=" *** Exif ***";
} else if ( !name.find("mime\0xmp") || !name.find("mime\0application/rdf+xml") ) {
xmpID_ = ID;
id=" *** XMP ***";
}
#ifdef EXIV2_DEBUG_MESSAGES
std::cerr << Internal::stringFormat("%3d ", ID) << name << " ";
std::cerr << Internal::stringFormat("ID = %3d ", ID) << name << " " << id;
#endif
} break;
@ -286,13 +291,23 @@ namespace Exiv2
while ((long)io_->tell() < (long)(address + box.length)) {
io_->seek(boxHandler(depth + 1), BasicIo::beg);
}
if (box.type == TAG_meta && ilocs_.find(exifID_) != ilocs_.end()) {
// post-process meta box to recover Exif and XMP
if (box.type == TAG_meta) {
if ( ilocs_.find(exifID_) != ilocs_.end()) {
const Iloc& iloc = ilocs_.find(exifID_)->second;
#ifdef EXIV2_DEBUG_MESSAGES
#ifdef EXIV2_DEBUG_MESSAGES
std::cerr << indent(depth) << "Exiv2::BMFF Exif: " << iloc.toString() << std::endl;
#endif
#endif
parseTiff(Internal::Tag::root,iloc.length_,iloc.start_);
exifID_ = unknownID_; // don't do this again!
}
if ( ilocs_.find(xmpID_) != ilocs_.end()) {
const Iloc& iloc = ilocs_.find(xmpID_)->second;
#ifdef EXIV2_DEBUG_MESSAGES
std::cerr << indent(depth) << "Exiv2::BMFF XMP: " << iloc.toString() << std::endl;
#endif
parseXmp(iloc.length_,iloc.start_);
}
ilocs_.clear() ;
}
} break;
@ -322,10 +337,13 @@ namespace Exiv2
uint32_t step = (box.length - 16) / itemCount; // length of data per item.
uint32_t base = skip;
for (uint32_t i = 0; i < itemCount; i++) {
skip = base + i * step; // move in 16 or 14 byte steps
skip = base + i * step; // move in 14, 16 or 18 byte steps
uint32_t ID = version > 2 ? getLong(data.pData_ + skip, bigEndian)
: getShort(data.pData_ + skip, bigEndian);
uint32_t offset = getLong(data.pData_ + skip + step - 8, bigEndian);
uint32_t offset = step==14 || step==16 ? getLong(data.pData_ + skip + step - 8, bigEndian)
: step== 18 ? getLong(data.pData_ + skip + 4, bigEndian)
: 0 ;
uint32_t ldata = getLong(data.pData_ + skip + step - 4, bigEndian);
#ifdef EXIV2_DEBUG_MESSAGES
std::cerr << indent(depth)
@ -333,9 +351,12 @@ namespace Exiv2
ID, offset, ldata)
<< std::endl;
#endif
// save data for post-processing in meta box
if ( offset && ldata && ID != unknownID_ ) {
ilocs_[ID] = Iloc(ID, offset, ldata);
}
}
}
} break;
case TAG_ispe: {
@ -437,6 +458,28 @@ namespace Exiv2
}
}
void BmffImage::parseXmp(uint32_t length,uint32_t start)
{
if (length > 8) {
long restore = io_->tell() ;
io_->seek(start,BasicIo::beg);
DataBuf xmp(length+1);
xmp.pData_[length]=0 ; // ensure xmp is null terminated!
if ( io_->read(xmp.pData_, length) != length )
throw Error(kerInputDataReadFailed);
if ( io_->error() )
throw Error(kerFailedToReadImageData);
try {
Exiv2::XmpParser::decode(xmpData(),std::string((char*)xmp.pData_));
} catch (...) {
throw Error(kerFailedToReadImageData);
}
io_->seek(restore,BasicIo::beg);
}
}
void BmffImage::setComment(const std::string& /*comment*/)
{
// bmff files are read-only

Loading…
Cancel
Save