|
|
@ -20,14 +20,14 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
File: exif.cpp
|
|
|
|
File: exif.cpp
|
|
|
|
Version: $Name: $ $Revision: 1.58 $
|
|
|
|
Version: $Name: $ $Revision: 1.59 $
|
|
|
|
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
|
|
|
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
|
|
|
History: 26-Jan-04, ahu: created
|
|
|
|
History: 26-Jan-04, ahu: created
|
|
|
|
11-Feb-04, ahu: isolated as a component
|
|
|
|
11-Feb-04, ahu: isolated as a component
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
// *****************************************************************************
|
|
|
|
// *****************************************************************************
|
|
|
|
#include "rcsid.hpp"
|
|
|
|
#include "rcsid.hpp"
|
|
|
|
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.58 $ $RCSfile: exif.cpp,v $");
|
|
|
|
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.59 $ $RCSfile: exif.cpp,v $");
|
|
|
|
|
|
|
|
|
|
|
|
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
|
|
|
|
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
|
|
|
|
#undef DEBUG_MAKERNOTE
|
|
|
|
#undef DEBUG_MAKERNOTE
|
|
|
@ -73,22 +73,62 @@ namespace {
|
|
|
|
// class member definitions
|
|
|
|
// class member definitions
|
|
|
|
namespace Exiv2 {
|
|
|
|
namespace Exiv2 {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char* ExifKey::familyName_ = "Exif";
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey::ExifKey(const std::string& key)
|
|
|
|
ExifKey::ExifKey(const std::string& key)
|
|
|
|
: idx_(0), pMakerNote_(0), key_(key)
|
|
|
|
: tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
|
|
|
|
|
|
|
|
idx_(0), pMakerNote_(0), key_(key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
decomposeKey();
|
|
|
|
decomposeKey();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey::ExifKey(uint16_t tag, const std::string& ifdItem)
|
|
|
|
|
|
|
|
: tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
|
|
|
|
|
|
|
|
idx_(0), pMakerNote_(0), key_("")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem);
|
|
|
|
|
|
|
|
if (ifdId == makerIfdId) throw Error("Invalid key");
|
|
|
|
|
|
|
|
MakerNote* pMakerNote = 0;
|
|
|
|
|
|
|
|
if (ifdId == ifdIdNotSet) {
|
|
|
|
|
|
|
|
pMakerNote = MakerNoteFactory::instance().create(ifdItem);
|
|
|
|
|
|
|
|
if (pMakerNote) ifdId = makerIfdId;
|
|
|
|
|
|
|
|
else throw Error("Invalid key");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
tag_ = tag;
|
|
|
|
|
|
|
|
ifdId_ = ifdId;
|
|
|
|
|
|
|
|
ifdItem_ = ifdItem;
|
|
|
|
|
|
|
|
pMakerNote_ = pMakerNote;
|
|
|
|
|
|
|
|
makeKey();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey::ExifKey(const Entry& e)
|
|
|
|
ExifKey::ExifKey(const Entry& e)
|
|
|
|
: tag_(e.tag()), ifdId_(e.ifdId()), idx_(e.idx()),
|
|
|
|
: tag_(e.tag()), ifdId_(e.ifdId()), ifdItem_(""),
|
|
|
|
pMakerNote_(e.makerNote()), key_(makeKey(e))
|
|
|
|
idx_(e.idx()), pMakerNote_(0), key_("")
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ifdId_ == makerIfdId) {
|
|
|
|
|
|
|
|
if (e.makerNote()) {
|
|
|
|
|
|
|
|
ifdItem_ = e.makerNote()->ifdItem();
|
|
|
|
|
|
|
|
pMakerNote_ = e.makerNote()->clone();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else throw Error("Invalid Key");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
ifdItem_ = ExifTags::ifdItem(ifdId_);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
makeKey();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey::ExifKey(const ExifKey& rhs)
|
|
|
|
ExifKey::ExifKey(const ExifKey& rhs)
|
|
|
|
: tag_(rhs.tag_), ifdId_(rhs.ifdId_), idx_(rhs.idx_),
|
|
|
|
: tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_),
|
|
|
|
pMakerNote_(rhs.pMakerNote_), key_(rhs.key_)
|
|
|
|
idx_(rhs.idx_),
|
|
|
|
|
|
|
|
pMakerNote_(rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0),
|
|
|
|
|
|
|
|
key_(rhs.key_)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey::~ExifKey()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
delete pMakerNote_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey& ExifKey::operator=(const ExifKey& rhs)
|
|
|
|
ExifKey& ExifKey::operator=(const ExifKey& rhs)
|
|
|
@ -97,40 +137,22 @@ namespace Exiv2 {
|
|
|
|
Key::operator=(rhs);
|
|
|
|
Key::operator=(rhs);
|
|
|
|
tag_ = rhs.tag_;
|
|
|
|
tag_ = rhs.tag_;
|
|
|
|
ifdId_ = rhs.ifdId_;
|
|
|
|
ifdId_ = rhs.ifdId_;
|
|
|
|
|
|
|
|
ifdItem_ = rhs.ifdItem_;
|
|
|
|
idx_ = rhs.idx_;
|
|
|
|
idx_ = rhs.idx_;
|
|
|
|
pMakerNote_ = rhs.pMakerNote_;
|
|
|
|
pMakerNote_ = rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0;
|
|
|
|
key_ = rhs.key_;
|
|
|
|
key_ = rhs.key_;
|
|
|
|
return *this;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ExifKey::setMakerNote(MakerNote* pMakerNote)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ifdId_ == makerIfdId && pMakerNote_ != pMakerNote) {
|
|
|
|
|
|
|
|
pMakerNote_ = pMakerNote;
|
|
|
|
|
|
|
|
decomposeKey();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string ExifKey::tagName() const
|
|
|
|
std::string ExifKey::tagName() const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
|
|
|
|
if (ifdId_ == makerIfdId) {
|
|
|
|
|
|
|
|
assert(pMakerNote_);
|
|
|
|
return pMakerNote_->tagName(tag_);
|
|
|
|
return pMakerNote_->tagName(tag_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ExifTags::tagName(tag(), ifdId());
|
|
|
|
return ExifTags::tagName(tag_, ifdId_);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t ExifKey::tag() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (tag_ == 0xffff) throw Error("Invalid key");
|
|
|
|
|
|
|
|
return tag_;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfdId ExifKey::ifdId() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (ifdId_ == ifdIdNotSet) throw Error("Invalid key");
|
|
|
|
|
|
|
|
return ifdId_;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExifKey* ExifKey::clone() const
|
|
|
|
ExifKey* ExifKey::clone() const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return new ExifKey(*this);
|
|
|
|
return new ExifKey(*this);
|
|
|
@ -138,7 +160,8 @@ namespace Exiv2 {
|
|
|
|
|
|
|
|
|
|
|
|
std::string ExifKey::sectionName() const
|
|
|
|
std::string ExifKey::sectionName() const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
|
|
|
|
if (ifdId_ == makerIfdId) {
|
|
|
|
|
|
|
|
assert(pMakerNote_);
|
|
|
|
return pMakerNote_->ifdItem();
|
|
|
|
return pMakerNote_->ifdItem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ExifTags::sectionName(tag(), ifdId());
|
|
|
|
return ExifTags::sectionName(tag(), ifdId());
|
|
|
@ -146,26 +169,57 @@ namespace Exiv2 {
|
|
|
|
|
|
|
|
|
|
|
|
void ExifKey::decomposeKey()
|
|
|
|
void ExifKey::decomposeKey()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::pair<uint16_t, IfdId> p;
|
|
|
|
// Get the family name, IFD name and tag name parts of the key
|
|
|
|
if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
|
|
|
|
std::string::size_type pos1 = key_.find('.');
|
|
|
|
p.first = pMakerNote_->decomposeKey(key_);
|
|
|
|
if (pos1 == std::string::npos) throw Error("Invalid key");
|
|
|
|
if (p.first == 0xffff) throw Error("Invalid key");
|
|
|
|
std::string familyName = key_.substr(0, pos1);
|
|
|
|
p.second = makerIfdId;
|
|
|
|
if (familyName != std::string(familyName_)) {
|
|
|
|
}
|
|
|
|
throw Error("Invalid key");
|
|
|
|
else {
|
|
|
|
}
|
|
|
|
p = ExifTags::decomposeKey(key_);
|
|
|
|
std::string::size_type pos0 = pos1 + 1;
|
|
|
|
// If it's couldn't be parsed, we assume it is an incomplete
|
|
|
|
pos1 = key_.find('.', pos0);
|
|
|
|
// makernote key (pMakerNote_ not set)
|
|
|
|
if (pos1 == std::string::npos) throw Error("Invalid key");
|
|
|
|
if (p.second == ifdIdNotSet) p.second = makerIfdId;
|
|
|
|
std::string ifdItem = key_.substr(pos0, pos1 - pos0);
|
|
|
|
// No checks as this could still be an incomplete makernote key
|
|
|
|
pos0 = pos1 + 1;
|
|
|
|
}
|
|
|
|
std::string tagName = key_.substr(pos0);
|
|
|
|
tag_ = p.first;
|
|
|
|
if (tagName == "") throw Error("Invalid key");
|
|
|
|
ifdId_ = p.second;
|
|
|
|
|
|
|
|
|
|
|
|
// Find IfdId
|
|
|
|
|
|
|
|
IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem);
|
|
|
|
|
|
|
|
if (ifdId == makerIfdId) throw Error("Invalid key");
|
|
|
|
|
|
|
|
MakerNote* pMakerNote = 0;
|
|
|
|
|
|
|
|
if (ifdId == ifdIdNotSet) {
|
|
|
|
|
|
|
|
pMakerNote = MakerNoteFactory::instance().create(ifdItem);
|
|
|
|
|
|
|
|
if (pMakerNote) ifdId = makerIfdId;
|
|
|
|
|
|
|
|
else throw Error("Invalid key");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Convert tag
|
|
|
|
|
|
|
|
uint16_t tag = pMakerNote ?
|
|
|
|
|
|
|
|
pMakerNote->tag(tagName) : ExifTags::tag(tagName, ifdId);
|
|
|
|
|
|
|
|
// Translate hex tag name (0xabcd) to a real tag name if there is one
|
|
|
|
|
|
|
|
tagName = pMakerNote ?
|
|
|
|
|
|
|
|
pMakerNote->tagName(tag) : ExifTags::tagName(tag, ifdId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tag_ = tag;
|
|
|
|
|
|
|
|
ifdId_ = ifdId;
|
|
|
|
|
|
|
|
ifdItem_ = ifdItem;
|
|
|
|
|
|
|
|
pMakerNote_ = pMakerNote;
|
|
|
|
|
|
|
|
key_ = familyName + "." + ifdItem + "." + tagName;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ExifKey::makeKey()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
key_ = std::string(familyName_)
|
|
|
|
|
|
|
|
+ "." + ifdItem_
|
|
|
|
|
|
|
|
+ "." + (pMakerNote_ ?
|
|
|
|
|
|
|
|
pMakerNote_->tagName(tag_) : ExifTags::tagName(tag_, ifdId_));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::ostream& ExifKey::printTag(std::ostream& os, const Value& value) const
|
|
|
|
std::ostream& ExifKey::printTag(std::ostream& os, const Value& value) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
|
|
|
|
if (ifdId_ == makerIfdId) {
|
|
|
|
|
|
|
|
assert(pMakerNote_);
|
|
|
|
return pMakerNote_->printTag(os, tag(), value);
|
|
|
|
return pMakerNote_->printTag(os, tag(), value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ExifTags::printTag(os, tag(), ifdId(), value);
|
|
|
|
return ExifTags::printTag(os, tag(), ifdId(), value);
|
|
|
@ -974,7 +1028,6 @@ namespace Exiv2 {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Todo: Implement a more suitable ExifKey c'tor
|
|
|
|
// Todo: Implement a more suitable ExifKey c'tor
|
|
|
|
ExifKey k(key);
|
|
|
|
ExifKey k(key);
|
|
|
|
k.setMakerNote(pMakerNote_);
|
|
|
|
|
|
|
|
add(Exifdatum(k, pValue));
|
|
|
|
add(Exifdatum(k, pValue));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1316,7 +1369,8 @@ namespace Exiv2 {
|
|
|
|
|
|
|
|
|
|
|
|
DataBuf buf(md.size());
|
|
|
|
DataBuf buf(md.size());
|
|
|
|
md.copy(buf.pData_, byteOrder);
|
|
|
|
md.copy(buf.pData_, byteOrder);
|
|
|
|
e.setValue(static_cast<uint16_t>(md.typeId()), md.count(), buf.pData_, md.size());
|
|
|
|
e.setValue(static_cast<uint16_t>(md.typeId()), md.count(),
|
|
|
|
|
|
|
|
buf.pData_, md.size());
|
|
|
|
ifd.add(e);
|
|
|
|
ifd.add(e);
|
|
|
|
} // addToIfd
|
|
|
|
} // addToIfd
|
|
|
|
|
|
|
|
|
|
|
@ -1355,24 +1409,6 @@ namespace Exiv2 {
|
|
|
|
return md.pKey_->printTag(os, md.value());
|
|
|
|
return md.pKey_->printTag(os, md.value());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string makeKey(const Entry& entry)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (entry.ifdId() == makerIfdId && entry.makerNote() != 0) {
|
|
|
|
|
|
|
|
return entry.makerNote()->makeKey(entry.tag());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ExifTags::makeKey(entry.tag(), entry.ifdId());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<uint16_t, IfdId> decomposeKey(const std::string& key,
|
|
|
|
|
|
|
|
const MakerNote* makerNote)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::pair<uint16_t, IfdId> p = ExifTags::decomposeKey(key);
|
|
|
|
|
|
|
|
if (p.second == makerIfdId && makerNote != 0) {
|
|
|
|
|
|
|
|
p.first = makerNote->decomposeKey(key);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Exiv2
|
|
|
|
} // namespace Exiv2
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************************
|
|
|
|
// *****************************************************************************
|
|
|
|