[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:36:17 UTC 2017


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=0b24a0a

The following commit has been merged in the master branch:
commit 0b24a0ad293e9a8b79d83b25ae41ac27bee3add9
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Fri May 7 05:09:57 2004 +0000

    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
---
 src/exif.cpp      | 140 +++++++++++++++++++++++++++++++++++++++++-------------
 src/exif.hpp      |  83 ++++++++++++++++++++++----------
 src/ifd.cpp       |  43 ++++++++++-------
 src/ifd.hpp       |  25 +++++++---
 src/makernote.cpp |  30 ++++++++----
 src/makernote.hpp |  30 +++++++-----
 6 files changed, 251 insertions(+), 100 deletions(-)

diff --git a/src/exif.cpp b/src/exif.cpp
index c571003..2b28adc 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -20,14 +20,14 @@
  */
 /*
   File:      exif.cpp
-  Version:   $Name:  $ $Revision: 1.39 $
+  Version:   $Name:  $ $Revision: 1.40 $
   Author(s): Andreas Huggel (ahu) <ahuggel at 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 <<<<<<-
";
 #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_;
diff --git a/src/exif.hpp b/src/exif.hpp
index 47006b3..735e3bb 100644
--- a/src/exif.hpp
+++ b/src/exif.hpp
@@ -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 at gmx.net">ahuggel at 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
 
 // *****************************************************************************
diff --git a/src/ifd.cpp b/src/ifd.cpp
index 89db135..c07176b 100644
--- a/src/ifd.cpp
+++ b/src/ifd.cpp
@@ -20,14 +20,14 @@
  */
 /*
   File:      ifd.cpp
-  Version:   $Name:  $ $Revision: 1.15 $
+  Version:   $Name:  $ $Revision: 1.16 $
   Author(s): Andreas Huggel (ahu) <ahuggel at 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
diff --git a/src/ifd.hpp b/src/ifd.hpp
index c8e0dc6..01b5a4c 100644
--- a/src/ifd.hpp
+++ b/src/ifd.hpp
@@ -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 at gmx.net">ahuggel at 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
diff --git a/src/makernote.cpp b/src/makernote.cpp
index f9fb06b..16a3926 100644
--- a/src/makernote.cpp
+++ b/src/makernote.cpp
@@ -20,13 +20,13 @@
  */
 /*
   File:      makernote.cpp
-  Version:   $Name:  $ $Revision: 1.15 $
+  Version:   $Name:  $ $Revision: 1.16 $
   Author(s): Andreas Huggel (ahu) <ahuggel at 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) {
diff --git a/src/makernote.hpp b/src/makernote.hpp
index e94b6a5..8b81461 100644
--- a/src/makernote.hpp
+++ b/src/makernote.hpp
@@ -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 at gmx.net">ahuggel at 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

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list