makernote:

Added MakerNote::offset()
Fixed IfdMakerNote::copy() for IfdMakerNote with a prefix
Various doc fixes

ifd:
Fixed Ifd::erase(pos) to return an iterator
Added Ifd::dataOffset()
Various doc fixes

exif:
Added Thumbnail::offset()
Fixed ExifData::eraseThumbnail()
Fixed ExifData::erase(pos) to return an iterator
v0.27.3
Andreas Huggel 21 years ago
parent 1f943f45d2
commit 0b24a0ad29

@ -20,14 +20,14 @@
*/
/*
File: exif.cpp
Version: $Name: $ $Revision: 1.39 $
Version: $Name: $ $Revision: 1.40 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.39 $ $RCSfile: exif.cpp,v $")
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.40 $ $RCSfile: exif.cpp,v $")
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@ -159,7 +159,7 @@ namespace Exif {
}
TiffThumbnail::TiffThumbnail()
: size_(0), pImage_(0), ifd_(ifd1, 0, false)
: offset_(0), size_(0), pImage_(0), ifd_(ifd1, 0, false)
{
}
@ -169,7 +169,8 @@ namespace Exif {
}
TiffThumbnail::TiffThumbnail(const TiffThumbnail& rhs)
: size_(rhs.size_), pImage_(0), ifd_(ifd1, 0, false)
: offset_(rhs.offset_), size_(rhs.size_), pImage_(0),
ifd_(ifd1, 0, false)
{
if (rhs.pImage_ && rhs.size_ > 0) {
pImage_ = new char[rhs.size_];
@ -190,6 +191,7 @@ namespace Exif {
ifd_.read(pNewImage + tiffHeader_.offset(),
tiffHeader_.byteOrder(), tiffHeader_.offset());
}
offset_ = rhs.offset_;
size_ = rhs.size_;
delete[] pImage_;
pImage_ = pNewImage;
@ -212,10 +214,8 @@ namespace Exif {
// Create IFD (without Exif and GPS tags) from metadata
Ifd ifd1(ifd1);
addToIfd(ifd1, exifData.begin(), exifData.end(), tiffHeader.byteOrder());
Ifd::iterator i = ifd1.findTag(0x8769);
if (i != ifd1.end()) ifd1.erase(i);
i = ifd1.findTag(0x8825);
if (i != ifd1.end()) ifd1.erase(i);
ifd1.erase(0x8769);
ifd1.erase(0x8825);
// Do not copy the IFD yet, remember the location and leave a gap
long ifdOffset = len;
@ -229,19 +229,23 @@ namespace Exif {
ExifData::const_iterator sizes = exifData.findKey(key);
if (sizes == exifData.end()) return 2;
std::ostringstream os; // for the new strip offsets
long minOffset = 0;
for (long k = 0; k < offsets->count(); ++k) {
long offset = offsets->toLong(k);
long size = sizes->toLong(k);
memcpy(img.pData_ + len, buf + offset, size);
os << len << " ";
len += size;
}
minOffset = offset; // just to initialize minOffset
}
for (long k = 0; k < offsets->count(); ++k) {
minOffset = std::min(minOffset, offsets->toLong(k));
}
// Update the IFD with the actual strip offsets (replace existing entry)
Metadatum newOffsets(*offsets);
newOffsets.setValue(os.str());
i = ifd1.findTag(0x0111);
if (i != ifd1.end()) ifd1.erase(i);
ifd1.erase(0x0111);
addToIfd(ifd1, newOffsets, tiffHeader.byteOrder());
// Finally, sort and copy the IFD
@ -252,6 +256,7 @@ namespace Exif {
pImage_ = new char[len];
memcpy(pImage_, img.pData_, len);
size_ = len;
offset_ = minOffset;
tiffHeader_.read(pImage_);
ifd_.read(pImage_ + tiffHeader_.offset(),
tiffHeader_.byteOrder(), tiffHeader_.offset());
@ -326,7 +331,12 @@ namespace Exif {
return size_;
}
void TiffThumbnail::setOffsets(Ifd& ifd1, ByteOrder byteOrder) const
long TiffThumbnail::offset() const
{
return offset_;
}
void TiffThumbnail::setOffsets(Ifd& ifd1, ByteOrder byteOrder)
{
// Adjust the StripOffsets, assuming that the existing TIFF strips
// start immediately after the thumbnail IFD
@ -336,20 +346,25 @@ namespace Exif {
if (pos == ifd_.end()) throw Error("Bad thumbnail (0x0111)");
Metadatum offsets(*pos, tiffHeader_.byteOrder());
std::ostringstream os;
long minOffset = 0;
for (long k = 0; k < offsets.count(); ++k) {
os << offsets.toLong(k) + shift << " ";
minOffset = offsets.toLong(k) + shift; // initialize minOffset
}
offsets.setValue(os.str());
for (long k = 0; k < offsets.count(); ++k) {
minOffset = std::min(minOffset, offsets.toLong(k));
}
offset_ = minOffset;
// Update the IFD with the re-calculated strip offsets
// (replace existing entry)
Ifd::iterator i = ifd1.findTag(0x0111);
if (i != ifd1.end()) ifd1.erase(i);
ifd1.erase(0x0111);
addToIfd(ifd1, offsets, byteOrder);
} // TiffThumbnail::setOffsets
JpegThumbnail::JpegThumbnail()
: size_(0), pImage_(0)
: offset_(0), size_(0), pImage_(0)
{
}
@ -359,7 +374,7 @@ namespace Exif {
}
JpegThumbnail::JpegThumbnail(const JpegThumbnail& rhs)
: size_(rhs.size_), pImage_(0)
: offset_(rhs.offset_), size_(rhs.size_), pImage_(0)
{
if (rhs.pImage_ && rhs.size_ > 0) {
pImage_ = new char[rhs.size_];
@ -374,6 +389,7 @@ namespace Exif {
pNewImage = new char[rhs.size_];
memcpy(pNewImage, rhs.pImage_, rhs.size_);
}
offset_ = rhs.offset_;
size_ = rhs.size_;
delete[] pImage_;
pImage_ = pNewImage;
@ -396,6 +412,7 @@ namespace Exif {
pImage_ = new char[size];
memcpy(pImage_, buf + offset, size);
size_ = size;
offset_ = offset;
return 0;
} // JpegThumbnail::read
@ -429,7 +446,7 @@ namespace Exif {
delete value;
pos = exifData.findKey(key);
}
pos->setValue("0");
pos->setValue(toString(offset_));
key = "Thumbnail.RecordingOffset.JPEGInterchangeFormatLength";
pos = exifData.findKey(key);
@ -459,18 +476,24 @@ namespace Exif {
return size_;
}
void JpegThumbnail::setOffsets(Ifd& ifd1, ByteOrder byteOrder) const
long JpegThumbnail::offset() const
{
return offset_;
}
void JpegThumbnail::setOffsets(Ifd& ifd1, ByteOrder byteOrder)
{
Ifd::iterator pos = ifd1.findTag(0x0201);
if (pos == ifd1.end()) throw Error("Bad thumbnail (0x0201)");
pos->setValue(ifd1.offset() + ifd1.size() + ifd1.dataSize(), byteOrder);
offset_ = ifd1.offset() + ifd1.size() + ifd1.dataSize();
pos->setValue(offset_, byteOrder);
}
ExifData::ExifData()
: pThumbnail_(0), pMakerNote_(0), ifd0_(ifd0, 0, false),
exifIfd_(exifIfd, 0, false), iopIfd_(iopIfd, 0, false),
gpsIfd_(gpsIfd, 0, false), ifd1_(ifd1, 0, false),
size_(0), pData_(0)
size_(0), pData_(0), compatible_(true)
{
}
@ -571,7 +594,6 @@ namespace Exif {
ifd1_.erase(pos);
ret = -99;
}
// Copy all entries from the IFDs and the MakerNote to the metadata
metadata_.clear();
add(ifd0_.begin(), ifd0_.end(), byteOrder());
@ -582,7 +604,6 @@ namespace Exif {
add(iopIfd_.begin(), iopIfd_.end(), byteOrder());
add(gpsIfd_.begin(), gpsIfd_.end(), byteOrder());
add(ifd1_.begin(), ifd1_.end(), byteOrder());
// Read the thumbnail
readThumbnail();
@ -626,7 +647,7 @@ namespace Exif {
// If we can update the internal IFDs and the underlying data buffer
// from the metadata without changing the data size, then it is enough
// to copy the data buffer.
if (updateEntries()) {
if (compatible_ && updateEntries()) {
#ifdef DEBUG_MAKERNOTE
std::cerr << "->>>>>> using non-intrusive writing <<<<<<-\n";
#endif
@ -845,28 +866,79 @@ namespace Exif {
std::sort(metadata_.begin(), metadata_.end(), cmpMetadataByTag);
}
void ExifData::erase(ExifData::iterator pos)
ExifData::iterator ExifData::erase(ExifData::iterator pos)
{
metadata_.erase(pos);
return metadata_.erase(pos);
}
long ExifData::eraseThumbnail()
{
// Delete all Thumbnail.*.* (IFD1) metadata
for (Metadata::iterator i = begin(); i != end(); ++i) {
if (i->ifdId() == ifd1) erase(i);
Metadata::iterator i = begin();
while (i != end()) {
if (i->ifdId() == ifd1) {
i = erase(i);
}
else {
++i;
}
}
long delta = 0;
if (stdThumbPosition()) {
delta = size_;
if (size_ > 0 && ifd0_.next() > 0) {
// Truncate IFD1 and thumbnail data from the data buffer
size_ = ifd0_.next();
ifd0_.setNext(0, byteOrder());
}
delta -= size_;
}
else {
// We will have to write the hard way and re-arrange the data
compatible_ = false;
delta = ifd1_.size() + ifd1_.dataSize()
+ pThumbnail_ ? pThumbnail_->size() : 0;
}
// Truncate IFD1 and thumbnail data from the data buffer
long delta = size_;
if (size_ > 0) size_ = ifd0_.next();
delta -= size_;
ifd0_.setNext(0, byteOrder());
// Delete the thumbnail itself
delete pThumbnail_;
pThumbnail_ = 0;
if (pThumbnail_) {
delete pThumbnail_;
pThumbnail_ = 0;
}
return delta;
}
bool ExifData::stdThumbPosition() const
{
// Todo: There is still an invalid assumption here: The data of an IFD
// can be stored in multiple non-contiguous blocks. In this case,
// dataOffset + dataSize does not point to the end of the IFD data.
// in particular, this is potentially the case for the remaining Exif
// data in the presence of a known Makernote.
bool rc = true;
if (pThumbnail_) {
long maxOffset;
maxOffset = std::max(ifd0_.offset(), ifd0_.dataOffset());
maxOffset = std::max(maxOffset, exifIfd_.offset());
maxOffset = std::max(maxOffset, exifIfd_.dataOffset()
+ exifIfd_.dataSize());
if (pMakerNote_) {
maxOffset = std::max(maxOffset, pMakerNote_->offset()
+ pMakerNote_->size());
}
maxOffset = std::max(maxOffset, iopIfd_.offset());
maxOffset = std::max(maxOffset, iopIfd_.dataOffset()
+ iopIfd_.dataSize());
maxOffset = std::max(maxOffset, gpsIfd_.offset());
maxOffset = std::max(maxOffset, gpsIfd_.dataOffset()
+ gpsIfd_.dataSize());
if ( maxOffset > ifd1_.offset()
|| maxOffset > ifd1_.dataOffset() && ifd1_.dataOffset() > 0
|| maxOffset > pThumbnail_->offset()) rc = false;
}
return rc;
}
int ExifData::readThumbnail()
{
delete pThumbnail_;

@ -21,7 +21,7 @@
/*!
@file exif.hpp
@brief Encoding and decoding of %Exif data
@version $Name: $ $Revision: 1.37 $
@version $Name: $ $Revision: 1.38 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created
@ -271,6 +271,20 @@ namespace Exif {
virtual int read(const char* buf,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian) =0;
/*!
@brief Update the internal offset and the thumbnail data offsets
in IFD1 assuming the thumbnail data follows immediately after
IFD1.
If the type of the thumbnail image is JPEG, JPEGInterchangeFormat is
set to point directly behind the data area of IFD1. If the type is
TIFF, StripOffsets from the thumbnail image are adjusted to point to
the strips, which have to follow immediately after IFD1. Use copy() to
write the thumbnail image data. The offset of IFD1 must be set
correctly. Changing the size or data size of IFD1 invalidates the
thumbnail data offsets set by this method.
*/
virtual void setOffsets(Ifd& ifd1, ByteOrder byteOrder) =0;
//@}
//! @name Accessors
@ -308,18 +322,10 @@ namespace Exif {
*/
virtual void update(ExifData& exifData) const =0;
/*!
@brief Update the thumbnail data offsets in IFD1 assuming the
thumbnail data follows immediately after IFD1.
If the type of the thumbnail image is JPEG, JPEGInterchangeFormat is
set to point directly behind the data area of IFD1. If the type is
TIFF, StripOffsets from the thumbnail image are adjusted to point to
the strips, which have to follow immediately after IFD1. Use copy() to
write the thumbnail image data. The offset of IFD1 must be set
correctly. Changing the size of IFD1 invalidates the thumbnail data
offsets set by this method.
@brief Return the position of the thumbnail image data from the
start of the TIFF header in the original %Exif data.
*/
virtual void setOffsets(Ifd& ifd1, ByteOrder byteOrder) const =0;
virtual long offset() const =0;
/*!
@brief Return the size of the thumbnail image (the size it
would occupy when extracted from the %Exif data)
@ -364,6 +370,7 @@ namespace Exif {
int read(const char* buf,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian);
void setOffsets(Ifd& ifd1, ByteOrder byteOrder);
//@}
//! @name Accessors
@ -373,13 +380,15 @@ namespace Exif {
const char* extension() const;
long copy(char* buf) const;
void update(ExifData& exifData) const;
void setOffsets(Ifd& ifd1, ByteOrder byteOrder) const;
long offset() const;
long size() const;
long dataSize() const;
//@}
private:
// DATA
long offset_; // Original offset of the thumbnail data
// from the start of the TIFF header
long size_; //!< Size of the image data
char* pImage_; //!< Thumbnail image data
TiffHeader tiffHeader_; //!< Thumbnail TIFF Header
@ -407,6 +416,7 @@ namespace Exif {
int read(const char* buf,
const ExifData& exifData,
ByteOrder byteOrder =littleEndian);
void setOffsets(Ifd& ifd1, ByteOrder byteOrder);
//@}
//! @name Accessors
@ -416,13 +426,15 @@ namespace Exif {
const char* extension() const;
long copy(char* buf) const;
void update(ExifData& exifData) const;
void setOffsets(Ifd& ifd1, ByteOrder byteOrder) const;
long offset() const;
long size() const;
long dataSize() const;
//@}
private:
// DATA
long offset_; // Original offset of the thumbnail data
// from the start of the TIFF header
long size_; // Size of the image data
char* pImage_; // Thumbnail image data
@ -562,7 +574,7 @@ namespace Exif {
buffer has enough memory. Otherwise the call results in
undefined behaviour.
@return Number of characters written to the buffer.
*/
*/
long copy(char* buf);
/*!
@brief Add all (IFD) entries in the range from iterator position begin
@ -586,8 +598,13 @@ namespace Exif {
multiple metadata with the same key.
*/
void add(const Metadatum& metadatum);
//! Delete the metadatum at iterator position pos
void erase(iterator pos);
/*!
@brief Delete the metadatum at iterator position pos, return the
position of the next metadatum. Note that iterators into
the metadata, including pos, are potentially invalidated
by this call.
*/
iterator erase(iterator pos);
//! Sort metadata by key
void sortByKey();
//! Sort metadata by tag
@ -617,8 +634,8 @@ namespace Exif {
iterator findIfdIdIdx(IfdId ifdId, int idx);
/*!
@brief Delete the thumbnail from the %Exif data. Removes all related
(Thumbnail.*.*, i.e., IFD1) metadata as well.
@return The number of bytes truncated from the original %Exif data.
(%Thumbnail.*.*, i.e., IFD1) metadata as well.
@return The number of bytes erased from the original %Exif data.
*/
long eraseThumbnail();
//@}
@ -666,18 +683,21 @@ namespace Exif {
//! Returns the byte order as specified in the TIFF header
ByteOrder byteOrder() const { return tiffHeader_.byteOrder(); }
/*!
@brief Write the thumbnail image to a file. The filename extension
will be set according to the image type of the thumbnail, so
the path should not include an extension.
@brief Write the thumbnail image to a file. A filename extension
is appended to path according to the image type of the
thumbnail, so the path should not include an extension.
*/
int writeThumbnail(const std::string& path) const
{ return pThumbnail_ ? pThumbnail_->write(path) : 0; }
//! Return the file extension of the thumbnail image file
/*!
@brief Return a short string describing the format of the %Exif
thumbnail ("TIFF", "JPEG").
*/
const char* thumbnailFormat() const
{ return pThumbnail_ ? pThumbnail_->format() : ""; }
/*!
@brief Return the file extension for the format of the thumbnail
(".tif", ".jpg").
@brief Return the file extension for the %Exif thumbnail depending
on the format (".tif", ".jpg").
*/
const char* thumbnailExtension() const
{ return pThumbnail_ ? pThumbnail_->extension() : ""; }
@ -751,6 +771,12 @@ namespace Exif {
findEntry(IfdId ifdId, int idx) const;
//! Return a pointer to the internal IFD identified by its IFD id
const Ifd* getIfd(IfdId ifdId) const;
/*!
@brief Check if IFD1, the IFD1 data and thumbnail data are located at
the end of the Exif data. Return true, if they are or if there
is no thumbnail at all, else return false.
*/
bool stdThumbPosition() const;
//@}
// DATA
@ -770,6 +796,13 @@ namespace Exif {
long size_; //!< Size of the Exif raw data in bytes
char* pData_; //!< Exif raw data buffer
/*!
Can be set to false to indicate that non-intrusive writing is not
possible. If it is true (the default), then the compatibility checks
will be performed to determine which writing method to use.
*/
bool compatible_;
}; // class ExifData
// *****************************************************************************

@ -20,14 +20,14 @@
*/
/*
File: ifd.cpp
Version: $Name: $ $Revision: 1.15 $
Version: $Name: $ $Revision: 1.16 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.15 $ $RCSfile: ifd.cpp,v $")
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.16 $ $RCSfile: ifd.cpp,v $")
// *****************************************************************************
// included header files
@ -156,21 +156,24 @@ namespace Exif {
} // Entry::component
Ifd::Ifd(IfdId ifdId)
: alloc_(true), ifdId_(ifdId), offset_(0), pNext_(0), next_(0)
: alloc_(true), ifdId_(ifdId), offset_(0), dataOffset_(0),
pNext_(0), next_(0)
{
pNext_ = new char[4];
memset(pNext_, 0x0, 4);
}
Ifd::Ifd(IfdId ifdId, uint32 offset)
: alloc_(true), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0)
: alloc_(true), ifdId_(ifdId), offset_(offset), dataOffset_(0),
pNext_(0), next_(0)
{
pNext_ = new char[4];
memset(pNext_, 0x0, 4);
}
Ifd::Ifd(IfdId ifdId, uint32 offset, bool alloc)
: alloc_(alloc), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0)
: alloc_(alloc), ifdId_(ifdId), offset_(offset), dataOffset_(0),
pNext_(0), next_(0)
{
if (alloc_) {
pNext_ = new char[4];
@ -185,7 +188,8 @@ namespace Exif {
Ifd::Ifd(const Ifd& rhs)
: alloc_(rhs.alloc_), entries_(rhs.entries_), ifdId_(rhs.ifdId_),
offset_(rhs.offset_), pNext_(rhs.pNext_), next_(rhs.next_)
offset_(rhs.offset_), dataOffset_(rhs.dataOffset_),
pNext_(rhs.pNext_), next_(rhs.next_)
{
if (alloc_ && rhs.pNext_) {
pNext_ = new char[4];
@ -221,18 +225,24 @@ namespace Exif {
}
next_ = getULong(buf+o, byteOrder);
// Guess the offset of the IFD, if it was not given. The guess is based
// on the assumption that the smallest offset points to a data buffer
// directly following the IFD. Subsequently all offsets of IFD entries
// will need to be recalculated.
if (offset_ == 0 && preEntries.size() > 0) {
// Set the offset of the first data entry outside of the IFD.
// At the same time we guess the offset of the IFD, if it was not
// given. The guess is based on the assumption that the smallest offset
// points to a data buffer directly following the IFD. Subsequently all
// offsets of IFD entries will need to be recalculated.
if (preEntries.size() > 0) {
// Find the entry with the smallest offset
Ifd::PreEntries::const_iterator i = std::min_element(
preEntries.begin(), preEntries.end(), cmpPreEntriesByOffset);
// Set the 'guessed' IFD offset, the test is needed for the case when
// all entries have data sizes not exceeding 4.
// Only do something if there is at least one entry with data
// outside the IFD directory itself.
if (i->size_ > 4) {
offset_ = i->offset_ - size();
if (offset_ == 0) {
// Set the 'guessed' IFD offset
offset_ = i->offset_ - size();
}
// Set the offset of the first data entry outside of the IFD
dataOffset_ = i->offset_;
}
}
@ -362,6 +372,7 @@ namespace Exif {
pNext_ = 0;
}
offset_ = 0;
dataOffset_ = 0;
} // Ifd::clear
void Ifd::setNext(uint32 next, ByteOrder byteOrder)
@ -390,9 +401,9 @@ namespace Exif {
return idx;
}
void Ifd::erase(iterator pos)
Ifd::iterator Ifd::erase(iterator pos)
{
entries_.erase(pos);
return entries_.erase(pos);
}
long Ifd::size() const

@ -21,7 +21,7 @@
/*!
@file ifd.hpp
@brief Encoding and decoding of IFD (Image File Directory) data
@version $Name: $ $Revision: 1.13 $
@version $Name: $ $Revision: 1.14 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created
@ -385,8 +385,13 @@ namespace Exif {
of the deleted entry or 0 if no entry with tag was found.
*/
int erase(uint16 tag);
//! Delete the directory entry at iterator position pos
void erase(iterator pos);
/*!
@brief Delete the directory entry at iterator position pos, return the
position of the next entry. Note that iterators into the
directory, including pos, are potentially invalidated by this
call.
*/
iterator erase(iterator pos);
//! Sort the IFD entries by tag
void sortByTag();
//! The first entry
@ -415,6 +420,12 @@ namespace Exif {
IfdId ifdId() const { return ifdId_; }
//! Get the offset of the IFD from the start of the TIFF header
long offset() const { return offset_; }
/*!
@brief Get the offset of the first data entry outside of the IFD,
return 0 if there is none. The data offset is determined when
the IFD is read.
*/
long dataOffset() const { return dataOffset_; }
//! Get the offset to the next IFD from the start of the TIFF header
uint32 next() const { return next_; }
//! Get the number of directory entries in the IFD
@ -462,11 +473,13 @@ namespace Exif {
Entries entries_;
//! IFD Id
IfdId ifdId_;
//! offset of the IFD from the start of TIFF header
//! 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
//! Offset of the first data entry outside of the IFD directory
long dataOffset_;
//! 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_)
//! The offset of the next IFD as data value (always in sync with *pNext_)
uint32 next_;
}; // class Ifd

@ -20,13 +20,13 @@
*/
/*
File: makernote.cpp
Version: $Name: $ $Revision: 1.15 $
Version: $Name: $ $Revision: 1.16 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.15 $ $RCSfile: makernote.cpp,v $")
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.16 $ $RCSfile: makernote.cpp,v $")
// Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE
@ -155,6 +155,8 @@ namespace Exif {
ByteOrder byteOrder,
long offset)
{
// Remember the offset
offset_ = offset;
// Set byte order if none is set yet
if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder;
int rc = 0;
@ -182,7 +184,6 @@ namespace Exif {
i->setMakerNote(this);
}
}
#ifdef DEBUG_MAKERNOTE
hexdump(std::cerr, buf, len, offset);
if (rc == 0) ifd_.print(std::cerr);
@ -193,10 +194,23 @@ namespace Exif {
long IfdMakerNote::copy(char* buf, ByteOrder byteOrder, long offset)
{
// Remember the new offset
offset_ = offset;
// Set byte order if none is set yet
if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder;
return ifd_.copy(buf, byteOrder_, offset);
}
long len = 0;
if (!prefix_.empty()) {
// Write the prefix string to the Makernote buffer
memcpy(buf, prefix_.data(), prefix_.size());
len += prefix_.size();
}
if (!absOffset_) {
// Use offsets relative to the start of the Makernote field
offset = 0;
}
len += ifd_.copy(buf + len, byteOrder_, offset + len);
return len;
} // IfdMakerNote::copy
Entries::const_iterator IfdMakerNote::findIdx(int idx) const
{
@ -205,7 +219,7 @@ namespace Exif {
long IfdMakerNote::size() const
{
return ifd_.size() + ifd_.dataSize();
return prefix_.size() + ifd_.size() + ifd_.dataSize();
}
MakerNoteFactory* MakerNoteFactory::pInstance_ = 0;
@ -229,7 +243,7 @@ namespace Exif {
// Todo: use case insensitive make and model comparisons
// find or create a registry entry for make
// Find or create a registry entry for make
ModelRegistry* modelRegistry = 0;
Registry::const_iterator end1 = registry_.end();
Registry::const_iterator pos1;
@ -243,7 +257,7 @@ namespace Exif {
modelRegistry = new ModelRegistry;
registry_.push_back(std::make_pair(make, modelRegistry));
}
// find or create a registry entry for model
// Find or create a registry entry for model
ModelRegistry::iterator end2 = modelRegistry->end();
ModelRegistry::iterator pos2;
for (pos2 = modelRegistry->begin(); pos2 != end2; ++pos2) {

@ -22,7 +22,7 @@
@file makernote.hpp
@brief Contains the %Exif %MakerNote interface, IFD %MakerNote and a
MakerNote factory
@version $Name: $ $Revision: 1.14 $
@version $Name: $ $Revision: 1.15 $
@author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created
@ -113,7 +113,8 @@ namespace Exif {
for the Entries.
*/
MakerNote(const MnTagInfo* pMnTagInfo =0, bool alloc =true)
: pMnTagInfo_(pMnTagInfo), alloc_(alloc), byteOrder_(invalidByteOrder) {}
: pMnTagInfo_(pMnTagInfo), alloc_(alloc),
byteOrder_(invalidByteOrder), offset_(0) {}
//! Virtual destructor.
virtual ~MakerNote() {}
//@}
@ -160,6 +161,8 @@ namespace Exif {
uint16 decomposeKey(const std::string& key) const;
//! Return the byte order (little or big endian).
ByteOrder byteOrder() const { return byteOrder_; }
//! Return the offset of the makernote from the start of the TIFF header
long offset() const { return offset_; }
/*!
@brief Return the name of a makernote tag. The default implementation
looks up the makernote info tag array if one is set, else
@ -208,7 +211,7 @@ namespace Exif {
virtual Entries::const_iterator end() const =0;
//! Find an entry by idx, return a const iterator to the record
virtual Entries::const_iterator findIdx(int idx) const =0;
//! Return the size of the makernote in bytes.
//! Return the size of the makernote in bytes
virtual long size() const =0;
//! Return the name of the makernote section
virtual std::string sectionName(uint16 tag) const =0;
@ -219,19 +222,23 @@ namespace Exif {
//@}
protected:
// DATA
//! Pointer to an array of makernote tag infos
const MnTagInfo* pMnTagInfo_;
/*!
Memory management
True: requires memory allocation and deallocation,
False: no memory management needed.
@brief Flag to control the memory management: <BR>
True: requires memory allocation and deallocation, <BR>
False: no memory management needed.
*/
const bool alloc_;
/*!
Alternative byte order to use, invalid if the byte order of the
%Exif block can be used
@brief Alternative byte order to use, invalid if the byte order of the
%Exif block can be used
*/
ByteOrder byteOrder_;
//! Offset of the makernote from the start of the TIFF header
long offset_;
}; // class MakerNote
/*!
@ -279,11 +286,12 @@ namespace Exif {
//@}
protected:
//! Prefix before the start of the IFD
// DATA
//! String prefix at the beginning of the makernote, before the IFD
std::string prefix_;
/*!
True: Offsets are from start of the TIFF header
False: Offsets are from start of the makernote
@brief True: Offsets are from start of the TIFF header,
False: Offsets are from start of the makernote
*/
bool absOffset_;
//! MakerNote IFD

Loading…
Cancel
Save