Move ExifKey to component tags, moved IptcKey to component datasets

This commit is contained in:
Andreas Huggel 2004-09-29 13:48:55 +00:00
parent 6034d99950
commit 79721d04e0
11 changed files with 428 additions and 426 deletions

View File

@ -3,7 +3,7 @@
# Brief Dot file for a graph showing the component dependencies # Brief Dot file for a graph showing the component dependencies
# of the Exiv2 library. Run the following command to get the image: # of the Exiv2 library. Run the following command to get the image:
# $ dot -Tgif -oexiv2.gif exiv2.dot # $ dot -Tgif -oexiv2.gif exiv2.dot
# Version $Name: $ $Revision: 1.4 $ # Version $Name: $ $Revision: 1.5 $
# 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
@ -15,8 +15,9 @@ L1 [shape=plaintext] ;
L2 [shape=plaintext] ; L2 [shape=plaintext] ;
L3 [shape=plaintext] ; L3 [shape=plaintext] ;
L4 [shape=plaintext] ; L4 [shape=plaintext] ;
L5 [shape=plaintext] ;
"L4" -> "L3" -> "L2" -> "L1" [style=invis] ; "L5" -> "L4" -> "L3" -> "L2" -> "L1" [style=invis] ;
"exif" [shape=box] ; "exif" [shape=box] ;
"iptc" [shape=box] ; "iptc" [shape=box] ;
@ -30,11 +31,9 @@ L4 [shape=plaintext] ;
"error" [shape=box] ; "error" [shape=box] ;
"makernote" [shape=box] ; "makernote" [shape=box] ;
"exif" -> "metadatum" ;
"exif" -> "tags" ; "exif" -> "tags" ;
"exif" -> "makernote" ; "exif" -> "makernote" ;
"exif" -> "image" ; "exif" -> "image" ;
"iptc" -> "metadatum" ;
"iptc" -> "datasets" ; "iptc" -> "datasets" ;
"iptc" -> "image" ; "iptc" -> "image" ;
"metadatum" -> "value" ; "metadatum" -> "value" ;
@ -44,10 +43,8 @@ L4 [shape=plaintext] ;
"ifd" -> "error" ; "ifd" -> "error" ;
"ifd" -> "types" ; "ifd" -> "types" ;
"image" -> "types" ; "image" -> "types" ;
"tags" -> "error" ; "tags" -> "metadatum";
"tags" -> "value" ; "datasets" -> "metadatum" ;
"datasets" -> "error" ;
"datasets" -> "value" ;
"value" -> "types" ; "value" -> "types" ;
{ rank=same; L1 error types } { rank=same; L1 error types }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -86,7 +86,7 @@ own header and source files.</p>
<center> <center>
<h3><a class="anchor">Exiv2 Components Diagram</a></h3> <h3><a class="anchor">Exiv2 Components Diagram</a></h3>
<p><img src="exiv2.gif" width="620" height="369" alt="Exiv2 components diagram"></p> <p><img src="exiv2.gif" width="470" height="465" alt="Exiv2 components diagram"></p>
</center> </center>
<p>&nbsp;</p> <p>&nbsp;</p>

View File

@ -20,13 +20,13 @@
*/ */
/* /*
File: datasets.cpp File: datasets.cpp
Version: $Name: $ $Revision: 1.6 $ Version: $Name: $ $Revision: 1.7 $
Author(s): Brad Schick (brad) <schick@robotbattle.com> Author(s): Brad Schick (brad) <schick@robotbattle.com>
History: 24-Jul-04, brad: created History: 24-Jul-04, brad: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.6 $ $RCSfile: datasets.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.7 $ $RCSfile: datasets.cpp,v $");
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -34,14 +34,12 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.6 $ $RCSfile: datasets.cpp,v $");
#include "error.hpp" #include "error.hpp"
#include "types.hpp" #include "types.hpp"
#include "value.hpp" #include "value.hpp"
#include "metadatum.hpp"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
// Todo: remove circular dependency
#include "iptc.hpp" // for DataSet operator<<
// ***************************************************************************** // *****************************************************************************
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
@ -291,6 +289,77 @@ namespace Exiv2 {
} }
} // IptcDataSets::dataSetList } // IptcDataSets::dataSetList
const char* IptcKey::familyName_ = "Iptc";
IptcKey::IptcKey(const std::string& key)
: key_(key)
{
decomposeKey();
}
IptcKey::IptcKey(uint16_t tag, uint16_t record)
: tag_(tag), record_(record)
{
makeKey();
}
IptcKey::IptcKey(const IptcKey& rhs)
: tag_(rhs.tag_), record_(rhs.record_), key_(rhs.key_)
{
}
IptcKey& IptcKey::operator=(const IptcKey& rhs)
{
if (this == &rhs) return *this;
Key::operator=(rhs);
tag_ = rhs.tag_;
record_ = rhs.record_;
key_ = rhs.key_;
return *this;
}
IptcKey* IptcKey::clone() const
{
return new IptcKey(*this);
}
void IptcKey::decomposeKey()
{
// Get the family name, record name and dataSet 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 recordName = key_.substr(pos0, pos1 - pos0);
if (recordName == "") throw Error("Invalid key");
std::string dataSetName = key_.substr(pos1 + 1);
if (dataSetName == "") throw Error("Invalid key");
// Use the parts of the key to find dataSet and recordId
uint16_t recId = IptcDataSets::recordId(recordName);
uint16_t dataSet = IptcDataSets::dataSet(dataSetName, recId);
// Possibly translate hex name parts (0xabcd) to real names
recordName = IptcDataSets::recordName(recId);
dataSetName = IptcDataSets::dataSetName(dataSet, recId);
tag_ = dataSet;
record_ = recId;
key_ = familyName + "." + recordName + "." + dataSetName;
} // IptcKey::decomposeKey
void IptcKey::makeKey()
{
key_ = std::string(familyName_)
+ "." + IptcDataSets::recordName(record_)
+ "." + IptcDataSets::dataSetName(tag_, record_);
}
// ************************************************************************* // *************************************************************************
// free functions // free functions

View File

@ -21,7 +21,7 @@
/*! /*!
@file datasets.hpp @file datasets.hpp
@brief Iptc dataSet and type information @brief Iptc dataSet and type information
@version $Name: $ $Revision: 1.5 $ @version $Name: $ $Revision: 1.6 $
@author Brad Schick (brad) <schick@robotbattle.com> @author Brad Schick (brad) <schick@robotbattle.com>
@date 24-Jul-04, brad: created @date 24-Jul-04, brad: created
*/ */
@ -31,6 +31,7 @@
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#include "types.hpp" #include "types.hpp"
#include "metadatum.hpp"
// + standard includes // + standard includes
#include <string> #include <string>
@ -256,6 +257,89 @@ namespace Exiv2 {
}; // class IptcDataSets }; // class IptcDataSets
/*!
@brief Concrete keys for Iptc metadata.
*/
class IptcKey : public Key {
public:
//! @name Creators
//@{
/*!
@brief Constructor to create an Iptc key from a key string.
@param key The key string.
@throw Error ("Invalid key") if the first part of the key is not
'Iptc' or the remaining parts of the key cannot be parsed and
converted to a record name and a dataset name.
*/
explicit IptcKey(const std::string& key);
/*!
@brief Constructor to create an Iptc key from dataset and record ids.
@param tag Dataset id
@param record Record id
*/
IptcKey(uint16_t tag, uint16_t record);
//! Copy constructor
IptcKey(const IptcKey& rhs);
//@}
//! @name Manipulators
//@{
/*!
@brief Assignment operator.
*/
IptcKey& operator=(const IptcKey& rhs);
//@}
//! @name Accessors
//@{
virtual std::string key() const { return key_; }
virtual const char* familyName() const { return familyName_; }
/*!
@brief Return the name of the group (the second part of the key).
For Iptc keys, the group name is the record name.
*/
virtual std::string groupName() const { return recordName(); }
virtual std::string tagName() const
{ return IptcDataSets::dataSetName(tag_, record_); }
virtual uint16_t tag() const { return tag_; }
virtual IptcKey* clone() const;
//! Return the name of the record
std::string recordName() const
{ return IptcDataSets::recordName(record_); }
//! Return the record id
uint16_t record() const { return record_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
@brief Set the key corresponding to the dataset and record id.
The key is of the form '<b>Iptc</b>.recordName.dataSetName'.
*/
void makeKey();
/*!
@brief Parse and convert the key string into dataset and record id.
Updates data members if the string can be decomposed, or throws
Error ("Invalid key").
@throw Error ("Invalid key") if the key cannot be decomposed.
*/
void decomposeKey();
//@}
private:
// DATA
static const char* familyName_;
uint16_t tag_; //!< Tag value
uint16_t record_; //!< Record value
std::string key_; //!< Key
}; // class IptcKey
// ***************************************************************************** // *****************************************************************************
// free functions // free functions

View File

@ -20,14 +20,14 @@
*/ */
/* /*
File: exif.cpp File: exif.cpp
Version: $Name: $ $Revision: 1.62 $ Version: $Name: $ $Revision: 1.63 $
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.62 $ $RCSfile: exif.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.63 $ $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,158 +73,6 @@ namespace {
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
const char* ExifKey::familyName_ = "Exif";
ExifKey::ExifKey(const std::string& 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()), 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_), 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)
{
if (this == &rhs) return *this;
Key::operator=(rhs);
tag_ = rhs.tag_;
ifdId_ = rhs.ifdId_;
ifdItem_ = rhs.ifdItem_;
idx_ = rhs.idx_;
pMakerNote_ = rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0;
key_ = rhs.key_;
return *this;
}
std::string ExifKey::tagName() const
{
if (ifdId_ == makerIfdId) {
assert(pMakerNote_);
return pMakerNote_->tagName(tag_);
}
return ExifTags::tagName(tag_, ifdId_);
}
ExifKey* ExifKey::clone() const
{
return new ExifKey(*this);
}
std::string ExifKey::sectionName() const
{
if (ifdId_ == makerIfdId) {
assert(pMakerNote_);
return pMakerNote_->ifdItem();
}
return ExifTags::sectionName(tag(), ifdId());
}
void ExifKey::decomposeKey()
{
// 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);
if (ifdItem == "") throw Error("Invalid key");
std::string tagName = key_.substr(pos1 + 1);
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) {
assert(pMakerNote_);
return pMakerNote_->printTag(os, tag(), value);
}
return ExifTags::printTag(os, tag(), ifdId(), value);
}
Exifdatum::Exifdatum(const Entry& e, ByteOrder byteOrder) Exifdatum::Exifdatum(const Entry& e, ByteOrder byteOrder)
: pKey_(new ExifKey(e)), pValue_(0) : pKey_(new ExifKey(e)), pValue_(0)
{ {

View File

@ -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.54 $ @version $Name: $ $Revision: 1.55 $
@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
@ -60,101 +60,6 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
//! Concrete keys for Exif metadata.
class ExifKey : public Key {
public:
//! @name Creators
//@{
/*!
@brief Constructor to create an Exif key from a key string.
@param key The key string.
@throw Error ("Invalid key") if the key cannot be parsed into three
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);
virtual ~ExifKey();
//@}
//! @name Manipulators
//@{
/*!
@brief Assignment operator.
*/
ExifKey& operator=(const ExifKey& rhs);
//@}
//! @name Accessors
//@{
virtual std::string key() const { return key_; }
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 item.
*/
virtual std::string groupName() const { return ifdItem(); }
virtual std::string tagName() 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;
//! 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
std::string ifdItem() const { return ifdItem_; }
//! Return the name of the Exif section (deprecated)
std::string sectionName() const;
//! Return the index (unique id of this key within the original IFD)
int idx() const { return idx_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
@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 members if the string can be decomposed,
or throws Error ("Invalid key").
@throw Error ("Invalid key") if the key cannot be decomposed.
*/
void decomposeKey();
//@}
private:
// DATA
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
}; // class ExifKey
/*! /*!
@brief Information related to one Exif tag. @brief Information related to one Exif tag.
*/ */

View File

@ -20,13 +20,13 @@
*/ */
/* /*
File: iptc.cpp File: iptc.cpp
Version: $Name: $ $Revision: 1.5 $ Version: $Name: $ $Revision: 1.6 $
Author(s): Brad Schick (brad) <schick@robotbattle.com> Author(s): Brad Schick (brad) <schick@robotbattle.com>
History: 31-July-04, brad: created History: 31-July-04, brad: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.5 $ $RCSfile: iptc.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.6 $ $RCSfile: iptc.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
@ -48,77 +48,6 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.5 $ $RCSfile: iptc.cpp,v $");
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
const char* IptcKey::familyName_ = "Iptc";
IptcKey::IptcKey(const std::string& key)
: key_(key)
{
decomposeKey();
}
IptcKey::IptcKey(uint16_t tag, uint16_t record)
: tag_(tag), record_(record)
{
makeKey();
}
IptcKey::IptcKey(const IptcKey& rhs)
: tag_(rhs.tag_), record_(rhs.record_), key_(rhs.key_)
{
}
IptcKey& IptcKey::operator=(const IptcKey& rhs)
{
if (this == &rhs) return *this;
Key::operator=(rhs);
tag_ = rhs.tag_;
record_ = rhs.record_;
key_ = rhs.key_;
return *this;
}
IptcKey* IptcKey::clone() const
{
return new IptcKey(*this);
}
void IptcKey::decomposeKey()
{
// Get the family name, record name and dataSet 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 recordName = key_.substr(pos0, pos1 - pos0);
if (recordName == "") throw Error("Invalid key");
std::string dataSetName = key_.substr(pos1 + 1);
if (dataSetName == "") throw Error("Invalid key");
// Use the parts of the key to find dataSet and recordId
uint16_t recId = IptcDataSets::recordId(recordName);
uint16_t dataSet = IptcDataSets::dataSet(dataSetName, recId);
// Possibly translate hex name parts (0xabcd) to real names
recordName = IptcDataSets::recordName(recId);
dataSetName = IptcDataSets::dataSetName(dataSet, recId);
tag_ = dataSet;
record_ = recId;
key_ = familyName + "." + recordName + "." + dataSetName;
} // IptcKey::decomposeKey
void IptcKey::makeKey()
{
key_ = std::string(familyName_)
+ "." + IptcDataSets::recordName(record_)
+ "." + IptcDataSets::dataSetName(tag_, record_);
}
Iptcdatum::Iptcdatum(const IptcKey& key, Iptcdatum::Iptcdatum(const IptcKey& key,
const Value* value) const Value* value)
: pKey_(key.clone()), pValue_(0), modified_(false) : pKey_(key.clone()), pValue_(0), modified_(false)

View File

@ -21,7 +21,7 @@
/*! /*!
@file iptc.hpp @file iptc.hpp
@brief Encoding and decoding of Iptc data @brief Encoding and decoding of Iptc data
@version $Name: $ $Revision: 1.6 $ @version $Name: $ $Revision: 1.7 $
@author Brad Schick (brad) @author Brad Schick (brad)
<a href="mailto:schick@robotbattle.com">schick@robotbattle.com</a> <a href="mailto:schick@robotbattle.com">schick@robotbattle.com</a>
@date 31-Jul-04, brad: created @date 31-Jul-04, brad: created
@ -48,87 +48,6 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
//! Concrete keys for Iptc metadata.
class IptcKey : public Key {
public:
//! @name Creators
//@{
/*!
@brief Constructor to create an Iptc key from a key string.
@param key The key string.
@throw Error ("Invalid key") if the first part of the key is not
'Iptc' or the remaining parts of the key cannot be parsed and
converted to a record name and a dataset name.
*/
explicit IptcKey(const std::string& key);
/*!
@brief Constructor to create an Iptc key from dataset and record ids.
@param tag Dataset id
@param record Record id
*/
IptcKey(uint16_t tag, uint16_t record);
//! Copy constructor
IptcKey(const IptcKey& rhs);
//@}
//! @name Manipulators
//@{
/*!
@brief Assignment operator.
*/
IptcKey& operator=(const IptcKey& rhs);
//@}
//! @name Accessors
//@{
virtual std::string key() const { return key_; }
virtual const char* familyName() const { return familyName_; }
/*!
@brief Return the name of the group (the second part of the key).
For Iptc keys, the group name is the record name.
*/
virtual std::string groupName() const { return recordName(); }
virtual std::string tagName() const
{ return IptcDataSets::dataSetName(tag_, record_); }
virtual uint16_t tag() const { return tag_; }
virtual IptcKey* clone() const;
//! Return the name of the record
std::string recordName() const
{ return IptcDataSets::recordName(record_); }
//! Return the record id
uint16_t record() const { return record_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
@brief Set the key corresponding to the dataset and record id.
The key is of the form '<b>Iptc</b>.recordName.dataSetName'.
*/
void makeKey();
/*!
@brief Parse and convert the key string into dataset and record id.
Updates data members if the string can be decomposed, or throws
Error ("Invalid key").
@throw Error ("Invalid key") if the key cannot be decomposed.
*/
void decomposeKey();
//@}
private:
// DATA
static const char* familyName_;
uint16_t tag_; //!< Tag value
uint16_t record_; //!< Record value
std::string key_; //!< Key
}; // class IptcKey
/*! /*!
@brief Information related to one Iptc dataset. @brief Information related to one Iptc dataset.
*/ */

View File

@ -20,23 +20,22 @@
*/ */
/* /*
File: tags.cpp File: tags.cpp
Version: $Name: $ $Revision: 1.36 $ Version: $Name: $ $Revision: 1.37 $
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.36 $ $RCSfile: tags.cpp,v $"); EXIV2_RCSID("@(#) $Name: $ $Revision: 1.37 $ $RCSfile: tags.cpp,v $");
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#include "tags.hpp" #include "tags.hpp"
#include "error.hpp" #include "error.hpp"
#include "types.hpp" #include "types.hpp"
#include "ifd.hpp"
#include "value.hpp" #include "value.hpp"
#include "makernote.hpp"
// Todo: remove circular dependency
#include "exif.hpp" // for TagInfo operator<<
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
@ -392,6 +391,158 @@ namespace Exiv2 {
os << gpsTagInfo[i] << "\n"; os << gpsTagInfo[i] << "\n";
} }
} // ExifTags::taglist } // ExifTags::taglist
const char* ExifKey::familyName_ = "Exif";
ExifKey::ExifKey(const std::string& 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()), 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_), 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)
{
if (this == &rhs) return *this;
Key::operator=(rhs);
tag_ = rhs.tag_;
ifdId_ = rhs.ifdId_;
ifdItem_ = rhs.ifdItem_;
idx_ = rhs.idx_;
pMakerNote_ = rhs.pMakerNote_ ? rhs.pMakerNote_->clone() : 0;
key_ = rhs.key_;
return *this;
}
std::string ExifKey::tagName() const
{
if (ifdId_ == makerIfdId) {
assert(pMakerNote_);
return pMakerNote_->tagName(tag_);
}
return ExifTags::tagName(tag_, ifdId_);
}
ExifKey* ExifKey::clone() const
{
return new ExifKey(*this);
}
std::string ExifKey::sectionName() const
{
if (ifdId_ == makerIfdId) {
assert(pMakerNote_);
return pMakerNote_->ifdItem();
}
return ExifTags::sectionName(tag(), ifdId());
}
void ExifKey::decomposeKey()
{
// 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);
if (ifdItem == "") throw Error("Invalid key");
std::string tagName = key_.substr(pos1 + 1);
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) {
assert(pMakerNote_);
return pMakerNote_->printTag(os, tag(), value);
}
return ExifTags::printTag(os, tag(), ifdId(), value);
}
// ************************************************************************* // *************************************************************************
// free functions // free functions

View File

@ -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.27 $ @version $Name: $ $Revision: 1.28 $
@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>
@ -32,6 +32,7 @@
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#include "metadatum.hpp"
#include "types.hpp" #include "types.hpp"
// + standard includes // + standard includes
@ -46,6 +47,8 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// class declarations // class declarations
class Value; class Value;
class Entry;
class MakerNote;
// ***************************************************************************** // *****************************************************************************
// type definitions // type definitions
@ -192,6 +195,103 @@ namespace Exiv2 {
}; // class ExifTags }; // class ExifTags
/*!
@brief Concrete keys for Exif metadata.
*/
class ExifKey : public Key {
public:
//! @name Creators
//@{
/*!
@brief Constructor to create an Exif key from a key string.
@param key The key string.
@throw Error ("Invalid key") if the key cannot be parsed into three
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);
virtual ~ExifKey();
//@}
//! @name Manipulators
//@{
/*!
@brief Assignment operator.
*/
ExifKey& operator=(const ExifKey& rhs);
//@}
//! @name Accessors
//@{
virtual std::string key() const { return key_; }
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 item.
*/
virtual std::string groupName() const { return ifdItem(); }
virtual std::string tagName() 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;
//! 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
std::string ifdItem() const { return ifdItem_; }
//! Return the name of the Exif section (deprecated)
std::string sectionName() const;
//! Return the index (unique id of this key within the original IFD)
int idx() const { return idx_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
@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 members if the string can be decomposed,
or throws Error ("Invalid key").
@throw Error ("Invalid key") if the key cannot be decomposed.
*/
void decomposeKey();
//@}
private:
// DATA
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
}; // class ExifKey
// ***************************************************************************** // *****************************************************************************
// free functions // free functions