diff --git a/src/canonmn.hpp b/src/canonmn.hpp
index 05c958b9..1f341977 100644
--- a/src/canonmn.hpp
+++ b/src/canonmn.hpp
@@ -23,7 +23,7 @@
@brief Canon MakerNote implemented according to the specification
EXIF MakerNote of Canon by David Burren
- @version $Name: $ $Revision: 1.11 $
+ @version $Name: $ $Revision: 1.12 $
@author Andreas Huggel (ahu)
ahuggel@gmx.net
@date 18-Feb-04, ahu: created
@@ -177,6 +177,7 @@ namespace Exiv2 {
{
MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("Canon", "*", createCanonMakerNote);
+ mnf.registerMakerNote(new CanonMakerNote);
}
};
/*!
diff --git a/src/exif.cpp b/src/exif.cpp
index 1f23ad77..5cb2f632 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -20,14 +20,14 @@
*/
/*
File: exif.cpp
- Version: $Name: $ $Revision: 1.58 $
+ Version: $Name: $ $Revision: 1.59 $
Author(s): Andreas Huggel (ahu)
History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component
*/
// *****************************************************************************
#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
#undef DEBUG_MAKERNOTE
@@ -73,22 +73,62 @@ namespace {
// class member definitions
namespace Exiv2 {
+ const char* ExifKey::familyName_ = "Exif";
+
ExifKey::ExifKey(const std::string& key)
- : idx_(0), pMakerNote_(0), key_(key)
+ : tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""),
+ idx_(0), pMakerNote_(0), key_(key)
{
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)
- : tag_(e.tag()), ifdId_(e.ifdId()), idx_(e.idx()),
- pMakerNote_(e.makerNote()), key_(makeKey(e))
+ : tag_(e.tag()), ifdId_(e.ifdId()), ifdItem_(""),
+ 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)
- : tag_(rhs.tag_), ifdId_(rhs.ifdId_), idx_(rhs.idx_),
- pMakerNote_(rhs.pMakerNote_), key_(rhs.key_)
+ : tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_),
+ idx_(rhs.idx_),
+ pMakerNote_(rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0),
+ key_(rhs.key_)
+ {
+ }
+
+ ExifKey::~ExifKey()
{
+ delete pMakerNote_;
}
ExifKey& ExifKey::operator=(const ExifKey& rhs)
@@ -97,40 +137,22 @@ namespace Exiv2 {
Key::operator=(rhs);
tag_ = rhs.tag_;
ifdId_ = rhs.ifdId_;
+ ifdItem_ = rhs.ifdItem_;
idx_ = rhs.idx_;
- pMakerNote_ = rhs.pMakerNote_;
+ pMakerNote_ = rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0;
key_ = rhs.key_;
return *this;
}
- void ExifKey::setMakerNote(MakerNote* pMakerNote)
- {
- if (ifdId_ == makerIfdId && pMakerNote_ != pMakerNote) {
- pMakerNote_ = pMakerNote;
- decomposeKey();
- }
- }
-
std::string ExifKey::tagName() const
{
- if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
+ if (ifdId_ == makerIfdId) {
+ assert(pMakerNote_);
return pMakerNote_->tagName(tag_);
}
- 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_;
+ return ExifTags::tagName(tag_, ifdId_);
}
-
+
ExifKey* ExifKey::clone() const
{
return new ExifKey(*this);
@@ -138,7 +160,8 @@ namespace Exiv2 {
std::string ExifKey::sectionName() const
{
- if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
+ if (ifdId_ == makerIfdId) {
+ assert(pMakerNote_);
return pMakerNote_->ifdItem();
}
return ExifTags::sectionName(tag(), ifdId());
@@ -146,26 +169,57 @@ namespace Exiv2 {
void ExifKey::decomposeKey()
{
- std::pair p;
- if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
- p.first = pMakerNote_->decomposeKey(key_);
- if (p.first == 0xffff) throw Error("Invalid key");
- p.second = makerIfdId;
- }
- else {
- p = ExifTags::decomposeKey(key_);
- // If it's couldn't be parsed, we assume it is an incomplete
- // makernote key (pMakerNote_ not set)
- if (p.second == ifdIdNotSet) p.second = makerIfdId;
- // No checks as this could still be an incomplete makernote key
- }
- tag_ = p.first;
- ifdId_ = p.second;
+ // 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");
+ std::string familyName = key_.substr(0, pos1);
+ if (familyName != std::string(familyName_)) {
+ throw Error("Invalid key");
+ }
+ std::string::size_type pos0 = pos1 + 1;
+ pos1 = key_.find('.', pos0);
+ if (pos1 == std::string::npos) throw Error("Invalid key");
+ std::string ifdItem = key_.substr(pos0, pos1 - pos0);
+ pos0 = pos1 + 1;
+ std::string tagName = key_.substr(pos0);
+ if (tagName == "") throw Error("Invalid key");
+
+ // 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
{
- if (ifdId_ == makerIfdId && pMakerNote_ != 0) {
+ if (ifdId_ == makerIfdId) {
+ assert(pMakerNote_);
return pMakerNote_->printTag(os, tag(), value);
}
return ExifTags::printTag(os, tag(), ifdId(), value);
@@ -974,7 +1028,6 @@ namespace Exiv2 {
{
// Todo: Implement a more suitable ExifKey c'tor
ExifKey k(key);
- k.setMakerNote(pMakerNote_);
add(Exifdatum(k, pValue));
}
@@ -1316,7 +1369,8 @@ namespace Exiv2 {
DataBuf buf(md.size());
md.copy(buf.pData_, byteOrder);
- e.setValue(static_cast(md.typeId()), md.count(), buf.pData_, md.size());
+ e.setValue(static_cast(md.typeId()), md.count(),
+ buf.pData_, md.size());
ifd.add(e);
} // addToIfd
@@ -1355,24 +1409,6 @@ namespace Exiv2 {
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 decomposeKey(const std::string& key,
- const MakerNote* makerNote)
- {
- std::pair p = ExifTags::decomposeKey(key);
- if (p.second == makerIfdId && makerNote != 0) {
- p.first = makerNote->decomposeKey(key);
- }
- return p;
- }
-
} // namespace Exiv2
// *****************************************************************************
diff --git a/src/exif.hpp b/src/exif.hpp
index 63071da8..0f4b09f1 100644
--- a/src/exif.hpp
+++ b/src/exif.hpp
@@ -21,7 +21,7 @@
/*!
@file exif.hpp
@brief Encoding and decoding of Exif data
- @version $Name: $ $Revision: 1.51 $
+ @version $Name: $ $Revision: 1.52 $
@author Andreas Huggel (ahu)
ahuggel@gmx.net
@date 09-Jan-04, ahu: created
@@ -73,11 +73,21 @@ namespace Exiv2 {
parts or the first part of the key is not 'Exif'.
*/
explicit ExifKey(const std::string& key);
+ /*!
+ @brief Constructor to create an Exif key from a tag and IFD item
+ string.
+ @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.
+ */
+ ExifKey(uint16_t tag, const std::string& ifdItem);
//! Constructor to build an ExifKey from an IFD entry.
explicit ExifKey(const Entry& e);
//! Copy constructor
ExifKey(const ExifKey& rhs);
- // A destructor is not needed, as we do *not* delete the makernote
+ virtual ~ExifKey();
//@}
//! @name Manipulators
@@ -86,34 +96,25 @@ namespace Exiv2 {
@brief Assignment operator.
*/
ExifKey& operator=(const ExifKey& rhs);
- //! Set the makernote pointer.
- void setMakerNote(MakerNote* pMakerNote);
//@}
//! @name Accessors
//@{
virtual std::string key() const { return key_; }
- virtual const char* familyName() const { return ExifTags::familyName(); }
+ virtual const char* familyName() const { return familyName_; }
/*!
@brief Return the name of the group (the second part of the key).
- For Exif keys, the group name is the IFD name.
+ For Exif keys, the group name is the IFD item.
*/
- virtual std::string groupName() const { return ifdName(); }
+ virtual std::string groupName() const { return ifdItem(); }
virtual std::string tagName() const;
- /*!
- @brief Return the tag.
- @throw Error ("Invalid key") if the tag is not set.
- */
- virtual uint16_t tag() const;
+ virtual uint16_t tag() const { return tag_; }
virtual ExifKey* clone() const;
//! Interpret and print the value of an Exif tag
std::ostream& printTag(std::ostream& os, const Value& value) const;
- /*!
- @brief Return the IFD id
- @throw Error ("Invalid key") if the IFD id is not set.
- */
- IfdId ifdId() const;
+ //! Return the IFD id
+ IfdId ifdId() const { return ifdId_; }
//! Return the name of the IFD
const char* ifdName() const { return ExifTags::ifdName(ifdId()); }
//! Return the related image item
@@ -122,30 +123,33 @@ namespace Exiv2 {
std::string sectionName() const;
//! Return the index (unique id of this key within the original IFD)
int idx() const { return idx_; }
- //! Return the pointer to the associated MakerNote
- MakerNote* makerNote() const { return pMakerNote_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
- @brief Parse and convert the key string into tag, and IFD Id.
- Forwards the request to MakerNote::decomposeKey if necessary.
- Updates key_ and ifdId_ if the string can be decomposed,
+ @brief Set the key corresponding to the tag and IFD id.
+ The key is of the form 'Exif.ifdItem.tagName'.
+ */
+ void makeKey();
+ /*!
+ @brief Parse and convert the key string into tag and IFD Id.
+ Updates data memebers if the string can be decomposed,
or throws Error ("Invalid key").
- @throw Error ("Invalid key") if pMakerNote_ is ot 0 and the key
- cannot be parsed into family name, group name and tag name
- parts.
+ @throw Error ("Invalid key") Todo: add conditions
*/
void decomposeKey();
//@}
private:
// DATA
- uint16_t tag_; //!< Tag value
+ static const char* familyName_;
+
+ uint16_t tag_; //!< Tag value
IfdId ifdId_; //!< The IFD associated with this tag
+ std::string ifdItem_; //!< The IFD item
int idx_; //!< Unique id of an entry within one IFD
MakerNote* pMakerNote_; //!< Pointer to the associated MakerNote
std::string key_; //!< Key
@@ -951,22 +955,6 @@ namespace Exiv2 {
void addToMakerNote(MakerNote* makerNote,
const Exifdatum& exifdatum,
ByteOrder byteOrder);
- /*!
- @brief Return a key for the entry. The key is of the form
- 'Exif.ifdItem.tagName'. This function knows about
- MakerNotes, i.e., it will invoke MakerNote::makeKey if necessary.
- */
- std::string makeKey(const Entry& entry);
- /*!
- @brief Return the tag and IFD id pair for the key. This function knows
- about MakerNotes, i.e., it will forward the request to
- MakerNote::decomposeKey if necessary.
- @return A pair consisting of the tag and IFD id.
- @throw Error ("Invalid key") if the key cannot be parsed into
- item item, section name and tag name parts.
- */
- std::pair decomposeKey(const std::string& key,
- const MakerNote* makerNote);
} // namespace Exiv2
diff --git a/src/fujimn.hpp b/src/fujimn.hpp
index bacb7688..1223511f 100644
--- a/src/fujimn.hpp
+++ b/src/fujimn.hpp
@@ -24,7 +24,7 @@
in Appendix 4: Makernote of Fujifilm of the document
Exif file format by TsuruZoh Tachibanaya
- @version $Name: $ $Revision: 1.8 $
+ @version $Name: $ $Revision: 1.9 $
@author Andreas Huggel (ahu)
ahuggel@gmx.net
@date 11-Feb-04, ahu: created
@@ -141,6 +141,7 @@ namespace Exiv2 {
{
MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("FUJIFILM", "*", createFujiMakerNote);
+ mnf.registerMakerNote(new FujiMakerNote);
}
};
/*!
diff --git a/src/key-test.cpp b/src/key-test.cpp
index c3ad6d53..03d531ba 100644
--- a/src/key-test.cpp
+++ b/src/key-test.cpp
@@ -3,7 +3,7 @@
Abstract : Key unit tests
File : key-test.cpp
- Version : $Name: $ $Revision: 1.2 $
+ Version : $Name: $ $Revision: 1.3 $
Author(s): Andreas Huggel (ahu)
History : 24-Aug-04, ahu: created
@@ -201,6 +201,34 @@ int main()
// -----
+ ExifKey ek4("Exif.Image.0x0110");
+ tc += 1;
+ if (ek4.key() != "Exif.Image.Model") {
+ std::cout << "Testcase failed (converted key)" << std::endl;
+ rc += 1;
+ }
+ tc += 1;
+ if (ek4.tagName() != "Model") {
+ std::cout << "Testcase failed (converted tagName)" << std::endl;
+ rc += 1;
+ }
+
+ // -----
+
+ ExifKey ek5("Exif.Nikon3.0x0007");
+ tc += 1;
+ if (ek5.key() != "Exif.Nikon3.Focus") {
+ std::cout << "Testcase failed (converted key)" << std::endl;
+ rc += 1;
+ }
+ tc += 1;
+ if (ek5.tagName() != "Focus") {
+ std::cout << "Testcase failed (converted tagName)" << std::endl;
+ rc += 1;
+ }
+
+ // -----
+
if (rc == 0) {
std::cout << "All " << tc << " testcases passed." << std::endl;
}
diff --git a/src/makernote.cpp b/src/makernote.cpp
index 8eb81968..99a5822e 100644
--- a/src/makernote.cpp
+++ b/src/makernote.cpp
@@ -20,13 +20,13 @@
*/
/*
File: makernote.cpp
- Version: $Name: $ $Revision: 1.27 $
+ Version: $Name: $ $Revision: 1.28 $
Author(s): Andreas Huggel (ahu)
History: 18-Feb-04, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
-EXIV2_RCSID("@(#) $Name: $ $Revision: 1.27 $ $RCSfile: makernote.cpp,v $");
+EXIV2_RCSID("@(#) $Name: $ $Revision: 1.28 $ $RCSfile: makernote.cpp,v $");
// Define DEBUG_* to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@@ -38,14 +38,17 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.27 $ $RCSfile: makernote.cpp,v $");
#include "tags.hpp" // for ExifTags::ifdItem
#include "error.hpp"
+// Todo: remove circular dependency
+#include "exif.hpp" // for MakerNote::writeMnTagInfo
+
// + standard includes
#include
#include
#include
-
#if defined DEBUG_MAKERNOTE || defined DEBUG_REGISTRY
-# include
+# include
#endif
+#include
// *****************************************************************************
// class member definitions
@@ -57,35 +60,6 @@ namespace Exiv2 {
{
}
- std::string MakerNote::makeKey(uint16_t tag) const
- {
- return std::string(ExifTags::familyName())
- + "." + std::string(ifdItem())
- + "." + tagName(tag);
- } // MakerNote::makeKey
-
- uint16_t MakerNote::decomposeKey(const std::string& key) const
- {
- // Get the family, item and tag name parts of the key
- std::string::size_type pos1 = key.find('.');
- if (pos1 == std::string::npos) throw Error("Invalid key");
- std::string familyName = key.substr(0, pos1);
- std::string::size_type pos0 = pos1 + 1;
- pos1 = key.find('.', pos0);
- if (pos1 == std::string::npos) throw Error("Invalid key");
- std::string ifdItem = key.substr(pos0, pos1 - pos0);
- pos0 = pos1 + 1;
- std::string tagName = key.substr(pos0);
- if (tagName == "") throw Error("Invalid key");
-
- if (familyName != ExifTags::familyName()) return 0xffff;
- uint16_t tag = this->tag(tagName);
- if (tag == 0xffff) return tag;
- if (ifdItem != this->ifdItem()) return 0xffff;
-
- return tag;
- } // MakerNote::decomposeKey
-
std::string MakerNote::tagName(uint16_t tag) const
{
std::string tagName;
@@ -149,12 +123,13 @@ namespace Exiv2 {
std::ostream& MakerNote::writeMnTagInfo(std::ostream& os, uint16_t tag) const
{
+ ExifKey exifKey(tag, ifdItem());
return os << tagName(tag) << ", "
<< std::dec << tag << ", "
<< "0x" << std::setw(4) << std::setfill('0')
<< std::right << std::hex << tag << ", "
<< ExifTags::ifdItem(makerIfdId) << ", "
- << makeKey(tag) << ", "
+ << exifKey.key() << ", "
<< tagDesc(tag);
} // MakerNote::writeMnTagInfo
@@ -268,6 +243,21 @@ namespace Exiv2 {
return *pInstance_;
} // MakerNoteFactory::instance
+ void MakerNoteFactory::registerMakerNote(MakerNote* pMakerNote)
+ {
+ assert(pMakerNote);
+ ifdItemRegistry_[pMakerNote->ifdItem()] = pMakerNote;
+ } // MakerNoteFactory::registerMakerNote
+
+ MakerNote* MakerNoteFactory::create(const std::string& ifdItem,
+ bool alloc) const
+ {
+ IfdItemRegistry::const_iterator i = ifdItemRegistry_.find(ifdItem);
+ if (i == ifdItemRegistry_.end()) return 0;
+ assert(i->second);
+ return i->second->clone(alloc);
+ } // MakerNoteFactory::create
+
void MakerNoteFactory::registerMakerNote(const std::string& make,
const std::string& model,
CreateFct createMakerNote)
diff --git a/src/makernote.hpp b/src/makernote.hpp
index aef50307..af81d9f1 100644
--- a/src/makernote.hpp
+++ b/src/makernote.hpp
@@ -22,7 +22,7 @@
@file makernote.hpp
@brief Contains the Exif %MakerNote interface, IFD %MakerNote and a
MakerNote factory
- @version $Name: $ $Revision: 1.23 $
+ @version $Name: $ $Revision: 1.24 $
@author Andreas Huggel (ahu)
ahuggel@gmx.net
@date 18-Feb-04, ahu: created
@@ -40,6 +40,7 @@
#include
#include
#include
+#include