TiffParser can now be parametrized with a decoder. Added Cr2Image which uses this to filter not applicable IFD0 tags.

v0.27.3
Andreas Huggel 19 years ago
parent 28f1dbe8b4
commit fe512e1470

@ -56,6 +56,7 @@ CCHDR = exiv2_version.h \
# Add library C++ source files to this list
CCSRC = basicio.cpp \
canonmn.cpp \
cr2image.cpp \
crwimage.cpp \
datasets.cpp \
error.cpp \

@ -0,0 +1,285 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2006 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., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*
File: cr2image.cpp
Version: $Rev$
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 22-Apr-06, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$")
// *****************************************************************************
// included header files
#ifdef _MSC_VER
# include "exv_msvc.h"
#else
# include "exv_conf.h"
#endif
#include "cr2image.hpp"
#include "tiffparser.hpp"
#include "tiffvisitor.hpp"
#include "image.hpp"
#include "error.hpp"
#include "futils.hpp"
// + standard includes
#include <iostream>
#include <iomanip>
#include <cassert>
#include <cstring>
// *****************************************************************************
// class member definitions
namespace Exiv2 {
// CR2 decoder table for special CR2 decoding requirements
const TiffDecoderInfo Cr2DecoderItems::cr2DecoderInfo_[] = {
{ "*", Tag::all, Group::ignr, 0 }, // Do not decode tags with group == Group::ignr
{ "*", 0x014a, Group::ifd0, 0 }, // Todo: Controversial, causes problems with Exiftool
{ "*", 0x0100, Group::ifd0, 0 }, // CR2 IFD0 refers to a preview image, ignore these tags
{ "*", 0x0101, Group::ifd0, 0 },
{ "*", 0x0102, Group::ifd0, 0 },
{ "*", 0x0103, Group::ifd0, 0 },
{ "*", 0x0111, Group::ifd0, 0 },
{ "*", 0x0117, Group::ifd0, 0 },
{ "*", 0x011a, Group::ifd0, 0 },
{ "*", 0x011b, Group::ifd0, 0 },
{ "*", 0x0128, Group::ifd0, 0 },
{ "*", 0x8649, Group::ifd0, &TiffMetadataDecoder::decodeIrbIptc }
};
const DecoderFct Cr2DecoderItems::findDecoder(const std::string& make,
uint32_t extendedTag,
uint16_t group)
{
DecoderFct decoderFct = &TiffMetadataDecoder::decodeStdTiffEntry;
const TiffDecoderInfo* td = find(cr2DecoderInfo_,
TiffDecoderInfo::Key(make, extendedTag, group));
if (td) {
// This may set decoderFct to 0, meaning that the tag should not be decoded
decoderFct = td->decoderFct_;
}
return decoderFct;
}
Cr2Image::Cr2Image(BasicIo::AutoPtr io, bool create)
: Image(mdExif | mdIptc), io_(io)
{
if (create) {
IoCloser closer(*io_);
io_->open();
}
} // Cr2Image::Cr2Image
bool Cr2Image::good() const
{
if (io_->open() != 0) return false;
IoCloser closer(*io_);
return isThisType(*io_, false);
}
void Cr2Image::clearMetadata()
{
clearExifData();
clearComment();
}
void Cr2Image::setMetadata(const Image& image)
{
setExifData(image.exifData());
setComment(image.comment());
}
void Cr2Image::clearExifData()
{
exifData_.clear();
}
void Cr2Image::setExifData(const ExifData& exifData)
{
exifData_ = exifData;
}
void Cr2Image::clearIptcData()
{
iptcData_.clear();
}
void Cr2Image::setIptcData(const IptcData& iptcData)
{
iptcData_ = iptcData;
}
void Cr2Image::clearComment()
{
comment_.erase();
}
void Cr2Image::setComment(const std::string& comment)
{
comment_ = comment;
}
void Cr2Image::readMetadata()
{
#ifdef DEBUG
std::cerr << "Reading CR2 file " << io_->path() << "\n";
#endif
if (io_->open() != 0) {
throw Error(9, io_->path(), strError());
}
IoCloser closer(*io_);
// Ensure that this is the correct image type
if (!isThisType(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(14);
throw Error(3, "CR2");
}
clearMetadata();
// Read the image into a memory buffer
long len = io_->size();
DataBuf buf(len);
io_->read(buf.pData_, len);
if (io_->error() || io_->eof()) throw Error(14);
TiffParser::decode(this, buf.pData_, buf.size_,
TiffCreator::create, Cr2DecoderItems::findDecoder);
} // Cr2Image::readMetadata
void Cr2Image::writeMetadata()
{
/*
Todo: implement me!
#ifdef DEBUG
std::cerr << "Writing CR2 file " << io_->path() << "\n";
#endif
// Read existing image
DataBuf buf;
if (io_->open() == 0) {
IoCloser closer(*io_);
// Ensure that this is the correct image type
if (isThisType(*io_, false)) {
// Read the image into a memory buffer
buf.alloc(io_->size());
io_->read(buf.pData_, buf.size_);
if (io_->error() || io_->eof()) {
buf.reset();
}
}
}
// Parse image, starting with a CR2 header component
Cr2Header::AutoPtr head(new Cr2Header);
if (buf.size_ != 0) {
head->read(buf.pData_, buf.size_);
}
Blob blob;
Cr2Parser::encode(blob, head.get(), this);
// Write new buffer to file
BasicIo::AutoPtr tempIo(io_->temporary()); // may throw
assert (tempIo.get() != 0);
tempIo->write(&blob[0], static_cast<long>(blob.size()));
io_->close();
io_->transfer(*tempIo); // may throw
*/
} // Cr2Image::writeMetadata
bool Cr2Image::isThisType(BasicIo& iIo, bool advance) const
{
return isCr2Type(iIo, advance);
}
const uint16_t Cr2Header::tag_ = 42;
const char* Cr2Header::cr2sig_ = "CR\2\0";
bool Cr2Header::read(const byte* pData, uint32_t size)
{
if (size < 16) return false;
if (pData[0] == 0x49 && pData[1] == 0x49) {
byteOrder_ = littleEndian;
}
else if (pData[0] == 0x4d && pData[1] == 0x4d) {
byteOrder_ = bigEndian;
}
else {
return false;
}
if (tag_ != getUShort(pData + 2, byteOrder_)) return false;
offset_ = getULong(pData + 4, byteOrder_);
if (0 != memcmp(pData + 8, cr2sig_, 4)) return false;
offset2_ = getULong(pData + 12, byteOrder_);
return true;
} // Cr2Header::read
void Cr2Header::print(std::ostream& os, const std::string& prefix) const
{
os << prefix
<< "Header, offset = 0x" << std::setw(8) << std::setfill('0')
<< std::hex << std::right << offset_;
switch (byteOrder_) {
case littleEndian: os << ", little endian encoded"; break;
case bigEndian: os << ", big endian encoded"; break;
case invalidByteOrder: break;
}
os << "\n";
} // Cr2Header::print
// *************************************************************************
// free functions
Image::AutoPtr newCr2Instance(BasicIo::AutoPtr io, bool create)
{
Image::AutoPtr image(new Cr2Image(io, create));
if (!image->good()) {
image.reset();
}
return image;
}
bool isCr2Type(BasicIo& iIo, bool advance)
{
const int32_t len = 16;
byte buf[len];
iIo.read(buf, len);
if (iIo.error() || iIo.eof()) {
return false;
}
Cr2Header header;
bool rc = header.read(buf, len);
if (!advance || !rc) {
iIo.seek(-len, BasicIo::cur);
}
return rc;
}
} // namespace Exiv2

@ -0,0 +1,264 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2006 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., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*!
@file cr2image.hpp
@brief Class Cr2Image
@version $Rev$
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 22-Apr-06, ahu: created
*/
#ifndef CR2IMAGE_HPP_
#define CR2IMAGE_HPP_
// *****************************************************************************
// included header files
#include "exif.hpp"
#include "iptc.hpp"
#include "image.hpp"
#include "tiffcomposite.hpp"
// + standard includes
#include <string>
// *****************************************************************************
// namespace extensions
namespace Exiv2 {
struct TiffDecoderInfo;
// *****************************************************************************
// class definitions
// Add CR2 to the supported image formats
namespace ImageType {
const int cr2 = 7; //!< CR2 image type (see class Cr2Image)
}
/*!
@brief Class to access Canon CR2 images. Exif metadata and a comment
are supported directly, IPTC is read from the Exif data, if present.
*/
class Cr2Image : public Image {
friend bool isCr2Type(BasicIo& iIo, bool advance);
//! @name NOT Implemented
//@{
//! Copy constructor
Cr2Image(const Cr2Image& rhs);
//! Assignment operator
Cr2Image& operator=(const Cr2Image& rhs);
//@}
public:
//! @name Creators
//@{
/*!
@brief Constructor that can either open an existing CR2 image or create
a new image from scratch. If a new image is to be created, any
existing data is overwritten. Since the constructor can not return
a result, callers should check the good() method after object
construction to determine success or failure.
@param io An auto-pointer that owns a BasicIo instance used for
reading and writing image metadata. \b Important: The constructor
takes ownership of the passed in BasicIo instance through the
auto-pointer. Callers should not continue to use the BasicIo
instance after it is passed to this method. Use the Image::io()
method to get a temporary reference.
@param create Specifies if an existing image should be read (false)
or if a new file should be created (true).
*/
Cr2Image(BasicIo::AutoPtr io, bool create);
//! Destructor
~Cr2Image() {}
//@}
//! @name Manipulators
//@{
void readMetadata();
/*!
@brief Todo: Write metadata back to the image. This method is not
yet implemented.
*/
void writeMetadata();
void setExifData(const ExifData& exifData);
void clearExifData();
void setIptcData(const IptcData& iptcData);
void clearIptcData();
void setComment(const std::string& comment);
void clearComment();
void setMetadata(const Image& image);
void clearMetadata();
ExifData& exifData() { return exifData_; }
IptcData& iptcData() { return iptcData_; }
//@}
//! @name Accessors
//@{
bool good() const;
const ExifData& exifData() const { return exifData_; }
const IptcData& iptcData() const { return iptcData_; }
std::string comment() const { return comment_; }
BasicIo& io() const { return *io_; }
//@}
private:
//! @name Accessors
//@{
/*!
@brief Determine if the content of the BasicIo instance is a CR2 image.
The advance flag determines if the read position in the stream is
moved (see below). This applies only if the type matches and the
function returns true. If the type does not match, the stream
position is not changed. However, if reading from the stream fails,
the stream position is undefined. Consult the stream state to obtain
more information in this case.
@param iIo BasicIo instance to read from.
@param advance Flag indicating whether the position of the io
should be advanced by the number of characters read to
analyse the data (true) or left at its original
position (false). This applies only if the type matches.
@return true if the data matches the type of this class;<BR>
false if the data does not match
*/
bool isThisType(BasicIo& iIo, bool advance) const;
/*!
@brief Todo: Write CR2 header. Not implemented yet.
*/
int writeHeader(BasicIo& oIo) const;
//@}
// DATA
BasicIo::AutoPtr io_; //!< Image data io pointer
ExifData exifData_; //!< Exif data container
IptcData iptcData_; //!< IPTC data container
std::string comment_; //!< User comment
}; // class Cr2Image
/*!
@brief Table of special Cr2 decoding functions and find function. See
TiffDecoderItems for details.
*/
class Cr2DecoderItems {
public:
/*!
@brief Find the decoder function for a key.
If the returned pointer is 0, the tag should not be decoded,
else the decoder function should be used.
@param make Camera make
@param extendedTag Extended tag
@param group %Group
@return Pointer to the decoder function
*/
static const DecoderFct findDecoder(const std::string& make,
uint32_t extendedTag,
uint16_t group);
private:
static const TiffDecoderInfo cr2DecoderInfo_[]; //<! CR2 decoder table
}; // class Cr2DecoderItems
/*!
@brief This class models a Canon CR2 header structure.
*/
class Cr2Header {
public:
//! @name Creators
//@{
//! Default constructor
Cr2Header()
: byteOrder_ (littleEndian),
offset_ (0x00000010),
offset2_ (0x00000000)
{}
//@}
//! @name Manipulators
//@{
/*!
@brief Read the CR2 header from a data buffer. Return false if the
data buffer does not contain a CR2 header, else true.
@param pData Pointer to the data buffer.
@param size Number of bytes in the data buffer.
*/
bool read(const byte* pData, uint32_t size);
//@}
//! @name Accessors
//@{
/*!
@brief Write the CR2 header to the binary image \em blob.
This method appends to the blob.
@param blob Binary image to add to.
@throw Error If the header cannot be written.
*/
void write(Blob& blob) const;
/*!
@brief Print debug info for the CR2 header to \em os.
@param os Output stream to write to.
@param prefix Prefix to be written before each line of output.
*/
void print(std::ostream& os, const std::string& prefix ="") const;
//! Return the byte order (little or big endian).
ByteOrder byteOrder() const { return byteOrder_; }
//! Return the offset to the start of the root directory
uint32_t offset() const { return offset_; }
//@}
private:
// DATA
ByteOrder byteOrder_; //!< Applicable byte order
uint32_t offset_; //!< Offset to the start of the root dir
uint32_t offset2_; //!< Bytes 12-15 from the header
static const uint16_t tag_; //!< 42, identifies the buffer as TIFF data
static const char* cr2sig_; //!< Signature for CR2 type TIFF
}; // class Cr2Header
// *****************************************************************************
// template, inline and free functions
// These could be static private functions on Image subclasses but then
// ImageFactory needs to be made a friend.
/*!
@brief Create a new Cr2Image instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newCr2Instance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is a CR2 image.
bool isCr2Type(BasicIo& iIo, bool advance);
} // namespace Exiv2
#endif // #ifndef CR2IMAGE_HPP_

@ -33,7 +33,7 @@ EXIV2_RCSID("@(#) $Id$")
// included header files
#include "image.hpp"
#include "jpgimage.hpp"
//#include "cr2image.hpp"
#include "cr2image.hpp"
#include "crwimage.hpp"
#include "mrwimage.hpp"
#include "tiffimage.hpp"
@ -50,7 +50,7 @@ namespace Exiv2 {
ImageFactory::Registry ImageFactory::registry_[] = {
Registry(ImageType::jpeg, newJpegInstance, isJpegType),
Registry(ImageType::exv, newExvInstance, isExvType),
// Registry(ImageType::cr2, newCr2Instance, isCr2Type),
Registry(ImageType::cr2, newCr2Instance, isCr2Type),
Registry(ImageType::crw, newCrwInstance, isCrwType),
Registry(ImageType::mrw, newMrwInstance, isMrwType),
Registry(ImageType::tiff, newTiffInstance, isTiffType),

@ -155,7 +155,8 @@ namespace Exiv2 {
io_->read(buf.pData_, buf.size_);
if (io_->error() || io_->eof()) throw Error(14);
TiffParser::decode(this, buf.pData_, buf.size_, TiffCreator::create);
TiffParser::decode(this, buf.pData_, buf.size_,
TiffCreator::create, TiffDecoderItems::findDecoder);
} // MrwImage::readMetadata
void MrwImage::writeMetadata()

@ -237,7 +237,8 @@ namespace Exiv2 {
std::cerr << "Exiv2::PngChunk::decode: Exif header found at position " << pos << "\n";
#endif
pos = pos + sizeof(exifHeader);
TiffParser::decode(pImage, exifData.pData_+pos, length-pos, TiffCreator::create);
TiffParser::decode(pImage, exifData.pData_ + pos, length - pos,
TiffCreator::create, TiffDecoderItems::findDecoder);
}
}
}

@ -54,6 +54,7 @@ namespace Exiv2 {
class TiffPrinter;
class TiffIfdMakernote;
struct TiffStructure;
class TiffEntryBase;
// *****************************************************************************
// class definitions
@ -173,6 +174,19 @@ namespace Exiv2 {
}; // class TiffComponent
/*!
@brief Function pointer type for a TiffMetadataDecoder member function
to decode a TIFF component.
*/
typedef void (TiffMetadataDecoder::*DecoderFct)(const TiffEntryBase*);
/*!
Type for a function pointer for a function to decode a TIFF component.
*/
typedef const DecoderFct (*FindDecoderFct)(const std::string& make,
uint32_t extendedTag,
uint16_t group);
/*!
Type for a function pointer for a function to create a TIFF component.
*/

@ -133,7 +133,9 @@ namespace Exiv2 {
io_->read(buf.pData_, len);
if (io_->error() || io_->eof()) throw Error(14);
TiffParser::decode(this, buf.pData_, buf.size_, TiffCreator::create);
TiffParser::decode(this, buf.pData_, buf.size_,
TiffCreator::create, TiffDecoderItems::findDecoder);
} // TiffImage::readMetadata
void TiffImage::writeMetadata()

@ -37,6 +37,7 @@ EXIV2_RCSID("@(#) $Id$")
# include "exv_conf.h"
#endif
#include "types.hpp"
#include "tiffparser.hpp"
#include "tiffcomposite.hpp"
#include "makernote2.hpp"
@ -130,6 +131,38 @@ namespace Exiv2 {
{ Tag::all, Group::minocs5, newTiffArrayElement<unsignedShort, bigEndian>, Group::minocs5 }
};
// TIFF Decoder table for special decoding requirements
const TiffDecoderInfo TiffDecoderItems::tiffDecoderInfo_[] = {
{ "*", Tag::all, Group::ignr, 0 }, // Do not decode tags with group == Group::ignr
{ "OLYMPUS", 0x0100, Group::olympmn, &TiffMetadataDecoder::decodeOlympThumb },
{ "*", 0x014a, Group::ifd0, 0 }, // Todo: Controversial, causes problems with Exiftool
{ "*", Tag::all, Group::sub0_0, &TiffMetadataDecoder::decodeSubIfd },
{ "*", Tag::all, Group::sub0_1, &TiffMetadataDecoder::decodeSubIfd },
{ "*", 0x8649, Group::ifd0, &TiffMetadataDecoder::decodeIrbIptc }
};
bool TiffDecoderInfo::operator==(const TiffDecoderInfo::Key& key) const
{
std::string make(make_);
return ("*" == make || make == key.m_.substr(0, make.length()))
&& (Tag::all == extendedTag_ || key.e_ == extendedTag_)
&& key.g_ == group_;
}
const DecoderFct TiffDecoderItems::findDecoder(const std::string& make,
uint32_t extendedTag,
uint16_t group)
{
DecoderFct decoderFct = &TiffMetadataDecoder::decodeStdTiffEntry;
const TiffDecoderInfo* td = find(tiffDecoderInfo_,
TiffDecoderInfo::Key(make, extendedTag, group));
if (td) {
// This may set decoderFct to 0, meaning that the tag should not be decoded
decoderFct = td->decoderFct_;
}
return decoderFct;
}
TiffComponent::AutoPtr TiffCreator::create(uint32_t extendedTag,
uint16_t group)
{
@ -146,10 +179,11 @@ namespace Exiv2 {
return tc;
} // TiffCreator::create
void TiffParser::decode(Image* pImage,
const byte* pData,
uint32_t size,
TiffCompFactoryFct createFct)
void TiffParser::decode(Image* pImage,
const byte* pData,
uint32_t size,
TiffCompFactoryFct createFct,
FindDecoderFct findDecoderFct)
{
assert(pImage != 0);
assert(pData != 0);
@ -167,7 +201,7 @@ namespace Exiv2 {
TiffReader reader(pData, size, rootDir.get(), state);
rootDir->accept(reader);
TiffMetadataDecoder decoder(pImage, rootDir.get(), 4096);
TiffMetadataDecoder decoder(pImage, rootDir.get(), findDecoderFct, 4096);
rootDir->accept(decoder);
} // TiffParser::decode

@ -90,13 +90,76 @@ namespace Exiv2 {
in TIFF format; no checks are performed.
@param size Length of the data buffer.
@param createFct Factory function to create new TIFF components.
@param findDecoderFct Function to access special decoding info.
*/
static void decode( Image* pImage,
const byte* pData,
uint32_t size,
TiffCompFactoryFct createFct);
TiffCompFactoryFct createFct,
FindDecoderFct findDecoderFct);
}; // class TiffParser
//! TIFF decoder table for functions to decode special cases
struct TiffDecoderInfo {
struct Key;
/*!
@brief Compare a TiffDecoderInfo with a TiffDecoderInfo::Key.
The two are equal if TiffDecoderInfo::make_ equals a substring
of the key of the same size. E.g., decoder info = "OLYMPUS",
key = "OLYMPUS OPTICAL CO.,LTD" (found in the image) match,
the extendedTag is Tag::all or equal to the extended tag of the
key, and the group is equal to that of the key.
*/
bool operator==(const Key& key) const;
//! Return the tag corresponding to the extended tag
uint16_t tag() const { return static_cast<uint16_t>(extendedTag_ & 0xffff); }
// DATA
const char* make_; //!< Camera make for which this decoder function applies
uint32_t extendedTag_; //!< Tag (32 bit so that it can contain special tags)
uint16_t group_; //!< Group that contains the tag
DecoderFct decoderFct_; //!< Decoder function for matching tags
}; // struct TiffDecoderInfo
//! Search key for TIFF decoder structures.
struct TiffDecoderInfo::Key {
//! Constructor
Key(const std::string& m, uint32_t e, uint16_t g) : m_(m), e_(e), g_(g) {}
std::string m_; //!< Camera make
uint32_t e_; //!< Extended tag
uint16_t g_; //!< %Group
};
/*!
@brief Table of special TIFF decoding functions and find function.
This class is separated from the metadata decoder visitor so that
the parser can be parametrized with a different table if needed.
This is used, eg., for CR2 format.
*/
class TiffDecoderItems {
public:
/*!
@brief Find the decoder function for a key.
If the returned pointer is 0, the tag should not be decoded,
else the decoder function should be used.
@param make Camera make
@param extendedTag Extended tag
@param group %Group
@return Pointer to the decoder function
*/
static const DecoderFct findDecoder(const std::string& make,
uint32_t extendedTag,
uint16_t group);
private:
static const TiffDecoderInfo tiffDecoderInfo_[]; //<! TIFF decoder table
}; // class TiffDecoderItems
} // namespace Exiv2
#endif // #ifndef TIFFPARSER_HPP_

@ -38,6 +38,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "tiffvisitor.hpp"
#include "tiffcomposite.hpp"
#include "tiffparser.hpp"
#include "makernote2.hpp"
#include "exif.hpp"
#include "iptc.hpp"
@ -55,24 +56,6 @@ EXIV2_RCSID("@(#) $Id$")
// class member definitions
namespace Exiv2 {
// TIFF Decoder table for special decoding requirements
const TiffDecoderInfo TiffMetadataDecoder::tiffDecoderInfo_[] = {
{ "*", Tag::all, Group::ignr, 0 }, // Do not decode tags with group == Group::ignr
{ "OLYMPUS", 0x0100, Group::olympmn, &TiffMetadataDecoder::decodeOlympThumb },
{ "*", 0x014a, Group::ifd0, 0 }, // Todo: Controversial, causes problems with Exiftool
{ "*", Tag::all, Group::sub0_0, &TiffMetadataDecoder::decodeSubIfd },
{ "*", Tag::all, Group::sub0_1, &TiffMetadataDecoder::decodeSubIfd },
{ "*", 0x8649, Group::ifd0, &TiffMetadataDecoder::decodeIrbIptc }
};
bool TiffDecoderInfo::operator==(const TiffDecoderInfo::Key& key) const
{
std::string make(make_);
return ("*" == make || make == key.m_.substr(0, make.length()))
&& (Tag::all == extendedTag_ || key.e_ == extendedTag_)
&& key.g_ == group_;
}
void TiffFinder::init(uint16_t tag, uint16_t group)
{
tag_ = tag;
@ -135,8 +118,12 @@ namespace Exiv2 {
TiffMetadataDecoder::TiffMetadataDecoder(Image* pImage,
TiffComponent* const pRoot,
FindDecoderFct findDecoderFct,
uint32_t threshold)
: pImage_(pImage), pRoot_(pRoot), threshold_(threshold)
: pImage_(pImage),
pRoot_(pRoot),
findDecoderFct_(findDecoderFct),
threshold_(threshold)
{
// Find camera make
TiffFinder finder(0x010f, Group::ifd0);
@ -252,15 +239,18 @@ namespace Exiv2 {
groupType_[object->group()] = object->pValue()->toLong();
}
const TiffDecoderInfo* td = find(tiffDecoderInfo_,
TiffDecoderInfo::Key(make_, object->tag(), object->group()));
if (td) {
// skip decoding if td->decoderFct_ == 0
if (td->decoderFct_) {
EXV_CALL_MEMBER_FN(*this, td->decoderFct_)(object);
}
return;
const DecoderFct decoderFct = findDecoderFct_(make_,
object->tag(),
object->group());
// skip decoding if decoderFct == 0
if (decoderFct) {
EXV_CALL_MEMBER_FN(*this, decoderFct)(object);
}
} // TiffMetadataDecoder::decodeTiffEntry
void TiffMetadataDecoder::decodeStdTiffEntry(const TiffEntryBase* object)
{
assert(object !=0);
assert(pImage_ != 0);
// "Normal" tag has low priority: only decode if it doesn't exist yet.
// Todo: ExifKey should have an appropriate c'tor, it should not be

@ -196,41 +196,6 @@ namespace Exiv2 {
TiffComponent* tiffComponent_;
}; // class TiffFinder
//! Function pointer type for a function to decode a TIFF component.
typedef void (TiffMetadataDecoder::*DecoderFct)(const TiffEntryBase*);
//! TIFF decoder table
struct TiffDecoderInfo {
struct Key;
/*!
@brief Compare a TiffDecoderInfo with a TiffDecoderInfo::Key.
The two are equal if TiffDecoderInfo::make_ equals a substring
of the key of the same size. E.g., decoder info = "OLYMPUS",
key = "OLYMPUS OPTICAL CO.,LTD" (found in the image) match,
the extendedTag is Tag::all or equal to the extended tag of the
key, and the group is equal to that of the key.
*/
bool operator==(const Key& key) const;
//! Return the tag corresponding to the extended tag
uint16_t tag() const { return static_cast<uint16_t>(extendedTag_ & 0xffff); }
// DATA
const char* make_; //!< Camera make for which this decoder function applies
uint32_t extendedTag_; //!< Tag (32 bit so that it can contain special tags)
uint16_t group_; //!< Group that contains the tag
DecoderFct decoderFct_; //!< Decoder function for matching tags
}; // struct TiffDecoderInfo
//! Search key for TIFF decoder structures.
struct TiffDecoderInfo::Key {
//! Constructor
Key(const std::string& m, uint32_t e, uint16_t g) : m_(m), e_(e), g_(g) {}
std::string m_; //!< Camera make
uint32_t e_; //!< Extended tag
uint16_t g_; //!< %Group
};
/*!
@brief TIFF composite visitor to decode metadata from the TIFF tree and
add it to an Image, which is supplied in the constructor (Visitor
@ -250,6 +215,7 @@ namespace Exiv2 {
*/
TiffMetadataDecoder(Image* pImage,
TiffComponent* const pRoot,
FindDecoderFct findDecoderFct =0,
uint32_t threshold =0);
//! Virtual destructor
virtual ~TiffMetadataDecoder() {}
@ -276,8 +242,10 @@ namespace Exiv2 {
//! Decode an array element
virtual void visitArrayElement(TiffArrayElement* object);
//! Decode a standard TIFF entry
//! Entry function, determines how to decode each tag
void decodeTiffEntry(const TiffEntryBase* object);
//! Decode a standard TIFF entry
void decodeStdTiffEntry(const TiffEntryBase* object);
//! Decode Olympus Thumbnail from the TIFF makernote into IFD1
void decodeOlympThumb(const TiffEntryBase* object);
//! Decode SubIFD contents to Image group if it contains primary image data
@ -293,6 +261,7 @@ namespace Exiv2 {
// DATA
Image* pImage_; //!< Pointer to the image to which the metadata is added
TiffComponent* const pRoot_; //!< Root element of the composite
const FindDecoderFct findDecoderFct_; //!< Ptr to the function to find special decoding functions
const uint32_t threshold_; //!< Threshold, see constructor documentation.
std::string make_; //!< Camera make, determined from the tags to decode
@ -300,8 +269,6 @@ namespace Exiv2 {
typedef std::map<uint16_t, uint32_t> GroupType;
GroupType groupType_; //!< NewSubfileType for each group
static const TiffDecoderInfo tiffDecoderInfo_[]; //<! TIFF decoder table
}; // class TiffMetadataDecoder
/*!

Loading…
Cancel
Save