Added MakerNote support, basics

v0.27.3
Andreas Huggel 22 years ago
parent d42550f8aa
commit 1f94309899

@ -20,7 +20,7 @@
# 02111-1307, USA.
#
# File: Makefile
# Version: $Name: $ $Revision: 1.10 $
# Version: $Name: $ $Revision: 1.11 $
# Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
# History: 10-Dec-03, ahu: created
#
@ -51,7 +51,7 @@ include $(top_srcdir)/config.mk
CCHDR = rcsid.hpp error.hpp
# Add library C++ source files to this list
CCSRC = exif.cpp ifd.cpp image.cpp tags.cpp types.cpp value.cpp
CCSRC = exif.cpp ifd.cpp image.cpp makernote.cpp tags.cpp types.cpp value.cpp
# Add source files of simple applications to this list
BINSRC = example1.cpp taglist.cpp exifprint.cpp exiftest.cpp
@ -130,7 +130,7 @@ ifeq ($(strip $(MAKECMDGOALS)),)
-include $(DEP)
else
# ...or the target is _not_ one in the list of targets below.
NOINCLUDE = uninstall uninstall-lib check doc mostlyclean clean \
NOINCLUDE = uninstall uninstall-lib check doc ctags mostlyclean clean \
install-header uninstall-header distclean maintainer-clean \
uninstall-archive uninstall-sharedlib
ifneq ($(MAKECMDGOALS), $(filter $(MAKECMDGOALS), $(NOINCLUDE)))
@ -168,7 +168,7 @@ $(EXIV2BIN): %: %.o
# ******************************************************************************
# Targets
.PHONY: all archive sharedlib bin check doc \
.PHONY: all archive sharedlib bin check ctags doc \
clean mostlyclean distclean maintainer-clean \
install install-archive install-header \
install-sharedlib install-lib \
@ -251,6 +251,10 @@ uninstall-sharedlib:
uninstall-lib: $(UNINSTALL_LIB) uninstall-header
ctags:
ctags-exuberant --extra=+q -e *
ctags-exuberant --extra=+q *
check:
@echo "No checks available for this library."

@ -0,0 +1,597 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
File: makernote.cpp
Version: $Name: $ $Revision: 1.1 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created
Credits: Canon MakerNote implemented according to the specification
"EXIF MakerNote of Canon" <http://www.burren.cx/david/canon.html>
by David Burren
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.1 $ $RCSfile: makernote.cpp,v $")
// *****************************************************************************
// included header files
#include "makernote.hpp"
#include "value.hpp"
#include "tags.hpp" // for ExifTags::ifdItem, printValue
#include "error.hpp"
// + standard includes
#include <string>
#include <sstream>
#include <iomanip>
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#define DEBUG_MAKERNOTE
// *****************************************************************************
// class member definitions
namespace Exif {
std::string MakerNote::makeKey(uint16 tag) const
{
return std::string(ExifTags::ifdItem(makerIfd))
+ "." + sectionName(tag) + "." + tagName(tag);
}
uint16 MakerNote::decomposeKey(const std::string& key) const
{
// Get the IFD, section 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::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);
pos0 = pos1 + 1;
std::string tagName = key.substr(pos0);
if (tagName == "") throw Error("Invalid key");
if (ifdItem != ExifTags::ifdItem(makerIfd)) return 0xffff;
uint16 tag = this->tag(tagName);
if (tag == 0xffff) return tag;
if (sectionName != this->sectionName(tag)) return 0xffff;
return tag;
}
std::string MakerNote::tagName(uint16 tag) const
{
std::string tagName;
if (mnTagInfo_) {
for (int i = 0; mnTagInfo_[i].tag_ != 0xffff; ++i) {
if (mnTagInfo_[i].tag_ == tag) {
tagName = mnTagInfo_[i].name_;
break;
}
}
}
if (tagName.empty()) {
std::ostringstream os;
os << "0x" << std::setw(4) << std::setfill('0') << std::right
<< std::hex << tag;
tagName = os.str();
}
return tagName;
}
uint16 MakerNote::tag(const std::string& tagName) const
{
uint16 tag = 0xffff;
if (mnTagInfo_) {
for (int i = 0; mnTagInfo_[i].tag_ != 0xffff; ++i) {
if (mnTagInfo_[i].name_ == tagName) {
tag = mnTagInfo_[i].tag_;
break;
}
}
}
if (tag == 0xffff) {
std::istringstream is(tagName);
is >> std::hex >> tag;
}
return tag;
}
MakerNoteFactory* MakerNoteFactory::instance_ = 0;
MakerNoteFactory& MakerNoteFactory::instance()
{
if (0 == instance_) {
instance_ = new MakerNoteFactory;
}
return *instance_;
} // MakerNoteFactory::instance
void MakerNoteFactory::registerMakerNote(const std::string& make,
const std::string& model,
MakerNote* makerNote)
{
std::string key = make + "+" + model;
Registry::iterator i = registry_.find(key);
if (i != registry_.end()) {
delete i->second;
}
registry_[key] = makerNote;
} // MakerNoteFactory::registerMakerNote
MakerNoteFactory::MakerNoteFactory()
{
// Register a prototype of each known MakerNote
registerMakerNote("Canon", "Canon PowerShot S40", new CanonMakerNote);
} // MakerNoteFactory c'tor
MakerNote* MakerNoteFactory::create(const std::string& make,
const std::string& model) const
{
MakerNote* makerNote = 0;
std::string key = make + "+" + model;
Registry::const_iterator i = registry_.find(key);
if (i != registry_.end() && i->second != 0) {
makerNote = i->second->clone();
}
return makerNote;
} // MakerNoteFactory::create
int IfdMakerNote::read(const char* buf,
long len,
ByteOrder byteOrder,
long offset)
{
int rc = ifd_.read(buf, byteOrder, offset);
if (rc == 0) {
// Todo: Make sure the Next field is 0.
Entries::iterator end = ifd_.end();
for (Entries::iterator i = ifd_.begin(); i != end; ++i) {
i->setMakerNote(this);
}
}
#ifdef DEBUG_MAKERNOTE
hexdump(std::cerr, buf, len);
if (rc == 0) ifd_.print(std::cerr);
#endif
return rc;
}
long IfdMakerNote::copy(char* buf, ByteOrder byteOrder, long offset) const
{
return ifd_.copy(buf, byteOrder, offset);
}
long IfdMakerNote::size() const
{
return ifd_.size() + ifd_.dataSize();
}
// Canon MakerNote Tag Info
static const MakerNote::MnTagInfo canonMnTagInfo[] = {
MakerNote::MnTagInfo(0x0001, "CameraSettings1", "Various camera settings (1)"),
MakerNote::MnTagInfo(0x0004, "CameraSettings2", "Various camera settings (2)"),
MakerNote::MnTagInfo(0x0006, "ImageType", "Image type"),
MakerNote::MnTagInfo(0x0007, "FirmwareVersion", "Firmware version"),
MakerNote::MnTagInfo(0x0008, "ImageNumber", "Image number"),
MakerNote::MnTagInfo(0x0009, "OwnerName", "Owner Name"),
MakerNote::MnTagInfo(0x000c, "SerialNumber", "Camera serial number"),
MakerNote::MnTagInfo(0x000f, "EosD30Functions", "EOS D30 Custom Functions"),
// End of list marker
MakerNote::MnTagInfo(0xffff, "(UnknownCanonMakerNoteTag)", "Unknown CanonMakerNote tag")
};
CanonMakerNote::CanonMakerNote()
: IfdMakerNote(canonMnTagInfo), sectionName_("Canon")
{
}
MakerNote* CanonMakerNote::clone() const
{
return new CanonMakerNote(*this);
}
std::ostream& CanonMakerNote::printTag(std::ostream& os,
uint16 tag,
const Value& value) const
{
switch (tag) {
case 0x0001: print0x0001(os, value); break;
case 0x0004: print0x0004(os, value); break;
case 0x0008: print0x0008(os, value); break;
case 0x000c: print0x000c(os, value); break;
case 0x000f: print0x000f(os, value); break;
default:
// All other tags (known or unknown) go here
os << value;
break;
}
return os;
}
std::ostream& CanonMakerNote::print0x0001(
std::ostream& os, const Value& value) const
{
if (0 == dynamic_cast<const UShortValue*>(&value)) {
return os << value;
}
const UShortValue& val = dynamic_cast<const UShortValue&>(value);
uint32 count = val.count();
if (count < 2) return os;
uint16 s = val.value_[1];
os << std::setw(30) << "\n Macro mode ";
switch (s) {
case 1: os << "On"; break;
case 2: os << "Off"; break;
default: os << "(" << s << ")"; break;
}
if (count < 3) return os;
s = val.value_[2];
os << std::setw(30) << "\n Self timer ";
if (s == 0) {
os << "Off";
}
else {
os << s / 10.0 << " s";
}
if (count < 4) return os;
s = val.value_[3];
os << std::setw(30) << "\n Quality ";
switch (s) {
case 2: os << "Normal"; break;
case 3: os << "Fine"; break;
case 5: os << "Superfine"; break;
default: os << "(" << s << ")"; break;
}
if (count < 5) return os;
s = val.value_[4];
os << std::setw(30) << "\n Flash mode ";
switch (s) {
case 0: os << "Off"; break;
case 1: os << "Auto"; break;
case 2: os << "On"; break;
case 3: os << "Red-eye"; break;
case 4: os << "Slow sync"; break;
case 5: os << "Auto + red-eye"; break;
case 6: os << "On + red-eye"; break;
case 16: os << "External"; break;
default: os << "(" << s << ")"; break;
}
if (count < 6) return os;
s = val.value_[5];
os << std::setw(30) << "\n Drive mode ";
switch (s) {
case 0: os << "Single / timer"; break;
case 1: os << "Continuous"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of the 6th ushort is unknown - ignore it
if (count < 8) return os;
s = val.value_[7];
os << std::setw(30) << "\n Focus mode ";
switch (s) {
case 0: os << "One shot"; break;
case 1: os << "AI servo"; break;
case 2: os << "AI Focus"; break;
case 3: os << "MF"; break;
case 4: os << "Single"; break;
case 5: os << "Continuous"; break;
case 6: os << "MF"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of the 8th ushort is unknown - ignore it
// Meaning of the 9th ushort is unknown - ignore it
if (count < 11) return os;
s = val.value_[10];
os << std::setw(30) << "\n Image size ";
switch (s) {
case 0: os << "Large"; break;
case 1: os << "Medium"; break;
case 2: os << "Small"; break;
default: os << "(" << s << ")"; break;
}
if (count < 12) return os;
s = val.value_[11];
os << std::setw(30) << "\n Easy shooting mode ";
switch (s) {
case 0: os << "Full auto"; break;
case 1: os << "Manual"; break;
case 2: os << "Landscape"; break;
case 3: os << "Fast shutter"; break;
case 4: os << "Slow shutter"; break;
case 5: os << "Night"; break;
case 6: os << "B&W"; break;
case 7: os << "Sepia"; break;
case 8: os << "Portrait"; break;
case 9: os << "Sports"; break;
case 10: os << "Macro / close-up"; break;
case 11: os << "Pan focus"; break;
default: os << "(" << s << ")"; break;
}
if (count < 13) return os;
s = val.value_[12];
os << std::setw(30) << "\n Digital zoom ";
switch (s) {
case 0: os << "None"; break;
case 1: os << "2x"; break;
case 2: os << "4x"; break;
default: os << "(" << s << ")"; break;
}
if (count < 14) return os;
s = val.value_[13];
os << std::setw(30) << "\n Contrast ";
switch (s) {
case 0xffff: os << "Low"; break;
case 0x0000: os << "Normal"; break;
case 0x0001: os << "High"; break;
default: os << "(" << s << ")"; break;
}
if (count < 15) return os;
s = val.value_[14];
os << std::setw(30) << "\n Saturation ";
switch (s) {
case 0xffff: os << "Low"; break;
case 0x0000: os << "Normal"; break;
case 0x0001: os << "High"; break;
default: os << "(" << s << ")"; break;
}
if (count < 16) return os;
s = val.value_[15];
os << std::setw(30) << "\n Sharpness ";
switch (s) {
case 0xffff: os << "Low"; break;
case 0x0000: os << "Normal"; break;
case 0x0001: os << "High"; break;
default: os << "(" << s << ")"; break;
}
if (count < 17) return os;
s = val.value_[16];
if (s != 0) {
os << std::setw(30) << "\n ISO ";
switch (s) {
case 15: os << "Auto"; break;
case 16: os << "50"; break;
case 17: os << "100"; break;
case 18: os << "200"; break;
case 19: os << "400"; break;
default: os << "(" << s << ")"; break;
}
}
if (count < 18) return os;
s = val.value_[17];
os << std::setw(30) << "\n Metering mode ";
switch (s) {
case 3: os << "Evaluative"; break;
case 4: os << "Partial"; break;
case 5: os << "Center weighted"; break;
default: os << "(" << s << ")"; break;
}
if (count < 19) return os;
s = val.value_[18];
os << std::setw(30) << "\n Focus type ";
switch (s) {
case 0: os << "Manual"; break;
case 1: os << "Auto"; break;
case 3: os << "Close-up (macro)"; break;
case 8: os << "Locked (pan mode)"; break;
default: os << "(" << s << ")"; break;
}
if (count < 20) return os;
s = val.value_[19];
os << std::setw(30) << "\n AF point selected ";
switch (s) {
case 0x3000: os << "None (MF)"; break;
case 0x3001: os << "Auto-selected"; break;
case 0x3002: os << "Right"; break;
case 0x3003: os << "Center"; break;
case 0x3004: os << "Left"; break;
default: os << "(" << s << ")"; break;
}
if (count < 21) return os;
s = val.value_[20];
os << std::setw(30) << "\n Exposure mode ";
switch (s) {
case 0: os << "Easy shooting"; break;
case 1: os << "Program"; break;
case 2: os << "Tv priority"; break;
case 3: os << "Av priority"; break;
case 4: os << "Manual"; break;
case 5: os << "A-DEP"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of the 21st ushort is unknown - ignore it
// Meaning of the 22nd ushort is unknown - ignore it
if (count < 26) return os;
float fu = val.value_[25];
float len1 = val.value_[23] / fu;
float len2 = val.value_[24] / fu;
std::ostringstream oss;
oss.copyfmt(os);
os << std::setw(30) << "\n Lens "
<< std::fixed << std::setprecision(1)
<< len2 << " - " << len1 << " mm";
os.copyfmt(oss);
// Meaning of the 26th ushort is unknown - ignore it
// Meaning of the 27th ushort is unknown - ignore it
if (count < 29) return os;
s = val.value_[28];
os << std::setw(30) << "\n Flash activity ";
switch (s) {
case 0: os << "Did not fire"; break;
case 1: os << "Fired"; break;
default: os << "(" << s << ")"; break;
}
if (count < 30) return os;
s = val.value_[29];
// Todo: decode bitmask
os << std::setw(30) << "\n Flash details "
<< std::dec << s << " (Todo: decode bitmask)";
// Meaning of the 30th ushort is unknown - ignore it
// Meaning of the 31st ushort is unknown - ignore it
if (count < 33) return os;
s = val.value_[32];
os << std::setw(30) << "\n Focus mode ";
switch (s) {
case 0: os << "Single"; break;
case 1: os << "Continuous"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of any further ushorts is unknown - ignore them
return os;
} // CanonMakerNote::print0x0001
std::ostream& CanonMakerNote::print0x0004(
std::ostream& os, const Value& value) const
{
if (0 == dynamic_cast<const UShortValue*>(&value)) {
return os << value;
}
const UShortValue& val = dynamic_cast<const UShortValue&>(value);
uint32 count = val.count();
// Meaning of ushorts 1-6 is unknown - ignore them
if (count < 8) return os;
uint16 s = val.value_[7];
os << std::setw(30) << "\n White balance ";
switch (s) {
case 0: os << "Auto"; break;
case 1: os << "Sunny"; break;
case 2: os << "Cloudy"; break;
case 3: os << "Tungsten"; break;
case 4: os << "Fluorescent"; break;
case 5: os << "Flash"; break;
case 6: os << "Custom"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of ushort 8 is unknown - ignore it
if (count < 10) return os;
s = val.value_[9];
os << std::setw(30) << "\n Sequence number " << s << "";
// Meaning of ushorts 10-13 is unknown - ignore them
if (count < 15) return os;
s = val.value_[14];
// Todo: decode bitmask
os << std::setw(30) << "\n AF point used "
<< s << " (Todo: decode bitmask)";
if (count < 16) return os;
s = val.value_[15];
os << std::setw(30) << "\n Flash bias ";
switch (s) {
case 0xffc0: os << "-2 EV"; break;
case 0xffcc: os << "-1.67 EV"; break;
case 0xffd0: os << "-1.50 EV"; break;
case 0xffd4: os << "-1.33 EV"; break;
case 0xffe0: os << "-1 EV"; break;
case 0xffec: os << "-0.67 EV"; break;
case 0xfff0: os << "-0.50 EV"; break;
case 0xfff4: os << "-0.33 EV"; break;
case 0x0000: os << "0 EV"; break;
case 0x000c: os << "0.33 EV"; break;
case 0x0010: os << "0.50 EV"; break;
case 0x0014: os << "0.67 EV"; break;
case 0x0020: os << "1 EV"; break;
case 0x002c: os << "1.33 EV"; break;
case 0x0030: os << "1.50 EV"; break;
case 0x0034: os << "1.67 EV"; break;
case 0x0040: os << "2 EV"; break;
default: os << "(" << s << ")"; break;
}
// Meaning of ushorts 16-18 is unknown - ignore them
if (count < 20) return os;
s = val.value_[19];
os << std::setw(30) << "\n Subject distance (0.01m or 0.001m) ";
if (s == 0xffff) {
os << "Infinite";
}
else {
os << s << "";
}
return os;
} // CanonMakerNote::print0x0004
std::ostream& CanonMakerNote::print0x0008(
std::ostream& os, const Value& value) const
{
std::string n = value.toString();
return os << n.substr(0, n.length() - 4) << "-"
<< n.substr(n.length() - 4);
}
std::ostream& CanonMakerNote::print0x000c(
std::ostream& os, const Value& value) const
{
std::istringstream is(value.toString());
uint32 l;
is >> l;
return os << std::setw(4) << std::setfill('0') << std::hex
<< ((l & 0xffff0000) >> 16)
<< std::setw(5) << std::setfill('0') << std::dec
<< (l & 0x0000ffff);
}
std::ostream& CanonMakerNote::print0x000f(
std::ostream& os, const Value& value) const
{
// Todo: Decode EOS D30 Custom Functions
return os << "EOS D30 Custom Functions "
<< value << " (Todo: decode this field)";
}
} // namespace Exif

@ -0,0 +1,281 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*!
@file makernote.hpp
@brief
@version $Name: $ $Revision: 1.1 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created
*/
#ifndef MAKERNOTE_HPP_
#define MAKERNOTE_HPP_
// *****************************************************************************
// included header files
#include "types.hpp"
#include "ifd.hpp"
// + standard includes
#include <string>
#include <iosfwd>
#include <map>
// *****************************************************************************
// namespace extensions
namespace Exif {
class Value;
// *****************************************************************************
// class definitions
/*!
@brief %Exif makernote interface
Defines methods to
- read the makernote from a character buffer
- copy the makernote to a character buffer
- add the makernote tags to the %Exif metadata
- access Makernote specific tag descriptions and print functions
Todo: Synchronization with ExifData:
Add a MakerNote pointer to ExifData (owner) and Metadata
Instead of ExifData as the owner, there should be a reference counter
Does Entry need a MakerNote poiner too? (not nice cos of the circ deps)
*/
class MakerNote {
public:
//! MakerNote Tag information
struct MnTagInfo {
//! Constructor
MnTagInfo(uint16 tag, const char* name, const char* desc)
: tag_(tag), name_(name), desc_(desc) {}
uint16 tag_; //!< Tag
const char* name_; //!< One word tag label
const char* desc_; //!< Short tag description
}; // struct MnTagInfo
//! Constructor. Takes an optional MakerNote info tag array.
MakerNote(const MnTagInfo* mnTagInfo =0) : mnTagInfo_(mnTagInfo) {}
//! Virtual destructor.
virtual ~MakerNote() {}
/*!
@brief Return a pointer to a copy of itself (deep copy).
The caller owns this copy and is responsible to delete it!
*/
virtual MakerNote* clone() const =0;
/*!
@brief Read the MakerNote from character buffer buf of length len at
position offset (from the start of the TIFF header) and encoded
in byte order byteOrder.
*/
virtual int read(const char* buf,
long len,
ByteOrder byteOrder,
long offset) =0;
/*!
@brief Copy (write) the makerNote to the character buffer buf at
position offset (from the start of the TIFF header), encoded
in byte order byteOrder. Return the number of bytes written.
*/
virtual long copy(char* buf, ByteOrder byteOrder, long offset) const =0;
//! @name Accessors
//@{
//! Return the size of the makernote in bytes.
virtual long size() const =0;
//! The first %MakerNote entry
virtual Entries::const_iterator begin() const =0;
//! End of the %MakerNote entries
virtual Entries::const_iterator end() const =0;
//! The first %MakerNote entry
virtual Entries::iterator begin() =0;
//! End of the %MakerNote entries
virtual Entries::iterator end() =0;
//! Return the key for the tag.
std::string makeKey(uint16 tag) const;
//! Return the associated tag for a makernote key.
uint16 decomposeKey(const std::string& key) const;
/*!
@brief Return the name of a makernote tag. The default implementation
looks up the %MakerNote info tag array if one is set, else
it translates the tag to a string with the hexadecimal value of
the tag.
*/
virtual std::string tagName(uint16 tag) const;
/*!
@brief Return the tag associated with a makernote tag name. The
default implementation looks up the %MakerNote info tag array
if one is set, else it expects tag names in the form \"0x01ff\"
and converts them to unsigned integer.
*/
virtual uint16 tag(const std::string& tagName) const;
//! Return the name of the makernote section
virtual std::string sectionName(uint16 tag) const =0;
//! Interpret and print the value of a makernote tag
virtual std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const =0;
//@}
protected:
//! Pointer to an array of MakerNote tag infos
const MnTagInfo* mnTagInfo_;
}; // class MakerNote
/*!
@brief %MakerNote factory.
Creates an instance of the %MakerNote for one camera model. The factory is
implemented as a singleton, which can be accessed only through the static
member function instance().
Todo: Implement more intelligent registry that allows wildcards in the
make and model strings to register classes
*/
class MakerNoteFactory {
public:
/*!
@brief Access the makerNote factory. Clients access the task factory
exclusively through this method.
*/
static MakerNoteFactory& instance();
/*!
@brief Create the appropriate %MakerNote based on camera make and
model, return a pointer to the newly created MakerNote
instance. Return 0 if no %MakerNote is defined for the camera
model.
@param make Camera manufacturer. (Typically the string from the %Exif
make tag.)
@param model Camera model. (Typically the string from the %Exif
model tag.)
@return A pointer that owns a %MakerNote for the camera model. If
the camera is not supported, the pointer is 0.
*/
MakerNote* create(const std::string& make,
const std::string& model) const;
/*!
@brief Register a %MakerNote prototype for a camera model.
The %MakerNote factory creates new %MakerNotes for a camera by cloning
the associated prototype. Additional %MakerNotes can be registered.
If called for a camera model for which a %MakerNote is already
registered, the corresponding prototype is replaced.
@param make Camera manufacturer. (Typically the string from the %Exif
make tag.)
@param model Camera model. (Typically the string from the %Exif
model tag.)
@param makerNote Pointer to the prototype. Ownership is transfered to the
%MakerNote factory.
*/
void registerMakerNote(const std::string& make,
const std::string& model,
MakerNote* makerNote);
private:
//! Prevent construction other than through instance().
MakerNoteFactory();
//! Prevent copy construction: not implemented.
MakerNoteFactory(const MakerNoteFactory& rhs);
//! Pointer to the one and only instance of this class.
static MakerNoteFactory* instance_;
//! Type used to store %MakerNote prototype classes
typedef std::map<std::string, MakerNote*> Registry;
//! List of makernote types and corresponding prototypes.
Registry registry_;
}; // class MakerNoteFactory
/*!
@brief Interface for MakerNotes in IFD format
Todo: Allow for a 'prefix' before the IFD (OLYMP, etc)
Cater for offsets from start of TIFF header as well as relative to Mn
*/
class IfdMakerNote : public MakerNote {
public:
//! Constructor. Takes an optional MakerNote info tag array.
IfdMakerNote(const MakerNote::MnTagInfo* mnTagInfo =0)
: MakerNote(mnTagInfo), ifd_(makerIfd, 0, false) {}
virtual ~IfdMakerNote() {}
virtual MakerNote* clone() const =0;
int read(const char* buf, long len, ByteOrder byteOrder, long offset);
long copy(char* buf, ByteOrder byteOrder, long offset) const;
long size() const;
Entries::const_iterator begin() const { return ifd_.begin(); }
Entries::const_iterator end() const { return ifd_.end(); }
Entries::iterator begin() { return ifd_.begin(); }
Entries::iterator end() { return ifd_.end(); }
virtual std::string sectionName(uint16 tag) const =0;
virtual std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const =0;
protected:
Ifd ifd_; //!< MakerNote IFD
}; // class IfdMakerNote
//! MakerNote for Canon cameras
class CanonMakerNote : public IfdMakerNote {
public:
//! Default constructor
CanonMakerNote();
virtual ~CanonMakerNote() {}
MakerNote* clone() const;
//! Return the name of the makernote section ("Canon")
std::string sectionName(uint16 tag) const { return sectionName_; }
std::ostream& printTag(std::ostream& os,
uint16 tag,
const Value& value) const;
//! @name Print functions for Canon %MakerNote tags
//@{
//! Print various camera settings, part 1
std::ostream& print0x0001(std::ostream& os, const Value& value) const;
//! Print various camera settings, part 2
std::ostream& print0x0004(std::ostream& os, const Value& value) const;
//! Print the image number
std::ostream& print0x0008(std::ostream& os, const Value& value) const;
//! Print the serial number of the camera
std::ostream& print0x000c(std::ostream& os, const Value& value) const;
//! Print EOS D30 custom functions
std::ostream& print0x000f(std::ostream& os, const Value& value) const;
//@}
private:
std::string sectionName_;
}; // class CanonMakerNote
} // namespace Exif
#endif // #ifndef MAKERNOTE_HPP_
Loading…
Cancel
Save