Experimental TIFF read-only support, without Makernotes. As a side-effect, the parser also handles NEF images. Only tried on Linux so far.
This commit is contained in:
parent
bec3e47dfe
commit
70695ded92
@ -53,7 +53,8 @@ CCHDR = exv_conf.h exv_msvc.h mn.hpp rcsid.hpp
|
||||
CCSRC = basicio.cpp canonmn.cpp crwimage.cpp datasets.cpp error.cpp exif.cpp \
|
||||
futils.cpp fujimn.cpp ifd.cpp image.cpp imgreg.cpp iptc.cpp jpgimage.cpp \
|
||||
makernote.cpp metadatum.cpp nikonmn.cpp olympusmn.cpp panasonicmn.cpp \
|
||||
sigmamn.cpp sonymn.cpp tags.cpp types.cpp value.cpp
|
||||
sigmamn.cpp sonymn.cpp tags.cpp tiffimage.cpp tiffparser.cpp types.cpp \
|
||||
value.cpp
|
||||
|
||||
# Add library C source files to this list
|
||||
ifndef HAVE_TIMEGM
|
||||
@ -64,7 +65,7 @@ endif
|
||||
BINSRC = addmoddel.cpp crwedit.cpp crwparse.cpp dataarea-test.cpp \
|
||||
exifcomment.cpp exifdata-test.cpp exifprint.cpp ifd-test.cpp iotest.cpp \
|
||||
iptceasy.cpp iptcprint.cpp iptctest.cpp key-test.cpp makernote-test.cpp \
|
||||
taglist.cpp write-test.cpp write2-test.cpp
|
||||
taglist.cpp write-test.cpp write2-test.cpp tiffparse.cpp
|
||||
|
||||
# Main source file of the Exiv2 application
|
||||
EXIV2MAIN = exiv2.cpp
|
||||
|
||||
@ -43,10 +43,8 @@ namespace Exiv2 {
|
||||
ErrMsg( -1, "Error %0: arg1=%1, arg2=%2, arg3=%3."),
|
||||
ErrMsg( 0, "Success"),
|
||||
ErrMsg( 1, "%1"), // %1=error message
|
||||
|
||||
ErrMsg( 2, "%1: %2 (%3)"), // %1=path, %2=strerror, %3=function that failed
|
||||
// ErrMsg( 3, ""),
|
||||
|
||||
ErrMsg( 3, "This does not look like a %1 image"), // %1=Image type
|
||||
ErrMsg( 4, "Invalid dataset name `%1'"), // %1=dataset name
|
||||
ErrMsg( 5, "Invalid record name `%1'"), // %1=record name
|
||||
ErrMsg( 6, "Invalid key `%1'"), // %1=key
|
||||
|
||||
@ -34,6 +34,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
#include "image.hpp"
|
||||
#include "jpgimage.hpp"
|
||||
#include "crwimage.hpp"
|
||||
#include "tiffimage.hpp"
|
||||
|
||||
// + standard includes
|
||||
|
||||
@ -44,7 +45,8 @@ namespace Exiv2 {
|
||||
ImageFactory::Registry ImageFactory::registry_[] = {
|
||||
Registry(ImageType::jpeg, newJpegInstance, isJpegType),
|
||||
Registry(ImageType::exv, newExvInstance, isExvType),
|
||||
Registry(ImageType::crw, newCrwInstance, isCrwType)
|
||||
Registry(ImageType::crw, newCrwInstance, isCrwType),
|
||||
Registry(ImageType::tiff, newTiffInstance, isTiffType)
|
||||
};
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
@ -44,7 +44,7 @@ namespace Exiv2 {
|
||||
|
||||
// *****************************************************************************
|
||||
// class declarations
|
||||
|
||||
|
||||
struct TiffStructure;
|
||||
|
||||
// *****************************************************************************
|
||||
@ -59,7 +59,7 @@ namespace Exiv2 {
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Class to access raw TIFF images. Only Exif metadata and a comment
|
||||
@brief Class to access raw TIFF images. Only Exif metadata and a comment
|
||||
are supported. TIFF format does not contain IPTC metadata.
|
||||
*/
|
||||
class TiffImage : public Image {
|
||||
|
||||
@ -49,12 +49,18 @@ try {
|
||||
TiffHeade2 tiffHeader;
|
||||
if (!tiffHeader.read(buf.pData_, buf.size_)) throw Error(3, "TIFF");
|
||||
|
||||
TiffComponent::AutoPtr rootDir
|
||||
TiffComponent::AutoPtr rootDir
|
||||
= TiffParser::create(Tag::root, Group::none, tiffStructure);
|
||||
if (0 == rootDir.get()) {
|
||||
throw Error(1, "No root element defined in TIFF structure");
|
||||
}
|
||||
rootDir->read(buf.pData_, buf.size_, tiffHeader.offset(), tiffHeader.byteOrder());
|
||||
TiffReader reader(buf.pData_,
|
||||
buf.size_,
|
||||
tiffHeader.byteOrder(),
|
||||
tiffStructure);
|
||||
|
||||
rootDir->setStart(buf.pData_ + tiffHeader.offset());
|
||||
rootDir->accept(reader);
|
||||
|
||||
tiffHeader.print(std::cerr);
|
||||
rootDir->print(std::cerr, tiffHeader.byteOrder());
|
||||
|
||||
@ -58,10 +58,9 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
|
||||
Todo:
|
||||
|
||||
+ Add child mgmt stuff to TIFF composite: add, remove, find
|
||||
+ Better encapsulate TiffStructure
|
||||
+ Remove read methods from Composite and turn them into a visitor
|
||||
+ Remove TiffStructure from Composite
|
||||
+ Add further child mgmt stuff to TIFF composite: remove, find
|
||||
+ Better handling of TiffStructure
|
||||
+ Add Makernote support
|
||||
|
||||
in crwimage.* :
|
||||
|
||||
@ -77,7 +76,7 @@ EXIV2_RCSID("@(#) $Id$");
|
||||
// class member definitions
|
||||
namespace Exiv2 {
|
||||
|
||||
void TiffParser::decode(const byte* pData,
|
||||
void TiffParser::decode(const byte* pData,
|
||||
uint32_t size,
|
||||
const TiffStructure* pTiffStructure,
|
||||
TiffVisitor& decoder)
|
||||
@ -89,10 +88,16 @@ namespace Exiv2 {
|
||||
throw Error(3, "TIFF");
|
||||
}
|
||||
|
||||
TiffComponent::AutoPtr rootDir
|
||||
TiffComponent::AutoPtr rootDir
|
||||
= TiffParser::create(Tag::root, Group::none, pTiffStructure);
|
||||
if (0 == rootDir.get()) return;
|
||||
rootDir->read(pData, size, tiffHeader.offset(), tiffHeader.byteOrder());
|
||||
|
||||
TiffReader reader(pData,
|
||||
size,
|
||||
tiffHeader.byteOrder(),
|
||||
pTiffStructure);
|
||||
rootDir->setStart(pData + tiffHeader.offset());
|
||||
rootDir->accept(reader);
|
||||
|
||||
#ifdef DEBUG
|
||||
tiffHeader.print(std::cerr);
|
||||
@ -110,7 +115,7 @@ namespace Exiv2 {
|
||||
const TiffStructure* ts = 0;
|
||||
int idx = 0;
|
||||
for (; pTiffStructure[idx].extendedTag_ != Tag::none; ++idx) {
|
||||
if ( extendedTag == pTiffStructure[idx].extendedTag_
|
||||
if ( extendedTag == pTiffStructure[idx].extendedTag_
|
||||
&& group == pTiffStructure[idx].group_) {
|
||||
ts = &pTiffStructure[idx];
|
||||
break;
|
||||
@ -119,7 +124,7 @@ namespace Exiv2 {
|
||||
|
||||
TiffComponent::AutoPtr tc(0);
|
||||
if (ts && ts->newTiffCompFct_) {
|
||||
tc = ts->newTiffCompFct_(pTiffStructure, idx);
|
||||
tc = ts->newTiffCompFct_(ts);
|
||||
}
|
||||
if (!ts) {
|
||||
uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff);
|
||||
@ -137,7 +142,7 @@ namespace Exiv2 {
|
||||
}
|
||||
delete pNext_;
|
||||
} // TiffDirectory::~TiffDirectory
|
||||
|
||||
|
||||
TiffEntryBase::~TiffEntryBase()
|
||||
{
|
||||
if (isAllocated_) {
|
||||
@ -167,142 +172,49 @@ namespace Exiv2 {
|
||||
return true;
|
||||
} // TiffHeade2::read
|
||||
|
||||
void TiffComponent::read(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder)
|
||||
void TiffComponent::addChild(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
doRead(pData, size, start, byteOrder);
|
||||
} // TiffComponent::read
|
||||
doAddChild(tiffComponent);
|
||||
} // TiffComponent::addChild
|
||||
|
||||
void TiffEntryBase::readEntry(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder)
|
||||
void TiffDirectory::doAddChild(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
if (size - start < 12) throw Error(3, "TIFF");
|
||||
const byte* p = pData + start;
|
||||
// Component already has tag
|
||||
p += 2;
|
||||
type_ = getUShort(p, byteOrder);
|
||||
// todo: check type
|
||||
p += 2;
|
||||
count_ = getULong(p, byteOrder);
|
||||
p += 4;
|
||||
offset_ = getULong(p, byteOrder);
|
||||
size_ = TypeInfo::typeSize(typeId()) * count();
|
||||
if (size_ > 4) {
|
||||
if (size < offset() + size_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Warning: Upper boundary of data for "
|
||||
<< "directory " << group() << ", " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " entry 0x" << std::setw(4)
|
||||
<< std::setfill('0') << std::hex << tag()
|
||||
<< " is out of bounds:\n"
|
||||
<< " Offset = 0x" << std::setw(8)
|
||||
<< std::setfill('0') << std::hex << offset()
|
||||
<< ", size = " << std::dec << size_
|
||||
<< ", exceeds buffer size by "
|
||||
<< offset() + size_ - size
|
||||
<< " Bytes; adjusting the size\n";
|
||||
#endif
|
||||
size_ = size - offset();
|
||||
// todo: adjust count_, make size_ a multiple of typeSize
|
||||
}
|
||||
pData_ = pData + offset();
|
||||
}
|
||||
else {
|
||||
pData_ = pData + start + 8;
|
||||
}
|
||||
pValue_ = Value::create(typeId()).release();
|
||||
if (pValue_) pValue_->read(pData_, size_, byteOrder);
|
||||
components_.push_back(tiffComponent.release());
|
||||
} // TiffDirectory::doAddChild
|
||||
|
||||
} // TiffEntryBase::readEntry
|
||||
|
||||
void TiffEntry::doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder)
|
||||
void TiffSubIfd::doAddChild(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
TiffEntryBase::readEntry(pData, size, start, byteOrder);
|
||||
} // TiffEntry::doRead
|
||||
ifd_.addChild(tiffComponent);
|
||||
} // TiffSubIfd::doAddChild
|
||||
|
||||
void TiffDirectory::doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder)
|
||||
void TiffComponent::addNext(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
if (size < start + 2) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD exceeds data buffer, cannot read entry count.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint32_t o = start;
|
||||
const uint16_t n = getUShort(pData + o, byteOrder);
|
||||
o += 2;
|
||||
doAddNext(tiffComponent);
|
||||
} // TiffComponent::addNext
|
||||
|
||||
for (uint16_t i = 0; i < n; ++i) {
|
||||
if (size < o + 12) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD entry " << i
|
||||
<< " lies outside of the data buffer.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint16_t tag = getUShort(pData + o, byteOrder);
|
||||
TiffComponent::AutoPtr tc
|
||||
= TiffParser::create(tag, group(), pTiffStructure());
|
||||
tc->read(pData, size, o, byteOrder);
|
||||
components_.push_back(tc.release());
|
||||
o += 12;
|
||||
}
|
||||
if (size < o + 4) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD exceeds data buffer, cannot read next pointer.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint32_t next = getLong(pData + o, byteOrder);
|
||||
if (next) {
|
||||
pNext_ = TiffParser::create(Tag::next, group(), pTiffStructure()).release();
|
||||
pNext_->read(pData, size, next, byteOrder);
|
||||
}
|
||||
|
||||
} // TiffDirectory::doRead
|
||||
|
||||
void TiffSubIfd::doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder)
|
||||
void TiffDirectory::doAddNext(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
TiffEntryBase::readEntry(pData, size, start, byteOrder);
|
||||
if (typeId() == unsignedLong && count() >= 1) {
|
||||
uint32_t offset = getULong(this->pData(), byteOrder);
|
||||
ifd_.read(pData, size, offset, byteOrder);
|
||||
}
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
else {
|
||||
std::cerr << "Warning: "
|
||||
<< "Directory " << group() << ", " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " entry 0x" << std::setw(4)
|
||||
<< std::setfill('0') << std::hex << tag()
|
||||
<< " doesn't look like a sub-IFD.";
|
||||
}
|
||||
#endif
|
||||
} // TiffSubIfd::read
|
||||
pNext_ = tiffComponent.release();
|
||||
} // TiffDirectory::doAddNext
|
||||
|
||||
void TiffSubIfd::doAddNext(TiffComponent::AutoPtr tiffComponent)
|
||||
{
|
||||
ifd_.addNext(tiffComponent);
|
||||
} // TiffSubIfd::doAddNext
|
||||
|
||||
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_ << "\n";
|
||||
<< 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
|
||||
|
||||
void TiffComponent::print(std::ostream& os,
|
||||
@ -317,15 +229,17 @@ namespace Exiv2 {
|
||||
const std::string& prefix) const
|
||||
{
|
||||
os << prefix
|
||||
<< "tag = 0x" << std::setw(4) << std::setfill('0')
|
||||
<< "tag 0x" << std::setw(4) << std::setfill('0')
|
||||
<< std::hex << std::right << tag()
|
||||
<< ", type = " << TypeInfo::typeName(typeId())
|
||||
<< ", count = " << std::dec << count()
|
||||
<< ", offset = " << offset() << "\n";
|
||||
|
||||
if (pValue_ && pValue_->size() < 100) {
|
||||
os << prefix << *pValue_ << "\n";
|
||||
}
|
||||
<< ", type " << TypeInfo::typeName(typeId())
|
||||
<< ", " << std::dec << count() << " component";
|
||||
if (count() > 1) os << "s";
|
||||
os <<" in " << size() << " bytes";
|
||||
if (size() > 4) os << ", offset " << offset();
|
||||
os << "\n";
|
||||
if (pValue_ && pValue_->count() < 100) os << prefix << *pValue_;
|
||||
else os << prefix << "...";
|
||||
os << "\n";
|
||||
|
||||
} // TiffEntryBase::printEntry
|
||||
|
||||
@ -340,7 +254,7 @@ namespace Exiv2 {
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const
|
||||
{
|
||||
os << prefix << "Directory " << group()
|
||||
os << prefix << "Directory " << group()
|
||||
<< " with " << components_.size() << " entries.\n";
|
||||
Components::const_iterator b = components_.begin();
|
||||
Components::const_iterator e = components_.end();
|
||||
@ -365,17 +279,17 @@ namespace Exiv2 {
|
||||
ifd_.print(os, byteOrder, prefix);
|
||||
} // TiffSubIfd::doPrint
|
||||
|
||||
void TiffComponent::accept(TiffVisitor& visitor) const
|
||||
void TiffComponent::accept(TiffVisitor& visitor)
|
||||
{
|
||||
doAccept(visitor);
|
||||
} // TiffComponent::accept
|
||||
|
||||
void TiffEntry::doAccept(TiffVisitor& visitor) const
|
||||
void TiffEntry::doAccept(TiffVisitor& visitor)
|
||||
{
|
||||
visitor.visitEntry(this);
|
||||
} // TiffEntry::doAccept
|
||||
|
||||
void TiffDirectory::doAccept(TiffVisitor& visitor) const
|
||||
void TiffDirectory::doAccept(TiffVisitor& visitor)
|
||||
{
|
||||
visitor.visitDirectory(this);
|
||||
|
||||
@ -387,33 +301,35 @@ namespace Exiv2 {
|
||||
if (pNext_) {
|
||||
pNext_->accept(visitor);
|
||||
}
|
||||
|
||||
|
||||
} // TiffDirectory::doAccept
|
||||
|
||||
void TiffSubIfd::doAccept(TiffVisitor& visitor) const
|
||||
void TiffSubIfd::doAccept(TiffVisitor& visitor)
|
||||
{
|
||||
visitor.visitSubIfd(this);
|
||||
ifd_.accept(visitor);
|
||||
} // TiffSubIfd::doAccept
|
||||
|
||||
void TiffMetadataDecoder::visitEntry(const TiffEntry* object)
|
||||
void TiffMetadataDecoder::visitEntry(TiffEntry* object)
|
||||
{
|
||||
decodeTiffEntry(object);
|
||||
decodeTiffEntry(object);
|
||||
}
|
||||
|
||||
void TiffMetadataDecoder::visitDirectory(const TiffDirectory* object)
|
||||
void TiffMetadataDecoder::visitDirectory(TiffDirectory* object)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
void TiffMetadataDecoder::visitSubIfd(const TiffSubIfd* object)
|
||||
void TiffMetadataDecoder::visitSubIfd(TiffSubIfd* object)
|
||||
{
|
||||
decodeTiffEntry(object);
|
||||
}
|
||||
|
||||
void TiffMetadataDecoder::decodeTiffEntry(const TiffEntryBase* object)
|
||||
{
|
||||
// Todo: ExifKey should have an appropriate c'tor, this mapping should
|
||||
assert(object != 0);
|
||||
|
||||
// Todo: ExifKey should have an appropriate c'tor, this mapping should
|
||||
// be a table and it belongs somewhere else
|
||||
std::string group;
|
||||
switch (object->group()) {
|
||||
@ -427,22 +343,172 @@ namespace Exiv2 {
|
||||
ExifKey k(object->tag(), group);
|
||||
assert(pImage_ != 0);
|
||||
pImage_->exifData().add(k, object->pValue());
|
||||
} // TiffEntryBase::decodeTiffEntry
|
||||
} // TiffMetadataDecoder::decodeTiffEntry
|
||||
|
||||
TiffReader::TiffReader(const byte* pData,
|
||||
uint32_t size,
|
||||
ByteOrder byteOrder,
|
||||
const TiffStructure* pTiffStructure)
|
||||
: pData_(pData),
|
||||
size_(size),
|
||||
pLast_(pData + size - 1),
|
||||
byteOrder_(byteOrder),
|
||||
pTiffStructure_(pTiffStructure)
|
||||
{
|
||||
assert(pData);
|
||||
assert(size > 0);
|
||||
assert(pTiffStructure);
|
||||
} // TiffReader::TiffReader
|
||||
|
||||
void TiffReader::visitEntry(TiffEntry* object)
|
||||
{
|
||||
readTiffEntry(object);
|
||||
}
|
||||
|
||||
void TiffReader::visitDirectory(TiffDirectory* object)
|
||||
{
|
||||
assert(object != 0);
|
||||
|
||||
byte* p = const_cast<byte*>(object->start());
|
||||
assert(p >= pData_);
|
||||
|
||||
if (p + 2 > pLast_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << object->group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD exceeds data buffer, cannot read entry count.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const uint16_t n = getUShort(p, byteOrder_);
|
||||
p += 2;
|
||||
|
||||
for (uint16_t i = 0; i < n; ++i) {
|
||||
if (p + 12 > pLast_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << object->group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD entry " << i
|
||||
<< " lies outside of the data buffer.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint16_t tag = getUShort(p, byteOrder_);
|
||||
TiffComponent::AutoPtr tc
|
||||
= TiffParser::create(tag, object->group(), pTiffStructure_);
|
||||
tc->setStart(p);
|
||||
object->addChild(tc);
|
||||
|
||||
p += 12;
|
||||
}
|
||||
|
||||
if (p + 4 > pLast_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: "
|
||||
<< "Directory " << object->group() << ": " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " IFD exceeds data buffer, cannot read next pointer.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
uint32_t next = getLong(p, byteOrder_);
|
||||
if (next) {
|
||||
TiffComponent::AutoPtr tc
|
||||
= TiffParser::create(Tag::next, object->group(), pTiffStructure_);
|
||||
tc->setStart(p);
|
||||
object->addNext(tc);
|
||||
}
|
||||
|
||||
} // TiffReader::visitDirectory
|
||||
|
||||
void TiffReader::visitSubIfd(TiffSubIfd* object)
|
||||
{
|
||||
assert(object != 0);
|
||||
|
||||
readTiffEntry(object);
|
||||
if (object->typeId() == unsignedLong && object->count() >= 1) {
|
||||
uint32_t offset = getULong(object->pData(), byteOrder_);
|
||||
object->ifd_.setStart(pData_ + offset);
|
||||
}
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
else {
|
||||
std::cerr << "Warning: "
|
||||
<< "Directory " << object->group() << ", " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " entry 0x" << std::setw(4)
|
||||
<< std::setfill('0') << std::hex << object->tag()
|
||||
<< " doesn't look like a sub-IFD.";
|
||||
}
|
||||
#endif
|
||||
|
||||
} // TiffReader::visitSubIfd
|
||||
|
||||
void TiffReader::readTiffEntry(TiffEntryBase* object)
|
||||
{
|
||||
assert(object != 0);
|
||||
|
||||
byte* p = const_cast<byte*>(object->start());
|
||||
assert(p >= pData_);
|
||||
|
||||
if (p + 12 > pLast_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Error: Entry in directory " << object->group() // todo: ExifTags::ifdName(ifdId_)
|
||||
<< "requests access to memory beyond the data buffer. "
|
||||
<< "Skipping entry.\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// Component already has tag
|
||||
p += 2;
|
||||
object->type_ = getUShort(p, byteOrder_);
|
||||
// todo: check type
|
||||
p += 2;
|
||||
object->count_ = getULong(p, byteOrder_);
|
||||
p += 4;
|
||||
object->offset_ = getULong(p, byteOrder_);
|
||||
object->size_ = TypeInfo::typeSize(object->typeId()) * object->count();
|
||||
object->pData_ = p;
|
||||
if (object->size() > 4) {
|
||||
object->pData_ = pData_ + object->offset();
|
||||
if (object->pData() + object->size() > pLast_) {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Warning: Upper boundary of data for "
|
||||
<< "directory " << object->group() << ", " // todo: ExifTags::ifdName(ifdId_)
|
||||
<< " entry 0x" << std::setw(4)
|
||||
<< std::setfill('0') << std::hex << object->tag()
|
||||
<< " is out of bounds:\n"
|
||||
<< " Offset = 0x" << std::setw(8)
|
||||
<< std::setfill('0') << std::hex << object->offset()
|
||||
<< ", size = " << std::dec << object->size()
|
||||
<< ", exceeds buffer size by "
|
||||
<< object->pData() + object->size() - pLast_
|
||||
<< " Bytes; adjusting the size\n";
|
||||
#endif
|
||||
object->size_ = size_ - object->offset();
|
||||
// todo: adjust count_, make size_ a multiple of typeSize
|
||||
}
|
||||
}
|
||||
Value::AutoPtr v = Value::create(object->typeId());
|
||||
if (v.get()) {
|
||||
v->read(object->pData(), object->size(), byteOrder_);
|
||||
object->pValue_ = v.release();
|
||||
}
|
||||
|
||||
} // TiffReader::readTiffEntry
|
||||
|
||||
// *************************************************************************
|
||||
// free functions
|
||||
|
||||
TiffComponent::AutoPtr newTiffDirectory(const TiffStructure* ts, int i)
|
||||
TiffComponent::AutoPtr newTiffDirectory(const TiffStructure* ts)
|
||||
{
|
||||
return TiffComponent::AutoPtr(new TiffDirectory(ts[i].tag(), ts[i].newGroup_, ts));
|
||||
assert(ts);
|
||||
return TiffComponent::AutoPtr(new TiffDirectory(ts->tag(), ts->newGroup_));
|
||||
}
|
||||
|
||||
TiffComponent::AutoPtr newTiffSubIfd(const TiffStructure* ts, int i)
|
||||
TiffComponent::AutoPtr newTiffSubIfd(const TiffStructure* ts)
|
||||
{
|
||||
return TiffComponent::AutoPtr(new TiffSubIfd(ts[i].tag(),
|
||||
ts[i].group_,
|
||||
ts[i].newGroup_,
|
||||
ts));
|
||||
assert(ts);
|
||||
return TiffComponent::AutoPtr(new TiffSubIfd(ts->tag(),
|
||||
ts->group_,
|
||||
ts->newGroup_));
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
@ -50,7 +50,10 @@ namespace Exiv2 {
|
||||
// class declarations
|
||||
|
||||
struct TiffStructure;
|
||||
class TiffVisitor;
|
||||
class TiffDirectory;
|
||||
class TiffEntryBase;
|
||||
class TiffEntry;
|
||||
class TiffSubIfd;
|
||||
|
||||
// *****************************************************************************
|
||||
// type definitions
|
||||
@ -62,7 +65,7 @@ namespace Exiv2 {
|
||||
Known TIFF groups
|
||||
|
||||
Todo: what exactly are these and where should they go?
|
||||
Are they going to be mapped to the second part of an Exif key or are they
|
||||
Are they going to be mapped to the second part of an Exif key or are they
|
||||
the second part of the key?
|
||||
*/
|
||||
namespace Group {
|
||||
@ -72,11 +75,11 @@ namespace Exiv2 {
|
||||
const uint16_t exif = 3; //!< Exif IFD
|
||||
const uint16_t gps = 4; //!< GPS IFD
|
||||
const uint16_t iop = 5; //!< Interoperability IFD
|
||||
const uint16_t makernote = 256; //!< Makernote
|
||||
const uint16_t makernote = 256; //!< Makernote
|
||||
const uint16_t canonmn = 257; //!< Canon makernote
|
||||
}
|
||||
|
||||
/*!
|
||||
/*!
|
||||
Special TIFF tags for the use in TIFF structures only
|
||||
|
||||
Todo: Same Q as above...
|
||||
@ -87,279 +90,6 @@ namespace Exiv2 {
|
||||
const uint32_t next = 0x30000; //!< Special tag: next IFD
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Interface class for components of a TIFF directory hierarchy
|
||||
(Composite pattern). Both TIFF directories as well as entries
|
||||
implement this interface. A component can be un iquely identified
|
||||
bya tag, group tupel. This class is implemented as a NVI
|
||||
(Non-Virtual Interface). It has an interface for visitors (Visitor
|
||||
pattern).
|
||||
*/
|
||||
class TiffComponent {
|
||||
public:
|
||||
//! TiffComponent auto_ptr type
|
||||
typedef std::auto_ptr<TiffComponent> AutoPtr;
|
||||
//! Container type to hold all metadata
|
||||
typedef std::vector<TiffComponent*> Components;
|
||||
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor
|
||||
TiffComponent(uint16_t tag,
|
||||
uint16_t group,
|
||||
const TiffStructure* pTiffStructure)
|
||||
: tag_(tag), group_(group), pTiffStructure_(pTiffStructure) {}
|
||||
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffComponent() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
/*!
|
||||
@brief Read a component from a data buffer
|
||||
|
||||
@param pData Pointer to the data buffer, starting with a TIFF header.
|
||||
@param size Number of bytes in the data buffer.
|
||||
@param start Component starts at \em pData + \em start.
|
||||
@param byteOrder Applicable byte order (little or big endian).
|
||||
|
||||
@throw Error If the component cannot be parsed.
|
||||
*/
|
||||
void read(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Return the tag of this entry.
|
||||
uint16_t tag() const { return tag_; }
|
||||
//! Return the group id of this component
|
||||
uint16_t group() const { return group_; }
|
||||
//! Return the TIFF structure
|
||||
const TiffStructure* pTiffStructure() const { return pTiffStructure_; }
|
||||
/*!
|
||||
@brief Print debug info about a component to \em os.
|
||||
|
||||
@param os Output stream to write to
|
||||
@param byteOrder Byte order
|
||||
@param prefix Prefix to be written before each line of output
|
||||
*/
|
||||
void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const;
|
||||
/*!
|
||||
@brief Interface to accept visitors (Visitor pattern).
|
||||
|
||||
@param visitor The visitor.
|
||||
*/
|
||||
void accept(TiffVisitor& visitor) const;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Implements read().
|
||||
virtual void doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder) =0;
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Implements print()
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const =0;
|
||||
|
||||
//! Implements accept()
|
||||
virtual void doAccept(TiffVisitor& visitor) const =0;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
uint16_t tag_; //!< Tag that identifies the component
|
||||
uint16_t group_; //!< Group id for this component
|
||||
const TiffStructure* pTiffStructure_; //!< TIFF structure for this component
|
||||
|
||||
}; // class TiffComponent
|
||||
|
||||
/*!
|
||||
@brief This baseclass provides the common functionality of an IFD
|
||||
directory entry and defines the interface for derived concrete
|
||||
entries.
|
||||
*/
|
||||
class TiffEntryBase : public TiffComponent {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffEntryBase(uint16_t tag, uint16_t group)
|
||||
: TiffComponent(tag, group, 0),
|
||||
type_(0), count_(0), offset_(0),
|
||||
size_(0), pData_(0), isAllocated_(false), pValue_(0) {}
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffEntryBase();
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Return the Exiv2 type which corresponds to the field type.
|
||||
TypeId typeId() const { return TypeId(type_); }
|
||||
//! Return the number of components in this entry.
|
||||
uint32_t count() const { return count_; }
|
||||
//! Return the offset relative to the start of the TIFF header.
|
||||
uint32_t offset() const { return offset_; }
|
||||
//! Return the size of this component in bytes
|
||||
uint32_t size() const { return size_; }
|
||||
//! Return a pointer to the data area of this component
|
||||
const byte* pData() const { return pData_; }
|
||||
//! Return a pointer to the converted value of this component
|
||||
const Value* pValue() const { return pValue_; }
|
||||
|
||||
//! Print base entry
|
||||
void printEntry(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Read base entry
|
||||
void readEntry(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder);
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
uint16_t type_; //!< Field Type
|
||||
uint32_t count_; //!< The number of values of the indicated Type
|
||||
uint32_t offset_; //!< Offset to data area from start of TIFF header
|
||||
/*!
|
||||
Size of the data buffer holding the value in bytes, there is no
|
||||
minimum size.
|
||||
*/
|
||||
uint32_t size_;
|
||||
const byte* pData_; //!< Pointer to the data area
|
||||
bool isAllocated_; //!< True if this entry owns the value data
|
||||
Value* pValue_; //!< Converted data value
|
||||
|
||||
}; // class TiffEntryBase
|
||||
|
||||
/*!
|
||||
@brief A standard TIFF IFD entry. The value is kept in a data buffer.
|
||||
*/
|
||||
class TiffEntry : public TiffEntryBase {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor
|
||||
TiffEntry(uint16_t tag, uint16_t group) : TiffEntryBase(tag, group) {}
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffEntry() {}
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Implements read().
|
||||
virtual void doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
virtual void doAccept(TiffVisitor& visitor) const;
|
||||
//@}
|
||||
|
||||
}; // class TiffEntry
|
||||
|
||||
//! This class models a TIFF directory (%Ifd).
|
||||
class TiffDirectory : public TiffComponent {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffDirectory(uint16_t tag, uint16_t group, const TiffStructure* pTiffStructure)
|
||||
: TiffComponent(tag, group, pTiffStructure), pNext_(0) {}
|
||||
//! Virtual destructor
|
||||
virtual ~TiffDirectory();
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
|
||||
virtual void doAccept(TiffVisitor& visitor) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
Components components_; //!< List of components in this directory
|
||||
TiffComponent* pNext_; //!< Pointer to the next IFD
|
||||
|
||||
}; // class TiffDirectory
|
||||
|
||||
//! This class models a TIFF sub-directory (%SubIfd).
|
||||
class TiffSubIfd : public TiffEntryBase {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffSubIfd(uint16_t tag,
|
||||
uint16_t group,
|
||||
uint16_t newGroup,
|
||||
const TiffStructure* pTiffStructure)
|
||||
: TiffEntryBase(tag, group), ifd_(tag, newGroup, pTiffStructure) {}
|
||||
//! Virtual destructor
|
||||
virtual ~TiffSubIfd() {}
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void doRead(const byte* pData,
|
||||
uint32_t size,
|
||||
uint32_t start,
|
||||
ByteOrder byteOrder);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
|
||||
virtual void doAccept(TiffVisitor& visitor) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
TiffDirectory ifd_; //!< The subdirectory
|
||||
|
||||
}; // class TiffDirectory
|
||||
|
||||
/*!
|
||||
@brief This class models a TIFF header structure.
|
||||
*/
|
||||
@ -377,7 +107,7 @@ namespace Exiv2 {
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
/*!
|
||||
@brief Read the TIFF header from a data buffer. Return false if the
|
||||
@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.
|
||||
@ -389,7 +119,7 @@ namespace Exiv2 {
|
||||
//! @name Accessors
|
||||
//@{
|
||||
/*!
|
||||
@brief Write the TIFF header to the binary image \em blob.
|
||||
@brief Write the TIFF header to the binary image \em blob.
|
||||
This method appends to the blob.
|
||||
|
||||
@param blob Binary image to add to.
|
||||
@ -419,29 +149,20 @@ namespace Exiv2 {
|
||||
|
||||
}; // class TiffHeade2
|
||||
|
||||
/*!
|
||||
Type for a function pointer for functions to create TIFF components.
|
||||
Todo: This may eventually need to also have access to the image or parse tree
|
||||
in order to make decisions based on the value of other tags.
|
||||
/*!
|
||||
@brief Abstract base class for TIFF composite vistors (Visitor pattern)
|
||||
|
||||
A concrete visitor class is used as shown in the example below. Accept()
|
||||
will invoke the member function corresponding to the concrete type of each
|
||||
component in the composite.
|
||||
|
||||
@code
|
||||
void visitorExample(Exiv2::TiffComponent* tiffComponent, Exiv2::TiffVisitor& visitor)
|
||||
{
|
||||
tiffComponent->accept(visitor);
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
typedef TiffComponent::AutoPtr (*NewTiffCompFct)(const TiffStructure* ts, int i);
|
||||
|
||||
/*!
|
||||
This structure is meant to be used as an entry (row) of a table describing
|
||||
the TIFF structure of an image format for reading and writing. Different
|
||||
tables can be used to support different TIFF based image formats.
|
||||
*/
|
||||
struct TiffStructure {
|
||||
//! Return the tag corresponding to the extended tag
|
||||
uint16_t tag() const { return static_cast<uint16_t>(extendedTag_ & 0xffff); }
|
||||
|
||||
uint32_t extendedTag_; //!< Tag (32 bit so that it can contain special tags)
|
||||
uint16_t group_; //!< Group that contains the tag
|
||||
NewTiffCompFct newTiffCompFct_; //!< Function to create the correct TIFF component
|
||||
uint16_t newGroup_; //!< Group of the newly created component
|
||||
};
|
||||
|
||||
//! Abstract base class for TIFF composite vistors (Visitor pattern)
|
||||
class TiffVisitor {
|
||||
public:
|
||||
//! @name Creators
|
||||
@ -451,25 +172,27 @@ namespace Exiv2 {
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Decode a TIFF entry
|
||||
virtual void visitEntry(const TiffEntry* object) =0;
|
||||
//! Decode a TIFF directory
|
||||
virtual void visitDirectory(const TiffDirectory* object) =0;
|
||||
//! Decode a TIFF sub-IFD
|
||||
virtual void visitSubIfd(const TiffSubIfd* object) =0;
|
||||
//! Operation to perform for a TIFF entry
|
||||
virtual void visitEntry(TiffEntry* object) =0;
|
||||
//! Operation to perform for a TIFF directory
|
||||
virtual void visitDirectory(TiffDirectory* object) =0;
|
||||
//! Operation to perform for a TIFF sub-IFD
|
||||
virtual void visitSubIfd(TiffSubIfd* object) =0;
|
||||
//@}
|
||||
|
||||
}; // class TiffVisitor
|
||||
|
||||
/*!
|
||||
TIFF composite visitor to decode metadata from the composite and add it
|
||||
to an Image, which is supplied in the constructor.
|
||||
@brief TIFF composite visitor to decode metadata from the TIFF tree and
|
||||
add it to an Image, which is supplied in the constructor (Visitor
|
||||
pattern). Used by TiffParser to decode the metadata from a
|
||||
TIFF composite.
|
||||
*/
|
||||
class TiffMetadataDecoder : public TiffVisitor {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor
|
||||
//! Constructor, taking the image to add the metadata to
|
||||
TiffMetadataDecoder(Image* pImage) : pImage_(pImage) {}
|
||||
//! Virtual destructor
|
||||
virtual ~TiffMetadataDecoder() {}
|
||||
@ -477,9 +200,12 @@ namespace Exiv2 {
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void visitEntry(const TiffEntry* object);
|
||||
virtual void visitDirectory(const TiffDirectory* object);
|
||||
virtual void visitSubIfd(const TiffSubIfd* object);
|
||||
//! Decode a TIFF entry
|
||||
virtual void visitEntry(TiffEntry* object);
|
||||
//! Decode a TIFF directory
|
||||
virtual void visitDirectory(TiffDirectory* object);
|
||||
//! Decode a TIFF sub-IFD
|
||||
virtual void visitSubIfd(TiffSubIfd* object);
|
||||
//! Decode a standard TIFF entry
|
||||
void decodeTiffEntry(const TiffEntryBase* object);
|
||||
//@}
|
||||
@ -491,38 +217,376 @@ namespace Exiv2 {
|
||||
}; // class TiffMetadataDecoder
|
||||
|
||||
/*!
|
||||
Stateless parser class for data in TIFF format.
|
||||
@brief TIFF composite visitor to read the TIFF structure from a block of
|
||||
memory and build the composite from it (Visitor pattern). Used by
|
||||
TiffParser to read the TIFF data from a block of memory.
|
||||
*/
|
||||
class TiffReader : public TiffVisitor {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
/*!
|
||||
@brief Constructor. The data buffer and table describing the TIFF
|
||||
structure of the data are set in the constructor.
|
||||
@param pData Pointer to the data buffer, starting with a TIFF header.
|
||||
@param size Number of bytes in the data buffer.
|
||||
@param byteOrder Applicable byte order (little or big endian).
|
||||
@param pTiffStructure Pointer to a table describing the TIFF structure
|
||||
used to decode the data.
|
||||
*/
|
||||
TiffReader(const byte* pData,
|
||||
uint32_t size,
|
||||
ByteOrder byteOrder,
|
||||
const TiffStructure* pTiffStructure);
|
||||
|
||||
//! Virtual destructor
|
||||
virtual ~TiffReader() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Read a TIFF entry from the data buffer
|
||||
virtual void visitEntry(TiffEntry* object);
|
||||
//! Read a TIFF directory from the data buffer
|
||||
virtual void visitDirectory(TiffDirectory* object);
|
||||
//! Read a TIFF sub-IFD from the data buffer
|
||||
virtual void visitSubIfd(TiffSubIfd* object);
|
||||
//! Read a standard TIFF entry from the data buffer
|
||||
void readTiffEntry(TiffEntryBase* object);
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
const byte* pData_; //!< Pointer to the memory buffer
|
||||
const uint32_t size_; //!< Size of the buffer
|
||||
const byte* pLast_; //!< Pointer to the last byte
|
||||
const ByteOrder byteOrder_; //!< Byteorder for the image
|
||||
const TiffStructure* pTiffStructure_; //!< Pointer to the TIFF structure
|
||||
|
||||
}; // class TiffReader
|
||||
|
||||
/*!
|
||||
@brief Interface class for components of a TIFF directory hierarchy
|
||||
(Composite pattern). Both TIFF directories as well as entries
|
||||
implement this interface. A component can be un iquely identified
|
||||
by a tag, group tupel. This class is implemented as a NVI
|
||||
(Non-Virtual Interface) and it has an interface for visitors (Visitor
|
||||
pattern).
|
||||
*/
|
||||
class TiffComponent {
|
||||
public:
|
||||
//! TiffComponent auto_ptr type
|
||||
typedef std::auto_ptr<TiffComponent> AutoPtr;
|
||||
//! Container type to hold all metadata
|
||||
typedef std::vector<TiffComponent*> Components;
|
||||
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor
|
||||
TiffComponent(uint16_t tag, uint16_t group)
|
||||
: tag_(tag), group_(group), pData_(0) {}
|
||||
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffComponent() {}
|
||||
//@}
|
||||
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Add a child to the component. Default is to do nothing.
|
||||
void addChild(AutoPtr tiffComponent);
|
||||
//! Add a "next" component to the component. Default is to do nothing.
|
||||
void addNext(AutoPtr tiffComponent);
|
||||
/*!
|
||||
@brief Interface to accept visitors (Visitor pattern).
|
||||
|
||||
@param visitor The visitor.
|
||||
*/
|
||||
void accept(TiffVisitor& visitor);
|
||||
/*!
|
||||
@brief Set a pointer to the start of the binary representation of the
|
||||
component in a memory buffer. The buffer must be allocated and
|
||||
freed outside of this class.
|
||||
*/
|
||||
void setStart(const byte* pData) { pData_ = const_cast<byte*>(pData); }
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Return the tag of this entry.
|
||||
uint16_t tag() const { return tag_; }
|
||||
//! Return the group id of this component
|
||||
uint16_t group() const { return group_; }
|
||||
//! Return a pointer to the start of the binary representation of the component
|
||||
const byte* start() const { return pData_; }
|
||||
/*!
|
||||
@brief Print debug info about a component to \em os.
|
||||
|
||||
@param os Output stream to write to
|
||||
@param byteOrder Byte order
|
||||
@param prefix Prefix to be written before each line of output
|
||||
*/
|
||||
void print(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix ="") const;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
//! Implements addChild().
|
||||
virtual void doAddChild(AutoPtr tiffComponent) {}
|
||||
|
||||
//! Implements addNext().
|
||||
virtual void doAddNext(AutoPtr tiffComponent) {}
|
||||
|
||||
//! Implements accept()
|
||||
virtual void doAccept(TiffVisitor& visitor) =0;
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Implements print()
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const =0;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
uint16_t tag_; //!< Tag that identifies the component
|
||||
uint16_t group_; //!< Group id for this component
|
||||
/*!
|
||||
Pointer to the start of the binary representation of the component in
|
||||
a memory buffer. The buffer is allocated and freed outside of this class.
|
||||
*/
|
||||
byte* pData_;
|
||||
|
||||
}; // class TiffComponent
|
||||
|
||||
/*!
|
||||
@brief This abstract base class provides the common functionality of an
|
||||
IFD directory entry and defines an extended interface for derived
|
||||
concrete entries, which allows access to the attributes of the
|
||||
entry.
|
||||
*/
|
||||
class TiffEntryBase : public TiffComponent {
|
||||
friend void TiffReader::readTiffEntry(TiffEntryBase* object);
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffEntryBase(uint16_t tag, uint16_t group)
|
||||
: TiffComponent(tag, group),
|
||||
type_(0), count_(0), offset_(0),
|
||||
size_(0), pData_(0), isAllocated_(false), pValue_(0) {}
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffEntryBase();
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Return the Exiv2 type which corresponds to the field type.
|
||||
TypeId typeId() const { return TypeId(type_); }
|
||||
//! Return the number of components in this entry.
|
||||
uint32_t count() const { return count_; }
|
||||
//! Return the offset relative to the start of the TIFF header.
|
||||
uint32_t offset() const { return offset_; }
|
||||
//! Return the size of this component in bytes
|
||||
uint32_t size() const { return size_; }
|
||||
//! Return a pointer to the data area of this component
|
||||
const byte* pData() const { return pData_; }
|
||||
//! Return a pointer to the converted value of this component
|
||||
const Value* pValue() const { return pValue_; }
|
||||
|
||||
//! Print base entry
|
||||
void printEntry(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
uint16_t type_; //!< Field Type
|
||||
uint32_t count_; //!< The number of values of the indicated Type
|
||||
uint32_t offset_; //!< Offset to data area from start of TIFF header
|
||||
/*!
|
||||
Size of the data buffer holding the value in bytes, there is no
|
||||
minimum size.
|
||||
*/
|
||||
uint32_t size_;
|
||||
const byte* pData_; //!< Pointer to the data area
|
||||
bool isAllocated_; //!< True if this entry owns the value data
|
||||
Value* pValue_; //!< Converted data value
|
||||
|
||||
}; // class TiffEntryBase
|
||||
|
||||
/*!
|
||||
@brief A standard TIFF IFD entry.
|
||||
*/
|
||||
class TiffEntry : public TiffEntryBase {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Constructor
|
||||
TiffEntry(uint16_t tag, uint16_t group) : TiffEntryBase(tag, group) {}
|
||||
//! Virtual destructor.
|
||||
virtual ~TiffEntry() {}
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void doAccept(TiffVisitor& visitor);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
//@}
|
||||
|
||||
}; // class TiffEntry
|
||||
|
||||
/*!
|
||||
@brief This class models a TIFF directory (%Ifd). It is a composite
|
||||
component of the TIFF tree.
|
||||
*/
|
||||
class TiffDirectory : public TiffComponent {
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffDirectory(uint16_t tag, uint16_t group)
|
||||
: TiffComponent(tag, group), pNext_(0) {}
|
||||
//! Virtual destructor
|
||||
virtual ~TiffDirectory();
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void doAddChild(TiffComponent::AutoPtr tiffComponent);
|
||||
|
||||
virtual void doAddNext(TiffComponent::AutoPtr tiffComponent);
|
||||
|
||||
virtual void doAccept(TiffVisitor& visitor);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
Components components_; //!< List of components in this directory
|
||||
TiffComponent* pNext_; //!< Pointer to the next IFD
|
||||
|
||||
}; // class TiffDirectory
|
||||
|
||||
/*!
|
||||
@brief This class models a TIFF sub-directory (sub-IFD). A sub-IFD
|
||||
is an entry with a value that is a pointer to an IFD
|
||||
structure and contains this IFD. The TIFF standard defines
|
||||
some important tags to be sub-IFDs, including the %Exif and
|
||||
GPS tags.
|
||||
*/
|
||||
class TiffSubIfd : public TiffEntryBase {
|
||||
friend void TiffReader::visitSubIfd(TiffSubIfd* object);
|
||||
public:
|
||||
//! @name Creators
|
||||
//@{
|
||||
//! Default constructor
|
||||
TiffSubIfd(uint16_t tag, uint16_t group, uint16_t newGroup)
|
||||
: TiffEntryBase(tag, group), ifd_(tag, newGroup) {}
|
||||
//! Virtual destructor
|
||||
virtual ~TiffSubIfd() {}
|
||||
//@}
|
||||
|
||||
private:
|
||||
//! @name Manipulators
|
||||
//@{
|
||||
virtual void doAddChild(TiffComponent::AutoPtr tiffComponent);
|
||||
|
||||
virtual void doAddNext(TiffComponent::AutoPtr tiffComponent);
|
||||
|
||||
virtual void doAccept(TiffVisitor& visitor);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
//@{
|
||||
virtual void doPrint(std::ostream& os,
|
||||
ByteOrder byteOrder,
|
||||
const std::string& prefix) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
// DATA
|
||||
TiffDirectory ifd_; //!< The subdirectory
|
||||
|
||||
}; // class TiffSubIfd
|
||||
|
||||
/*!
|
||||
Type for a function pointer for functions to create TIFF components.
|
||||
Todo: This may eventually need to also have access to the image or parse tree
|
||||
in order to make decisions based on the value of other tags.
|
||||
*/
|
||||
typedef TiffComponent::AutoPtr (*NewTiffCompFct)(const TiffStructure* ts);
|
||||
|
||||
/*!
|
||||
@brief Data structure used as a row (element) of a table (array)
|
||||
describing the TIFF structure of an image format for reading and
|
||||
writing. Different tables can be used to support different TIFF
|
||||
based image formats.
|
||||
*/
|
||||
struct TiffStructure {
|
||||
//! Return the tag corresponding to the extended tag
|
||||
uint16_t tag() const { return static_cast<uint16_t>(extendedTag_ & 0xffff); }
|
||||
|
||||
uint32_t extendedTag_; //!< Tag (32 bit so that it can contain special tags)
|
||||
uint16_t group_; //!< Group that contains the tag
|
||||
NewTiffCompFct newTiffCompFct_; //!< Function to create the correct TIFF component
|
||||
uint16_t newGroup_; //!< Group of the newly created component
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief Stateless parser class for data in TIFF format. Images use this
|
||||
class to decode and encode TIFF-based data.
|
||||
*/
|
||||
class TiffParser {
|
||||
public:
|
||||
/*!
|
||||
@brief Decode TIFF metadata from a data buffer \em pData of length
|
||||
@brief Decode TIFF metadata from a data buffer \em pData of length
|
||||
\em size into \em image.
|
||||
|
||||
This is the entry point to access image data in TIFF format. The
|
||||
parser uses classes TiffHeade2, TiffEntry, TiffDirectory.
|
||||
parser uses classes TiffHeade2 and the TiffComponent and TiffVisitor
|
||||
hierarchies.
|
||||
|
||||
@param pData Pointer to the data buffer. Must point to data
|
||||
@param pData Pointer to the data buffer. Must point to data
|
||||
in TIFF format; no checks are performed.
|
||||
@param size Length of the data buffer.
|
||||
@param pTiffStructure Pointer to a table describing the TIFF structure
|
||||
@param pTiffStructure Pointer to a table describing the TIFF structure
|
||||
used to decode the data.
|
||||
@param decoder Reference to a TIFF visitor to decode and extract
|
||||
the metadata from the TIFF composite structure.
|
||||
|
||||
@throw Error If the data buffer cannot be parsed.
|
||||
*/
|
||||
static void decode(const byte* pData,
|
||||
static void decode(const byte* pData,
|
||||
uint32_t size,
|
||||
const TiffStructure* pTiffStructure,
|
||||
TiffVisitor& decoder);
|
||||
/*!
|
||||
@brief Create the appropriate TiffComponent to handle the \em tag in
|
||||
\em group.
|
||||
@brief Create the TiffComponent for TIFF entry \em tag in \em group
|
||||
based on the lookup list \em pTiffStructure.
|
||||
|
||||
Uses table \em pTiffStructure to derive the correct component. If a
|
||||
tag, group tupel is not found in the table, a TiffEntry is created. If
|
||||
the pointer that is returned is 0, then the TIFF entry should be ignored.
|
||||
If a tag, group tupel is not found in the table, a TiffEntry is
|
||||
created. If the pointer that is returned is 0, then the TIFF entry
|
||||
should be ignored.
|
||||
*/
|
||||
static TiffComponent::AutoPtr create( uint32_t extendedTag,
|
||||
uint16_t group,
|
||||
@ -533,10 +597,10 @@ namespace Exiv2 {
|
||||
// template, inline and free functions
|
||||
|
||||
//! Function to create and initialize a new TIFF directory
|
||||
TiffComponent::AutoPtr newTiffDirectory(const TiffStructure* ts, int i);
|
||||
TiffComponent::AutoPtr newTiffDirectory(const TiffStructure* ts);
|
||||
|
||||
//! Function to create and initialize a new TIFF sub-directory
|
||||
TiffComponent::AutoPtr newTiffSubIfd(const TiffStructure* ts, int i);
|
||||
TiffComponent::AutoPtr newTiffSubIfd(const TiffStructure* ts);
|
||||
|
||||
} // namespace Exiv2
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user