Improved and cleaned-up ExifKey implementation

v0.27.3
Andreas Huggel 21 years ago
parent a25763d070
commit e88a307858

@ -23,7 +23,7 @@
@brief Canon MakerNote implemented according to the specification @brief Canon MakerNote implemented according to the specification
<a href="http://www.burren.cx/david/canon.html"> <a href="http://www.burren.cx/david/canon.html">
EXIF MakerNote of Canon</a> by David Burren EXIF MakerNote of Canon</a> by David Burren
@version $Name: $ $Revision: 1.11 $ @version $Name: $ $Revision: 1.12 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created<BR> @date 18-Feb-04, ahu: created<BR>
@ -177,6 +177,7 @@ namespace Exiv2 {
{ {
MakerNoteFactory& mnf = MakerNoteFactory::instance(); MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("Canon", "*", createCanonMakerNote); mnf.registerMakerNote("Canon", "*", createCanonMakerNote);
mnf.registerMakerNote(new CanonMakerNote);
} }
}; };
/*! /*!

@ -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,62 +73,84 @@ 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)
{ {
if (this == &rhs) return *this; if (this == &rhs) return *this;
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
@ -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);
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;
} }
tag_ = p.first;
ifdId_ = p.second; 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
// ***************************************************************************** // *****************************************************************************

@ -21,7 +21,7 @@
/*! /*!
@file exif.hpp @file exif.hpp
@brief Encoding and decoding of Exif data @brief Encoding and decoding of Exif data
@version $Name: $ $Revision: 1.51 $ @version $Name: $ $Revision: 1.52 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created
@ -73,11 +73,21 @@ namespace Exiv2 {
parts or the first part of the key is not '<b>Exif</b>'. parts or the first part of the key is not '<b>Exif</b>'.
*/ */
explicit ExifKey(const std::string& key); 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. //! Constructor to build an ExifKey from an IFD entry.
explicit ExifKey(const Entry& e); explicit ExifKey(const Entry& e);
//! Copy constructor //! Copy constructor
ExifKey(const ExifKey& rhs); ExifKey(const ExifKey& rhs);
// A destructor is not needed, as we do *not* delete the makernote virtual ~ExifKey();
//@} //@}
//! @name Manipulators //! @name Manipulators
@ -86,34 +96,25 @@ namespace Exiv2 {
@brief Assignment operator. @brief Assignment operator.
*/ */
ExifKey& operator=(const ExifKey& rhs); ExifKey& operator=(const ExifKey& rhs);
//! Set the makernote pointer.
void setMakerNote(MakerNote* pMakerNote);
//@} //@}
//! @name Accessors //! @name Accessors
//@{ //@{
virtual std::string key() const { return key_; } 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). @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; virtual std::string tagName() const;
/*! virtual uint16_t tag() const { return tag_; }
@brief Return the tag.
@throw Error ("Invalid key") if the tag is not set.
*/
virtual uint16_t tag() const;
virtual ExifKey* clone() const; virtual ExifKey* clone() const;
//! Interpret and print the value of an Exif tag //! Interpret and print the value of an Exif tag
std::ostream& printTag(std::ostream& os, const Value& value) const; std::ostream& printTag(std::ostream& os, const Value& value) const;
/*! //! Return the IFD id
@brief Return the IFD id IfdId ifdId() const { return ifdId_; }
@throw Error ("Invalid key") if the IFD id is not set.
*/
IfdId ifdId() const;
//! Return the name of the IFD //! Return the name of the IFD
const char* ifdName() const { return ExifTags::ifdName(ifdId()); } const char* ifdName() const { return ExifTags::ifdName(ifdId()); }
//! Return the related image item //! Return the related image item
@ -122,30 +123,33 @@ namespace Exiv2 {
std::string sectionName() const; std::string sectionName() const;
//! Return the index (unique id of this key within the original IFD) //! Return the index (unique id of this key within the original IFD)
int idx() const { return idx_; } int idx() const { return idx_; }
//! Return the pointer to the associated MakerNote
MakerNote* makerNote() const { return pMakerNote_; }
//@} //@}
protected: protected:
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! /*!
@brief Parse and convert the key string into tag, and IFD Id. @brief Set the key corresponding to the tag and IFD id.
Forwards the request to MakerNote::decomposeKey if necessary. The key is of the form '<b>Exif</b>.ifdItem.tagName'.
Updates key_ and ifdId_ if the string can be decomposed, */
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"). or throws Error ("Invalid key").
@throw Error ("Invalid key") if pMakerNote_ is ot 0 and the key @throw Error ("Invalid key") Todo: add conditions
cannot be parsed into family name, group name and tag name
parts.
*/ */
void decomposeKey(); void decomposeKey();
//@} //@}
private: private:
// DATA // DATA
static const char* familyName_;
uint16_t tag_; //!< Tag value uint16_t tag_; //!< Tag value
IfdId ifdId_; //!< The IFD associated with this tag IfdId ifdId_; //!< The IFD associated with this tag
std::string ifdItem_; //!< The IFD item
int idx_; //!< Unique id of an entry within one IFD int idx_; //!< Unique id of an entry within one IFD
MakerNote* pMakerNote_; //!< Pointer to the associated MakerNote MakerNote* pMakerNote_; //!< Pointer to the associated MakerNote
std::string key_; //!< Key std::string key_; //!< Key
@ -951,22 +955,6 @@ namespace Exiv2 {
void addToMakerNote(MakerNote* makerNote, void addToMakerNote(MakerNote* makerNote,
const Exifdatum& exifdatum, const Exifdatum& exifdatum,
ByteOrder byteOrder); ByteOrder byteOrder);
/*!
@brief Return a key for the entry. The key is of the form
'<b>Exif</b>.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<uint16_t, IfdId> decomposeKey(const std::string& key,
const MakerNote* makerNote);
} // namespace Exiv2 } // namespace Exiv2

@ -24,7 +24,7 @@
in Appendix 4: Makernote of Fujifilm of the document in Appendix 4: Makernote of Fujifilm of the document
<a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html">
Exif file format</a> by TsuruZoh Tachibanaya Exif file format</a> by TsuruZoh Tachibanaya
@version $Name: $ $Revision: 1.8 $ @version $Name: $ $Revision: 1.9 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 11-Feb-04, ahu: created @date 11-Feb-04, ahu: created
@ -141,6 +141,7 @@ namespace Exiv2 {
{ {
MakerNoteFactory& mnf = MakerNoteFactory::instance(); MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("FUJIFILM", "*", createFujiMakerNote); mnf.registerMakerNote("FUJIFILM", "*", createFujiMakerNote);
mnf.registerMakerNote(new FujiMakerNote);
} }
}; };
/*! /*!

@ -3,7 +3,7 @@
Abstract : Key unit tests Abstract : Key unit tests
File : key-test.cpp File : key-test.cpp
Version : $Name: $ $Revision: 1.2 $ Version : $Name: $ $Revision: 1.3 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History : 24-Aug-04, ahu: created 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) { if (rc == 0) {
std::cout << "All " << tc << " testcases passed." << std::endl; std::cout << "All " << tc << " testcases passed." << std::endl;
} }

@ -20,13 +20,13 @@
*/ */
/* /*
File: makernote.cpp File: makernote.cpp
Version: $Name: $ $Revision: 1.27 $ Version: $Name: $ $Revision: 1.28 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created History: 18-Feb-04, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #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 // Define DEBUG_* to output debug information to std::cerr
#undef DEBUG_MAKERNOTE #undef DEBUG_MAKERNOTE
@ -38,14 +38,17 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.27 $ $RCSfile: makernote.cpp,v $");
#include "tags.hpp" // for ExifTags::ifdItem #include "tags.hpp" // for ExifTags::ifdItem
#include "error.hpp" #include "error.hpp"
// Todo: remove circular dependency
#include "exif.hpp" // for MakerNote::writeMnTagInfo
// + standard includes // + standard includes
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#if defined DEBUG_MAKERNOTE || defined DEBUG_REGISTRY #if defined DEBUG_MAKERNOTE || defined DEBUG_REGISTRY
# include <iostream> # include <iostream>
#endif #endif
#include <cassert>
// ***************************************************************************** // *****************************************************************************
// class member definitions // 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 MakerNote::tagName(uint16_t tag) const
{ {
std::string tagName; std::string tagName;
@ -149,12 +123,13 @@ namespace Exiv2 {
std::ostream& MakerNote::writeMnTagInfo(std::ostream& os, uint16_t tag) const std::ostream& MakerNote::writeMnTagInfo(std::ostream& os, uint16_t tag) const
{ {
ExifKey exifKey(tag, ifdItem());
return os << tagName(tag) << ", " return os << tagName(tag) << ", "
<< std::dec << tag << ", " << std::dec << tag << ", "
<< "0x" << std::setw(4) << std::setfill('0') << "0x" << std::setw(4) << std::setfill('0')
<< std::right << std::hex << tag << ", " << std::right << std::hex << tag << ", "
<< ExifTags::ifdItem(makerIfdId) << ", " << ExifTags::ifdItem(makerIfdId) << ", "
<< makeKey(tag) << ", " << exifKey.key() << ", "
<< tagDesc(tag); << tagDesc(tag);
} // MakerNote::writeMnTagInfo } // MakerNote::writeMnTagInfo
@ -268,6 +243,21 @@ namespace Exiv2 {
return *pInstance_; return *pInstance_;
} // MakerNoteFactory::instance } // 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, void MakerNoteFactory::registerMakerNote(const std::string& make,
const std::string& model, const std::string& model,
CreateFct createMakerNote) CreateFct createMakerNote)

@ -22,7 +22,7 @@
@file makernote.hpp @file makernote.hpp
@brief Contains the Exif %MakerNote interface, IFD %MakerNote and a @brief Contains the Exif %MakerNote interface, IFD %MakerNote and a
MakerNote factory MakerNote factory
@version $Name: $ $Revision: 1.23 $ @version $Name: $ $Revision: 1.24 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created @date 18-Feb-04, ahu: created
@ -40,6 +40,7 @@
#include <iosfwd> #include <iosfwd>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <map>
// ***************************************************************************** // *****************************************************************************
// namespace extensions // namespace extensions
@ -73,7 +74,7 @@ namespace Exiv2 {
- read the makernote from a character buffer - read the makernote from a character buffer
- copy the makernote to a character buffer - copy the makernote to a character buffer
- maintain a list of makernote entries (similar to IFD entries) - maintain a list of makernote entries (similar to IFD entries)
- provide makernote specific tag names and keys - provide makernote specific tag names and tag information
- interpret (print) the values of makernote tags - interpret (print) the values of makernote tags
Makernotes can be added to the system by subclassing %MakerNote and Makernotes can be added to the system by subclassing %MakerNote and
@ -164,10 +165,6 @@ namespace Exiv2 {
//! @name Accessors //! @name Accessors
//@{ //@{
//! Return the key for the tag.
std::string makeKey(uint16_t tag) const;
//! Return the associated tag for a makernote key.
uint16_t decomposeKey(const std::string& key) const;
//! Return the byte order (little or big endian). //! Return the byte order (little or big endian).
ByteOrder byteOrder() const { return byteOrder_; } ByteOrder byteOrder() const { return byteOrder_; }
//! Return the offset of the makernote from the start of the TIFF header //! Return the offset of the makernote from the start of the TIFF header
@ -179,24 +176,24 @@ namespace Exiv2 {
the tag. the tag.
*/ */
virtual std::string tagName(uint16_t tag) const; virtual std::string tagName(uint16_t tag) const;
/*!
@brief Return the tag associated with a makernote tag name. The
default implementation looks up the makernote info tag array
if one is set, else it expects tag names in the form "0x01ff"
and converts them to unsigned integer.
*/
virtual uint16_t tag(const std::string& tagName) const;
/*! /*!
@brief Return the description of a makernote tag. The default @brief Return the description of a makernote tag. The default
implementation looks up the makernote info tag array if one is implementation looks up the makernote info tag array if one is
set, else it returns an empty string. set, else it returns an empty string.
*/ */
virtual uint16_t tag(const std::string& tagName) const; virtual std::string tagDesc(uint16_t tag) const;
/*! /*!
@brief Print a list of all tags known by this MakerNote to the output @brief Print a list of all tags known by this MakerNote to the output
stream os. The default implementation prints all tags in the stream os. The default implementation prints all tags in the
makernote info tag array if one is set. makernote info tag array if one is set.
*/ */
virtual std::string tagDesc(uint16_t tag) const;
/*!
@brief Return the tag associated with a makernote tag name. The
default implementation looks up the makernote info tag array
if one is set, else it expects tag names in the form \"0x01ff\"
and converts them to unsigned integer.
*/
virtual void taglist(std::ostream& os) const; virtual void taglist(std::ostream& os) const;
/*! /*!
@brief Write the makernote tag info of tag to the output stream os. @brief Write the makernote tag info of tag to the output stream os.
@ -395,6 +392,9 @@ namespace Exiv2 {
void registerMakerNote(const std::string& make, void registerMakerNote(const std::string& make,
const std::string& model, const std::string& model,
CreateFct createMakerNote); CreateFct createMakerNote);
//! Register a %MakerNote prototype in the IFD item registry.
void registerMakerNote(MakerNote* pMakerNote);
//@} //@}
//! @name Accessors //! @name Accessors
@ -449,6 +449,9 @@ namespace Exiv2 {
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) const; long offset) const;
//! Create a %MakerNote based on its IFD item string.
MakerNote* create(const std::string& ifdItem, bool alloc =true) const;
//@} //@}
/*! /*!
@ -483,12 +486,16 @@ namespace Exiv2 {
typedef std::vector<std::pair<std::string, CreateFct> > ModelRegistry; typedef std::vector<std::pair<std::string, CreateFct> > ModelRegistry;
//! Type used to store a list of make labels and model registries //! Type used to store a list of make labels and model registries
typedef std::vector<std::pair<std::string, ModelRegistry*> > Registry; typedef std::vector<std::pair<std::string, ModelRegistry*> > Registry;
//! Type used to store a list of IFD items and %MakerNote prototypes
typedef std::map<std::string, MakerNote*> IfdItemRegistry;
// DATA // DATA
//! Pointer to the one and only instance of this class. //! Pointer to the one and only instance of this class.
static MakerNoteFactory* pInstance_; static MakerNoteFactory* pInstance_;
//! List of makernote types and corresponding makernote create functions. //! List of makernote types and corresponding makernote create functions.
Registry registry_; Registry registry_;
//! List of makernote IfdItems and corresponding create functions.
IfdItemRegistry ifdItemRegistry_;
}; // class MakerNoteFactory }; // class MakerNoteFactory

@ -20,14 +20,14 @@
*/ */
/* /*
File: nikon1mn.cpp File: nikon1mn.cpp
Version: $Name: $ $Revision: 1.6 $ Version: $Name: $ $Revision: 1.7 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 17-May-04, ahu: created History: 17-May-04, ahu: created
25-May-04, ahu: combined all Nikon formats in one component 25-May-04, ahu: combined all Nikon formats in one component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.6 $ $RCSfile: nikonmn.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.7 $ $RCSfile: nikonmn.cpp,v $");
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -183,6 +183,8 @@ namespace Exiv2 {
return os; return os;
} }
const Nikon2MakerNote::RegisterMakerNote Nikon2MakerNote::register_;
// Nikon2 MakerNote Tag Info // Nikon2 MakerNote Tag Info
static const MakerNote::MnTagInfo nikon2MnTagInfo[] = { static const MakerNote::MnTagInfo nikon2MnTagInfo[] = {
MakerNote::MnTagInfo(0x0003, "Quality", "Image quality setting"), MakerNote::MnTagInfo(0x0003, "Quality", "Image quality setting"),
@ -348,6 +350,8 @@ namespace Exiv2 {
return os; return os;
} }
const Nikon3MakerNote::RegisterMakerNote Nikon3MakerNote::register_;
// Nikon3 MakerNote Tag Info // Nikon3 MakerNote Tag Info
static const MakerNote::MnTagInfo nikon3MnTagInfo[] = { static const MakerNote::MnTagInfo nikon3MnTagInfo[] = {
MakerNote::MnTagInfo(0x0001, "Version", "Nikon Makernote version"), MakerNote::MnTagInfo(0x0001, "Version", "Nikon Makernote version"),

@ -28,7 +28,7 @@
<a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html">
Exif file format</a> by TsuruZoh Tachibanaya.<BR> Exif file format</a> by TsuruZoh Tachibanaya.<BR>
Format 3: "EXIFutils Field Reference Guide". Format 3: "EXIFutils Field Reference Guide".
@version $Name: $ $Revision: 1.5 $ @version $Name: $ $Revision: 1.6 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 17-May-04, ahu: created<BR> @date 17-May-04, ahu: created<BR>
@ -132,6 +132,7 @@ namespace Exiv2 {
{ {
MakerNoteFactory& mnf = MakerNoteFactory::instance(); MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("NIKON*", "*", createNikonMakerNote); mnf.registerMakerNote("NIKON*", "*", createNikonMakerNote);
mnf.registerMakerNote(new Nikon1MakerNote);
} }
}; };
// DATA // DATA
@ -206,6 +207,30 @@ namespace Exiv2 {
//@} //@}
private: private:
//! Structure used to auto-register the MakerNote.
struct RegisterMakerNote {
//! Default constructor
RegisterMakerNote()
{
MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote(new Nikon2MakerNote);
}
};
// DATA
/*!
The static member variable is initialized before main (see note) and
will in the process register the MakerNote class. (Remember the
definition of the variable in the implementation file!)
@note The standard says that, if no function is explicitly called ever
in a module, then that module's static data might be never
initialized. This clause was introduced to allow dynamic link
libraries. The idea is, with this clause the loader is not
forced to eagerly load all modules, but load them only on
demand.
*/
static const RegisterMakerNote register_;
//! The item name (second part of the key) used for makernote tags //! The item name (second part of the key) used for makernote tags
std::string ifdItem_; std::string ifdItem_;
@ -258,6 +283,30 @@ namespace Exiv2 {
//@} //@}
private: private:
//! Structure used to auto-register the MakerNote.
struct RegisterMakerNote {
//! Default constructor
RegisterMakerNote()
{
MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote(new Nikon3MakerNote);
}
};
// DATA
/*!
The static member variable is initialized before main (see note) and
will in the process register the MakerNote class. (Remember the
definition of the variable in the implementation file!)
@note The standard says that, if no function is explicitly called ever
in a module, then that module's static data might be never
initialized. This clause was introduced to allow dynamic link
libraries. The idea is, with this clause the loader is not
forced to eagerly load all modules, but load them only on
demand.
*/
static const RegisterMakerNote register_;
//! The item name (second part of the key) used for makernote tags //! The item name (second part of the key) used for makernote tags
std::string ifdItem_; std::string ifdItem_;

@ -23,7 +23,7 @@
@brief Sigma and Foveon MakerNote implemented according to the specification @brief Sigma and Foveon MakerNote implemented according to the specification
<a href="http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html"> <a href="http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html">
SIGMA and FOVEON EXIF MakerNote Documentation</a> by Foveon. SIGMA and FOVEON EXIF MakerNote Documentation</a> by Foveon.
@version $Name: $ $Revision: 1.8 $ @version $Name: $ $Revision: 1.9 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 02-Apr-04, ahu: created @date 02-Apr-04, ahu: created
@ -131,6 +131,7 @@ namespace Exiv2 {
MakerNoteFactory& mnf = MakerNoteFactory::instance(); MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("SIGMA", "*", createSigmaMakerNote); mnf.registerMakerNote("SIGMA", "*", createSigmaMakerNote);
mnf.registerMakerNote("FOVEON", "*", createSigmaMakerNote); mnf.registerMakerNote("FOVEON", "*", createSigmaMakerNote);
mnf.registerMakerNote(new SigmaMakerNote);
} }
}; };
// DATA // DATA

@ -3,19 +3,15 @@
Abstract: Print a simple comma separated list of tags defined in Exiv2 Abstract: Print a simple comma separated list of tags defined in Exiv2
File: taglist.cpp File: taglist.cpp
Version: $Name: $ $Revision: 1.9 $ Version: $Name: $ $Revision: 1.10 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 07-Jan-04, ahu: created History: 07-Jan-04, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: taglist.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.10 $ $RCSfile: taglist.cpp,v $");
#include "makernote.hpp" #include "makernote.hpp"
#include "nikonmn.hpp"
#include "sigmamn.hpp"
#include "fujimn.hpp"
#include "canonmn.hpp"
#include "tags.hpp" #include "tags.hpp"
#include "datasets.hpp" #include "datasets.hpp"
#include "error.hpp" #include "error.hpp"
@ -39,25 +35,7 @@ try {
break; break;
} }
if (item == "Canon") { pMakerNote = MakerNoteFactory::instance().create(item);
pMakerNote = new CanonMakerNote;
}
else if (item == "Fujifilm") {
pMakerNote = new FujiMakerNote;
}
else if (item == "Sigma") {
pMakerNote = new SigmaMakerNote;
}
else if (item == "Nikon1") {
pMakerNote = new Nikon1MakerNote;
}
else if (item == "Nikon2") {
pMakerNote = new Nikon2MakerNote;
}
else if (item == "Nikon3") {
pMakerNote = new Nikon3MakerNote;
}
if (pMakerNote) { if (pMakerNote) {
pMakerNote->taglist(std::cout); pMakerNote->taglist(std::cout);
delete pMakerNote; delete pMakerNote;

@ -20,13 +20,13 @@
*/ */
/* /*
File: tags.cpp File: tags.cpp
Version: $Name: $ $Revision: 1.35 $ Version: $Name: $ $Revision: 1.36 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 15-Jan-04, ahu: created History: 15-Jan-04, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.35 $ $RCSfile: tags.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.36 $ $RCSfile: tags.cpp,v $");
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -35,6 +35,9 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.35 $ $RCSfile: tags.cpp,v $");
#include "types.hpp" #include "types.hpp"
#include "value.hpp" #include "value.hpp"
// Todo: remove circular dependency
#include "exif.hpp" // for TagInfo operator<<
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -266,24 +269,26 @@ namespace Exiv2 {
0 0
}; };
const char* ExifTags::familyName_ = "Exif";
int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId) int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
{ {
const TagInfo* tagInfo = tagInfos_[ifdId]; const TagInfo* tagInfo = tagInfos_[ifdId];
if (tagInfo == 0) return -1; if (tagInfo == 0) return -1;
int idx; int idx;
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) { for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
if (tagInfo[idx].tag_ == tag) break; if (tagInfo[idx].tag_ == tag) return idx;
} }
return idx; return -1;
} }
const char* ExifTags::tagName(uint16_t tag, IfdId ifdId) std::string ExifTags::tagName(uint16_t tag, IfdId ifdId)
{ {
int idx = tagInfoIdx(tag, ifdId); int idx = tagInfoIdx(tag, ifdId);
if (idx == -1) throw Error("No taginfo for IFD"); if (idx != -1) return tagInfos_[ifdId][idx].name_;
return tagInfos_[ifdId][idx].name_;
std::ostringstream os;
os << "0x" << std::setw(4) << std::setfill('0') << std::right
<< std::hex << tag;
return os.str();
} }
const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId) const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId)
@ -311,13 +316,30 @@ namespace Exiv2 {
uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId) uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
{ {
uint16_t tag = 0xffff;
const TagInfo* tagInfo = tagInfos_[ifdId]; const TagInfo* tagInfo = tagInfos_[ifdId];
if (tagInfo == 0) return 0xffff; if (tagInfo) {
int idx; int idx;
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) { for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
if (tagInfo[idx].name_ == tagName) break; if (tagInfo[idx].name_ == tagName) break;
} }
return tagInfo[idx].tag_; tag = tagInfo[idx].tag_;
}
if (tag == 0xffff) {
// Todo: Check format of tagName
std::istringstream is(tagName);
is >> std::hex >> tag;
}
return tag;
}
IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem)
{
int i;
for (i = int(lastIfdId) - 1; i > 0; --i) {
if (ifdInfo_[i].item_ == ifdItem) break;
}
return IfdId(i);
} }
const char* ExifTags::ifdName(IfdId ifdId) const char* ExifTags::ifdName(IfdId ifdId)
@ -344,44 +366,6 @@ namespace Exiv2 {
return SectionId(i); return SectionId(i);
} }
std::string ExifTags::makeKey(uint16_t tag, IfdId ifdId)
{
return std::string(familyName())
+ "." + std::string(ifdItem(ifdId))
+ "." + std::string(tagName(tag, ifdId));
}
// This 'database lookup' function returns the first match that
// we find, it doesn't verify whether this is the only match.
std::pair<uint16_t, IfdId> ExifTags::decomposeKey(const std::string& key)
{
// 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(ExifTags::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
int i;
for (i = int(lastIfdId) - 1; i > 0; --i) {
if (ifdInfo_[i].item_ == ifdItem) break;
}
IfdId ifdId = IfdId(i);
if (ifdId == ifdIdNotSet) return std::make_pair(0xffff, ifdId);
return std::make_pair(tag(tagName, ifdId), ifdId);
} // ExifTags::decomposeKey
std::ostream& ExifTags::printTag(std::ostream& os, std::ostream& ExifTags::printTag(std::ostream& os,
uint16_t tag, uint16_t tag,
IfdId ifdId, IfdId ifdId,
@ -414,12 +398,13 @@ namespace Exiv2 {
std::ostream& operator<<(std::ostream& os, const TagInfo& ti) std::ostream& operator<<(std::ostream& os, const TagInfo& ti)
{ {
ExifKey exifKey(ti.tag_, ExifTags::ifdItem(ti.ifdId_));
return os << ExifTags::tagName(ti.tag_, ti.ifdId_) << ", " return os << ExifTags::tagName(ti.tag_, ti.ifdId_) << ", "
<< std::dec << ti.tag_ << ", " << std::dec << ti.tag_ << ", "
<< "0x" << std::setw(4) << std::setfill('0') << "0x" << std::setw(4) << std::setfill('0')
<< std::right << std::hex << ti.tag_ << ", " << std::right << std::hex << ti.tag_ << ", "
<< ExifTags::ifdName(ti.ifdId_) << ", " << ExifTags::ifdName(ti.ifdId_) << ", "
<< ExifTags::makeKey(ti.tag_, ti.ifdId_) << ", " << exifKey.key() << ", "
<< ExifTags::tagDesc(ti.tag_, ti.ifdId_); << ExifTags::tagDesc(ti.tag_, ti.ifdId_);
} }

@ -21,7 +21,7 @@
/*! /*!
@file tags.hpp @file tags.hpp
@brief Exif tag and type information @brief Exif tag and type information
@version $Name: $ $Revision: 1.26 $ @version $Name: $ $Revision: 1.27 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 15-Jan-04, ahu: created<BR> @date 15-Jan-04, ahu: created<BR>
@ -114,19 +114,18 @@ namespace Exiv2 {
ExifTags& operator=(const ExifTags& rhs); ExifTags& operator=(const ExifTags& rhs);
public: public:
//! Return an identifier for Exif metadata
static const char* familyName() { return familyName_; }
/*! /*!
@brief Return the name of the tag. @brief Return the name of the tag or a string with the hexadecimal
value of the tag in the form "0x01ff", if the tag is not
a known Exif tag.
@param tag The tag @param tag The tag
@param ifdId IFD id @param ifdId IFD id
@return The name of the tag or a string indicating that the @return The name of the tag or a string containing the hexadecimal
tag is unknown. value of the tag in the form "0x01ff", if this is an unknown
@throw Error ("No taginfo for IFD") if there is no tag info tag.
data for the given IFD id in the lookup tables.
*/ */
static const char* tagName(uint16_t tag, IfdId ifdId); static std::string tagName(uint16_t tag, IfdId ifdId);
/*! /*!
@brief Return the description of the tag. @brief Return the description of the tag.
@param tag The tag @param tag The tag
@ -137,8 +136,14 @@ namespace Exiv2 {
data for the given IFD id in the lookup tables. data for the given IFD id in the lookup tables.
*/ */
static const char* tagDesc(uint16_t tag, IfdId ifdId); static const char* tagDesc(uint16_t tag, IfdId ifdId);
//! Return the tag for one combination of IFD id and tagName /*!
@brief Return the tag for one combination of IFD id and tagName.
If the tagName is not known, it expects tag names in the
form "0x01ff" and converts them to unsigned integer.
*/
static uint16_t tag(const std::string& tagName, IfdId ifdId); static uint16_t tag(const std::string& tagName, IfdId ifdId);
//! Return the IFD id for an IFD item
static IfdId ifdIdByIfdItem(const std::string& ifdItem);
//! Return the name of the IFD //! Return the name of the IFD
static const char* ifdName(IfdId ifdId); static const char* ifdName(IfdId ifdId);
//! Return the related image item (image or thumbnail) //! Return the related image item (image or thumbnail)
@ -169,18 +174,6 @@ namespace Exiv2 {
static const char* sectionDesc(uint16_t tag, IfdId ifdId); static const char* sectionDesc(uint16_t tag, IfdId ifdId);
//! Return the section id for a section name //! Return the section id for a section name
static SectionId sectionId(const std::string& sectionName); static SectionId sectionId(const std::string& sectionName);
/*!
@brief Return the key for the tag and IFD id. The key is of the form
'<b>Exif</b>.ifdItem.tagName'.
*/
static std::string makeKey(uint16_t tag, IfdId ifdId);
/*!
@brief Return tag and IFD id pair for the key.
@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.
*/
static std::pair<uint16_t, IfdId> decomposeKey(const std::string& key);
//! Interpret and print the value of an Exif tag //! Interpret and print the value of an Exif tag
static std::ostream& printTag(std::ostream& os, static std::ostream& printTag(std::ostream& os,
uint16_t tag, uint16_t tag,
@ -192,8 +185,6 @@ namespace Exiv2 {
private: private:
static int tagInfoIdx(uint16_t tag, IfdId ifdId); static int tagInfoIdx(uint16_t tag, IfdId ifdId);
static const char* familyName_;
static const IfdInfo ifdInfo_[]; static const IfdInfo ifdInfo_[];
static const SectionInfo sectionInfo_[]; static const SectionInfo sectionInfo_[];

Loading…
Cancel
Save