Added Key, ExifKey and IptcKey class hierarchy

Changed Exif keys to 'Exif.ifdItem.tagName'
v0.27.3
Andreas Huggel 21 years ago
parent 84a121bbe2
commit 0147a77c7b

@ -20,13 +20,13 @@
*/
/*
File: actions.cpp
Version: $Name: $ $Revision: 1.32 $
Version: $Name: $ $Revision: 1.33 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 08-Dec-03, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.32 $ $RCSfile: actions.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.33 $ $RCSfile: actions.cpp,v $");
// *****************************************************************************
// included header files
@ -163,25 +163,26 @@ namespace Action {
}
// Camera make
printTag(exifData, "Image.OtherTags.Make", "Camera make");
printTag(exifData, "Exif.Image.Make", "Camera make");
// Camera model
printTag(exifData, "Image.OtherTags.Model", "Camera model");
printTag(exifData, "Exif.Image.Model", "Camera model");
// Image Timestamp
printTag(exifData, "Image.DateTime.DateTimeOriginal", "Image timestamp");
printTag(exifData, "Exif.Photo.DateTimeOriginal", "Image timestamp");
// Image number
// Todo: Image number for cameras other than Canon
printTag(exifData, "Makernote.Canon.ImageNumber", "Image number");
printTag(exifData, "Exif.Canon.ImageNumber", "Image number");
// Exposure time
// From ExposureTime, failing that, try ShutterSpeedValue
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Exposure time" << ": ";
Exiv2::ExifData::const_iterator md;
if (0 == printTag(exifData, "Image.CaptureConditions.ExposureTime")) {
md = exifData.findKey("Image.CaptureConditions.ShutterSpeedValue");
if (0 == printTag(exifData, "Exif.Photo.ExposureTime")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Photo.ShutterSpeedValue"));
if (md != exifData.end()) {
double tmp = exp(log(2.0) * md->toFloat()) + 0.5;
if (tmp > 1) {
@ -198,8 +199,9 @@ namespace Action {
// Get if from FNumber and, failing that, try ApertureValue
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Aperture" << ": ";
if (0 == printTag(exifData, "Image.CaptureConditions.FNumber")) {
md = exifData.findKey("Image.CaptureConditions.ApertureValue");
if (0 == printTag(exifData, "Exif.Photo.FNumber")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Photo.ApertureValue"));
if (md != exifData.end()) {
std::cout << std::fixed << std::setprecision(1)
<< "F" << exp(log(2.0) * md->toFloat() / 2);
@ -208,16 +210,16 @@ namespace Action {
std::cout << "\n";
// Exposure bias
printTag(exifData, "Image.CaptureConditions.ExposureBiasValue", "Exposure bias");
printTag(exifData, "Exif.Photo.ExposureBiasValue", "Exposure bias");
// Flash
printTag(exifData, "Image.CaptureConditions.Flash", "Flash");
printTag(exifData, "Exif.Photo.Flash", "Flash");
// Todo: Flash bias, flash energy
// Todo: Implement this for other cameras
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Flash bias" << ": ";
md = exifData.findKey("Makernote.Canon.CameraSettings2");
md = exifData.findKey(Exiv2::ExifKey("Exif.Canon.CameraSettings2"));
if (md != exifData.end() && md->count() >= 15) {
Exiv2::CanonMakerNote::print0x0004_15(std::cout, md->toLong(15));
}
@ -227,8 +229,9 @@ namespace Action {
// Todo: Calculate 35 mm equivalent a la jhead
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Focal length" << ": ";
if (1 == printTag(exifData, "Image.CaptureConditions.FocalLength")) {
md = exifData.findKey("Image.CaptureConditions.FocalLengthIn35mmFilm");
if (1 == printTag(exifData, "Exif.Photo.FocalLength")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Photo.FocalLengthIn35mmFilm"));
if (md != exifData.end()) {
std::cout << " (35 mm equivalent: " << *md << ")";
}
@ -238,8 +241,9 @@ namespace Action {
// Subject distance
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Subject distance" << ": ";
if (0 == printTag(exifData, "Image.CaptureConditions.SubjectDistance")) {
md = exifData.findKey("Makernote.Canon.CameraSettings2");
if (0 == printTag(exifData, "Exif.Photo.SubjectDistance")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Canon.CameraSettings2"));
if (md != exifData.end() && md->count() >= 19) {
Exiv2::CanonMakerNote::print0x0004_19(std::cout, md->toLong(19));
}
@ -251,20 +255,21 @@ namespace Action {
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "ISO speed" << ": ";
bool done = false;
if (0 == printTag(exifData, "Image.CaptureConditions.ISOSpeedRatings")) {
md = exifData.findKey("Makernote.Canon.CameraSettings1");
if (0 == printTag(exifData, "Exif.Photo.ISOSpeedRatings")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Canon.CameraSettings1"));
if (md != exifData.end() && md->count() >= 16) {
Exiv2::CanonMakerNote::print0x0001_16(std::cout, md->toLong(16));
done = true;
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon1.ISOSpeed");
done = printTag(exifData, "Exif.Nikon1.ISOSpeed");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon2.ISOSpeed");
done = printTag(exifData, "Exif.Nikon2.ISOSpeed");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon3.ISOSpeed");
done = printTag(exifData, "Exif.Nikon3.ISOSpeed");
}
}
std::cout << "\n";
@ -273,8 +278,9 @@ namespace Action {
// From ExposureProgram or Canon Makernote
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Exposure mode" << ": ";
if (0 == printTag(exifData, "Image.CaptureConditions.ExposureProgram")) {
md = exifData.findKey("Makernote.Canon.CameraSettings1");
if (0 == printTag(exifData, "Exif.Photo.ExposureProgram")) {
md = exifData.findKey(
Exiv2::ExifKey("Exif.Canon.CameraSettings1"));
if (md != exifData.end() && md->count() >= 20) {
Exiv2::CanonMakerNote::print0x0001_20(std::cout, md->toLong(20));
}
@ -282,20 +288,21 @@ namespace Action {
std::cout << "\n";
// Metering mode
printTag(exifData, "Image.CaptureConditions.MeteringMode", "Metering mode");
printTag(exifData, "Exif.Photo.MeteringMode", "Metering mode");
// Macro mode
// Todo: Implement this for other cameras
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Macro mode" << ": ";
done = false;
md = exifData.findKey("Makernote.Canon.CameraSettings1");
md = exifData.findKey(
Exiv2::ExifKey("Exif.Canon.CameraSettings1"));
if (md != exifData.end() && md->count() >= 1) {
Exiv2::CanonMakerNote::print0x0001_01(std::cout, md->toLong(1));
done = true;
}
if (!done) {
done = printTag(exifData, "Makernote.Fujifilm.Macro");
done = printTag(exifData, "Exif.Fujifilm.Macro");
}
std::cout << "\n";
@ -304,25 +311,25 @@ namespace Action {
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "Image quality" << ": ";
done = false;
md = exifData.findKey("Makernote.Canon.CameraSettings1");
md = exifData.findKey(Exiv2::ExifKey("Exif.Canon.CameraSettings1"));
if (md != exifData.end() && md->count() >= 3) {
Exiv2::CanonMakerNote::print0x0001_03(std::cout, md->toLong(3));
done = true;
}
if (!done) {
done = printTag(exifData, "Makernote.Fujifilm.Quality");
done = printTag(exifData, "Exif.Fujifilm.Quality");
}
if (!done) {
done = printTag(exifData, "Makernote.Sigma.Quality");
done = printTag(exifData, "Exif.Sigma.Quality");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon1.Quality");
done = printTag(exifData, "Exif.Nikon1.Quality");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon2.Quality");
done = printTag(exifData, "Exif.Nikon2.Quality");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon3.Quality");
done = printTag(exifData, "Exif.Nikon3.Quality");
}
std::cout << "\n";
@ -331,9 +338,9 @@ namespace Action {
<< "Exif Resolution" << ": ";
long xdim = 0;
long ydim = 0;
md = exifData.findKey("Image.ImageConfig.PixelXDimension");
md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
if (md != exifData.end()) xdim = md->toLong();
md = exifData.findKey("Image.ImageConfig.PixelYDimension");
md = exifData.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
if (md != exifData.end()) ydim = md->toLong();
if (xdim != 0 && ydim != 0) {
std::cout << xdim << " x " << ydim;
@ -345,25 +352,25 @@ namespace Action {
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< "White balance" << ": ";
done = false;
md = exifData.findKey("Makernote.Canon.CameraSettings2");
md = exifData.findKey(Exiv2::ExifKey("Exif.Canon.CameraSettings2"));
if (md != exifData.end() && md->count() >= 7) {
Exiv2::CanonMakerNote::print0x0004_07(std::cout, md->toLong(7));
done = true;
}
if (!done) {
done = printTag(exifData, "Makernote.Fujifilm.WhiteBalance");
done = printTag(exifData, "Exif.Fujifilm.WhiteBalance");
}
if (!done) {
done = printTag(exifData, "Makernote.Sigma.WhiteBalance");
done = printTag(exifData, "Exif.Sigma.WhiteBalance");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon1.WhiteBalance");
done = printTag(exifData, "Exif.Nikon1.WhiteBalance");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon2.WhiteBalance");
done = printTag(exifData, "Exif.Nikon2.WhiteBalance");
}
if (!done) {
done = printTag(exifData, "Makernote.Nikon3.WhiteBalance");
done = printTag(exifData, "Exif.Nikon3.WhiteBalance");
}
std::cout << "\n";
@ -381,10 +388,10 @@ namespace Action {
std::cout << "\n";
// Copyright
printTag(exifData, "Image.OtherTags.Copyright", "Copyright");
printTag(exifData, "Exif.Image.Copyright", "Copyright");
// Exif Comment
printTag(exifData, "Image.UserInfo.UserComment", "Exif comment");
printTag(exifData, "Exif.Photo.UserComment", "Exif comment");
std::cout << std::endl;
} // Print::printSummary
@ -399,7 +406,8 @@ namespace Action {
std::cout << std::setw(align_) << std::setfill(' ') << std::left
<< label << ": ";
}
Exiv2::ExifData::const_iterator md = exifData.findKey(key);
Exiv2::ExifKey ek(key);
Exiv2::ExifData::const_iterator md = exifData.findKey(ek);
if (md != exifData.end()) {
std::cout << *md;
rc = 1;
@ -484,7 +492,7 @@ namespace Action {
std::cerr << Exiv2::ExifData::strError(rc, path) << "\n";
return rc;
}
std::string key = "Image.DateTime.DateTimeOriginal";
Exiv2::ExifKey key("Exif.Photo.DateTimeOriginal");
Exiv2::ExifData::iterator md = exifData.findKey(key);
if (md == exifData.end()) {
std::cerr << "Metadatum with key `" << key << "' "
@ -753,9 +761,9 @@ namespace Action {
std::cerr << Exiv2::ExifData::strError(rc, path) << "\n";
return rc;
}
rc = adjustDateTime(exifData, "Image.OtherTags.DateTime", path);
rc += adjustDateTime(exifData, "Image.DateTime.DateTimeOriginal", path);
rc += adjustDateTime(exifData, "Image.DateTime.DateTimeDigitized", path);
rc = adjustDateTime(exifData, "Exif.Image.DateTime", path);
rc += adjustDateTime(exifData, "Exif.Photo.DateTimeOriginal", path);
rc += adjustDateTime(exifData, "Exif.Photo.DateTimeDigitized", path);
if (rc) return 1;
rc = exifData.write(path);
if (rc) {
@ -784,7 +792,8 @@ namespace Action {
const std::string& key,
const std::string& path) const
{
Exiv2::ExifData::iterator md = exifData.findKey(key);
Exiv2::ExifKey ek(key);
Exiv2::ExifData::iterator md = exifData.findKey(ek);
if (md == exifData.end()) {
// Key not found. That's ok, we do nothing.
return 0;
@ -792,7 +801,7 @@ namespace Action {
std::string timeStr = md->toString();
if (timeStr == "" || timeStr[0] == ' ') {
std::cerr << path << ": Timestamp of metadatum with key `"
<< key << "' not set\n";
<< ek << "' not set\n";
return 1;
}
time_t time = str2Time(timeStr);
@ -802,7 +811,7 @@ namespace Action {
return 1;
}
if (Params::instance().verbose_) {
std::cout << "Adjusting `" << key << "' by"
std::cout << "Adjusting `" << ek << "' by"
<< (adjustment_ < 0 ? " " : " +")
<< adjustment_ << " s to ";
}

@ -3,7 +3,7 @@
Abstract: Sample program showing how to add, modify and delete Exif metadata.
File: addmoddel.cpp
Version: $Name: $ $Revision: 1.3 $
Version: $Name: $ $Revision: 1.4 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created
*/
@ -28,7 +28,7 @@ try {
// Set the value to a string
v->read("1999:12:31 23:59:59");
// Add the value together with its key to the Exif data container
std::string key = "Image.DateTime.DateTimeOriginal";
Exiv2::ExifKey key("Exif.Photo.DateTimeOriginal");
exifData.add(key, v);
std::cout << "Added key \"" << key << "\", value \"" << *v << "\"\n";
@ -43,7 +43,7 @@ try {
rv->value_.push_back(std::make_pair(2,3));
rv->value_.push_back(std::make_pair(3,4));
// Add the key and value pair to the Exif data
key = "Image.ImageCharacteristics.PrimaryChromaticities";
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
exifData.add(key, rv);
std::cout << "Added key \"" << key << "\", value \"" << *rv << "\"\n";
@ -54,7 +54,7 @@ try {
// Modify Exif data
// Find the timestamp metadatum by its key
key = "Image.DateTime.DateTimeOriginal";
key = Exiv2::ExifKey("Exif.Photo.DateTimeOriginal");
Exiv2::ExifData::iterator pos = exifData.findKey(key);
if (pos == exifData.end()) throw Exiv2::Error("Key not found");
// Modify the value
@ -65,7 +65,7 @@ try {
<< "\", new value \"" << pos->value() << "\"\n";
// Find the other key
key = "Image.ImageCharacteristics.PrimaryChromaticities";
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
pos = exifData.findKey(key);
if (pos == exifData.end()) throw Exiv2::Error("Key not found");
// Get a pointer to a copy of the value
@ -86,7 +86,7 @@ try {
// Delete metadata from the Exif data container
// Delete the metadatum at iterator position pos
key = "Image.ImageCharacteristics.PrimaryChromaticities";
key = Exiv2::ExifKey("Exif.Image.PrimaryChromaticities");
pos = exifData.findKey(key);
if (pos == exifData.end()) throw Exiv2::Error("Key not found");
exifData.erase(pos);

@ -20,7 +20,7 @@
*/
/*
File: canonmn.cpp
Version: $Name: $ $Revision: 1.12 $
Version: $Name: $ $Revision: 1.13 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created
07-Mar-04, ahu: isolated as a separate component
@ -30,7 +30,7 @@
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.12 $ $RCSfile: canonmn.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.13 $ $RCSfile: canonmn.cpp,v $");
// *****************************************************************************
// included header files
@ -68,7 +68,7 @@ namespace Exiv2 {
};
CanonMakerNote::CanonMakerNote(bool alloc)
: IfdMakerNote(canonMnTagInfo, alloc), sectionName_("Canon")
: IfdMakerNote(canonMnTagInfo, alloc), ifdItem_("Canon")
{
}

@ -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.9 $
@version $Name: $ $Revision: 1.10 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created<BR>
@ -98,8 +98,8 @@ namespace Exiv2 {
//! @name Accessors
//@{
CanonMakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Canon")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Canon")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -193,8 +193,8 @@ namespace Exiv2 {
*/
static const RegisterMakerNote register_;
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class CanonMakerNote

@ -20,13 +20,13 @@
*/
/*
File: datasets.cpp
Version: $Name: $ $Revision: 1.3 $
Version: $Name: $ $Revision: 1.4 $
Author(s): Brad Schick (brad) <schick@robotbattle.com>
History: 24-Jul-04, brad: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.3 $ $RCSfile: datasets.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.4 $ $RCSfile: datasets.cpp,v $");
// *****************************************************************************
// included header files
@ -162,6 +162,8 @@ namespace Exiv2 {
0
};
const char* IptcDataSets::familyName_ = "Iptc";
int IptcDataSets::dataSetIdx(uint16 number, uint16 recordId)
{
if( recordId != envelope && recordId != application2 ) return -1;
@ -248,13 +250,15 @@ namespace Exiv2 {
std::string IptcDataSets::makeKey(const DataSet& dataSet)
{
return "Iptc." + std::string(recordName(dataSet.recordId_))
return std::string(familyName())
+ "." + std::string(recordName(dataSet.recordId_))
+ "." + dataSet.name_;
}
std::string IptcDataSets::makeKey(uint16 number, uint16 recordId)
{
return "Iptc." + std::string(recordName(recordId))
return std::string(familyName())
+ "." + std::string(recordName(recordId))
+ "." + std::string(dataSetName(number, recordId));
}

@ -21,7 +21,7 @@
/*!
@file datasets.hpp
@brief Iptc dataSet and type information
@version $Name: $ $Revision: 1.2 $
@version $Name: $ $Revision: 1.3 $
@author Brad Schick (brad) <schick@robotbattle.com>
@date 24-Jul-04, brad: created
*/
@ -171,7 +171,10 @@ namespace Exiv2 {
static const uint16 PreviewVersion = 201;
static const uint16 Preview = 202;
//@}
private:
static const char* familyName_;
private:
//! Prevent construction: not implemented.
IptcDataSets() {}
@ -181,6 +184,8 @@ namespace Exiv2 {
IptcDataSets& operator=(const IptcDataSets& rhs);
public:
//! Return an identifier for Iptc datasets
static const char* familyName() { return familyName_; }
/*!
@brief Return the name of the dataset.
@param number The dataset number
@ -240,12 +245,12 @@ namespace Exiv2 {
static uint16 recordId(const std::string& recordName);
/*!
@brief Return the key for the dataSet number and record id. The key is
of the form 'recordName.dataSetName'.
of the form '<b>Iptc</b>.recordName.dataSetName'.
*/
static std::string makeKey(uint16 number, uint16 recordId);
/*!
@brief Return the key for the dataSet. The key is of the form
'recordName.dataSetName'.
'<b>Iptc</b>.recordName.dataSetName'.
*/
static std::string makeKey(const DataSet& dataSet);
/*!

@ -20,14 +20,14 @@
*/
/*
File: exif.cpp
Version: $Name: $ $Revision: 1.53 $
Version: $Name: $ $Revision: 1.54 $
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.53 $ $RCSfile: exif.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.54 $ $RCSfile: exif.cpp,v $");
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@ -73,37 +73,127 @@ namespace {
// class member definitions
namespace Exiv2 {
Exifdatum::Exifdatum(const Entry& e, ByteOrder byteOrder)
ExifKey::ExifKey(const std::string& key)
: idx_(0), pMakerNote_(0), key_(key)
{
decomposeKey();
}
ExifKey::ExifKey(const Entry& e)
: tag_(e.tag()), ifdId_(e.ifdId()), idx_(e.idx()),
pMakerNote_(e.makerNote()), pValue_(0), key_(makeKey(e))
pMakerNote_(e.makerNote()), key_(makeKey(e))
{
pValue_ = Value::create(TypeId(e.type()));
pValue_->read(e.data(), e.count() * e.typeSize(), byteOrder);
}
Exifdatum::Exifdatum(const std::string& key,
const Value* value,
MakerNote* makerNote)
: idx_(0), pMakerNote_(makerNote), pValue_(0), key_(key)
ExifKey::ExifKey(const ExifKey& rhs)
: tag_(rhs.tag_), ifdId_(rhs.ifdId_), idx_(rhs.idx_),
pMakerNote_(rhs.pMakerNote_), key_(rhs.key_)
{
}
ExifKey& ExifKey::operator=(const ExifKey& rhs)
{
if (this == &rhs) return *this;
Key::operator=(rhs);
tag_ = rhs.tag_;
ifdId_ = rhs.ifdId_;
idx_ = rhs.idx_;
pMakerNote_ = rhs.pMakerNote_;
key_ = rhs.key_;
return *this;
}
void ExifKey::setMakerNote(MakerNote* pMakerNote)
{
if (ifdId_ == makerIfd && pMakerNote_ != pMakerNote) {
pMakerNote_ = pMakerNote;
decomposeKey();
}
}
std::string ExifKey::tagName() const
{
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
return pMakerNote_->tagName(tag_);
}
return ExifTags::tagName(tag(), ifdId());
}
uint16 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
{
return new ExifKey(*this);
}
std::string ExifKey::sectionName() const
{
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
return pMakerNote_->ifdItem();
}
return ExifTags::sectionName(tag(), ifdId());
}
void ExifKey::decomposeKey()
{
if (value) pValue_ = value->clone();
std::pair<uint16, IfdId> p = decomposeKey(key, makerNote);
if (p.first == 0xffff) throw Error("Invalid key");
std::pair<uint16, IfdId> p;
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
p.first = pMakerNote_->decomposeKey(key_);
if (p.first == 0xffff) throw Error("Invalid key");
p.second = makerIfd;
}
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 = makerIfd;
// No checks as this could still be an incomplete makernote key
}
tag_ = p.first;
if (p.second == ifdIdNotSet) throw Error("Invalid key");
ifdId_ = p.second;
}
std::ostream& ExifKey::printTag(std::ostream& os, const Value& value) const
{
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
return pMakerNote_->printTag(os, tag(), value);
}
return ExifTags::printTag(os, tag(), ifdId(), value);
}
Exifdatum::Exifdatum(const Entry& e, ByteOrder byteOrder)
: pKey_(new ExifKey(e)), pValue_(0)
{
pValue_ = Value::create(TypeId(e.type()));
pValue_->read(e.data(), e.count() * e.typeSize(), byteOrder);
}
Exifdatum::Exifdatum(const ExifKey& key, const Value* pValue)
: pKey_(key.clone()), pValue_(0)
{
if (pValue) pValue_ = pValue->clone();
}
Exifdatum::~Exifdatum()
{
delete pKey_;
delete pValue_;
// do *not* delete the MakerNote
}
Exifdatum::Exifdatum(const Exifdatum& rhs)
: Metadatum(rhs), tag_(rhs.tag_), ifdId_(rhs.ifdId_), idx_(rhs.idx_),
pMakerNote_(rhs.pMakerNote_), pValue_(0), key_(rhs.key_)
: Metadatum(rhs), pKey_(0), pValue_(0)
{
if (rhs.pKey_ != 0) pKey_ = rhs.pKey_->clone(); // deep copy
if (rhs.pValue_ != 0) pValue_ = rhs.pValue_->clone(); // deep copy
}
@ -111,14 +201,15 @@ namespace Exiv2 {
{
if (this == &rhs) return *this;
Metadatum::operator=(rhs);
tag_ = rhs.tag_;
ifdId_ = rhs.ifdId_;
idx_ = rhs.idx_;
pMakerNote_ = rhs.pMakerNote_;
delete pKey_;
pKey_ = 0;
if (rhs.pKey_ != 0) pKey_ = rhs.pKey_->clone(); // deep copy
delete pValue_;
pValue_ = 0;
if (rhs.pValue_ != 0) pValue_ = rhs.pValue_->clone(); // deep copy
key_ = rhs.key_;
return *this;
} // Exifdatum::operator=
@ -141,22 +232,6 @@ namespace Exiv2 {
pValue_->read(buf);
}
std::string Exifdatum::tagName() const
{
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
return pMakerNote_->tagName(tag_);
}
return ExifTags::tagName(tag_, ifdId_);
}
std::string Exifdatum::sectionName() const
{
if (ifdId_ == makerIfd && pMakerNote_ != 0) {
return pMakerNote_->sectionName(tag_);
}
return ExifTags::sectionName(tag_, ifdId_);
}
TiffThumbnail::TiffThumbnail()
: offset_(0), size_(0), pImage_(0), ifd_(ifd1, 0, false)
{
@ -229,17 +304,16 @@ namespace Exiv2 {
buflen += ifd1.size() + ifd1.dataSize();
if (len < buflen) rc = 1;
}
std::string key;
ExifData::const_iterator offsets;
ExifData::const_iterator sizes;
if (rc == 0) {
// Copy thumbnail image data, remember the offsets used
key = "Thumbnail.RecordingOffset.StripOffsets";
ExifKey key("Exif.Thumbnail.StripOffsets");
offsets = exifData.findKey(key);
if (offsets == exifData.end()) rc = 2;
}
if (rc == 0) {
key = "Thumbnail.RecordingOffset.StripByteCounts";
ExifKey key("Exif.Thumbnail.StripByteCounts");
sizes = exifData.findKey(key);
if (sizes == exifData.end()) rc = 2;
}
@ -426,12 +500,12 @@ namespace Exiv2 {
const ExifData& exifData,
ByteOrder byteOrder)
{
std::string key = "Thumbnail.RecordingOffset.JPEGInterchangeFormat";
ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat");
ExifData::const_iterator pos = exifData.findKey(key);
if (pos == exifData.end()) return 2;
long offset = pos->toLong();
key = "Thumbnail.RecordingOffset.JPEGInterchangeFormatLength";
pos = exifData.findKey(key);
ExifKey key2("Exif.Thumbnail.JPEGInterchangeFormatLength");
pos = exifData.findKey(key2);
if (pos == exifData.end()) return 2;
long size = pos->toLong();
if (len < offset + size) return 1;
@ -466,7 +540,7 @@ namespace Exiv2 {
void JpegThumbnail::update(ExifData& exifData) const
{
std::string key = "Thumbnail.RecordingOffset.JPEGInterchangeFormat";
ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat");
ExifData::iterator pos = exifData.findKey(key);
if (pos == exifData.end()) {
Value* value = Value::create(unsignedLong);
@ -476,13 +550,13 @@ namespace Exiv2 {
}
pos->setValue(toString(offset_));
key = "Thumbnail.RecordingOffset.JPEGInterchangeFormatLength";
pos = exifData.findKey(key);
ExifKey key2("Exif.Thumbnail.JPEGInterchangeFormatLength");
pos = exifData.findKey(key2);
if (pos == exifData.end()) {
Value *value = Value::create(unsignedLong);
exifData.add(key, value);
exifData.add(key2, value);
delete value;
pos = exifData.findKey(key);
pos = exifData.findKey(key2);
}
pos->setValue(toString(size_));
@ -600,7 +674,7 @@ namespace Exiv2 {
if (rc) {
// Todo: How to handle debug output like this
std::cerr << "Warning: Failed to read "
<< pMakerNote_->sectionName(0)
<< pMakerNote_->ifdItem()
<< " Makernote, rc = " << rc << "\n";
delete pMakerNote_;
@ -896,9 +970,12 @@ namespace Exiv2 {
}
}
void ExifData::add(const std::string& key, Value* value)
void ExifData::add(const ExifKey& key, Value* pValue)
{
add(Exifdatum(key, value));
// Todo: Implement a more suitable ExifKey c'tor
ExifKey k(key);
k.setMakerNote(pMakerNote_);
add(Exifdatum(k, pValue));
}
void ExifData::add(const Exifdatum& exifdatum)
@ -907,16 +984,16 @@ namespace Exiv2 {
exifMetadata_.push_back(exifdatum);
}
ExifData::const_iterator ExifData::findKey(const std::string& key) const
ExifData::const_iterator ExifData::findKey(const ExifKey& key) const
{
return std::find_if(exifMetadata_.begin(), exifMetadata_.end(),
FindMetadatumByKey(key));
FindMetadatumByKey(key.key()));
}
ExifData::iterator ExifData::findKey(const std::string& key)
ExifData::iterator ExifData::findKey(const ExifKey& key)
{
return std::find_if(exifMetadata_.begin(), exifMetadata_.end(),
FindMetadatumByKey(key));
FindMetadatumByKey(key.key()));
}
ExifData::const_iterator ExifData::findIfdIdIdx(IfdId ifdId, int idx) const
@ -1019,7 +1096,8 @@ namespace Exiv2 {
delete pThumbnail_;
pThumbnail_ = 0;
int rc = -1;
const_iterator pos = findKey("Thumbnail.ImageStructure.Compression");
const_iterator pos
= findKey(ExifKey("Exif.Thumbnail.Compression"));
if (pos != end()) {
long compression = pos->toLong();
if (compression == 6) {
@ -1200,7 +1278,7 @@ namespace Exiv2 {
error += "Exif data contains a broken IFD";
break;
case 7:
error += "Unsupported Exif or GPS data found in IFD 1";
error += "Unsupported Exif or GPS data found in IFD1";
break;
default:
@ -1272,13 +1350,9 @@ namespace Exiv2 {
makerNote->add(e);
} // addToMakerNote
std::ostream& operator<<(std::ostream& os, const Exifdatum& md)
{
if (md.ifdId() == makerIfd && md.makerNote() != 0) {
return md.makerNote()->printTag(os, md.tag(), md.value());
}
return ExifTags::printTag(os, md.tag(), md.ifdId(), md.value());
return md.pKey_->printTag(os, md.value());
}
std::string makeKey(const Entry& entry)

@ -21,7 +21,7 @@
/*!
@file exif.hpp
@brief Encoding and decoding of Exif data
@version $Name: $ $Revision: 1.49 $
@version $Name: $ $Revision: 1.50 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created
@ -60,30 +60,117 @@ namespace Exiv2 {
// *****************************************************************************
// 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);
//! 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
//@}
//! @name Manipulators
//@{
/*!
@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(); }
/*!
@brief Return the name of the group (the second part of the key).
For Exif keys, the group name is the IFD name.
*/
virtual std::string groupName() const { return ifdName(); }
virtual std::string tagName() const;
/*!
@brief Return the tag.
@throw Error ("Invalid key") if the tag is not set.
*/
virtual uint16 tag() const;
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 name of the IFD
const char* ifdName() const { return ExifTags::ifdName(ifdId()); }
//! Return the related image item
const char* ifdItem() const { return ExifTags::ifdItem(ifdId()); }
//! 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_; }
//! 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,
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.
*/
void decomposeKey();
//@}
private:
// DATA
uint16 tag_; //!< Tag value
IfdId ifdId_; //!< The IFD associated with this tag
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.
*/
class Exifdatum : public Metadatum {
friend std::ostream& operator<<(std::ostream&, const Exifdatum&);
public:
//! @name Creators
//@{
/*!
@brief Constructor for new tags created by an application. The
Exifdatum is created from a key / value pair. %Exifdatum copies
(clones) the value if one is provided. Alternatively, a program
can create an 'empty' Exifdatum with only a key and set the
value using setValue().
@param key The key of the Exifdatum.
@param value Pointer to a Exifdatum value.
@param makerNote Pointer to the associated MakerNote (only needed for
MakerNote tags).
@throw Error ("Invalid key") if the key cannot be parsed and converted
to a tag number and an IFD id or the section name does not match.
*/
explicit Exifdatum(const std::string& key,
const Value* value =0,
MakerNote* makerNote =0);
%Exifdatum is created from a key / value pair. %Exifdatum copies
(clones) the key and value if one is provided. Alternatively,
a program can create an 'empty' %Exifdatum with only a key
and set the value using setValue().
@param key ExifKey.
@param pValue Pointer to a Exifdatum value.
@throw Error ("Invalid key") if the key cannot be parsed and converted.
*/
explicit Exifdatum(const ExifKey& key, const Value* pValue =0);
//! Constructor to build a Exifdatum from an IFD entry.
Exifdatum(const Entry& e, ByteOrder byteOrder);
//! Copy constructor
@ -115,6 +202,30 @@ namespace Exiv2 {
//! @name Accessors
//@{
//! Return the key of the %Exifdatum.
std::string key() const
{ return pKey_ == 0 ? "" : pKey_->key(); }
//! Return the name of the group (the second part of the key)
std::string groupName() const
{ return pKey_ == 0 ? "" : pKey_->groupName(); }
//! Return the name of the tag (which is also the third part of the key)
std::string tagName() const
{ return pKey_ == 0 ? "" : pKey_->tagName(); }
//! Return the tag
uint16 tag() const
{ return pKey_ == 0 ? 0xffff : pKey_->tag(); }
//! Return the IFD id
IfdId ifdId() const
{ return pKey_ == 0 ? ifdIdNotSet : pKey_->ifdId(); }
//! Return the name of the IFD
const char* ifdName() const
{ return pKey_ == 0 ? "" : pKey_->ifdName(); }
//! Return the related image item (deprecated)
const char* ifdItem() const
{ return pKey_ == 0 ? "" : pKey_->ifdItem(); }
//! Return the index (unique id of this key within the original IFD)
int idx() const
{ return pKey_ == 0 ? 0 : pKey_->idx(); }
/*!
@brief Write value to a data buffer and return the number
of bytes written.
@ -128,40 +239,21 @@ namespace Exiv2 {
*/
long copy(byte* buf, ByteOrder byteOrder) const
{ return pValue_ == 0 ? 0 : pValue_->copy(buf, byteOrder); }
/*!
@brief Return the key of the Exifdatum. The key is of the form
'ifdItem.sectionName.tagName'. Note however that the key
is not necessarily unique, i.e., an ExifData may contain
multiple metadata with the same key.
*/
std::string key() const { return key_; }
//! Return the related image item (the first part of the key)
const char* ifdItem() const { return ExifTags::ifdItem(ifdId_); }
//! Return the name of the section (the second part of the key)
std::string sectionName() const;
//! Return the name of the tag (which is also the third part of the key)
std::string tagName() const;
//! Return the tag
uint16 tag() const { return tag_; }
//! Return the type id of the value
TypeId typeId() const
{ return pValue_ == 0 ? invalidTypeId : pValue_->typeId(); }
//! Return the name of the type
const char* typeName() const { return TypeInfo::typeName(typeId()); }
const char* typeName() const
{ return TypeInfo::typeName(typeId()); }
//! Return the size in bytes of one component of this type
long typeSize() const { return TypeInfo::typeSize(typeId()); }
long typeSize() const
{ return TypeInfo::typeSize(typeId()); }
//! Return the number of components in the value
long count() const { return pValue_ == 0 ? 0 : pValue_->count(); }
long count() const
{ return pValue_ == 0 ? 0 : pValue_->count(); }
//! Return the size of the value in bytes
long size() const { return pValue_ == 0 ? 0 : pValue_->size(); }
//! 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 index (unique id of this Exifdatum within the original IFD)
int idx() const { return idx_; }
//! Return the pointer to the associated MakerNote
MakerNote* makerNote() const { return pMakerNote_; }
long size() const
{ return pValue_ == 0 ? 0 : pValue_->size(); }
//! Return the value as a string.
std::string toString() const
{ return pValue_ == 0 ? "" : pValue_->toString(); }
@ -201,7 +293,8 @@ namespace Exiv2 {
@return A pointer to a copy (clone) of the value, 0 if the value is
not set.
*/
Value* getValue() const { return pValue_ == 0 ? 0 : pValue_->clone(); }
Value* getValue() const
{ return pValue_ == 0 ? 0 : pValue_->clone(); }
/*!
@brief Return a constant reference to the value.
@ -227,17 +320,13 @@ namespace Exiv2 {
private:
// DATA
uint16 tag_; //!< Tag value
IfdId ifdId_; //!< The IFD associated with this tag
int idx_; //!< Unique id of an entry within one IFD
MakerNote* pMakerNote_; //!< Pointer to the associated MakerNote
ExifKey* pKey_; //!< Key
Value* pValue_; //!< Pointer to the value
std::string key_; //!< Key
}; // class Exifdatum
/*!
@brief Output operator for Exifdatum types, printing the interpreted
@brief Output operator for Exifdatum types, prints the interpreted
tag value.
*/
std::ostream& operator<<(std::ostream& os, const Exifdatum& md);
@ -579,11 +668,12 @@ namespace Exiv2 {
ByteOrder byteOrder);
/*!
@brief Add a Exifdatum from the supplied key and value pair. This
method copies (clones) the value. No duplicate checks are
method copies (clones) key and value and adds a pointer to
the MakerNote to the cloned key. No duplicate checks are
performed, i.e., it is possible to add multiple metadata with
the same key.
*/
void add(const std::string& key, Value* value);
void add(const ExifKey& key, Value* pValue);
/*!
@brief Add a copy of the Exifdatum to the Exif metadata. No
duplicate checks are performed, i.e., it is possible to add
@ -610,7 +700,7 @@ namespace Exiv2 {
If multiple metadata with the same key exist, it is undefined
which of the matching metadata is found.
*/
iterator findKey(const std::string& key);
iterator findKey(const ExifKey& key);
/*!
@brief Find the Exifdatum with the given ifd id and idx, return an
iterator to it.
@ -659,7 +749,7 @@ namespace Exiv2 {
it. If multiple metadata with the same key exist, it is
undefined which of the matching metadata is found.
*/
const_iterator findKey(const std::string& key) const;
const_iterator findKey(const ExifKey& key) const;
/*!
@brief Find the Exifdatum with the given ifd id and idx, return an
iterator to it.
@ -863,7 +953,7 @@ namespace Exiv2 {
ByteOrder byteOrder);
/*!
@brief Return a key for the entry. The key is of the form
'ifdItem.sectionName.tagName'. This function knows about
'<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);

@ -3,7 +3,7 @@
Abstract : Sample program showing how to set the Exif comment of an image
File: exifcomment.cpp
Version : $Name: $ $Revision: 1.3 $
Version : $Name: $ $Revision: 1.4 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History : 10-May-04, ahu: created
*/
@ -33,7 +33,7 @@ try {
/*
There are two pitfalls that we need to consider when setting the Exif user
comment (Image.UserInfo.UserComment) of an image:
comment (Exif.Photo.UserComment) of an image:
First, the type of the Exif user comment tag is "undefined" (and not
ASCII) according to the Exif standard. This means that in Exiv2, we have
@ -60,7 +60,7 @@ try {
8 + static_cast<long>(comment.size()));
// Set the Exif comment
std::string key = "Image.UserInfo.UserComment";
Exiv2::ExifKey key("Exif.Photo.UserComment");
Exiv2::ExifData::iterator pos = exifData.findKey(key);
if (pos != exifData.end()) {
// Use the existing Exif UserComment metadatum if there is one

@ -20,7 +20,7 @@
*/
/*
File: fujimn.cpp
Version: $Name: $ $Revision: 1.9 $
Version: $Name: $ $Revision: 1.10 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created
07-Mar-04, ahu: isolated as a separate component
@ -31,7 +31,7 @@
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: fujimn.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.10 $ $RCSfile: fujimn.cpp,v $");
// *****************************************************************************
// included header files
@ -78,7 +78,7 @@ namespace Exiv2 {
};
FujiMakerNote::FujiMakerNote(bool alloc)
: IfdMakerNote(fujiMnTagInfo, alloc), sectionName_("Fujifilm")
: IfdMakerNote(fujiMnTagInfo, alloc), ifdItem_("Fujifilm")
{
byteOrder_ = littleEndian;
absOffset_ = false;

@ -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.6 $
@version $Name: $ $Revision: 1.7 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 11-Feb-04, ahu: created
@ -106,8 +106,8 @@ namespace Exiv2 {
//@{
int checkHeader() const;
FujiMakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Fujifilm")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Fujifilm")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -157,8 +157,8 @@ namespace Exiv2 {
*/
static const RegisterMakerNote register_;
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class FujiMakerNote

@ -20,13 +20,13 @@
*/
/*
File: iptc.cpp
Version: $Name: $ $Revision: 1.2 $
Version: $Name: $ $Revision: 1.3 $
Author(s): Brad Schick (brad) <schick@robotbattle.com>
History: 31-July-04, brad: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.2 $ $RCSfile: iptc.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.3 $ $RCSfile: iptc.cpp,v $");
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@ -48,27 +48,63 @@ EXIV2_RCSID("@(#) $Name: $ $Revision: 1.2 $ $RCSfile: iptc.cpp,v $");
// class member definitions
namespace Exiv2 {
Iptcdatum::Iptcdatum(const std::string& key,
const Value* value)
: pValue_(0), key_(key), modified_(false)
IptcKey::IptcKey(const std::string& key)
: key_(key)
{
if (value) pValue_ = value->clone();
std::pair<uint16, uint16> p = decomposeKey(key);
decomposeKey();
}
IptcKey::IptcKey(uint16 tag, uint16 record)
: tag_(tag), record_(record), key_(IptcDataSets::makeKey(tag, record))
{
}
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()
{
std::pair<uint16, uint16> p = IptcDataSets::decomposeKey(key_);
if (p.first == 0xffff) throw Error("Invalid key");
tag_ = p.first;
if (p.second == IptcDataSets::invalidRecord) throw Error("Invalid key");
tag_ = p.first;
record_ = p.second;
}
Iptcdatum::Iptcdatum(const IptcKey& key,
const Value* value)
: pKey_(key.clone()), pValue_(0), modified_(false)
{
if (value) pValue_ = value->clone();
}
Iptcdatum::Iptcdatum(const Iptcdatum& rhs)
: Metadatum(rhs), tag_(rhs.tag_), record_(rhs.record_),
pValue_(0), key_(rhs.key_), modified_(false)
: Metadatum(rhs), pKey_(0), pValue_(0), modified_(false)
{
if (rhs.pKey_ != 0) pKey_ = rhs.pKey_->clone(); // deep copy
if (rhs.pValue_ != 0) pValue_ = rhs.pValue_->clone(); // deep copy
}
Iptcdatum::~Iptcdatum()
{
delete pKey_;
delete pValue_;
}
@ -77,12 +113,15 @@ namespace Exiv2 {
if (this == &rhs) return *this;
Metadatum::operator=(rhs);
modified_ = true;
tag_ = rhs.tag_;
record_ = rhs.record_;
delete pKey_;
pKey_ = 0;
if (rhs.pKey_ != 0) pKey_ = rhs.pKey_->clone(); // deep copy
delete pValue_;
pValue_ = 0;
if (rhs.pValue_ != 0) pValue_ = rhs.pValue_->clone(); // deep copy
key_ = rhs.key_;
return *this;
} // Iptcdatum::operator=
@ -100,16 +139,6 @@ namespace Exiv2 {
pValue_->read(buf);
}
std::string Iptcdatum::tagName() const
{
return IptcDataSets::dataSetName(tag_, record_);
}
std::string Iptcdatum::recordName() const
{
return IptcDataSets::recordName(record_);
}
const byte IptcData::marker_ = 0x1C; // Dataset marker
IptcData::IptcData()
@ -206,7 +235,7 @@ namespace Exiv2 {
val = Value::create(undefined);
val->read(data, sizeData, bigEndian);
}
std::string key = makeKey(dataSet, record);
IptcKey key(dataSet, record);
add(key, val);
delete val;
return 0;
@ -346,7 +375,7 @@ namespace Exiv2 {
return exvImage.writeMetadata();
} // IptcData::writeIptcData
int IptcData::add(const std::string& key, Value* value)
int IptcData::add(const IptcKey& key, Value* value)
{
return add(Iptcdatum(key, value));
}
@ -364,16 +393,16 @@ namespace Exiv2 {
return 0;
}
IptcData::const_iterator IptcData::findKey(const std::string& key) const
IptcData::const_iterator IptcData::findKey(const IptcKey& key) const
{
return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(),
FindMetadatumByKey(key));
FindMetadatumByKey(key.key()));
}
IptcData::iterator IptcData::findKey(const std::string& key)
IptcData::iterator IptcData::findKey(const IptcKey& key)
{
return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(),
FindMetadatumByKey(key));
FindMetadatumByKey(key.key()));
}
IptcData::const_iterator IptcData::findId(uint16 dataset, uint16 record) const
@ -453,14 +482,4 @@ namespace Exiv2 {
return os << md.value();
}
std::string makeKey(uint16 number, uint16 record)
{
return IptcDataSets::makeKey(number, record);
}
std::pair<uint16, uint16> decomposeKey(const std::string& key)
{
return IptcDataSets::decomposeKey(key);
}
} // namespace Exiv2

@ -21,7 +21,7 @@
/*!
@file iptc.hpp
@brief Encoding and decoding of Iptc data
@version $Name: $ $Revision: 1.3 $
@version $Name: $ $Revision: 1.4 $
@author Brad Schick (brad)
<a href="mailto:schick@robotbattle.com">schick@robotbattle.com</a>
@date 31-Jul-04, brad: created
@ -48,6 +48,82 @@ namespace Exiv2 {
// *****************************************************************************
// 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 tag, uint16 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 IptcDataSets::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 tag() const { return tag_; }
virtual IptcKey* clone() const;
//! Return the name of the record
const char* recordName() const
{ return IptcDataSets::recordName(record_); }
//! Return the record id
uint16 record() const { return record_; }
//@}
protected:
//! @name Manipulators
//@{
/*!
@brief Parse and convert the key string into dataset and record id.
Updates tag_ and record_ if the string can be decomposed,
or throws Error ("Invalid key").
@throw Error ("Invalid key") if the key cannot be parsed into
family name, group name and tag name parts.
*/
void decomposeKey();
//@}
private:
// DATA
uint16 tag_; //!< Tag value
uint16 record_; //!< Record value
std::string key_; //!< Key
}; // class IptcKey
/*!
@brief Information related to one Iptc dataset.
*/
@ -57,17 +133,17 @@ namespace Exiv2 {
//@{
/*!
@brief Constructor for new tags created by an application. The
Iptcdatum is created from a key / value pair. %Iptcdatum copies
(clones) the value if one is provided. Alternatively, a program
can create an 'empty' Iptcdatum with only a key and set the
value using setValue().
%Iptcdatum is created from a key / value pair. %Iptcdatum
copies (clones) the value if one is provided. Alternatively, a
program can create an 'empty' %Iptcdatum with only a key and
set the value using setValue().
@param key The key of the Iptcdatum.
@param value Pointer to a Iptcdatum value.
@param key The key of the %Iptcdatum.
@param value Pointer to a %Iptcdatum value.
@throw Error ("Invalid key") if the key cannot be parsed and converted
to a tag number and record id.
*/
explicit Iptcdatum(const std::string& key,
explicit Iptcdatum(const IptcKey& key,
const Value* value =0);
//! Copy constructor
Iptcdatum(const Iptcdatum& rhs);
@ -109,30 +185,34 @@ namespace Exiv2 {
{ return pValue_ == 0 ? 0 : pValue_->copy(buf, byteOrder); }
/*!
@brief Return the key of the Iptcdatum. The key is of the form
'Iptc.recordName.datasetName'. Note however that the key
'<b>Iptc</b>.recordName.datasetName'. Note however that the key
is not necessarily unique, i.e., an IptcData may contain
multiple metadata with the same key.
*/
std::string key() const { return key_; }
std::string key() const { return pKey_ == 0 ? "" : pKey_->key(); }
/*!
@brief Return the name of the record
@return record name
@throw Error("Unknown record");
*/
std::string recordName() const;
const char* recordName() const
{ return pKey_ == 0 ? "" : pKey_->recordName(); }
/*!
@brief Return the record id
@return record id
*/
uint16 record() const { return record_; }
uint16 record() const
{ return pKey_ == 0 ? 0 : pKey_->record(); }
/*!
@brief Return the name of the tag (aka dataset)
@return tag name
@throw Error("No dataSet for record Id") if tag is unknown
*/
std::string tagName() const;
std::string tagName() const
{ return pKey_ == 0 ? "" : pKey_->tagName(); }
//! Return the tag (aka dataset) number
uint16 tag() const { return tag_; }
uint16 tag() const
{ return pKey_ == 0 ? 0 : pKey_->tag(); }
//! Return the type id of the value
TypeId typeId() const
{ return pValue_ == 0 ? invalidTypeId : pValue_->typeId(); }
@ -217,10 +297,8 @@ namespace Exiv2 {
private:
// DATA
uint16 tag_; //!< Tag value
uint16 record_; //!< Record value
IptcKey* pKey_; //!< Key
Value* pValue_; //!< Pointer to the value
std::string key_; //!< Key
bool modified_; //!< Change indicator
}; // class Iptcdatum
@ -341,13 +419,13 @@ namespace Exiv2 {
*/
long copy(byte* buf);
/*!
@brief Add a Iptcdatum from the supplied key and value pair. This
@brief Add an %Iptcdatum from the supplied key and value pair. This
method copies (clones) the value. A check for non-repeatable
datasets is performed.
@return 0 if successful;<BR>
6 if the dataset already exists and is not repeatable;<BR>
6 if the dataset already exists and is not repeatable
*/
int add(const std::string& key, Value* value);
int add(const IptcKey& key, Value* value);
/*!
@brief Add a copy of the Iptcdatum to the Iptc metadata. A check
for non-repeatable datasets is performed.
@ -375,7 +453,7 @@ namespace Exiv2 {
If multiple entries with the same key exist, it is undefined
which of the matching metadata is found.
*/
iterator findKey(const std::string& key);
iterator findKey(const IptcKey& key);
/*!
@brief Find a Iptcdatum with the given record and dataset it,
return a const iterator to it. If multiple entries with the
@ -404,11 +482,11 @@ namespace Exiv2 {
//! End of the metadata
const_iterator end() const { return iptcMetadata_.end(); }
/*!
@brief Find a Iptcdatum with the given key, return a const iterator to
it. If multiple metadata with the same key exist it is
@brief Find an Iptcdatum with the given key, return a const iterator
to it. If multiple metadata with the same key exist it is
undefined which of the matching metadata is found.
*/
const_iterator findKey(const std::string& key) const;
const_iterator findKey(const IptcKey& key) const;
/*!
@brief Find a Iptcdatum with the given record and dataset number,
return a const iterator to it. If multiple metadata with the
@ -473,24 +551,6 @@ namespace Exiv2 {
mutable bool modified_;
}; // class IptcData
// *****************************************************************************
// free functions
/*!
@brief Return a key for the entry. The key is of the form
'Iptc.recordName.datasetName'.
@throw Error ("No dataSet for record Id") if the dataset number or
record Id is unknown
*/
std::string makeKey(uint16 number, uint16 record);
/*!
@brief Return the record and dataset id pair for the key.
@return A pair consisting of the record and dataset id.
@throw Error ("Invalid key") if the key cannot be parsed into
valid record and dataset parts.
*/
std::pair<uint16, uint16> decomposeKey(const std::string& key);
} // namespace Exiv2
#endif // #ifndef IPTC_HPP_

@ -4,7 +4,7 @@
This is not designed to be a robust application.
File : iptctest.cpp
Version : $Name: $ $Revision: 1.1 $
Version : $Name: $ $Revision: 1.2 $
Author(s): Brad Schick (brad) <schick@robotbattle.com>
History : 01-Aug-04, brad: created
*/
@ -118,7 +118,7 @@ void processAdd(const std::string& line, int num)
Value *val = Value::create(type);
val->read(data);
int rc = g_iptcData.add(key, val);
int rc = g_iptcData.add(IptcKey(key), val);
if (rc) {
std::string error = IptcData::strError(rc, "Input file");
throw Error(error);
@ -180,7 +180,7 @@ void processModify(const std::string& line, int num)
iter->setValue(val);
}
else {
int rc = g_iptcData.add(key, val);
int rc = g_iptcData.add(IptcKey(key), val);
if (rc) {
std::string error = IptcData::strError(rc, "Input file");
throw Error(error);

@ -20,13 +20,13 @@
*/
/*
File: makernote.cpp
Version: $Name: $ $Revision: 1.24 $
Version: $Name: $ $Revision: 1.25 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.24 $ $RCSfile: makernote.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.25 $ $RCSfile: makernote.cpp,v $");
// Define DEBUG_* to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@ -59,28 +59,29 @@ namespace Exiv2 {
std::string MakerNote::makeKey(uint16 tag) const
{
return std::string(ExifTags::ifdItem(makerIfd))
+ "." + sectionName(tag) + "." + tagName(tag);
return std::string(ExifTags::familyName())
+ "." + std::string(ifdItem())
+ "." + tagName(tag);
} // MakerNote::makeKey
uint16 MakerNote::decomposeKey(const std::string& key) const
{
// Get the IFD, section name and tag name parts of the key
// 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 ifdItem = key.substr(0, pos1);
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 sectionName = key.substr(pos0, pos1 - pos0);
std::string ifdItem = key.substr(pos0, pos1 - pos0);
pos0 = pos1 + 1;
std::string tagName = key.substr(pos0);
if (tagName == "") throw Error("Invalid key");
if (ifdItem != ExifTags::ifdItem(makerIfd)) return 0xffff;
if (familyName != ExifTags::familyName()) return 0xffff;
uint16 tag = this->tag(tagName);
if (tag == 0xffff) return tag;
if (sectionName != this->sectionName(tag)) return 0xffff;
if (ifdItem != this->ifdItem()) return 0xffff;
return tag;
} // MakerNote::decomposeKey

@ -22,7 +22,7 @@
@file makernote.hpp
@brief Contains the Exif %MakerNote interface, IFD %MakerNote and a
MakerNote factory
@version $Name: $ $Revision: 1.21 $
@version $Name: $ $Revision: 1.22 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created
@ -222,8 +222,8 @@ namespace Exiv2 {
virtual Entries::const_iterator findIdx(int idx) const =0;
//! Return the size of the makernote in bytes
virtual long size() const =0;
//! Return the name of the makernote section
virtual std::string sectionName(uint16 tag) const =0;
//! Return the name of the makernote item
virtual std::string ifdItem() const =0;
//! Interpret and print the value of a makernote tag
virtual std::ostream& printTag(std::ostream& os,
uint16 tag,
@ -327,7 +327,7 @@ namespace Exiv2 {
*/
virtual long headerSize() const;
virtual IfdMakerNote* clone(bool alloc =true) const =0;
virtual std::string sectionName(uint16 tag) const =0;
virtual std::string ifdItem() const =0;
virtual std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const =0;

@ -20,14 +20,15 @@
*/
/*!
@file metadatum.hpp
@brief Provides class Metadatum
@version $Name: $ $Revision: 1.1 $
@brief Provides abstract base classes Metadatum and Key
@version $Name: $ $Revision: 1.2 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@author Brad Schick (brad)
<a href="mailto:schick@robotbattle.com">schick@robotbattle.com</a>
@date 09-Jan-04, ahu: created<BR>
31-Jul-04, brad: isolated as a component
31-Jul-04, brad: isolated as a component<BR>
23-Aug-04, ahu: added Key
*/
#ifndef METADATUM_HPP_
#define METADATUM_HPP_
@ -48,10 +49,82 @@ namespace Exiv2 {
// class definitions
/*!
@brief Information related to one Exif tag.
@brief Abstract base class defining the %Key of a metadatum.
Keys are used to identify and group metadata.
*/
class Key {
public:
//! @name Creators
//@{
//! Destructor
virtual ~Key() {}
//@}
//! @name Accessors
//@{
/*!
@brief Return the key of the metadatum as a string. The key is of the
form 'familyName.groupName.tagName'. Note however that the
key is not necessarily unique, e.g., an ExifData may contain
multiple metadata with the same key.
*/
virtual std::string key() const =0;
//! Return an identifier for the type of metadata (the first part of the key)
virtual const char* familyName() const =0;
//! Return the name of the group (the second part of the key)
virtual std::string groupName() const =0;
//! Return the name of the tag (which is also the third part of the key)
virtual std::string tagName() const =0;
//! Return the tag number
virtual uint16 tag() const =0;
/*!
@brief Return a pointer to a copy of itself (deep copy).
The caller owns this copy and is responsible to delete it!
*/
virtual Key* clone() const =0;
/*!
@brief Write the key to an output stream. You do not usually have
to use this function; it is used for the implementation of
the output operator for %Key,
operator<<(std::ostream &os, const Key &key).
*/
std::ostream& write(std::ostream& os) const { return os << key(); }
//@}
protected:
//! @name Manipulators
//@{
/*!
@brief Assignment operator. Protected so that it can only be used
by subclasses but not directly.
*/
Key& operator=(const Key& rhs) { return *this; }
//@}
}; // class Key
//! Output operator for Key types
inline std::ostream& operator<<(std::ostream& os, const Key& key)
{
return key.write(os);
}
/*!
@brief Abstract base class defining the interface to access information
related to one metadata tag.
*/
class Metadatum {
public:
//! @name Creators
//@{
//! Default Constructor
Metadatum() {}
//! Copy constructor
Metadatum(const Metadatum& rhs) {}
//! Destructor
virtual ~Metadatum() {}
//@}
//! @name Manipulators
//@{
/*!
@ -83,7 +156,7 @@ namespace Exiv2 {
virtual long copy(byte* buf, ByteOrder byteOrder) const =0;
/*!
@brief Return the key of the metadatum. The key is of the form
'ifdItem.sectionName.tagName'. Note however that the key
'familyName.ifdItem.tagName'. Note however that the key
is not necessarily unique, i.e., an ExifData may contain
multiple metadata with the same key.
*/
@ -161,19 +234,12 @@ namespace Exiv2 {
//@}
protected:
//! @name Creators
//@{
//! Default Constructor
Metadatum() {}
//! Copy constructor
Metadatum(const Metadatum& rhs) {}
//! Destructor
virtual ~Metadatum() {}
//@}
//! @name Manipulators
//@{
//! Assignment operator
/*!
@brief Assignment operator. Protected so that it can only be used
by subclasses but not directly.
*/
Metadatum& operator=(const Metadatum& rhs) { return *this; }
//@}

@ -20,14 +20,14 @@
*/
/*
File: nikon1mn.cpp
Version: $Name: $ $Revision: 1.4 $
Version: $Name: $ $Revision: 1.5 $
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.4 $ $RCSfile: nikonmn.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.5 $ $RCSfile: nikonmn.cpp,v $");
// *****************************************************************************
// included header files
@ -73,7 +73,7 @@ namespace Exiv2 {
};
Nikon1MakerNote::Nikon1MakerNote(bool alloc)
: IfdMakerNote(nikon1MnTagInfo, alloc), sectionName_("Nikon1")
: IfdMakerNote(nikon1MnTagInfo, alloc), ifdItem_("Nikon1")
{
}
@ -198,7 +198,7 @@ namespace Exiv2 {
};
Nikon2MakerNote::Nikon2MakerNote(bool alloc)
: IfdMakerNote(nikon2MnTagInfo, alloc), sectionName_("Nikon2")
: IfdMakerNote(nikon2MnTagInfo, alloc), ifdItem_("Nikon2")
{
}
@ -383,7 +383,7 @@ namespace Exiv2 {
};
Nikon3MakerNote::Nikon3MakerNote(bool alloc)
: IfdMakerNote(nikon3MnTagInfo, alloc), sectionName_("Nikon3")
: IfdMakerNote(nikon3MnTagInfo, alloc), ifdItem_("Nikon3")
{
absOffset_ = false;
}

@ -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.3 $
@version $Name: $ $Revision: 1.4 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 17-May-04, ahu: created<BR>
@ -103,8 +103,8 @@ namespace Exiv2 {
//! @name Accessors
//@{
Nikon1MakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Nikon1")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Nikon1")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -149,8 +149,8 @@ namespace Exiv2 {
*/
static const RegisterMakerNote register_;
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class Nikon1MakerNote
@ -182,8 +182,8 @@ namespace Exiv2 {
//@{
int checkHeader() const;
Nikon2MakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Nikon2")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Nikon2")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -206,8 +206,8 @@ namespace Exiv2 {
//@}
private:
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class Nikon2MakerNote
@ -236,8 +236,8 @@ namespace Exiv2 {
//@{
int checkHeader() const;
Nikon3MakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Nikon3")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Nikon3")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -258,8 +258,8 @@ namespace Exiv2 {
//@}
private:
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class Nikon3MakerNote

@ -20,7 +20,7 @@
*/
/*
File: sigmamn.cpp
Version: $Name: $ $Revision: 1.8 $
Version: $Name: $ $Revision: 1.9 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 02-Apr-04, ahu: created
Credits: Sigma and Foveon MakerNote implemented according to the specification
@ -29,7 +29,7 @@
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.8 $ $RCSfile: sigmamn.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: sigmamn.cpp,v $");
// *****************************************************************************
// included header files
@ -83,7 +83,7 @@ namespace Exiv2 {
};
SigmaMakerNote::SigmaMakerNote(bool alloc)
: IfdMakerNote(sigmaMnTagInfo, alloc), sectionName_("Sigma")
: IfdMakerNote(sigmaMnTagInfo, alloc), ifdItem_("Sigma")
{
}

@ -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.6 $
@version $Name: $ $Revision: 1.7 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 02-Apr-04, ahu: created
@ -105,8 +105,8 @@ namespace Exiv2 {
//@{
int checkHeader() const;
SigmaMakerNote* clone(bool alloc =true) const;
//! Return the name of the makernote section ("Sigma")
std::string sectionName(uint16 tag) const { return sectionName_; }
//! Return the name of the makernote item ("Sigma")
std::string ifdItem() const { return ifdItem_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
@ -148,8 +148,8 @@ namespace Exiv2 {
*/
static const RegisterMakerNote register_;
//! The section name (second part of the key) used for makernote tags
std::string sectionName_;
//! The item name (second part of the key) used for makernote tags
std::string ifdItem_;
}; // class SigmaMakerNote

@ -3,13 +3,13 @@
Abstract: Print a simple comma separated list of tags defined in Exiv2
File: taglist.cpp
Version: $Name: $ $Revision: 1.8 $
Version: $Name: $ $Revision: 1.9 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 07-Jan-04, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.8 $ $RCSfile: taglist.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: taglist.cpp,v $");
#include "makernote.hpp"
#include "nikonmn.hpp"
@ -33,28 +33,28 @@ try {
case 2:
{
MakerNote* pMakerNote = 0;
std::string section(argv[1]);
if (section == "Iptc") {
std::string item(argv[1]);
if (item == "Iptc") {
IptcDataSets::dataSetList(std::cout);
break;
}
if (section == "Canon") {
if (item == "Canon") {
pMakerNote = new CanonMakerNote;
}
else if (section == "Fuji") {
else if (item == "Fujifilm") {
pMakerNote = new FujiMakerNote;
}
else if (section == "Sigma") {
else if (item == "Sigma") {
pMakerNote = new SigmaMakerNote;
}
else if (section == "Nikon1") {
else if (item == "Nikon1") {
pMakerNote = new Nikon1MakerNote;
}
else if (section == "Nikon2") {
else if (item == "Nikon2") {
pMakerNote = new Nikon2MakerNote;
}
else if (section == "Nikon3") {
else if (item == "Nikon3") {
pMakerNote = new Nikon3MakerNote;
}
@ -76,7 +76,8 @@ try {
break;
}
if (rc) {
std::cout << "Usage: " << argv[0] << " [SectionName|Iptc]\n"
std::cout << "Usage: " << argv[0]
<< " [Canon|Fujifilm|Nikon1|Nikon2|Nikon3|Sigma|Iptc]\n"
<< "Print Exif tags, MakerNote tags, or Iptc datasets\n";
}
return rc;

@ -1,12 +1,12 @@
################################################################################
# File : tags.awk
# Version : $Name: $ $Revision: 1.3 $
# Version : $Name: $ $Revision: 1.4 $
# Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
# History : 07-Feb-04, ahu: created
#
# Description:
# Awk script to convert a taglist to XML format used in the documentation.
# $ taglist [SectionName] | awk -f tags.awk > tags.xml
# $ taglist [itemName] | awk -f tags.awk > tags.xml
################################################################################
BEGIN {

@ -20,13 +20,13 @@
*/
/*
File: tags.cpp
Version: $Name: $ $Revision: 1.32 $
Version: $Name: $ $Revision: 1.33 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 15-Jan-04, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.32 $ $RCSfile: tags.cpp,v $");
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.33 $ $RCSfile: tags.cpp,v $");
// *****************************************************************************
// included header files
@ -50,15 +50,16 @@ namespace Exiv2 {
{
}
// Important: IFD item must be unique!
const IfdInfo ExifTags::ifdInfo_[] = {
IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown data area)"),
IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown item)"),
IfdInfo(ifd0, "IFD0", "Image"),
IfdInfo(exifIfd, "Exif", "Image"),
IfdInfo(gpsIfd, "GPSInfo", "Image"),
IfdInfo(exifIfd, "Exif", "Photo"), // just to avoid 'Exif.Exif.*' keys
IfdInfo(gpsIfd, "GPSInfo", "GPSInfo"),
IfdInfo(makerIfd, "Makernote", "Makernote"),
IfdInfo(iopIfd, "Iop", "Image"),
IfdInfo(iopIfd, "Iop", "Iop"),
IfdInfo(ifd1, "IFD1", "Thumbnail"),
IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD info)")
IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD item)")
};
SectionInfo::SectionInfo(
@ -265,6 +266,8 @@ namespace Exiv2 {
0
};
const char* ExifTags::familyName_ = "Exif";
int ExifTags::tagInfoIdx(uint16 tag, IfdId ifdId)
{
const TagInfo* tagInfo = tagInfos_[ifdId];
@ -276,17 +279,6 @@ namespace Exiv2 {
return idx;
}
int ExifTags::tagInfoIdx(const std::string& tagName, 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].name_ == tagName) break;
}
return idx;
}
const char* ExifTags::tagName(uint16 tag, IfdId ifdId)
{
int idx = tagInfoIdx(tag, ifdId);
@ -317,6 +309,17 @@ namespace Exiv2 {
return sectionInfo_[tagInfo[idx].sectionId_].desc_;
}
uint16 ExifTags::tag(const std::string& tagName, IfdId ifdId)
{
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;
}
return tagInfo[idx].tag_;
}
const char* ExifTags::ifdName(IfdId ifdId)
{
return ifdInfo_[ifdId].name_;
@ -343,8 +346,8 @@ namespace Exiv2 {
std::string ExifTags::makeKey(uint16 tag, IfdId ifdId)
{
return std::string(ifdItem(ifdId))
+ "." + std::string(sectionName(tag, ifdId))
return std::string(familyName())
+ "." + std::string(ifdItem(ifdId))
+ "." + std::string(tagName(tag, ifdId));
}
@ -352,41 +355,31 @@ namespace Exiv2 {
// we find, it doesn't verify whether this is the only match.
std::pair<uint16, IfdId> ExifTags::decomposeKey(const std::string& key)
{
// Get the IFD, section name and tag name parts of the 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 ifdItem = key.substr(0, pos1);
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 sectionName = key.substr(pos0, pos1 - pos0);
std::string ifdItem = key.substr(pos0, pos1 - pos0);
pos0 = pos1 + 1;
std::string tagName = key.substr(pos0);
if (tagName == "") throw Error("Invalid key");
// Check if this is a MakerNote key, stop processing if it is
if (ifdItem == ifdInfo_[makerIfd].item_) {
return std::make_pair(0xffff, makerIfd);
// Find IfdId
int i;
for (i = int(lastIfdId) - 1; i > 0; --i) {
if (ifdInfo_[i].item_ == ifdItem) break;
}
IfdId ifdId = IfdId(i);
// Use the parts of the key to find tag and IFD id
IfdId ifdId = ifdIdNotSet;
uint16 tag = 0xffff;
if (ifdId == ifdIdNotSet) return std::make_pair(0xffff, ifdId);
SectionId s = sectionId(sectionName);
if (s == sectionIdNotSet) return std::make_pair(tag, ifdId);
for (int i = 0; i < lastIfdId; ++i) {
if (ifdInfo_[i].item_ == ifdItem) {
ifdId = ifdInfo_[i].ifdId_;
int k = tagInfoIdx(tagName, ifdId);
if (k != -1 && tagInfos_[ifdId][k].sectionId_ == s) {
tag = tagInfos_[ifdId][k].tag_;
break;
}
}
}
return std::make_pair(tag, ifdId);
return std::make_pair(tag(tagName, ifdId), ifdId);
} // ExifTags::decomposeKey
std::ostream& ExifTags::printTag(std::ostream& os,

@ -21,7 +21,7 @@
/*!
@file tags.hpp
@brief Exif tag and type information
@version $Name: $ $Revision: 1.24 $
@version $Name: $ $Revision: 1.25 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 15-Jan-04, ahu: created<BR>
@ -72,7 +72,8 @@ namespace Exiv2 {
IfdInfo(IfdId ifdId, const char* name, const char* item);
IfdId ifdId_; //!< IFD id
const char* name_; //!< IFD name
const char* item_; //!< Related image item
//! Related IFD item. This is also an IFD name, unique for each IFD.
const char* item_;
};
//! Contains information pertaining to one section
@ -113,6 +114,9 @@ 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.
@param tag The tag
@ -167,7 +171,7 @@ namespace Exiv2 {
static SectionId sectionId(const std::string& sectionName);
/*!
@brief Return the key for the tag and IFD id. The key is of the form
'ifdItem.sectionName.tagName'.
'<b>Exif</b>.ifdItem.tagName'.
*/
static std::string makeKey(uint16 tag, IfdId ifdId);
/*!
@ -187,7 +191,8 @@ namespace Exiv2 {
private:
static int tagInfoIdx(uint16 tag, IfdId ifdId);
static int tagInfoIdx(const std::string& tagName, IfdId ifdId);
static const char* familyName_;
static const IfdInfo ifdInfo_[];
static const SectionInfo sectionInfo_[];

@ -3,7 +3,7 @@
Abstract : ExifData write unit tests
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
Version : $Name: $ $Revision: 1.7 $
Version : $Name: $ $Revision: 1.8 $
Test procedure:
$ rm -f test.jpg thumb.jpg iii ttt;
@ -59,77 +59,77 @@ try {
std::cerr << "Case 1: ";
std::cerr << "Non-intrusive change to the standard Exif metadata\n";
testCase(testFile, "test1.jpg", "thumb1",
"Image.DateTime.DateTimeOriginal",
"Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22");
break;
case 2:
std::cerr << "Case 2: ";
std::cerr << "Non-intrusive change to the makernote metadata\n";
testCase(testFile, "test2.jpg", "thumb2",
"Makernote.Canon.OwnerName",
"Exif.Canon.OwnerName",
"Chan YeeSend");
break;
case 3:
std::cerr << "Case 3: ";
std::cerr << "Non-intrusive change to the Exif metadata (w/o makernote)\n";
testCase(testFile, "test3.jpg", "thumb3",
"Image.DateTime.DateTimeOriginal",
"Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22");
break;
case 4:
std::cerr << "Case 4: ";
std::cerr << "Intrusive change to the standard Exif metadata\n";
testCase(testFile, "test4.jpg", "thumb4",
"Image.DateTime.DateTimeOriginal",
"Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22 and twenty seconds");
break;
case 5:
std::cerr << "Case 5: ";
std::cerr << "Intrusive change to the Canon makernote metadata\n";
testCase(testFile, "test5.jpg", "thumb5",
"Makernote.Canon.OwnerName",
"Exif.Canon.OwnerName",
"Frau Chan YeeSend und Herr Andreas Huggel");
break;
case 6:
std::cerr << "Case 6: ";
std::cerr << "Intrusive change to the Exif metadata (w/o makernote)\n";
testCase(testFile, "test6.jpg", "thumb6",
"Image.DateTime.DateTimeOriginal",
"Exif.Photo.DateTimeOriginal",
"1999:11:22 00:11:22 and twenty seconds");
break;
case 7:
std::cerr << "Case 7: ";
std::cerr << "Intrusive change to the Fujifilm makernote metadata\n";
testCase(testFile, "test7.jpg", "thumb7",
"Makernote.Fujifilm.Quality",
"Exif.Fujifilm.Quality",
"Typical Fujifilm Quality");
break;
case 8:
std::cerr << "Case 8: ";
std::cerr << "Intrusive change to the Sigma makernote metadata\n";
testCase(testFile, "test8.jpg", "thumb8",
"Makernote.Sigma.ResolutionMode",
"Exif.Sigma.ResolutionMode",
"Sigma HI resolution");
break;
case 9:
std::cerr << "Case 9: ";
std::cerr << "Intrusive change to the Nikon1 makernote metadata\n";
testCase(testFile, "test9.jpg", "thumb9",
"Makernote.Nikon1.Quality",
"Exif.Nikon1.Quality",
"Typical Nikon1 Quality");
break;
case 10:
std::cerr << "Case 10: ";
std::cerr << "Intrusive change to the Nikon2 makernote metadata\n";
testCase(testFile, "test10.jpg", "thumb10",
"Makernote.Nikon2.0x0002",
"Exif.Nikon2.0x0002",
"Nikon2 Version 2");
break;
case 11:
std::cerr << "Case 11: ";
std::cerr << "Intrusive change to the Nikon3 makernote metadata\n";
testCase(testFile, "test11.jpg", "thumb11",
"Makernote.Nikon3.Quality",
"Exif.Nikon3.Quality",
"Typical Nikon3 Quality");
break;
@ -159,6 +159,7 @@ void testCase(const std::string& file1,
const std::string& key,
const std::string& value)
{
ExifKey ek(key);
ExifData ed1;
std::cerr << "---> Reading file " << file1 << "\n";
@ -169,9 +170,9 @@ void testCase(const std::string& file1,
}
std::cerr << "---> Modifying Exif data\n";
Exiv2::ExifData::iterator pos = ed1.findKey(key);
Exiv2::ExifData::iterator pos = ed1.findKey(ek);
if (pos == ed1.end()) {
throw Error("Metadatum with key = " + key + " not found");
throw Error("Metadatum with key = " + ek.key() + " not found");
}
pos->setValue(value);

@ -3,7 +3,7 @@
Abstract : ExifData write unit tests for Exif data created from scratch
File : write2-test.cpp
Version : $Name: $ $Revision: 1.4 $
Version : $Name: $ $Revision: 1.5 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History : 26-Jun-04, ahu: created
@ -31,7 +31,7 @@ try {
std::cout <<"----- One IFD0 tag\n";
Exiv2::ExifData ed1;
Exiv2::Exifdatum md1(Exiv2::ExifKey("Image.OtherTags.Model"));
Exiv2::Exifdatum md1(Exiv2::ExifKey("Exif.Image.Model"));
md1.setValue("Test 1");
ed1.add(md1);
write(file, ed1);
@ -39,7 +39,7 @@ try {
std::cout <<"\n----- One Exif tag\n";
Exiv2::ExifData ed2;
Exiv2::Exifdatum md2(Exiv2::ExifKey("Image.DateTime.DateTimeOriginal"));
Exiv2::Exifdatum md2(Exiv2::ExifKey("Exif.Photo.DateTimeOriginal"));
md2.setValue("Test 2");
ed2.add(md2);
write(file, ed2);
@ -49,7 +49,7 @@ try {
std::cout <<"\n----- One IOP tag\n";
Exiv2::ExifData ed3;
Exiv2::Exifdatum md3(Exiv2::ExifKey("Image.Interoperability.InteroperabilityVersion"));
Exiv2::Exifdatum md3(Exiv2::ExifKey("Exif.Iop.InteroperabilityVersion"));
md3.setValue("Test 3");
ed3.add(md3);
write(file, ed3);
@ -57,7 +57,7 @@ try {
std::cout <<"\n----- One GPS tag\n";
Exiv2::ExifData ed4;
Exiv2::Exifdatum md4(Exiv2::ExifKey("Image.GPS.GPSVersionID"));
Exiv2::Exifdatum md4(Exiv2::ExifKey("Exif.GPSInfo.GPSVersionID"));
md4.setValue("Test 4");
ed4.add(md4);
write(file, ed4);
@ -66,11 +66,11 @@ try {
// Todo: Fix this
std::cout <<"\n----- One IFD1 tag\n";
Exiv2::ExifData ed5;
Exiv2::Exifdatum md5(Exiv2::ExifKey("Thumbnail.OtherTags.Artist"));
Exiv2::Exifdatum md5(Exiv2::ExifKey("Exif.Thumbnail.Artist"));
md5.setValue("Test 5");
ed5.add(md5);
Exiv2::Exifdatum md6(Exiv2::ExifKey("Image.OtherTags.Model"));
Exiv2::Exifdatum md6(Exiv2::ExifKey("Exif.Image.Model"));
md6.setValue("Test 5 (Fix me!)");
ed5.add(md6);

Loading…
Cancel
Save