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

@ -20,14 +20,14 @@
*/
/*
File: exif.cpp
Version: $Name: $ $Revision: 1.58 $
Version: $Name: $ $Revision: 1.59 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
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,38 +137,20 @@ 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
@ -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<uint16_t, IfdId> 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<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);
} // 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<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
// *****************************************************************************

@ -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)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@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>'.
*/
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 '<b>Exif</b>.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
'<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

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

@ -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) <ahuggel@gmx.net>
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;
}

@ -20,13 +20,13 @@
*/
/*
File: makernote.cpp
Version: $Name: $ $Revision: 1.27 $
Version: $Name: $ $Revision: 1.28 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
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 <string>
#include <sstream>
#include <iomanip>
#if defined DEBUG_MAKERNOTE || defined DEBUG_REGISTRY
# include <iostream>
# include <iostream>
#endif
#include <cassert>
// *****************************************************************************
// 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)

@ -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)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created
@ -40,6 +40,7 @@
#include <iosfwd>
#include <utility>
#include <vector>
#include <map>
// *****************************************************************************
// namespace extensions
@ -73,7 +74,7 @@ namespace Exiv2 {
- read the makernote from a character buffer
- copy the makernote to a character buffer
- 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
Makernotes can be added to the system by subclassing %MakerNote and
@ -164,10 +165,6 @@ namespace Exiv2 {
//! @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).
ByteOrder byteOrder() const { return byteOrder_; }
//! Return the offset of the makernote from the start of the TIFF header
@ -179,24 +176,24 @@ namespace Exiv2 {
the tag.
*/
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
implementation looks up the makernote info tag array if one is
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
stream os. The default implementation prints all tags in the
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;
/*!
@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,
const std::string& model,
CreateFct createMakerNote);
//! Register a %MakerNote prototype in the IFD item registry.
void registerMakerNote(MakerNote* pMakerNote);
//@}
//! @name Accessors
@ -449,6 +449,9 @@ namespace Exiv2 {
long len,
ByteOrder byteOrder,
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;
//! Type used to store a list of make labels and model registries
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
//! Pointer to the one and only instance of this class.
static MakerNoteFactory* pInstance_;
//! List of makernote types and corresponding makernote create functions.
Registry registry_;
//! List of makernote IfdItems and corresponding create functions.
IfdItemRegistry ifdItemRegistry_;
}; // class MakerNoteFactory

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

@ -28,7 +28,7 @@
<a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html">
Exif file format</a> by TsuruZoh Tachibanaya.<BR>
Format 3: "EXIFutils Field Reference Guide".
@version $Name: $ $Revision: 1.5 $
@version $Name: $ $Revision: 1.6 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 17-May-04, ahu: created<BR>
@ -132,6 +132,7 @@ namespace Exiv2 {
{
MakerNoteFactory& mnf = MakerNoteFactory::instance();
mnf.registerMakerNote("NIKON*", "*", createNikonMakerNote);
mnf.registerMakerNote(new Nikon1MakerNote);
}
};
// DATA
@ -206,6 +207,30 @@ namespace Exiv2 {
//@}
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
std::string ifdItem_;
@ -258,6 +283,30 @@ namespace Exiv2 {
//@}
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
std::string ifdItem_;

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

@ -3,19 +3,15 @@
Abstract: Print a simple comma separated list of tags defined in Exiv2
File: taglist.cpp
Version: $Name: $ $Revision: 1.9 $
Version: $Name: $ $Revision: 1.10 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 07-Jan-04, ahu: created
*/
// *****************************************************************************
#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 "nikonmn.hpp"
#include "sigmamn.hpp"
#include "fujimn.hpp"
#include "canonmn.hpp"
#include "tags.hpp"
#include "datasets.hpp"
#include "error.hpp"
@ -39,25 +35,7 @@ try {
break;
}
if (item == "Canon") {
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;
}
pMakerNote = MakerNoteFactory::instance().create(item);
if (pMakerNote) {
pMakerNote->taglist(std::cout);
delete pMakerNote;

@ -20,13 +20,13 @@
*/
/*
File: tags.cpp
Version: $Name: $ $Revision: 1.35 $
Version: $Name: $ $Revision: 1.36 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 15-Jan-04, ahu: created
*/
// *****************************************************************************
#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
@ -35,6 +35,9 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.35 $ $RCSfile: tags.cpp,v $");
#include "types.hpp"
#include "value.hpp"
// Todo: remove circular dependency
#include "exif.hpp" // for TagInfo operator<<
#include <iostream>
#include <iomanip>
#include <sstream>
@ -266,24 +269,26 @@ namespace Exiv2 {
0
};
const char* ExifTags::familyName_ = "Exif";
int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId)
{
const TagInfo* tagInfo = tagInfos_[ifdId];
if (tagInfo == 0) return -1;
int 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);
if (idx == -1) throw Error("No taginfo for IFD");
return tagInfos_[ifdId][idx].name_;
if (idx != -1) 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)
@ -311,13 +316,30 @@ namespace Exiv2 {
uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId)
{
uint16_t tag = 0xffff;
const TagInfo* tagInfo = tagInfos_[ifdId];
if (tagInfo == 0) return 0xffff;
int idx;
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
if (tagInfo[idx].name_ == tagName) break;
if (tagInfo) {
int idx;
for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) {
if (tagInfo[idx].name_ == tagName) break;
}
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 tagInfo[idx].tag_;
return IfdId(i);
}
const char* ExifTags::ifdName(IfdId ifdId)
@ -344,44 +366,6 @@ namespace Exiv2 {
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,
uint16_t tag,
IfdId ifdId,
@ -414,12 +398,13 @@ namespace Exiv2 {
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_) << ", "
<< std::dec << ti.tag_ << ", "
<< "0x" << std::setw(4) << std::setfill('0')
<< std::right << std::hex << ti.tag_ << ", "
<< ExifTags::ifdName(ti.ifdId_) << ", "
<< ExifTags::makeKey(ti.tag_, ti.ifdId_) << ", "
<< exifKey.key() << ", "
<< ExifTags::tagDesc(ti.tag_, ti.ifdId_);
}

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

Loading…
Cancel
Save