TIFF parser checkpoint (experimental): Improved CR2 support (changes in the TIFF structure table), added support for Jpeg thumbnails, enhanced TiffDirectory so that the next pointer is optional.

v0.27.3
Andreas Huggel 19 years ago
parent e6c88889cb
commit 5b57a1749b

@ -64,14 +64,14 @@ namespace Exiv2 {
TiffComponent::AutoPtr TiffCanonCreator::create(uint32_t extendedTag, TiffComponent::AutoPtr TiffCanonCreator::create(uint32_t extendedTag,
uint16_t group) uint16_t group)
{ {
const TiffStructure* ts = find(tiffStructure_,
TiffStructure::Key(extendedTag, group));
TiffComponent::AutoPtr tc(0); TiffComponent::AutoPtr tc(0);
uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff); uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff);
const TiffStructure* ts = find(tiffStructure_,
TiffStructure::Key(extendedTag, group));
if (ts && ts->newTiffCompFct_) { if (ts && ts->newTiffCompFct_) {
tc = ts->newTiffCompFct_(tag, ts); tc = ts->newTiffCompFct_(tag, ts);
} }
if (!ts) { if (!ts && extendedTag != Tag::next) {
tc = TiffComponent::AutoPtr(new TiffEntry(tag, group)); tc = TiffComponent::AutoPtr(new TiffEntry(tag, group));
} }
return tc; return tc;

@ -988,6 +988,10 @@ namespace Exiv2 {
thumbnail = Thumbnail::AutoPtr(new TiffThumbnail); thumbnail = Thumbnail::AutoPtr(new TiffThumbnail);
} }
} }
else {
pos = findKey(ExifKey("Exif.Thumbnail.JPEGInterchangeFormat"));
if (pos != end()) thumbnail = Thumbnail::AutoPtr(new JpegThumbnail);
}
return thumbnail; return thumbnail;
} // ExifData::getThumbnail } // ExifData::getThumbnail

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

@ -28,10 +28,6 @@
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$"); EXIV2_RCSID("@(#) $Id$");
// Define DEBUG to output debug information to std::cerr, e.g, by calling make
// like this: make DEFS=-DDEBUG tiffcomposite.o
//#define DEBUG
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#ifdef _MSC_VER #ifdef _MSC_VER
@ -60,21 +56,6 @@ namespace Exiv2 {
|| Tag::all == extendedTag_ && key.g_ == group_; || Tag::all == extendedTag_ && key.g_ == group_;
} }
void TiffHeade2::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";
} // TiffHeade2::print
TiffDirectory::~TiffDirectory() TiffDirectory::~TiffDirectory()
{ {
Components::iterator b = components_.begin(); Components::iterator b = components_.begin();
@ -107,27 +88,6 @@ namespace Exiv2 {
} }
} // TiffArrayEntry::~TiffArrayEntry } // TiffArrayEntry::~TiffArrayEntry
const uint16_t TiffHeade2::tag_ = 42;
bool TiffHeade2::read(const byte* pData, uint32_t size)
{
if (size < 8) 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_);
return true;
} // TiffHeade2::read
std::string TiffComponent::groupName() const std::string TiffComponent::groupName() const
{ {
// Todo: This mapping should be a table and it belongs somewhere else // Todo: This mapping should be a table and it belongs somewhere else
@ -182,7 +142,7 @@ namespace Exiv2 {
void TiffDirectory::doAddNext(TiffComponent::AutoPtr tiffComponent) void TiffDirectory::doAddNext(TiffComponent::AutoPtr tiffComponent)
{ {
pNext_ = tiffComponent.release(); if (hasNext_) pNext_ = tiffComponent.release();
} // TiffDirectory::doAddNext } // TiffDirectory::doAddNext
void TiffSubIfd::doAddNext(TiffComponent::AutoPtr tiffComponent) void TiffSubIfd::doAddNext(TiffComponent::AutoPtr tiffComponent)
@ -205,6 +165,16 @@ namespace Exiv2 {
visitor.visitEntry(this); visitor.visitEntry(this);
} // TiffEntry::doAccept } // TiffEntry::doAccept
void TiffDataEntry::doAccept(TiffVisitor& visitor)
{
visitor.visitDataEntry(this);
} // TiffDataEntry::doAccept
void TiffSizeEntry::doAccept(TiffVisitor& visitor)
{
visitor.visitSizeEntry(this);
} // TiffSizeEntry::doAccept
void TiffDirectory::doAccept(TiffVisitor& visitor) void TiffDirectory::doAccept(TiffVisitor& visitor)
{ {
visitor.visitDirectory(this); visitor.visitDirectory(this);
@ -214,9 +184,7 @@ namespace Exiv2 {
(*i)->accept(visitor); (*i)->accept(visitor);
} }
if (visitor.go()) visitor.visitDirectoryNext(this); if (visitor.go()) visitor.visitDirectoryNext(this);
if (pNext_) { if (pNext_) pNext_->accept(visitor);
pNext_->accept(visitor);
}
if (visitor.go()) visitor.visitDirectoryEnd(this); if (visitor.go()) visitor.visitDirectoryEnd(this);
} // TiffDirectory::doAccept } // TiffDirectory::doAccept
@ -293,4 +261,24 @@ namespace Exiv2 {
ts->group_)); ts->group_));
} }
TiffComponent::AutoPtr newTiffThumbData(uint16_t tag,
const TiffStructure* ts)
{
assert(ts);
return TiffComponent::AutoPtr(new TiffDataEntry(tag,
ts->group_,
0x0202,
Group::ifd1));
}
TiffComponent::AutoPtr newTiffThumbSize(uint16_t tag,
const TiffStructure* ts)
{
assert(ts);
return TiffComponent::AutoPtr(new TiffSizeEntry(tag,
ts->group_,
0x0201,
Group::ifd1));
}
} // namespace Exiv2 } // namespace Exiv2

@ -72,6 +72,7 @@ namespace Exiv2 {
const uint16_t gps = 4; //!< GPS IFD const uint16_t gps = 4; //!< GPS IFD
const uint16_t iop = 5; //!< Interoperability IFD const uint16_t iop = 5; //!< Interoperability IFD
const uint16_t mn = 256; //!< Makernote const uint16_t mn = 256; //!< Makernote
const uint16_t ignr = 511; //!< Read but do not decode
} }
/*! /*!
@ -86,65 +87,6 @@ namespace Exiv2 {
const uint32_t all = 0x40000; //!< Special tag: all tags in a group const uint32_t all = 0x40000; //!< Special tag: all tags in a group
} }
/*!
@brief This class models a TIFF header structure.
*/
class TiffHeade2 {
public:
//! @name Creators
//@{
//! Default constructor
TiffHeade2()
: byteOrder_ (littleEndian),
offset_ (0x00000008)
{}
//@}
//! @name Manipulators
//@{
/*!
@brief Read the TIFF header from a data buffer. Return false if the
data buffer does not contain a TIFF 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 TIFF 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 TIFF 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
static const uint16_t tag_; //!< 42, identifies the buffer as TIFF data
}; // class TiffHeade2
/*! /*!
@brief Interface class for components of a TIFF directory hierarchy @brief Interface class for components of a TIFF directory hierarchy
(Composite pattern). Both TIFF directories as well as entries (Composite pattern). Both TIFF directories as well as entries
@ -342,6 +284,84 @@ namespace Exiv2 {
}; // class TiffEntry }; // class TiffEntry
/*!
@brief A standard TIFF IFD entry consisting of a value which is an offset
to a data area and the data area. The size of the data area is
provided in a related TiffSizeEntry, tag and group of which are set
in the constructor. This component is used, e.g., for
\em Exif.Thumbnail.JPEGInterchangeFormat for which the size is
provided in \em Exif.Thumbnail.JPEGInterchangeFormatLength.
*/
class TiffDataEntry : public TiffEntryBase {
public:
//! @name Creators
//@{
//! Constructor
TiffDataEntry(uint16_t tag, uint16_t group, uint16_t szTag, uint16_t szGroup)
: TiffEntryBase(tag, group), szTag_(szTag), szGroup_(szGroup) {}
//! Virtual destructor.
virtual ~TiffDataEntry() {}
//@}
//! @name Accessors
//@{
//! Return the group of the entry which has the size
uint16_t szTag() const { return szTag_; }
//! Return the group of the entry which has the size
uint16_t szGroup() const { return szGroup_; }
//@}
private:
//! @name Manipulators
//@{
virtual void doAccept(TiffVisitor& visitor);
//@}
private:
// DATA
const uint16_t szTag_; //!< Tag of the entry with the size
const uint16_t szGroup_; //!< Group of the entry with the size
}; // class TiffDataEntry
/*!
@brief A TIFF IFD entry containing the size of a data area of a related
TiffDataEntry. This component is used, e.g. for
\em Exif.Thumbnail.JPEGInterchangeFormatLength, which contains the
size of \em Exif.Thumbnail.JPEGInterchangeFormat.
*/
class TiffSizeEntry : public TiffEntryBase {
public:
//! @name Creators
//@{
//! Constructor
TiffSizeEntry(uint16_t tag, uint16_t group, uint16_t dtTag, uint16_t dtGroup)
: TiffEntryBase(tag, group), dtTag_(dtTag), dtGroup_(dtGroup) {}
//! Virtual destructor.
virtual ~TiffSizeEntry() {}
//@}
//! @name Accessors
//@{
//! Return the group of the related entry which has the data area
uint16_t dtTag() const { return dtTag_; }
//! Return the group of the related entry which has the data area
uint16_t dtGroup() const { return dtGroup_; }
//@}
private:
//! @name Manipulators
//@{
virtual void doAccept(TiffVisitor& visitor);
//@}
private:
// DATA
const uint16_t dtTag_; //!< Tag of the entry with the data area
const uint16_t dtGroup_; //!< Group of the entry with the data area
}; // class TiffSizeEntry
/*! /*!
@brief This class models a TIFF directory (%Ifd). It is a composite @brief This class models a TIFF directory (%Ifd). It is a composite
component of the TIFF tree. component of the TIFF tree.
@ -352,12 +372,18 @@ namespace Exiv2 {
//! @name Creators //! @name Creators
//@{ //@{
//! Default constructor //! Default constructor
TiffDirectory(uint16_t tag, uint16_t group) TiffDirectory(uint16_t tag, uint16_t group, bool hasNext =true)
: TiffComponent(tag, group), pNext_(0) {} : TiffComponent(tag, group), hasNext_(hasNext), pNext_(0) {}
//! Virtual destructor //! Virtual destructor
virtual ~TiffDirectory(); virtual ~TiffDirectory();
//@} //@}
//! @name Manipulators
//@{
//! Return true if the directory has a next pointer
bool hasNext() const { return hasNext_; }
//@}
private: private:
//! @name Manipulators //! @name Manipulators
//@{ //@{
@ -369,6 +395,7 @@ namespace Exiv2 {
private: private:
// DATA // DATA
Components components_; //!< List of components in this directory Components components_; //!< List of components in this directory
const bool hasNext_; //!< True if the directory has a next pointer
TiffComponent* pNext_; //!< Pointer to the next IFD TiffComponent* pNext_; //!< Pointer to the next IFD
}; // class TiffDirectory }; // class TiffDirectory
@ -525,6 +552,14 @@ namespace Exiv2 {
TiffComponent::AutoPtr newTiffArrayElement(uint16_t tag, TiffComponent::AutoPtr newTiffArrayElement(uint16_t tag,
const TiffStructure* ts); const TiffStructure* ts);
//! Function to create and initialize a new TIFF entry for a Jpeg thumbnail (data)
TiffComponent::AutoPtr newTiffThumbData(uint16_t tag,
const TiffStructure* ts);
//! Function to create and initialize a new TIFF entry for a Jpeg thumbnail (size)
TiffComponent::AutoPtr newTiffThumbSize(uint16_t tag,
const TiffStructure* ts);
} // namespace Exiv2 } // namespace Exiv2
#endif // #ifndef TIFFCOMPOSITE_HPP_ #endif // #ifndef TIFFCOMPOSITE_HPP_

@ -29,10 +29,6 @@
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$"); EXIV2_RCSID("@(#) $Id$");
// Define DEBUG to output debug information to std::cerr, e.g, by calling make
// like this: make DEFS=-DDEBUG tiffparser.o
//#define DEBUG
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#ifdef _MSC_VER #ifdef _MSC_VER
@ -48,7 +44,9 @@ EXIV2_RCSID("@(#) $Id$");
#include "futils.hpp" #include "futils.hpp"
// + standard includes // + standard includes
#include <string>
#include <iostream> #include <iostream>
#include <iomanip>
#include <cassert> #include <cassert>
// ***************************************************************************** // *****************************************************************************
@ -185,6 +183,42 @@ namespace Exiv2 {
return isTiffType(iIo, advance); return isTiffType(iIo, advance);
} }
const uint16_t TiffHeade2::tag_ = 42;
bool TiffHeade2::read(const byte* pData, uint32_t size)
{
if (size < 8) 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_);
return true;
} // TiffHeade2::read
void TiffHeade2::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";
} // TiffHeade2::print
// ************************************************************************* // *************************************************************************
// free functions // free functions

@ -161,6 +161,65 @@ namespace Exiv2 {
}; // class TiffImage }; // class TiffImage
/*!
@brief This class models a TIFF header structure.
*/
class TiffHeade2 {
public:
//! @name Creators
//@{
//! Default constructor
TiffHeade2()
: byteOrder_ (littleEndian),
offset_ (0x00000008)
{}
//@}
//! @name Manipulators
//@{
/*!
@brief Read the TIFF header from a data buffer. Return false if the
data buffer does not contain a TIFF 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 TIFF 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 TIFF 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
static const uint16_t tag_; //!< 42, identifies the buffer as TIFF data
}; // class TiffHeade2
// ***************************************************************************** // *****************************************************************************
// template, inline and free functions // template, inline and free functions

@ -29,10 +29,6 @@
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$"); EXIV2_RCSID("@(#) $Id$");
// Define DEBUG to output debug information to std::cerr, e.g, by calling make
// like this: make DEFS=-DDEBUG tiffparser.o
//#define DEBUG
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#ifdef _MSC_VER #ifdef _MSC_VER
@ -44,6 +40,7 @@ EXIV2_RCSID("@(#) $Id$");
#include "tiffparser.hpp" #include "tiffparser.hpp"
#include "tiffcomposite.hpp" #include "tiffcomposite.hpp"
#include "tiffvisitor.hpp" #include "tiffvisitor.hpp"
#include "tiffimage.hpp"
#include "error.hpp" #include "error.hpp"
// + standard includes // + standard includes
@ -61,6 +58,9 @@ EXIV2_RCSID("@(#) $Id$");
images which need to be loaded completely. images which need to be loaded completely.
+ TiffComponent: should it have end() and setEnd() or pData and size? + TiffComponent: should it have end() and setEnd() or pData and size?
+ Can NewTiffCompFct and TiffCompFactoryFct be combined? + Can NewTiffCompFct and TiffCompFactoryFct be combined?
+ Create function is repeated when actually only the table changes. Fix it.
+ CR2 Makernotes don't seem to have a next pointer but Canon Jpeg Makernotes
do. What a mess. (That'll become an issue when it comes to writing to CR2)
in crwimage.* : in crwimage.* :
@ -93,27 +93,31 @@ namespace Exiv2 {
{ 0x8825, Group::ifd0, newTiffSubIfd, Group::gps }, { 0x8825, Group::ifd0, newTiffSubIfd, Group::gps },
{ 0xa005, Group::exif, newTiffSubIfd, Group::iop }, { 0xa005, Group::exif, newTiffSubIfd, Group::iop },
{ 0x927c, Group::exif, newTiffMnEntry, Group::mn }, { 0x927c, Group::exif, newTiffMnEntry, Group::mn },
{ Tag::next, Group::ifd0, newTiffDirectory, Group::ifd0 } { 0x0201, Group::ifd1, newTiffThumbData, Group::ifd1 },
{ 0x0202, Group::ifd1, newTiffThumbSize, Group::ifd1 },
{ Tag::next, Group::ifd0, newTiffDirectory, Group::ifd1 },
{ Tag::next, Group::ifd1, newTiffDirectory, Group::ignr },
{ Tag::next, Group::ignr, newTiffDirectory, Group::ignr }
}; };
TiffComponent::AutoPtr TiffCreator::create(uint32_t extendedTag, TiffComponent::AutoPtr TiffCreator::create(uint32_t extendedTag,
uint16_t group) uint16_t group)
{ {
const TiffStructure* ts = find(tiffStructure_,
TiffStructure::Key(extendedTag, group));
TiffComponent::AutoPtr tc(0); TiffComponent::AutoPtr tc(0);
uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff); uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff);
const TiffStructure* ts = find(tiffStructure_,
TiffStructure::Key(extendedTag, group));
if (ts && ts->newTiffCompFct_) { if (ts && ts->newTiffCompFct_) {
tc = ts->newTiffCompFct_(tag, ts); tc = ts->newTiffCompFct_(tag, ts);
} }
if (!ts) { if (!ts && extendedTag != Tag::next) {
tc = TiffComponent::AutoPtr(new TiffEntry(tag, group)); tc = TiffComponent::AutoPtr(new TiffEntry(tag, group));
} }
return tc; return tc;
} // TiffCreator::create } // TiffCreator::create
void TiffParser::decode(Image* pImage, void TiffParser::decode(Image* pImage,
const byte* pData, const byte* pData,
uint32_t size, uint32_t size,
TiffCompFactoryFct createFct) TiffCompFactoryFct createFct)
{ {

@ -77,6 +77,16 @@ namespace Exiv2 {
findObject(object); findObject(object);
} }
void TiffFinder::visitDataEntry(TiffDataEntry* object)
{
findObject(object);
}
void TiffFinder::visitSizeEntry(TiffSizeEntry* object)
{
findObject(object);
}
void TiffFinder::visitDirectory(TiffDirectory* object) void TiffFinder::visitDirectory(TiffDirectory* object)
{ {
findObject(object); findObject(object);
@ -112,6 +122,16 @@ namespace Exiv2 {
decodeTiffEntry(object); decodeTiffEntry(object);
} }
void TiffMetadataDecoder::visitDataEntry(TiffDataEntry* object)
{
decodeTiffEntry(object);
}
void TiffMetadataDecoder::visitSizeEntry(TiffSizeEntry* object)
{
decodeTiffEntry(object);
}
void TiffMetadataDecoder::visitDirectory(TiffDirectory* object) void TiffMetadataDecoder::visitDirectory(TiffDirectory* object)
{ {
// Nothing to do // Nothing to do
@ -136,11 +156,14 @@ namespace Exiv2 {
{ {
assert(object != 0); assert(object != 0);
if (object->group() == Group::ignr) return;
// Todo: ExifKey should have an appropriate c'tor, it should not be // Todo: ExifKey should have an appropriate c'tor, it should not be
// necessary to use groupName here // necessary to use groupName here
ExifKey k(object->tag(), object->groupName()); ExifKey k(object->tag(), object->groupName());
assert(pImage_ != 0); assert(pImage_ != 0);
pImage_->exifData().add(k, object->pValue()); pImage_->exifData().add(k, object->pValue());
} // TiffMetadataDecoder::decodeTiffEntry } // TiffMetadataDecoder::decodeTiffEntry
void TiffMetadataDecoder::visitArrayEntry(TiffArrayEntry* object) void TiffMetadataDecoder::visitArrayEntry(TiffArrayEntry* object)
@ -177,6 +200,21 @@ namespace Exiv2 {
printTiffEntry(object, prefix()); printTiffEntry(object, prefix());
} // TiffPrinter::visitEntry } // TiffPrinter::visitEntry
void TiffPrinter::visitDataEntry(TiffDataEntry* object)
{
printTiffEntry(object, prefix());
if (object->pValue()) {
os_ << prefix() << "Data area "
<< object->pValue()->sizeDataArea()
<< " bytes.\n";
}
} // TiffPrinter::visitEntry
void TiffPrinter::visitSizeEntry(TiffSizeEntry* object)
{
printTiffEntry(object, prefix());
}
void TiffPrinter::visitDirectory(TiffDirectory* object) void TiffPrinter::visitDirectory(TiffDirectory* object)
{ {
assert(object != 0); assert(object != 0);
@ -193,8 +231,10 @@ namespace Exiv2 {
void TiffPrinter::visitDirectoryNext(TiffDirectory* object) void TiffPrinter::visitDirectoryNext(TiffDirectory* object)
{ {
decIndent(); decIndent();
if (object->pNext_) os_ << prefix() << "Next directory:\n"; if (object->hasNext()) {
else os_ << prefix() << "No next directory\n"; if (object->pNext_) os_ << prefix() << "Next directory:\n";
else os_ << prefix() << "No next directory\n";
}
} // TiffPrinter::visitDirectoryNext } // TiffPrinter::visitDirectoryNext
void TiffPrinter::visitDirectoryEnd(TiffDirectory* object) void TiffPrinter::visitDirectoryEnd(TiffDirectory* object)
@ -318,6 +358,60 @@ namespace Exiv2 {
readTiffEntry(object); readTiffEntry(object);
} }
void TiffReader::visitDataEntry(TiffDataEntry* object)
{
assert(object != 0);
readTiffEntry(object);
TiffFinder finder(object->szTag(), object->szGroup());
pRoot_->accept(finder);
TiffEntryBase* te = dynamic_cast<TiffEntryBase*>(finder.result());
if (te && te->pValue()) {
long size = te->pValue()->toLong();
long offset = object->pValue()->toLong();
if (baseOffset() + offset + size <= size_) {
object->pValue_->setDataArea(pData_ + baseOffset() + offset, size);
}
#ifndef SUPPRESS_WARNINGS
else {
std::cerr << "Warning: "
<< "Directory " << object->groupName()
<< ", entry 0x" << std::setw(4)
<< std::setfill('0') << std::hex << object->tag()
<< " Data area exceeds data buffer, ignoring it.\n";
}
#endif
}
}
void TiffReader::visitSizeEntry(TiffSizeEntry* object)
{
assert(object != 0);
readTiffEntry(object);
TiffFinder finder(object->dtTag(), object->dtGroup());
pRoot_->accept(finder);
TiffEntryBase* te = dynamic_cast<TiffEntryBase*>(finder.result());
if (te && te->pValue()) {
long offset = te->pValue()->toLong();
long size = object->pValue()->toLong();
if (baseOffset() + offset + size <= size_) {
te->pValue_->setDataArea(pData_ + baseOffset() + offset, size);
}
#ifndef SUPPRESS_WARNINGS
else {
std::cerr << "Warning: "
<< "Directory " << object->groupName()
<< ", entry 0x" << std::setw(4)
<< std::setfill('0') << std::hex << object->tag()
<< " Data area exceeds data buffer, ignoring it.\n";
}
#endif
}
}
void TiffReader::visitDirectory(TiffDirectory* object) void TiffReader::visitDirectory(TiffDirectory* object)
{ {
assert(object != 0); assert(object != 0);
@ -347,6 +441,7 @@ namespace Exiv2 {
} }
uint16_t tag = getUShort(p, byteOrder()); uint16_t tag = getUShort(p, byteOrder());
TiffComponent::AutoPtr tc = create(tag, object->group()); TiffComponent::AutoPtr tc = create(tag, object->group());
assert(tc.get());
tc->setStart(p); tc->setStart(p);
object->addChild(tc); object->addChild(tc);
p += 12; p += 12;
@ -360,20 +455,32 @@ namespace Exiv2 {
#endif #endif
return; return;
} }
uint32_t next = getLong(p, byteOrder()); if (object->hasNext()) {
if (next) { TiffComponent::AutoPtr tc(0);
TiffComponent::AutoPtr tc = create(Tag::next, object->group()); uint32_t next = getLong(p, byteOrder());
if (baseOffset() + next > size_) { if (next) {
tc = create(Tag::next, object->group());
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
std::cerr << "Error: " if (tc.get() == 0) {
<< "Directory " << object->groupName() << ": " std::cerr << "Warning: "
<< " Next pointer is out of bounds.\n"; << "Directory " << object->groupName()
<< " has an unhandled next pointer.\n";
}
#endif #endif
return;
} }
tc->setStart(pData_ + baseOffset() + next); if (tc.get()) {
object->addNext(tc); if (baseOffset() + next > size_) {
} #ifndef SUPPRESS_WARNINGS
std::cerr << "Error: "
<< "Directory " << object->groupName() << ": "
<< " Next pointer is out of bounds.\n";
#endif
return;
}
tc->setStart(pData_ + baseOffset() + next);
object->addNext(tc);
}
} // object->hasNext()
} // TiffReader::visitDirectory } // TiffReader::visitDirectory
@ -539,6 +646,7 @@ namespace Exiv2 {
for (uint16_t i = 0; i < static_cast<uint16_t>(object->count()); ++i) { for (uint16_t i = 0; i < static_cast<uint16_t>(object->count()); ++i) {
uint16_t tag = i; uint16_t tag = i;
TiffComponent::AutoPtr tc = create(tag, object->elGroup()); TiffComponent::AutoPtr tc = create(tag, object->elGroup());
assert(tc.get());
tc->setStart(object->pData() + i * 2); tc->setStart(object->pData() + i * 2);
object->addChild(tc); object->addChild(tc);
} }

@ -84,6 +84,10 @@ namespace Exiv2 {
void setGo(bool go) { go_ = go; } void setGo(bool go) { go_ = go; }
//! Operation to perform for a TIFF entry //! Operation to perform for a TIFF entry
virtual void visitEntry(TiffEntry* object) =0; virtual void visitEntry(TiffEntry* object) =0;
//! Operation to perform for a TIFF data entry
virtual void visitDataEntry(TiffDataEntry* object) =0;
//! Operation to perform for a TIFF size entry
virtual void visitSizeEntry(TiffSizeEntry* object) =0;
//! Operation to perform for a TIFF directory //! Operation to perform for a TIFF directory
virtual void visitDirectory(TiffDirectory* object) =0; virtual void visitDirectory(TiffDirectory* object) =0;
/*! /*!
@ -142,6 +146,10 @@ namespace Exiv2 {
//@{ //@{
//! Find tag and group in a TIFF entry //! Find tag and group in a TIFF entry
virtual void visitEntry(TiffEntry* object); virtual void visitEntry(TiffEntry* object);
//! Find tag and group in a TIFF data entry
virtual void visitDataEntry(TiffDataEntry* object);
//! Find tag and group in a TIFF size entry
virtual void visitSizeEntry(TiffSizeEntry* object);
//! Find tag and group in a TIFF directory //! Find tag and group in a TIFF directory
virtual void visitDirectory(TiffDirectory* object); virtual void visitDirectory(TiffDirectory* object);
//! Find tag and group in a TIFF sub-IFD //! Find tag and group in a TIFF sub-IFD
@ -196,6 +204,10 @@ namespace Exiv2 {
//@{ //@{
//! Decode a TIFF entry //! Decode a TIFF entry
virtual void visitEntry(TiffEntry* object); virtual void visitEntry(TiffEntry* object);
//! Decode a TIFF data entry
virtual void visitDataEntry(TiffDataEntry* object);
//! Decode a TIFF size entry
virtual void visitSizeEntry(TiffSizeEntry* object);
//! Decode a TIFF directory //! Decode a TIFF directory
virtual void visitDirectory(TiffDirectory* object); virtual void visitDirectory(TiffDirectory* object);
//! Decode a TIFF sub-IFD //! Decode a TIFF sub-IFD
@ -290,6 +302,10 @@ namespace Exiv2 {
//@{ //@{
//! Read a TIFF entry from the data buffer //! Read a TIFF entry from the data buffer
virtual void visitEntry(TiffEntry* object); virtual void visitEntry(TiffEntry* object);
//! Read a TIFF data entry from the data buffer
virtual void visitDataEntry(TiffDataEntry* object);
//! Read a TIFF size entry from the data buffer
virtual void visitSizeEntry(TiffSizeEntry* object);
//! Read a TIFF directory from the data buffer //! Read a TIFF directory from the data buffer
virtual void visitDirectory(TiffDirectory* object); virtual void visitDirectory(TiffDirectory* object);
//! Read a TIFF sub-IFD from the data buffer //! Read a TIFF sub-IFD from the data buffer
@ -353,6 +369,10 @@ namespace Exiv2 {
//@{ //@{
//! Print a TIFF entry. //! Print a TIFF entry.
virtual void visitEntry(TiffEntry* object); virtual void visitEntry(TiffEntry* object);
//! Print a TIFF data entry.
virtual void visitDataEntry(TiffDataEntry* object);
//! Print a TIFF size entry.
virtual void visitSizeEntry(TiffSizeEntry* object);
//! Print a TIFF directory //! Print a TIFF directory
virtual void visitDirectory(TiffDirectory* object); virtual void visitDirectory(TiffDirectory* object);
//! Print header before next directory //! Print header before next directory

Loading…
Cancel
Save