Bugfix: Set offset to the next IFD directly in the underlying data buffer in non-alloc mode

v0.27.3
Andreas Huggel 22 years ago
parent 532b0c33a7
commit f7c55fcb64

@ -20,14 +20,14 @@
*/ */
/* /*
File: ifd.cpp File: ifd.cpp
Version: $Name: $ $Revision: 1.13 $ Version: $Name: $ $Revision: 1.14 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.13 $ $RCSfile: ifd.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.14 $ $RCSfile: ifd.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -156,18 +156,41 @@ namespace Exif {
} // Entry::component } // Entry::component
Ifd::Ifd(IfdId ifdId) Ifd::Ifd(IfdId ifdId)
: alloc_(true), ifdId_(ifdId), offset_(0), next_(0) : alloc_(true), ifdId_(ifdId), offset_(0), pNext_(0), next_(0)
{ {
pNext_ = new char[4];
memset(pNext_, 0x0, 4);
} }
Ifd::Ifd(IfdId ifdId, uint32 offset) Ifd::Ifd(IfdId ifdId, uint32 offset)
: alloc_(true), ifdId_(ifdId), offset_(offset), next_(0) : alloc_(true), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0)
{ {
pNext_ = new char[4];
memset(pNext_, 0x0, 4);
} }
Ifd::Ifd(IfdId ifdId, uint32 offset, bool alloc) Ifd::Ifd(IfdId ifdId, uint32 offset, bool alloc)
: alloc_(alloc), ifdId_(ifdId), offset_(offset), next_(0) : alloc_(alloc), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0)
{ {
if (alloc_) {
pNext_ = new char[4];
memset(pNext_, 0x0, 4);
}
}
Ifd::~Ifd()
{
if (alloc_) delete[] pNext_;
}
Ifd::Ifd(const Ifd& rhs)
: alloc_(rhs.alloc_), entries_(rhs.entries_), ifdId_(rhs.ifdId_),
offset_(rhs.offset_), pNext_(rhs.pNext_), next_(rhs.next_)
{
if (alloc_ && rhs.pNext_) {
pNext_ = new char[4];
memcpy(pNext_, rhs.pNext_, 4);
}
} }
int Ifd::read(const char* buf, ByteOrder byteOrder, long offset) int Ifd::read(const char* buf, ByteOrder byteOrder, long offset)
@ -190,6 +213,12 @@ namespace Exif {
preEntries.push_back(pe); preEntries.push_back(pe);
o += 12; o += 12;
} }
if (alloc_) {
memcpy(pNext_, buf + o, 4);
}
else {
pNext_ = const_cast<char*>(buf + o);
}
next_ = getULong(buf+o, byteOrder); next_ = getULong(buf+o, byteOrder);
// Guess the offset of the IFD, if it was not given. The guess is based // Guess the offset of the IFD, if it was not given. The guess is based
@ -304,7 +333,13 @@ namespace Exif {
} }
// Add the offset to the next IFD to the data buffer // Add the offset to the next IFD to the data buffer
o += ul2Data(buf + o, next_, byteOrder); if (pNext_) {
memcpy(buf + o, pNext_, 4);
}
else {
memset(buf + o, 0x0, 4);
}
o += 4;
// Add the data of all IFD entries to the data buffer // Add the data of all IFD entries to the data buffer
for (i = b; i != e; ++i) { for (i = b; i != e; ++i) {
@ -320,10 +355,22 @@ namespace Exif {
void Ifd::clear() void Ifd::clear()
{ {
entries_.clear(); entries_.clear();
next_ = 0; if (alloc_) {
memset(pNext_, 0x0, 4);
}
else {
pNext_ = 0;
}
offset_ = 0; offset_ = 0;
} // Ifd::clear } // Ifd::clear
void Ifd::setNext(uint32 next, ByteOrder byteOrder)
{
assert(pNext_);
ul2Data(pNext_, next, byteOrder);
next_ = next;
}
void Ifd::add(const Entry& entry) void Ifd::add(const Entry& entry)
{ {
assert(alloc_ == entry.alloc()); assert(alloc_ == entry.alloc());
@ -407,7 +454,7 @@ namespace Exif {
} }
os << prefix << "Next IFD: 0x" os << prefix << "Next IFD: 0x"
<< std::setw(8) << std::setfill('0') << std::hex << std::setw(8) << std::setfill('0') << std::hex
<< std::right << next_ << "\n"; << std::right << next() << "\n";
// Print data of IFD entries // Print data of IFD entries
for (i = b; i != e; ++i) { for (i = b; i != e; ++i) {
if (i->size() > 4) { if (i->size() > 4) {

@ -21,7 +21,7 @@
/*! /*!
@file ifd.hpp @file ifd.hpp
@brief Encoding and decoding of IFD (Image File Directory) data @brief Encoding and decoding of IFD (Image File Directory) data
@version $Name: $ $Revision: 1.11 $ @version $Name: $ $Revision: 1.12 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created
@ -265,6 +265,12 @@ namespace Exif {
and the same data buffer. and the same data buffer.
*/ */
class Ifd { class Ifd {
//! @name Not implemented
//@{
//! Assignment not allowed (memory management mode alloc_ is const)
Ifd& operator=(const Ifd& rhs);
//@}
public: public:
//! @name Creators //! @name Creators
//@{ //@{
@ -285,6 +291,10 @@ namespace Exif {
memory management is required for the Entries. memory management is required for the Entries.
*/ */
Ifd(IfdId ifdId, uint32 offset, bool alloc); Ifd(IfdId ifdId, uint32 offset, bool alloc);
//! Copy constructor
Ifd(const Ifd& rhs);
//! Destructor
~Ifd();
//@} //@}
//! Entries const iterator type //! Entries const iterator type
@ -356,8 +366,11 @@ namespace Exif {
entries. entries.
*/ */
void clear(); void clear();
//! Set the offset of the next IFD /*!
void setNext(uint32 next) { next_ = next; } @brief Set the offset of the next IFD. Byte order is needed to update
the underlying data buffer in non-alloc mode.
*/
void setNext(uint32 next, ByteOrder byteOrder);
/*! /*!
@brief Add the entry to the IFD. No duplicate-check is performed, @brief Add the entry to the IFD. No duplicate-check is performed,
i.e., it is possible to add multiple entries with the same tag. i.e., it is possible to add multiple entries with the same tag.
@ -402,7 +415,7 @@ namespace Exif {
//! Get the offset of the IFD from the start of the TIFF header //! Get the offset of the IFD from the start of the TIFF header
long offset() const { return offset_; } long offset() const { return offset_; }
//! Get the offset to the next IFD from the start of the TIFF header //! Get the offset to the next IFD from the start of the TIFF header
long next() const { return next_; } uint32 next() const { return next_; }
//! Get the number of directory entries in the IFD //! Get the number of directory entries in the IFD
long count() const { return entries_.size(); } long count() const { return entries_.size(); }
//! Get the size of this IFD in bytes (IFD only, without data) //! Get the size of this IFD in bytes (IFD only, without data)
@ -438,12 +451,21 @@ namespace Exif {
//! Container for 'pre-entries' //! Container for 'pre-entries'
typedef std::vector<PreEntry> PreEntries; typedef std::vector<PreEntry> PreEntries;
const bool alloc_; // True: requires memory allocation and deallocation, /*!
// False: no memory management needed. True: requires memory allocation and deallocation,
Entries entries_; // IFD entries False: no memory management needed.
IfdId ifdId_; // IFD Id */
long offset_; // offset of the IFD from the start of TIFF header const bool alloc_;
long next_; // offset of next IFD from the start of the TIFF header //! IFD entries
Entries entries_;
//! IFD Id
IfdId ifdId_;
//! offset of the IFD from the start of TIFF header
long offset_;
// Pointer to the offset of next IFD from the start of the TIFF header
char* pNext_;
// The offset of the next IFD as data value (always in sync with *pNext_)
uint32 next_;
}; // class Ifd }; // class Ifd

Loading…
Cancel
Save