From fe512e1470df4dd42d3502fc6418c8a89380ac57 Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Fri, 23 Jun 2006 12:08:27 +0000 Subject: [PATCH] TiffParser can now be parametrized with a decoder. Added Cr2Image which uses this to filter not applicable IFD0 tags. --- src/Makefile | 1 + src/cr2image.cpp | 285 ++++++++++++++++++++++++++++++++++++++++++ src/cr2image.hpp | 264 ++++++++++++++++++++++++++++++++++++++ src/imgreg.cpp | 4 +- src/mrwimage.cpp | 3 +- src/pngchunk.cpp | 3 +- src/tiffcomposite.hpp | 14 +++ src/tiffimage.cpp | 4 +- src/tiffparser.cpp | 44 ++++++- src/tiffparser.hpp | 65 +++++++++- src/tiffvisitor.cpp | 44 +++---- src/tiffvisitor.hpp | 43 +------ 12 files changed, 698 insertions(+), 76 deletions(-) create mode 100644 src/cr2image.cpp create mode 100644 src/cr2image.hpp diff --git a/src/Makefile b/src/Makefile index e9f10a7c..7b03d9f1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 \ diff --git a/src/cr2image.cpp b/src/cr2image.cpp new file mode 100644 index 00000000..727867cf --- /dev/null +++ b/src/cr2image.cpp @@ -0,0 +1,285 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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) + 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 +#include +#include +#include + +// ***************************************************************************** +// 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(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 diff --git a/src/cr2image.hpp b/src/cr2image.hpp new file mode 100644 index 00000000..ae7ab2e8 --- /dev/null +++ b/src/cr2image.hpp @@ -0,0 +1,264 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2006 Andreas Huggel + * + * 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) + ahuggel@gmx.net + @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 + +// ***************************************************************************** +// 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;
+ 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_[]; //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() diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp index 24b95e50..9aed4a6e 100644 --- a/src/pngchunk.cpp +++ b/src/pngchunk.cpp @@ -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); } } } diff --git a/src/tiffcomposite.hpp b/src/tiffcomposite.hpp index 8d3a001e..ff83737d 100644 --- a/src/tiffcomposite.hpp +++ b/src/tiffcomposite.hpp @@ -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. */ diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index 2ba51564..6dd5f7a6 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -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() diff --git a/src/tiffparser.cpp b/src/tiffparser.cpp index 629b43f3..d1c371e1 100644 --- a/src/tiffparser.cpp +++ b/src/tiffparser.cpp @@ -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, 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 diff --git a/src/tiffparser.hpp b/src/tiffparser.hpp index 8958401c..60903720 100644 --- a/src/tiffparser.hpp +++ b/src/tiffparser.hpp @@ -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(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_[]; //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 diff --git a/src/tiffvisitor.hpp b/src/tiffvisitor.hpp index d39c07de..a56b8bdc 100644 --- a/src/tiffvisitor.hpp +++ b/src/tiffvisitor.hpp @@ -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(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 GroupType; GroupType groupType_; //!< NewSubfileType for each group - static const TiffDecoderInfo tiffDecoderInfo_[]; //