From 8221293072d3e6b13ecc41ea7ab15b9d8eeb7b1b Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Mon, 21 Feb 2005 15:57:10 +0000 Subject: [PATCH] Completed ExifData assignment operator and copy constructor, added related code and tests. Fixes bug #417 --- src/Makefile | 15 +- src/canonmn.cpp | 21 +- src/canonmn.hpp | 9 +- src/exif.cpp | 266 +++++++++++++++-------- src/exif.hpp | 23 +- src/exifdata-test.cpp | 158 ++++++++++++++ src/fujimn.cpp | 21 +- src/fujimn.hpp | 9 +- src/ifd-test.cpp | 43 +++- src/ifd.cpp | 24 ++- src/ifd.hpp | 19 +- src/makernote.cpp | 36 +++- src/makernote.hpp | 43 +++- src/nikonmn.cpp | 63 +++++- src/nikonmn.hpp | 27 ++- src/sigmamn.cpp | 21 +- src/sigmamn.hpp | 9 +- src/tags.cpp | 6 +- test/data/exifdata-test.out | 420 ++++++++++++++++++++++++++++++++++++ test/data/exiv2-gc.jpg | Bin 0 -> 11623 bytes test/data/ifd-test.out | 30 +++ test/exifdata-test.sh | 29 +++ 22 files changed, 1120 insertions(+), 172 deletions(-) create mode 100644 src/exifdata-test.cpp create mode 100644 test/data/exifdata-test.out create mode 100644 test/data/exiv2-gc.jpg create mode 100755 test/exifdata-test.sh diff --git a/src/Makefile b/src/Makefile index 156cf4fc..7740f641 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,19 +48,20 @@ include $(top_srcdir)/config.mk # Source files # Add standalone C++ header files to this list -CCHDR = rcsid.hpp error.hpp +CCHDR = error.hpp rcsid.hpp # Add library C++ source files to this list -CCSRC = canonmn.cpp datasets.cpp exif.cpp fujimn.cpp ifd.cpp basicio.cpp iptc.cpp \ - makernote.cpp metadatum.cpp nikonmn.cpp sigmamn.cpp tags.cpp types.cpp \ - image.cpp jpgimage.cpp value.cpp +CCSRC = basicio.cpp canonmn.cpp datasets.cpp exif.cpp fujimn.cpp ifd.cpp \ + image.cpp iptc.cpp jpgimage.cpp makernote.cpp metadatum.cpp nikonmn.cpp \ + sigmamn.cpp tags.cpp types.cpp value.cpp # Add source files of simple applications to this list -BINSRC = addmoddel.cpp exifcomment.cpp exifprint.cpp ifd-test.cpp iptcprint.cpp \ +BINSRC = addmoddel.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 \ - iotest.cpp write2-test.cpp dataarea-test.cpp iptceasy.cpp + write2-test.cpp -# State the main source file of the Exiv2 application here +# Main source file of the Exiv2 application EXIV2MAIN = exiv2.cpp # Add additional source files of the Exiv2 application to this list diff --git a/src/canonmn.cpp b/src/canonmn.cpp index 16e33f86..fb01f260 100644 --- a/src/canonmn.cpp +++ b/src/canonmn.cpp @@ -72,16 +72,31 @@ namespace Exiv2 { { } - CanonMakerNote::AutoPtr CanonMakerNote::clone(bool alloc) const + CanonMakerNote::CanonMakerNote(const CanonMakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) { - return AutoPtr(clone_(alloc)); } - CanonMakerNote* CanonMakerNote::clone_(bool alloc) const + CanonMakerNote::AutoPtr CanonMakerNote::create(bool alloc) const + { + return AutoPtr(create_(alloc)); + } + + CanonMakerNote* CanonMakerNote::create_(bool alloc) const { return new CanonMakerNote(alloc); } + CanonMakerNote::AutoPtr CanonMakerNote::clone() const + { + return AutoPtr(clone_()); + } + + CanonMakerNote* CanonMakerNote::clone_() const + { + return new CanonMakerNote(*this); + } + std::ostream& CanonMakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const diff --git a/src/canonmn.hpp b/src/canonmn.hpp index 7a9c23a2..9e4e6341 100644 --- a/src/canonmn.hpp +++ b/src/canonmn.hpp @@ -97,13 +97,16 @@ namespace Exiv2 { is required for the makernote entries. */ CanonMakerNote(bool alloc =true); + //! Copy constructor + CanonMakerNote(const CanonMakerNote& rhs); //! Virtual destructor virtual ~CanonMakerNote() {} //@} //! @name Accessors //@{ - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Canon") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -176,8 +179,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + CanonMakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - CanonMakerNote* clone_(bool alloc =true) const; + CanonMakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { diff --git a/src/exif.cpp b/src/exif.cpp index 712f696c..0eb28868 100644 --- a/src/exif.cpp +++ b/src/exif.cpp @@ -181,7 +181,7 @@ namespace Exiv2 { value_->read(value); } - int TiffThumbnail::setDataArea(ExifData& exifData, Ifd& ifd1, + int TiffThumbnail::setDataArea(ExifData& exifData, Ifd* pIfd1, const byte* buf, long len) const { // Create a DataBuf that can hold all strips @@ -226,9 +226,9 @@ namespace Exiv2 { stripOffsets->setValue(os.str()); // Set corresponding data area at IFD1, if it is a contiguous area - if (firstOffset + totalSize == lastOffset + lastSize) { - Ifd::iterator pos = ifd1.findTag(0x0111); - assert(pos != ifd1.end()); + if (pIfd1 && firstOffset + totalSize == lastOffset + lastSize) { + Ifd::iterator pos = pIfd1->findTag(0x0111); + assert(pos != pIfd1->end()); pos->setDataArea(buf + firstOffset, totalSize); } @@ -265,7 +265,7 @@ namespace Exiv2 { return buf; } - int JpegThumbnail::setDataArea(ExifData& exifData, Ifd& ifd1, + int JpegThumbnail::setDataArea(ExifData& exifData, Ifd* pIfd1, const byte* buf, long len) const { ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat"); @@ -279,11 +279,13 @@ namespace Exiv2 { if (len < offset + size) return 2; format->setDataArea(buf + offset, size); format->setValue("0"); - Ifd::iterator pos = ifd1.findTag(0x0201); - assert(pos != ifd1.end()); - pos->setDataArea(buf + offset, size); + if (pIfd1) { + Ifd::iterator pos = pIfd1->findTag(0x0201); + assert(pos != pIfd1->end()); + pos->setDataArea(buf + offset, size); + } return 0; - } // JpegThumbnail::read + } // JpegThumbnail::setDataArea const char* JpegThumbnail::format() const { @@ -304,44 +306,107 @@ namespace Exiv2 { } ExifData::ExifData() - : ifd0_(ifd0Id, 0, false), - exifIfd_(exifIfdId, 0, false), iopIfd_(iopIfdId, 0, false), - gpsIfd_(gpsIfdId, 0, false), ifd1_(ifd1Id, 0, false), + : pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), size_(0), pData_(0), compatible_(true) { } ExifData::ExifData(const ExifData& rhs) : tiffHeader_(rhs.tiffHeader_), exifMetadata_(rhs.exifMetadata_), - ifd0_(ifd0Id, 0, false), - exifIfd_(exifIfdId, 0, false), iopIfd_(iopIfdId, 0, false), - gpsIfd_(gpsIfdId, 0, false), ifd1_(ifd1Id, 0, false), - size_(0), pData_(0), compatible_(false) + pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), + size_(0), pData_(0), compatible_(rhs.compatible_) { - if (rhs.makerNote_.get() != 0) makerNote_ = rhs.makerNote_->clone(); + pData_ = new byte[rhs.size_]; + size_ = rhs.size_; + memcpy(pData_, rhs.pData_, rhs.size_); + + if (rhs.makerNote_.get() != 0) { + makerNote_ = rhs.makerNote_->clone(); + makerNote_->updateBase(pData_); + } + if (rhs.pIfd0_) { + pIfd0_ = new Ifd(*rhs.pIfd0_); + pIfd0_->updateBase(pData_); + } + if (rhs.pExifIfd_) { + pExifIfd_ = new Ifd(*rhs.pExifIfd_); + pExifIfd_->updateBase(pData_); + } + if (rhs.pIopIfd_) { + pIopIfd_ = new Ifd(*rhs.pIopIfd_); + pIopIfd_->updateBase(pData_); + } + if (rhs.pGpsIfd_) { + pGpsIfd_ = new Ifd(*rhs.pGpsIfd_); + pGpsIfd_->updateBase(pData_); + } + if (rhs.pIfd1_) { + pIfd1_ = new Ifd(*rhs.pIfd1_); + pIfd1_->updateBase(pData_); + } } ExifData::~ExifData() { + delete pIfd0_; + delete pExifIfd_; + delete pIopIfd_; + delete pGpsIfd_; + delete pIfd1_; delete[] pData_; } ExifData& ExifData::operator=(const ExifData& rhs) { if (this == &rhs) return *this; + tiffHeader_ = rhs.tiffHeader_; exifMetadata_ = rhs.exifMetadata_; - makerNote_.reset(); - if (rhs.makerNote_.get() != 0) makerNote_ = rhs.makerNote_->clone(); - ifd0_.clear(); - exifIfd_.clear(); - iopIfd_.clear(); - gpsIfd_.clear(); - ifd1_.clear(); + size_ = 0; delete[] pData_; - pData_ = 0; - compatible_ = false; + pData_ = new byte[rhs.size_]; + size_ = rhs.size_; + memcpy(pData_, rhs.pData_, rhs.size_); + + makerNote_.reset(); + if (rhs.makerNote_.get() != 0) { + makerNote_ = rhs.makerNote_->clone(); + makerNote_->updateBase(pData_); + } + + delete pIfd0_; + pIfd0_ = 0; + if (rhs.pIfd0_) { + pIfd0_ = new Ifd(*rhs.pIfd0_); + pIfd0_->updateBase(pData_); + } + delete pExifIfd_; + pExifIfd_ = 0; + if (rhs.pExifIfd_) { + pExifIfd_ = new Ifd(*rhs.pExifIfd_); + pExifIfd_->updateBase(pData_); + } + delete pIopIfd_; + pIopIfd_ = 0; + if (rhs.pIopIfd_) { + pIopIfd_ = new Ifd(*rhs.pIopIfd_); + pIopIfd_->updateBase(pData_); + } + delete pGpsIfd_; + pGpsIfd_ = 0; + if (rhs.pGpsIfd_) { + pGpsIfd_ = new Ifd(*rhs.pGpsIfd_); + pGpsIfd_->updateBase(pData_); + } + delete pIfd1_; + pIfd1_ = 0; + if (rhs.pIfd1_) { + pIfd1_ = new Ifd(*rhs.pIfd1_); + pIfd1_->updateBase(pData_); + } + + compatible_ = rhs.compatible_; return *this; } @@ -370,19 +435,27 @@ namespace Exiv2 { if (rc) return rc; // Read IFD0 - rc = ifd0_.read(pData_ + tiffHeader_.offset(), - size_ - tiffHeader_.offset(), - byteOrder(), - tiffHeader_.offset()); + delete pIfd0_; + pIfd0_ = new Ifd(ifd0Id, 0, false); + assert(pIfd0_ != 0); + rc = pIfd0_->read(pData_ + tiffHeader_.offset(), + size_ - tiffHeader_.offset(), + byteOrder(), + tiffHeader_.offset()); if (rc) return rc; + + delete pExifIfd_; + pExifIfd_ = new Ifd(exifIfdId, 0, false); + assert(pExifIfd_ != 0); // Find and read ExifIFD sub-IFD of IFD0 - rc = ifd0_.readSubIfd(exifIfd_, pData_, size_, byteOrder(), 0x8769); + rc = pIfd0_->readSubIfd(*pExifIfd_, pData_, size_, byteOrder(), 0x8769); if (rc) return rc; // Find MakerNote in ExifIFD, create a MakerNote class - Ifd::iterator pos = exifIfd_.findTag(0x927c); - Ifd::iterator make = ifd0_.findTag(0x010f); - Ifd::iterator model = ifd0_.findTag(0x0110); - if (pos != exifIfd_.end() && make != ifd0_.end() && model != ifd0_.end()) { + Ifd::iterator pos = pExifIfd_->findTag(0x927c); + Ifd::iterator make = pIfd0_->findTag(0x010f); + Ifd::iterator model = pIfd0_->findTag(0x0110); + if ( pos != pExifIfd_->end() + && make != pIfd0_->end() && model != pIfd0_->end()) { MakerNoteFactory& mnf = MakerNoteFactory::instance(); // Todo: The conversion to string assumes that there is a \0 at the end // Todo: How to avoid the cast (is that a MSVC thing?) @@ -392,14 +465,14 @@ namespace Exiv2 { pos->data(), pos->size(), byteOrder(), - exifIfd_.offset() + pos->offset()); + pExifIfd_->offset() + pos->offset()); } // Read the MakerNote if (makerNote_.get() != 0) { rc = makerNote_->read(pos->data(), pos->size(), byteOrder(), - exifIfd_.offset() + pos->offset()); + pExifIfd_->offset() + pos->offset()); if (rc) { // Todo: How to handle debug output like this std::cerr << "Warning: Failed to read " @@ -412,49 +485,61 @@ namespace Exiv2 { // If we successfully parsed the MakerNote, delete the raw MakerNote, // the parsed MakerNote is the primary MakerNote from now on if (makerNote_.get() != 0) { - exifIfd_.erase(pos); + pExifIfd_->erase(pos); } + + delete pIopIfd_; + pIopIfd_ = new Ifd(iopIfdId, 0, false); + assert(pIopIfd_ != 0); // Find and read Interoperability IFD in ExifIFD - rc = exifIfd_.readSubIfd(iopIfd_, pData_, size_, byteOrder(), 0xa005); + rc = pExifIfd_->readSubIfd(*pIopIfd_, pData_, size_, byteOrder(), 0xa005); if (rc) return rc; + + delete pGpsIfd_; + pGpsIfd_ = new Ifd(gpsIfdId, 0, false); + assert(pGpsIfd_ != 0); // Find and read GPSInfo sub-IFD in IFD0 - rc = ifd0_.readSubIfd(gpsIfd_, pData_, size_, byteOrder(), 0x8825); + rc = pIfd0_->readSubIfd(*pGpsIfd_, pData_, size_, byteOrder(), 0x8825); if (rc) return rc; + + delete pIfd1_; + pIfd1_ = new Ifd(ifd1Id, 0, false); + assert(pIfd1_ != 0); // Read IFD1 - if (ifd0_.next()) { - rc = ifd1_.read(pData_ + ifd0_.next(), - size_ - ifd0_.next(), - byteOrder(), - ifd0_.next()); + if (pIfd0_->next()) { + rc = pIfd1_->read(pData_ + pIfd0_->next(), + size_ - pIfd0_->next(), + byteOrder(), + pIfd0_->next()); if (rc) return rc; } // Find and delete ExifIFD sub-IFD of IFD1 - pos = ifd1_.findTag(0x8769); - if (pos != ifd1_.end()) { - ifd1_.erase(pos); + pos = pIfd1_->findTag(0x8769); + if (pos != pIfd1_->end()) { + pIfd1_->erase(pos); ret = 7; } // Find and delete GPSInfo sub-IFD in IFD1 - pos = ifd1_.findTag(0x8825); - if (pos != ifd1_.end()) { - ifd1_.erase(pos); + pos = pIfd1_->findTag(0x8825); + if (pos != pIfd1_->end()) { + pIfd1_->erase(pos); ret = 7; } // Copy all entries from the IFDs and the MakerNote to the metadata exifMetadata_.clear(); - add(ifd0_.begin(), ifd0_.end(), byteOrder()); - add(exifIfd_.begin(), exifIfd_.end(), byteOrder()); + add(pIfd0_->begin(), pIfd0_->end(), byteOrder()); + add(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); if (makerNote_.get() != 0) { add(makerNote_->begin(), makerNote_->end(), makerNote_->byteOrder()); } - add(iopIfd_.begin(), iopIfd_.end(), byteOrder()); - add(gpsIfd_.begin(), gpsIfd_.end(), byteOrder()); - add(ifd1_.begin(), ifd1_.end(), byteOrder()); + add(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); + add(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); + add(pIfd1_->begin(), pIfd1_->end(), byteOrder()); // Read the thumbnail (but don't worry whether it was successful or not) readThumbnail(); return ret; - } // ExifData::read + } // ExifData::load DataBuf ExifData::copy() @@ -492,7 +577,7 @@ namespace Exiv2 { MakerNote::AutoPtr makerNote; if (makerNote_.get() != 0) { // Build MakerNote from metadata - makerNote = makerNote_->clone(); + makerNote = makerNote_->create(); addToMakerNote(makerNote.get(), begin(), end(), makerNote_->byteOrder()); @@ -726,24 +811,27 @@ namespace Exiv2 { long delta = 0; if (stp) { delta = size_; - if (size_ > 0 && ifd0_.next() > 0) { + if (size_ > 0 && pIfd0_ && pIfd0_->next() > 0) { // Truncate IFD1 and thumbnail data from the data buffer - size_ = ifd0_.next(); - ifd0_.setNext(0, byteOrder()); - ifd1_.clear(); + size_ = pIfd0_->next(); + pIfd0_->setNext(0, byteOrder()); + if (pIfd1_) pIfd1_->clear(); } delta -= size_; } else { // We will have to write the hard way and re-arrange the data compatible_ = false; - delta = ifd1_.size() + ifd1_.dataSize(); + if (pIfd1_) delta = pIfd1_->size() + pIfd1_->dataSize(); } return delta; } // ExifData::eraseThumbnail bool ExifData::stdThumbPosition() const { + if ( pIfd0_ == 0 || pExifIfd_ == 0 || pIopIfd_ == 0 + || pGpsIfd_ == 0 || pIfd1_ == 0) return true; + // 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. @@ -753,23 +841,23 @@ namespace Exiv2 { Thumbnail::AutoPtr thumbnail = getThumbnail(); if (thumbnail.get()) { long maxOffset; - maxOffset = std::max(ifd0_.offset(), ifd0_.dataOffset()); - maxOffset = std::max(maxOffset, exifIfd_.offset()); - maxOffset = std::max(maxOffset, exifIfd_.dataOffset() - + exifIfd_.dataSize()); + maxOffset = std::max(pIfd0_->offset(), pIfd0_->dataOffset()); + maxOffset = std::max(maxOffset, pExifIfd_->offset()); + maxOffset = std::max(maxOffset, pExifIfd_->dataOffset() + + pExifIfd_->dataSize()); if (makerNote_.get() != 0) { maxOffset = std::max(maxOffset, makerNote_->offset() + makerNote_->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 = std::max(maxOffset, pIopIfd_->offset()); + maxOffset = std::max(maxOffset, pIopIfd_->dataOffset() + + pIopIfd_->dataSize()); + maxOffset = std::max(maxOffset, pGpsIfd_->offset()); + maxOffset = std::max(maxOffset, pGpsIfd_->dataOffset() + + pGpsIfd_->dataSize()); + + if ( maxOffset > pIfd1_->offset() + || maxOffset > pIfd1_->dataOffset() && pIfd1_->dataOffset() > 0) rc = false; /* Todo: Removed condition from the above if(). Should be re-added... @@ -838,7 +926,7 @@ namespace Exiv2 { int rc = -1; Thumbnail::AutoPtr thumbnail = getThumbnail(); if (thumbnail.get() != 0) { - rc = thumbnail->setDataArea(*this, ifd1_, pData_, size_); + rc = thumbnail->setDataArea(*this, pIfd1_, pData_, size_); } return rc; @@ -846,19 +934,21 @@ namespace Exiv2 { bool ExifData::updateEntries() { + if ( pIfd0_ == 0 || pExifIfd_ == 0 || pIopIfd_ == 0 + || pGpsIfd_ == 0 || pIfd1_ == 0) return false; if (!this->compatible()) return false; bool compatible = true; - compatible &= updateRange(ifd0_.begin(), ifd0_.end(), byteOrder()); - compatible &= updateRange(exifIfd_.begin(), exifIfd_.end(), byteOrder()); + compatible &= updateRange(pIfd0_->begin(), pIfd0_->end(), byteOrder()); + compatible &= updateRange(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); if (makerNote_.get() != 0) { compatible &= updateRange(makerNote_->begin(), makerNote_->end(), makerNote_->byteOrder()); } - compatible &= updateRange(iopIfd_.begin(), iopIfd_.end(), byteOrder()); - compatible &= updateRange(gpsIfd_.begin(), gpsIfd_.end(), byteOrder()); - compatible &= updateRange(ifd1_.begin(), ifd1_.end(), byteOrder()); + compatible &= updateRange(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); + compatible &= updateRange(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); + compatible &= updateRange(pIfd1_->begin(), pIfd1_->end(), byteOrder()); return compatible; } // ExifData::updateEntries @@ -952,7 +1042,7 @@ namespace Exiv2 { return rc; } const Ifd* ifd = getIfd(ifdId); - if (ifdId != makerIfdId && ifd) { + if (ifd && ifdId != makerIfdId) { entry = ifd->findIdx(idx); if (entry != ifd->end()) { rc.first = true; @@ -967,19 +1057,19 @@ namespace Exiv2 { const Ifd* ifd = 0; switch (ifdId) { case ifd0Id: - ifd = &ifd0_; + ifd = pIfd0_; break; case exifIfdId: - ifd = &exifIfd_; + ifd = pExifIfd_; break; case iopIfdId: - ifd = &iopIfd_; + ifd = pIopIfd_; break; case gpsIfdId: - ifd = &gpsIfd_; + ifd = pGpsIfd_; break; case ifd1Id: - ifd = &ifd1_; + ifd = pIfd1_; break; default: ifd = 0; diff --git a/src/exif.hpp b/src/exif.hpp index 6fcea025..7b8e94af 100644 --- a/src/exif.hpp +++ b/src/exif.hpp @@ -354,7 +354,7 @@ namespace Exiv2 { \em buf. Return 0 if successful. @param exifData Exif data corresponding to the data buffer. - @param ifd1 Corresponding raw IFD1. + @param pIfd1 Corresponding raw IFD1. @param buf Data buffer containing the thumbnail data. The buffer must start with the TIFF header. @param len Number of bytes in the data buffer. @@ -363,7 +363,7 @@ namespace Exiv2 { 2 if the data area is outside of the data buffer */ virtual int setDataArea(ExifData& exifData, - Ifd& ifd1, + Ifd* pIfd1, const byte* buf, long len) const =0; /*! @@ -410,7 +410,7 @@ namespace Exiv2 { //! @name Accessors //@{ int setDataArea(ExifData& exifData, - Ifd& ifd1, + Ifd* pIfd1, const byte* buf, long len) const; DataBuf copy(const ExifData& exifData) const; @@ -435,7 +435,7 @@ namespace Exiv2 { //! @name Accessors //@{ int setDataArea(ExifData& exifData, - Ifd& ifd1, + Ifd* pIfd1, const byte* buf, long len) const; DataBuf copy(const ExifData& exifData) const; @@ -834,17 +834,18 @@ namespace Exiv2 { // DATA TiffHeader tiffHeader_; ExifMetadata exifMetadata_; + //! Pointer to the MakerNote std::auto_ptr makerNote_; - Ifd ifd0_; - Ifd exifIfd_; - Ifd iopIfd_; - Ifd gpsIfd_; - Ifd ifd1_; + Ifd* pIfd0_; //! Pointer to Ifd0 + Ifd* pExifIfd_; //! Pointer to ExifIfd + Ifd* pIopIfd_; //! Pointer to IopIfd + Ifd* pGpsIfd_; //! Pointer to GpsIfd + Ifd* pIfd1_; //! Pointer to Ifd1 - long size_; //!< Size of the Exif raw data in bytes - byte* pData_; //!< Exif raw data buffer + long size_; //!< Size of the Exif raw data in bytes + byte* pData_; //!< Exif raw data buffer /*! Can be set to false to indicate that non-intrusive writing is not diff --git a/src/exifdata-test.cpp b/src/exifdata-test.cpp new file mode 100644 index 00000000..a8fc2c2b --- /dev/null +++ b/src/exifdata-test.cpp @@ -0,0 +1,158 @@ +// ***************************************************************** -*- C++ -*- +/* + Abstract : ExifData assignment and copy construction unit tests + + File : exifdata-test.cpp + Version : $Rev$ + Author(s): Andreas Huggel (ahu) + History : 20-Feb-05, ahu: created + + */ +// ***************************************************************************** +// included header files +#include "image.hpp" +#include "exif.hpp" +#include +#include +#include + +void write(const std::string& file, Exiv2::ExifData& ed); +void print(const std::string& file); + +// ***************************************************************************** +// Main +int main(int argc, char* const argv[]) +{ +try { + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " file\n"; + return 1; + } + std::string file(argv[1]); + + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file); + if (image.get() == 0) { + std::string error(file); + error += " : Could not read file or unknown image type"; + throw Exiv2::Error(error); + } + + int rc = image->readMetadata(); + if (rc) { + std::string error = Exiv2::Image::strError(rc, file); + throw Exiv2::Error(error); + } + + Exiv2::ExifData &ed = image->exifData(); + + std::cout << "Copy construction, non-intrusive changes\n"; + Exiv2::ExifData ed1(ed); + ed1["Exif.Image.DateTime"] = "Sunday, 11am"; + ed1["Exif.Image.Orientation"] = uint16_t(2); + ed1["Exif.Photo.DateTimeOriginal"] = "Sunday, 11am"; + ed1["Exif.Photo.MeteringMode"] = uint16_t(1); + ed1["Exif.Iop.InteroperabilityIndex"] = "123"; +// ed1["Exif.Thumbnail.Orientation"] = uint16_t(2); + write(file, ed1); + print(file); + std::cout << "----------------------------------------------\n"; + + std::cout << "Copy construction, intrusive changes\n"; + Exiv2::ExifData ed2(ed); + ed2["Exif.Image.DateTime"] = "Sunday, 11am and ten minutes"; + ed2["Exif.Image.Orientation"] = "2 3 4 5"; + ed2["Exif.Photo.DateTimeOriginal"] = "Sunday, 11am and ten minutes"; + ed2["Exif.Photo.MeteringMode"] = "1 2 3 4 5 6"; + ed2["Exif.Iop.InteroperabilityIndex"] = "1234"; + ed2["Exif.Thumbnail.Orientation"] = "2 3 4 5 6"; + write(file, ed2); + print(file); + std::cout << "----------------------------------------------\n"; + + std::cout << "Assignment, non-intrusive changes\n"; + Exiv2::ExifData ed3; + ed3["Exif.Iop.InteroperabilityVersion"] = "Test 6 Iop tag"; + ed3["Exif.Thumbnail.Artist"] = "Test 6 Ifd1 tag"; + ed3 = ed; + ed3["Exif.Image.DateTime"] = "Sunday, 11am"; + ed3["Exif.Image.Orientation"] = uint16_t(2); + ed3["Exif.Photo.DateTimeOriginal"] = "Sunday, 11am"; + ed3["Exif.Photo.MeteringMode"] = uint16_t(1); + ed3["Exif.Iop.InteroperabilityIndex"] = "123"; +// ed3["Exif.Thumbnail.Orientation"] = uint16_t(2); + write(file, ed3); + print(file); + std::cout << "----------------------------------------------\n"; + + std::cout << "Assignment, intrusive changes\n"; + Exiv2::ExifData ed4; + ed4["Exif.Iop.InteroperabilityVersion"] = "Test 6 Iop tag"; + ed4["Exif.Thumbnail.Artist"] = "Test 6 Ifd1 tag"; + ed4 = ed; + ed4["Exif.Image.DateTime"] = "Sunday, 11am and ten minutes"; + ed4["Exif.Image.Orientation"] = "2 3 4 5"; + ed4["Exif.Photo.DateTimeOriginal"] = "Sunday, 11am and ten minutes"; + ed4["Exif.Photo.MeteringMode"] = uint16_t(1); + ed4["Exif.Iop.InteroperabilityIndex"] = "123"; + ed4["Exif.Thumbnail.Orientation"] = uint16_t(2); + write(file, ed4); + print(file); + + return 0; +} +catch (Exiv2::Error& e) { + std::cout << "Caught Exiv2 exception '" << e << "'\n"; + return -1; +} +} + +void write(const std::string& file, Exiv2::ExifData& ed) +{ + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file); + if (image.get() == 0) { + std::string error(file); + error += " : Could not read file or unknown image type"; + throw Exiv2::Error(error); + } + + image->setExifData(ed); + int rc = image->writeMetadata(); + if (rc) { + std::string error = Exiv2::Image::strError(rc, file); + throw Exiv2::Error(error); + } +} + +void print(const std::string& file) +{ + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file); + if (image.get() == 0) { + std::string error(file); + error += " : Could not read file or unknown image type"; + throw Exiv2::Error(error); + } + + int rc = image->readMetadata(); + if (rc) { + std::string error = Exiv2::Image::strError(rc, file); + throw Exiv2::Error(error); + } + + Exiv2::ExifData &ed = image->exifData(); + Exiv2::ExifData::const_iterator end = ed.end(); + for (Exiv2::ExifData::const_iterator i = ed.begin(); i != end; ++i) { + std::cout << std::setw(45) << std::setfill(' ') << std::left + << i->key() << " " + << "0x" << std::setw(4) << std::setfill('0') << std::right + << std::hex << i->tag() << " " + << std::setw(12) << std::setfill(' ') << std::left + << i->ifdName() << " " + << std::setw(9) << std::setfill(' ') << std::left + << i->typeName() << " " + << std::dec << std::setw(3) + << std::setfill(' ') << std::right + << i->count() << " " + << std::dec << i->value() + << "\n"; + } +} diff --git a/src/fujimn.cpp b/src/fujimn.cpp index cfc9ad09..c439909d 100644 --- a/src/fujimn.cpp +++ b/src/fujimn.cpp @@ -88,6 +88,11 @@ namespace Exiv2 { readHeader(buf, 12, byteOrder_); } + FujiMakerNote::FujiMakerNote(const FujiMakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) + { + } + int FujiMakerNote::readHeader(const byte* buf, long len, ByteOrder byteOrder) @@ -114,12 +119,12 @@ namespace Exiv2 { return rc; } - FujiMakerNote::AutoPtr FujiMakerNote::clone(bool alloc) const + FujiMakerNote::AutoPtr FujiMakerNote::create(bool alloc) const { - return AutoPtr(clone_(alloc)); + return AutoPtr(create_(alloc)); } - FujiMakerNote* FujiMakerNote::clone_(bool alloc) const + FujiMakerNote* FujiMakerNote::create_(bool alloc) const { AutoPtr makerNote = AutoPtr(new FujiMakerNote(alloc)); assert(makerNote.get() != 0); @@ -127,6 +132,16 @@ namespace Exiv2 { return makerNote.release(); } + FujiMakerNote::AutoPtr FujiMakerNote::clone() const + { + return AutoPtr(clone_()); + } + + FujiMakerNote* FujiMakerNote::clone_() const + { + return new FujiMakerNote(*this); + } + std::ostream& FujiMakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const diff --git a/src/fujimn.hpp b/src/fujimn.hpp index 5d0ab5bb..b329c855 100644 --- a/src/fujimn.hpp +++ b/src/fujimn.hpp @@ -97,6 +97,8 @@ namespace Exiv2 { is required for the makernote entries. */ FujiMakerNote(bool alloc =true); + //! Copy constructor + FujiMakerNote(const FujiMakerNote& rhs); //! Virtual destructor virtual ~FujiMakerNote() {} //@} @@ -111,7 +113,8 @@ namespace Exiv2 { //! @name Accessors //@{ int checkHeader() const; - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Fujifilm") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -140,8 +143,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + FujiMakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - FujiMakerNote* clone_(bool alloc =true) const; + FujiMakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { diff --git a/src/ifd-test.cpp b/src/ifd-test.cpp index 968fd4d2..c69bc702 100644 --- a/src/ifd-test.cpp +++ b/src/ifd-test.cpp @@ -14,15 +14,17 @@ #include #include +#include int main() try { // ------------------------------------------------------------------------- std::cout << "Read standard Ifd from data buffer\n"; - long len = 76; + const long len = 77; Exiv2::byte buf[] - = { // No + = { 0xff, // Filler + // No 0x00,0x04, // Tag Type Components Offset/Data 0x00,0x01, 0x00,0x02, 0x00,0x00,0x00,0x04, 'T', 'h', 'e', '\0', @@ -38,7 +40,7 @@ try { }; Exiv2::Ifd ifd(Exiv2::ifd0Id, 0, false); - int rc = ifd.read(buf, len, Exiv2::bigEndian, 1); + int rc = ifd.read(buf+1, len-1, Exiv2::bigEndian, 1); if (rc) { std::cout << "Ifd::read (1) failed, rc = " << rc << "\n"; return rc; @@ -68,7 +70,7 @@ try { // ------------------------------------------------------------------------- std::cout << "\nRead non-standard Ifd from data buffer\n"; - long len2 = 76; + const long len2 = 76; Exiv2::byte buf2[] = { // Data 'K', 'u', 'a', 'l', 'a', '\0', @@ -109,31 +111,31 @@ try { std::cout << "\nTest boundary checks, the following reads should generate warnings or errors\n"; std::cout << "--- read (3)" << std::endl; - rc = ifd.read(buf, len-1, Exiv2::bigEndian, 1); + rc = ifd.read(buf+1, len-1-1, Exiv2::bigEndian, 1); if (rc) { std::cout << "Ifd::read (3) failed, rc = " << rc << "\n"; } std::cout << "--- read (4)" << std::endl; - rc = ifd.read(buf, len-21, Exiv2::bigEndian, 1); + rc = ifd.read(buf+1, len-1-21, Exiv2::bigEndian, 1); if (rc) { std::cout << "Ifd::read (4) failed, rc = " << rc << "\n"; } std::cout << "--- read (5)" << std::endl; - rc = ifd.read(buf, len-22, Exiv2::bigEndian, 1); + rc = ifd.read(buf+1, len-1-22, Exiv2::bigEndian, 1); if (rc) { std::cout << "Ifd::read (5) failed, rc = " << rc << "\n"; } std::cout << "--- read (6)" << std::endl; - rc = ifd.read(buf, len-23, Exiv2::bigEndian, 1); + rc = ifd.read(buf+1, len-1-23, Exiv2::bigEndian, 1); if (rc) { std::cout << "Ifd::read (6) failed, rc = " << rc << "\n"; } std::cout << "--- read (7)" << std::endl; - rc = ifd2.read(buf2 + 22, len2 - 22 -1, Exiv2::bigEndian, 22); + rc = ifd2.read(buf2+22, len2-22-1, Exiv2::bigEndian, 22); if (rc) { std::cout << "Ifd::read (7) failed, rc = " << rc << "\n"; } @@ -171,15 +173,34 @@ try { ifd3.add(e); Exiv2::DataBuf ibuf(256); - len = ifd3.copy(ibuf.pData_, Exiv2::bigEndian); + long len3 = ifd3.copy(ibuf.pData_, Exiv2::bigEndian); Exiv2::Ifd ifd4(Exiv2::ifd0Id, 0, false); - rc = ifd4.read(ibuf.pData_, len, Exiv2::bigEndian, 0); + rc = ifd4.read(ibuf.pData_, len3, Exiv2::bigEndian, 0); if (rc) { std::cout << "Ifd::read (8) failed, rc = " << rc << "\n"; } ifd4.print(std::cout); + // ------------------------------------------------------------------------- + std::cout << "\nMove data buffer\n"; + + Exiv2::Ifd ifd5(Exiv2::ifd0Id, 0, false); + rc = ifd5.read(buf+1, len-1, Exiv2::bigEndian, 1); + if (rc) { + std::cout << "Ifd::read (1) failed, rc = " << rc << "\n"; + return rc; + } + ifd5.print(std::cout); + + Exiv2::byte* newBuf = new Exiv2::byte[len]; + memset(newBuf, 0x00, len); + memcpy(newBuf, buf, len); + memset(buf, 0x0, len); + ifd5.updateBase(newBuf); + ifd5.print(std::cout); + delete[] newBuf; + return 0; } catch (const Exiv2::Error& e) { diff --git a/src/ifd.cpp b/src/ifd.cpp index 2637cd3b..b2a603e1 100644 --- a/src/ifd.cpp +++ b/src/ifd.cpp @@ -282,9 +282,10 @@ namespace Exiv2 { pBase_(rhs.pBase_), offset_(rhs.offset_), dataOffset_(rhs.dataOffset_), pNext_(rhs.pNext_), next_(rhs.next_) { - if (alloc_ && rhs.pNext_) { + if (alloc_) { pNext_ = new byte[4]; - memcpy(pNext_, rhs.pNext_, 4); + memset(pNext_, 0x0, 4); + if (rhs.pNext_) memcpy(pNext_, rhs.pNext_, 4); } } @@ -296,7 +297,6 @@ namespace Exiv2 { if (len < 2) rc = 6; if (rc == 0) { - if (!alloc_) pBase_ = const_cast(buf); offset_ = offset; int n = getUShort(buf, byteOrder); o = 2; @@ -415,6 +415,7 @@ namespace Exiv2 { this->add(e); } } + if (!alloc_) pBase_ = const_cast(buf) - offset_; if (rc) this->clear(); return rc; @@ -585,6 +586,23 @@ namespace Exiv2 { return entries_.erase(pos); } + void Ifd::updateBase(byte* pNewBase) + { + if (!alloc_) { + iterator end = this->end(); + for (iterator pos = begin(); pos != end; ++pos) { + if (pos->pDataArea_) { + pos->pDataArea_ = pos->pDataArea_ - pBase_ + pNewBase; + } + if (pos->pData_) { + pos->pData_ = pos->pData_ - pBase_ + pNewBase; + } + } + pNext_ = pNext_ - pBase_ + pNewBase; + pBase_ = pNewBase; + } + } + long Ifd::size() const { if (entries_.size() == 0 && next_ == 0) return 0; diff --git a/src/ifd.hpp b/src/ifd.hpp index 75eb62b5..6da05aa9 100644 --- a/src/ifd.hpp +++ b/src/ifd.hpp @@ -46,6 +46,7 @@ namespace Exiv2 { // ***************************************************************************** // class declarations class MakerNote; + class Ifd; // ***************************************************************************** // class definitions @@ -56,6 +57,7 @@ namespace Exiv2 { allocation. */ class Entry { + friend class Ifd; public: //! @name Creators //@{ @@ -325,6 +327,11 @@ namespace Exiv2 { //@} public: + //! %Entries const iterator type + typedef Entries::const_iterator const_iterator; + //! %Entries iterator type + typedef Entries::iterator iterator; + //! @name Creators //@{ /*! @@ -350,11 +357,6 @@ namespace Exiv2 { ~Ifd(); //@} - //! Entries const iterator type - typedef Entries::const_iterator const_iterator; - //! Entries iterator type - typedef Entries::iterator iterator; - //! @name Manipulators //@{ /*! @@ -443,6 +445,13 @@ namespace Exiv2 { iterator findIdx(int idx); //! Find an IFD entry by tag, return an iterator into the entries list iterator findTag(uint16_t tag); + /* + @brief Update the base pointer of the Ifd and all entries to \em pNewBase. + + Allows to re-locate the underlying data buffer to a new location + \em pNewBase. This method only has an effect in non-alloc mode. + */ + void updateBase(byte* pNewBase); //@} //! @name Accessors diff --git a/src/makernote.cpp b/src/makernote.cpp index f6bf2817..098f5067 100644 --- a/src/makernote.cpp +++ b/src/makernote.cpp @@ -57,9 +57,14 @@ namespace Exiv2 { { } - MakerNote::AutoPtr MakerNote::clone(bool alloc) const + MakerNote::AutoPtr MakerNote::create(bool alloc) const { - return AutoPtr(clone_(alloc)); + return AutoPtr(create_(alloc)); + } + + MakerNote::AutoPtr MakerNote::clone() const + { + return AutoPtr(clone_()); } std::string MakerNote::tagName(uint16_t tag) const @@ -142,6 +147,13 @@ namespace Exiv2 { { } + IfdMakerNote::IfdMakerNote(const IfdMakerNote& rhs) + : MakerNote(rhs), absOffset_(rhs.absOffset_), adjOffset_(rhs.adjOffset_), + header_(rhs.header_.size_), ifd_(rhs.ifd_) + { + memcpy(header_.pData_, rhs.header_.pData_, header_.size_); + } + int IfdMakerNote::read(const byte* buf, long len, ByteOrder byteOrder, @@ -207,6 +219,15 @@ namespace Exiv2 { return 0; } + void IfdMakerNote::updateBase(byte* pNewBase) + { + ifd_.updateBase(pNewBase); + Entries::iterator end = ifd_.end(); + for (Entries::iterator i = ifd_.begin(); i != end; ++i) { + i->setMakerNote(this); + } + } + int IfdMakerNote::checkHeader() const { // Default implementation does nothing, assuming there is no header @@ -234,9 +255,14 @@ namespace Exiv2 { return headerSize() + ifd_.size() + ifd_.dataSize(); } - IfdMakerNote::AutoPtr IfdMakerNote::clone(bool alloc) const + IfdMakerNote::AutoPtr IfdMakerNote::create(bool alloc) const + { + return AutoPtr(create_(alloc)); + } + + IfdMakerNote::AutoPtr IfdMakerNote::clone() const { - return AutoPtr(clone_(alloc)); + return AutoPtr(clone_()); } MakerNoteFactory* MakerNoteFactory::pInstance_ = 0; @@ -262,7 +288,7 @@ namespace Exiv2 { IfdItemRegistry::const_iterator i = ifdItemRegistry_.find(ifdItem); if (i == ifdItemRegistry_.end()) return MakerNote::AutoPtr(0); assert(i->second); - return i->second->clone(alloc); + return i->second->create(alloc); } // MakerNoteFactory::create void MakerNoteFactory::registerMakerNote(const std::string& make, diff --git a/src/makernote.hpp b/src/makernote.hpp index 11bc39a2..8e90292e 100644 --- a/src/makernote.hpp +++ b/src/makernote.hpp @@ -158,6 +158,14 @@ namespace Exiv2 { virtual Entries::iterator begin() =0; //! End of the makernote entries virtual Entries::iterator end() =0; + /* + @brief Update the base pointer of the MakerNote and all its entries + to \em pNewBase. + + Allows to re-locate the underlying data buffer to a new location + \em pNewBase. This method only has an effect in non-alloc mode. + */ + virtual void updateBase(byte* pNewBase) =0; //@} //! @name Accessors @@ -172,13 +180,23 @@ namespace Exiv2 { copied. The caller owns the new object and the auto-pointer ensures that it will be deleted. - @param alloc Memory management model for the clone. Indicates if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. + @param alloc Memory management model for the newly created object. + Indicates if memory required to store data should be allocated + and deallocated (true) or not (false). If false, only pointers + to the buffer provided to read() will be kept. See Ifd for more + background on this concept. + */ + AutoPtr create(bool alloc =true) const; + /*! + @brief Return an auto-pointer to a clone of this object. The caller + owns the new object and the auto-pointer ensures that it will + be deleted. + + @note In non-alloc mode the clone potentially contains pointers to + the same data buffer as the original. + Use updateBase(byte* pNewBase) to adjust them. */ - AutoPtr clone(bool alloc =true) const; + AutoPtr clone() const; /*! @brief Return the name of a makernote tag. The default implementation looks up the makernote info tag array if one is set, else @@ -247,8 +265,10 @@ namespace Exiv2 { ByteOrder byteOrder_; private: + //! Internal virtual create function. + virtual MakerNote* create_(bool alloc =true) const =0; //! Internal virtual copy constructor. - virtual MakerNote* clone_(bool alloc =true) const =0; + virtual MakerNote* clone_() const =0; }; // class MakerNote @@ -277,6 +297,8 @@ namespace Exiv2 { */ explicit IfdMakerNote(const MakerNote::MnTagInfo* pMnTagInfo =0, bool alloc =true); + //! Copy constructor + IfdMakerNote(const IfdMakerNote& rhs); //! Virtual destructor virtual ~IfdMakerNote() {} //@} @@ -302,6 +324,7 @@ namespace Exiv2 { void add(const Entry& entry) { ifd_.add(entry); } Entries::iterator begin() { return ifd_.begin(); } Entries::iterator end() { return ifd_.end(); } + virtual void updateBase(byte* pNewBase); //@} //! @name Accessors @@ -310,7 +333,8 @@ namespace Exiv2 { Entries::const_iterator end() const { return ifd_.end(); } Entries::const_iterator findIdx(int idx) const; long size() const; - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; /*! @brief Check the makernote header. This will typically check if a required prefix string is present in the header. Return 0 if @@ -359,7 +383,8 @@ namespace Exiv2 { Ifd ifd_; private: - virtual IfdMakerNote* clone_(bool alloc =true) const =0; + virtual IfdMakerNote* create_(bool alloc =true) const =0; + virtual IfdMakerNote* clone_() const =0; }; // class IfdMakerNote diff --git a/src/nikonmn.cpp b/src/nikonmn.cpp index abdbd065..0723cfe1 100644 --- a/src/nikonmn.cpp +++ b/src/nikonmn.cpp @@ -77,16 +77,31 @@ namespace Exiv2 { { } - Nikon1MakerNote::AutoPtr Nikon1MakerNote::clone(bool alloc) const + Nikon1MakerNote::Nikon1MakerNote(const Nikon1MakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) { - return AutoPtr(clone_(alloc)); } - Nikon1MakerNote* Nikon1MakerNote::clone_(bool alloc) const + Nikon1MakerNote::AutoPtr Nikon1MakerNote::create(bool alloc) const + { + return AutoPtr(create_(alloc)); + } + + Nikon1MakerNote* Nikon1MakerNote::create_(bool alloc) const { return new Nikon1MakerNote(alloc); } + Nikon1MakerNote::AutoPtr Nikon1MakerNote::clone() const + { + return AutoPtr(clone_()); + } + + Nikon1MakerNote* Nikon1MakerNote::clone_() const + { + return new Nikon1MakerNote(*this); + } + std::ostream& Nikon1MakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const @@ -213,6 +228,11 @@ namespace Exiv2 { readHeader(buf, 8, byteOrder_); } + Nikon2MakerNote::Nikon2MakerNote(const Nikon2MakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) + { + } + int Nikon2MakerNote::readHeader(const byte* buf, long len, ByteOrder byteOrder) @@ -237,12 +257,12 @@ namespace Exiv2 { return rc; } - Nikon2MakerNote::AutoPtr Nikon2MakerNote::clone(bool alloc) const + Nikon2MakerNote::AutoPtr Nikon2MakerNote::create(bool alloc) const { - return AutoPtr(clone_(alloc)); + return AutoPtr(create_(alloc)); } - Nikon2MakerNote* Nikon2MakerNote::clone_(bool alloc) const + Nikon2MakerNote* Nikon2MakerNote::create_(bool alloc) const { AutoPtr makerNote(new Nikon2MakerNote(alloc)); assert(makerNote.get() != 0); @@ -250,6 +270,16 @@ namespace Exiv2 { return makerNote.release(); } + Nikon2MakerNote::AutoPtr Nikon2MakerNote::clone() const + { + return AutoPtr(clone_()); + } + + Nikon2MakerNote* Nikon2MakerNote::clone_() const + { + return new Nikon2MakerNote(*this); + } + std::ostream& Nikon2MakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const @@ -429,6 +459,11 @@ namespace Exiv2 { readHeader(buf, 18, byteOrder_); } + Nikon3MakerNote::Nikon3MakerNote(const Nikon3MakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) + { + } + int Nikon3MakerNote::read(const byte* buf, long len, ByteOrder byteOrder, @@ -478,12 +513,12 @@ namespace Exiv2 { return rc; } - Nikon3MakerNote::AutoPtr Nikon3MakerNote::clone(bool alloc) const + Nikon3MakerNote::AutoPtr Nikon3MakerNote::create(bool alloc) const { - return AutoPtr(clone_(alloc)); + return AutoPtr(create_(alloc)); } - Nikon3MakerNote* Nikon3MakerNote::clone_(bool alloc) const + Nikon3MakerNote* Nikon3MakerNote::create_(bool alloc) const { AutoPtr makerNote(new Nikon3MakerNote(alloc)); assert(makerNote.get() != 0); @@ -491,6 +526,16 @@ namespace Exiv2 { return makerNote.release(); } + Nikon3MakerNote::AutoPtr Nikon3MakerNote::clone() const + { + return AutoPtr(clone_()); + } + + Nikon3MakerNote* Nikon3MakerNote::clone_() const + { + return new Nikon3MakerNote(*this); + } + std::ostream& Nikon3MakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const diff --git a/src/nikonmn.hpp b/src/nikonmn.hpp index 0986d238..efa1b974 100644 --- a/src/nikonmn.hpp +++ b/src/nikonmn.hpp @@ -109,13 +109,16 @@ namespace Exiv2 { is required for the makernote entries. */ Nikon1MakerNote(bool alloc =true); + //! Copy constructor + Nikon1MakerNote(const Nikon1MakerNote& rhs); //! Virtual destructor virtual ~Nikon1MakerNote() {} //@} //! @name Accessors //@{ - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Nikon1") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -138,8 +141,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + Nikon1MakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - Nikon1MakerNote* clone_(bool alloc =true) const; + Nikon1MakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { @@ -186,6 +191,8 @@ namespace Exiv2 { is required for the makernote entries. */ Nikon2MakerNote(bool alloc =true); + //! Copy constructor + Nikon2MakerNote(const Nikon2MakerNote& rhs); //! Virtual destructor virtual ~Nikon2MakerNote() {} //@} @@ -200,7 +207,8 @@ namespace Exiv2 { //! @name Accessors //@{ int checkHeader() const; - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Nikon2") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -225,8 +233,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + Nikon2MakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - Nikon2MakerNote* clone_(bool alloc =true) const; + Nikon2MakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { @@ -270,6 +280,8 @@ namespace Exiv2 { is required for the makernote entries. */ Nikon3MakerNote(bool alloc =true); + //! Copy constructor + Nikon3MakerNote(const Nikon3MakerNote& rhs); //! Virtual destructor virtual ~Nikon3MakerNote() {} //@} @@ -288,7 +300,8 @@ namespace Exiv2 { //! @name Accessors //@{ int checkHeader() const; - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Nikon3") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -313,8 +326,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + Nikon3MakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - Nikon3MakerNote* clone_(bool alloc =true) const; + Nikon3MakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { diff --git a/src/sigmamn.cpp b/src/sigmamn.cpp index 3364f128..65fbbc1e 100644 --- a/src/sigmamn.cpp +++ b/src/sigmamn.cpp @@ -91,6 +91,11 @@ namespace Exiv2 { readHeader(buf, 10, byteOrder_); } + SigmaMakerNote::SigmaMakerNote(const SigmaMakerNote& rhs) + : IfdMakerNote(rhs), ifdItem_(rhs.ifdItem_) + { + } + int SigmaMakerNote::readHeader(const byte* buf, long len, ByteOrder byteOrder) @@ -121,12 +126,12 @@ namespace Exiv2 { return rc; } - SigmaMakerNote::AutoPtr SigmaMakerNote::clone(bool alloc) const + SigmaMakerNote::AutoPtr SigmaMakerNote::create(bool alloc) const { - return AutoPtr(clone_(alloc)); + return AutoPtr(create_(alloc)); } - SigmaMakerNote* SigmaMakerNote::clone_(bool alloc) const + SigmaMakerNote* SigmaMakerNote::create_(bool alloc) const { AutoPtr makerNote = AutoPtr(new SigmaMakerNote(alloc)); assert(makerNote.get() != 0); @@ -134,6 +139,16 @@ namespace Exiv2 { return makerNote.release(); } + SigmaMakerNote::AutoPtr SigmaMakerNote::clone() const + { + return AutoPtr(clone_()); + } + + SigmaMakerNote* SigmaMakerNote::clone_() const + { + return new SigmaMakerNote(*this); + } + std::ostream& SigmaMakerNote::printTag(std::ostream& os, uint16_t tag, const Value& value) const diff --git a/src/sigmamn.hpp b/src/sigmamn.hpp index 2469982b..b9c84de4 100644 --- a/src/sigmamn.hpp +++ b/src/sigmamn.hpp @@ -96,6 +96,8 @@ namespace Exiv2 { is required for the makernote entries. */ SigmaMakerNote(bool alloc =true); + //! Copy constructor + SigmaMakerNote(const SigmaMakerNote& rhs); //! Virtual destructor virtual ~SigmaMakerNote() {} //@} @@ -110,7 +112,8 @@ namespace Exiv2 { //! @name Accessors //@{ int checkHeader() const; - AutoPtr clone(bool alloc =true) const; + AutoPtr create(bool alloc =true) const; + AutoPtr clone() const; //! Return the name of the makernote item ("Sigma") std::string ifdItem() const { return ifdItem_; } std::ostream& printTag(std::ostream& os, @@ -129,8 +132,10 @@ namespace Exiv2 { //@} private: + //! Internal virtual create function. + SigmaMakerNote* create_(bool alloc =true) const; //! Internal virtual copy constructor. - SigmaMakerNote* clone_(bool alloc =true) const; + SigmaMakerNote* clone_() const; //! Structure used to auto-register the MakerNote. struct RegisterMakerNote { diff --git a/src/tags.cpp b/src/tags.cpp index 8efcb9d5..3daf348a 100644 --- a/src/tags.cpp +++ b/src/tags.cpp @@ -433,7 +433,7 @@ namespace Exiv2 { if (ifdId_ == makerIfdId) { if (e.makerNote()) { ifdItem_ = e.makerNote()->ifdItem(); - makerNote_ = e.makerNote()->clone(); + makerNote_ = e.makerNote()->create(); } else throw Error("Invalid Key"); } @@ -446,7 +446,7 @@ namespace Exiv2 { ExifKey::ExifKey(const ExifKey& rhs) : tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_), idx_(rhs.idx_), - makerNote_(rhs.makerNote_.get() != 0 ? rhs.makerNote_->clone() + makerNote_(rhs.makerNote_.get() != 0 ? rhs.makerNote_->create() : MakerNote::AutoPtr(0)), key_(rhs.key_) { @@ -464,7 +464,7 @@ namespace Exiv2 { ifdId_ = rhs.ifdId_; ifdItem_ = rhs.ifdItem_; idx_ = rhs.idx_; - makerNote_ = rhs.makerNote_.get() != 0 ? rhs.makerNote_->clone() + makerNote_ = rhs.makerNote_.get() != 0 ? rhs.makerNote_->create() : MakerNote::AutoPtr(0); key_ = rhs.key_; return *this; diff --git a/test/data/exifdata-test.out b/test/data/exifdata-test.out new file mode 100644 index 00000000..cc00c0fe --- /dev/null +++ b/test/data/exifdata-test.out @@ -0,0 +1,420 @@ +Copy construction, non-intrusive changes +Exif.Image.ImageDescription 0x010e IFD0 Ascii 18 Exif JPEG +Exif.Image.Make 0x010f IFD0 Ascii 8 Camera +Exif.Image.Model 0x0110 IFD0 Ascii 16 DC-4300 +Exif.Image.Orientation 0x0112 IFD0 Short 1 2 +Exif.Image.XResolution 0x011a IFD0 Rational 1 72/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 72/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.Software 0x0131 IFD0 Ascii 22 DC-4300 Ver1.03 +Exif.Image.DateTime 0x0132 IFD0 Ascii 20 Sunday, 11am +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 2 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 6480 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/95 +Exif.Photo.FNumber 0x829d Exif Rational 1 91/10 +Exif.Photo.ExposureProgram 0x8822 Exif Short 1 8 +Exif.Photo.ISOSpeedRatings 0x8827 Exif Short 1 100 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 49 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 20 Sunday, 11am +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2004:06:08 16:04:50 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 66/10 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 64/10 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/10 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 31/10 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.LightSource 0x9208 Exif Short 1 0 +Exif.Photo.Flash 0x9209 Exif Short 1 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Long 1 1600 +Exif.Photo.PixelYDimension 0xa003 Exif Long 1 2400 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 6738 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Thumbnail.ImageWidth 0x0100 IFD1 Long 1 133 +Exif.Thumbnail.ImageLength 0x0101 IFD1 Long 1 200 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Short 1 1 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 6144 +---------------------------------------------- +Copy construction, intrusive changes +Exif.Image.ImageDescription 0x010e IFD0 Ascii 18 Exif JPEG +Exif.Image.Make 0x010f IFD0 Ascii 8 Camera +Exif.Image.Model 0x0110 IFD0 Ascii 16 DC-4300 +Exif.Image.Orientation 0x0112 IFD0 Short 4 2 3 4 5 +Exif.Image.XResolution 0x011a IFD0 Rational 1 72/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 72/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.Software 0x0131 IFD0 Ascii 22 DC-4300 Ver1.03 +Exif.Image.DateTime 0x0132 IFD0 Ascii 29 Sunday, 11am and ten minutes +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 2 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 263 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/95 +Exif.Photo.FNumber 0x829d Exif Rational 1 91/10 +Exif.Photo.ExposureProgram 0x8822 Exif Short 1 8 +Exif.Photo.ISOSpeedRatings 0x8827 Exif Short 1 100 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 49 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 29 Sunday, 11am and ten minutes +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2004:06:08 16:04:50 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 66/10 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 64/10 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/10 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 31/10 +Exif.Photo.MeteringMode 0x9207 Exif Short 6 1 2 3 4 5 6 +Exif.Photo.LightSource 0x9208 Exif Short 1 0 +Exif.Photo.Flash 0x9209 Exif Short 1 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Long 1 1600 +Exif.Photo.PixelYDimension 0xa003 Exif Long 1 2400 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 630 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 5 1234 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Thumbnail.ImageWidth 0x0100 IFD1 Long 1 133 +Exif.Thumbnail.ImageLength 0x0101 IFD1 Long 1 200 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Short 5 2 3 4 5 6 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 6144 +---------------------------------------------- +Assignment, non-intrusive changes +Exif.Image.ImageDescription 0x010e IFD0 Ascii 18 Exif JPEG +Exif.Image.Make 0x010f IFD0 Ascii 8 Camera +Exif.Image.Model 0x0110 IFD0 Ascii 16 DC-4300 +Exif.Image.Orientation 0x0112 IFD0 Short 1 2 +Exif.Image.XResolution 0x011a IFD0 Rational 1 72/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 72/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.Software 0x0131 IFD0 Ascii 22 DC-4300 Ver1.03 +Exif.Image.DateTime 0x0132 IFD0 Ascii 20 Sunday, 11am +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 2 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 6480 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/95 +Exif.Photo.FNumber 0x829d Exif Rational 1 91/10 +Exif.Photo.ExposureProgram 0x8822 Exif Short 1 8 +Exif.Photo.ISOSpeedRatings 0x8827 Exif Short 1 100 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 49 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 20 Sunday, 11am +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2004:06:08 16:04:50 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 66/10 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 64/10 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/10 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 31/10 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.LightSource 0x9208 Exif Short 1 0 +Exif.Photo.Flash 0x9209 Exif Short 1 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Long 1 1600 +Exif.Photo.PixelYDimension 0xa003 Exif Long 1 2400 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 6738 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Thumbnail.ImageWidth 0x0100 IFD1 Long 1 133 +Exif.Thumbnail.ImageLength 0x0101 IFD1 Long 1 200 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Short 1 1 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 6144 +---------------------------------------------- +Assignment, intrusive changes +Exif.Image.ImageDescription 0x010e IFD0 Ascii 18 Exif JPEG +Exif.Image.Make 0x010f IFD0 Ascii 8 Camera +Exif.Image.Model 0x0110 IFD0 Ascii 16 DC-4300 +Exif.Image.Orientation 0x0112 IFD0 Short 4 2 3 4 5 +Exif.Image.XResolution 0x011a IFD0 Rational 1 72/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 72/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.Software 0x0131 IFD0 Ascii 22 DC-4300 Ver1.03 +Exif.Image.DateTime 0x0132 IFD0 Ascii 29 Sunday, 11am and ten minutes +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 2 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 263 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/95 +Exif.Photo.FNumber 0x829d Exif Rational 1 91/10 +Exif.Photo.ExposureProgram 0x8822 Exif Short 1 8 +Exif.Photo.ISOSpeedRatings 0x8827 Exif Short 1 100 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 49 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 29 Sunday, 11am and ten minutes +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2004:06:08 16:04:50 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 66/10 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 64/10 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/10 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 31/10 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.LightSource 0x9208 Exif Short 1 0 +Exif.Photo.Flash 0x9209 Exif Short 1 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Long 1 1600 +Exif.Photo.PixelYDimension 0xa003 Exif Long 1 2400 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 618 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Thumbnail.ImageWidth 0x0100 IFD1 Long 1 133 +Exif.Thumbnail.ImageLength 0x0101 IFD1 Long 1 200 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Short 1 2 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 6144 +Copy construction, non-intrusive changes +Exif.Image.Make 0x010f IFD0 Ascii 6 Canon +Exif.Image.Model 0x0110 IFD0 Ascii 20 Canon PowerShot S40 +Exif.Image.Orientation 0x0112 IFD0 Short 1 2 +Exif.Image.XResolution 0x011a IFD0 Rational 1 180/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 180/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.DateTime 0x0132 IFD0 Ascii 20 Sunday, 11am +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 1 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 196 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/500 +Exif.Photo.FNumber 0x829d Exif Rational 1 49/10 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 50 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 20 Sunday, 11am +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2003:12:14 12:01:44 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.CompressedBitsPerPixel 0x9102 Exif Rational 1 5/1 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 287/32 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 149/32 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/3 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 194698/65536 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.Flash 0x9209 Exif Short 1 24 +Exif.Photo.FocalLength 0x920a Exif Rational 1 682/32 +Exif.Photo.UserComment 0x9286 Exif Undefined 264 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Short 1 2272 +Exif.Photo.PixelYDimension 0xa003 Exif Short 1 1704 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 1416 +Exif.Photo.FocalPlaneXResolution 0xa20e Exif Rational 1 2272000/280 +Exif.Photo.FocalPlaneYResolution 0xa20f Exif Rational 1 1704000/210 +Exif.Photo.FocalPlaneResolutionUnit 0xa210 Exif Short 1 2 +Exif.Photo.SensingMethod 0xa217 Exif Short 1 2 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Photo.CustomRendered 0xa401 Exif Short 1 0 +Exif.Photo.ExposureMode 0xa402 Exif Short 1 0 +Exif.Photo.WhiteBalance 0xa403 Exif Short 1 0 +Exif.Photo.DigitalZoomRatio 0xa404 Exif Rational 1 2272/2272 +Exif.Photo.SceneCaptureType 0xa406 Exif Short 1 0 +Exif.Canon.CameraSettings1 0x0001 Makernote Short 40 80 2 0 5 1 0 0 4 0 1 0 1 0 0 0 0 17 5 1 12291 1 65535 65535 682 227 32 149 192 0 0 0 0 0 0 65535 49 2272 2272 0 1 +Exif.Canon.0x0002 0x0002 Makernote Short 4 2 682 286 215 +Exif.Canon.0x0003 0x0003 Makernote Short 4 0 0 0 0 +Exif.Canon.CameraSettings2 0x0004 Makernote Short 27 54 0 160 276 149 287 0 0 0 0 6 0 0 0 12290 0 0 0 1 782 0 149 289 0 0 0 250 +Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0 +Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0 +Exif.Canon.ImageType 0x0006 Makernote Ascii 32 IMG:PowerShot S40 JPEG +Exif.Canon.FirmwareVersion 0x0007 Makernote Ascii 24 Firmware Version 1.10 +Exif.Canon.ImageNumber 0x0008 Makernote Long 1 1171771 +Exif.Canon.OwnerName 0x0009 Makernote Ascii 32 Andreas Huggel +Exif.Canon.0x0010 0x0010 Makernote Long 1 17891328 +Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Iop.RelatedImageWidth 0x1001 Iop Short 1 2272 +Exif.Iop.RelatedImageLength 0x1002 Iop Short 1 1704 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.XResolution 0x011a IFD1 Rational 1 180/1 +Exif.Thumbnail.YResolution 0x011b IFD1 Rational 1 180/1 +Exif.Thumbnail.ResolutionUnit 0x0128 IFD1 Short 1 2 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 5448 +---------------------------------------------- +Copy construction, intrusive changes +Exif.Image.Make 0x010f IFD0 Ascii 6 Canon +Exif.Image.Model 0x0110 IFD0 Ascii 20 Canon PowerShot S40 +Exif.Image.Orientation 0x0112 IFD0 Short 4 2 3 4 5 +Exif.Image.XResolution 0x011a IFD0 Rational 1 180/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 180/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.DateTime 0x0132 IFD0 Ascii 29 Sunday, 11am and ten minutes +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 1 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 201 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/500 +Exif.Photo.FNumber 0x829d Exif Rational 1 49/10 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 50 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 29 Sunday, 11am and ten minutes +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2003:12:14 12:01:44 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.CompressedBitsPerPixel 0x9102 Exif Rational 1 5/1 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 287/32 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 149/32 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/3 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 194698/65536 +Exif.Photo.MeteringMode 0x9207 Exif Short 6 1 2 3 4 5 6 +Exif.Photo.Flash 0x9209 Exif Short 1 24 +Exif.Photo.FocalLength 0x920a Exif Rational 1 682/32 +Exif.Photo.UserComment 0x9286 Exif Undefined 264 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Short 1 2272 +Exif.Photo.PixelYDimension 0xa003 Exif Short 1 1704 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 1442 +Exif.Photo.FocalPlaneXResolution 0xa20e Exif Rational 1 2272000/280 +Exif.Photo.FocalPlaneYResolution 0xa20f Exif Rational 1 1704000/210 +Exif.Photo.FocalPlaneResolutionUnit 0xa210 Exif Short 1 2 +Exif.Photo.SensingMethod 0xa217 Exif Short 1 2 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Photo.CustomRendered 0xa401 Exif Short 1 0 +Exif.Photo.ExposureMode 0xa402 Exif Short 1 0 +Exif.Photo.WhiteBalance 0xa403 Exif Short 1 0 +Exif.Photo.DigitalZoomRatio 0xa404 Exif Rational 1 2272/2272 +Exif.Photo.SceneCaptureType 0xa406 Exif Short 1 0 +Exif.Canon.CameraSettings1 0x0001 Makernote Short 40 80 2 0 5 1 0 0 4 0 1 0 1 0 0 0 0 17 5 1 12291 1 65535 65535 682 227 32 149 192 0 0 0 0 0 0 65535 49 2272 2272 0 1 +Exif.Canon.0x0002 0x0002 Makernote Short 4 2 682 286 215 +Exif.Canon.0x0003 0x0003 Makernote Short 4 0 0 0 0 +Exif.Canon.CameraSettings2 0x0004 Makernote Short 27 54 0 160 276 149 287 0 0 0 0 6 0 0 0 12290 0 0 0 1 782 0 149 289 0 0 0 250 +Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0 +Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0 +Exif.Canon.ImageType 0x0006 Makernote Ascii 32 IMG:PowerShot S40 JPEG +Exif.Canon.FirmwareVersion 0x0007 Makernote Ascii 24 Firmware Version 1.10 +Exif.Canon.ImageNumber 0x0008 Makernote Long 1 1171771 +Exif.Canon.OwnerName 0x0009 Makernote Ascii 32 Andreas Huggel +Exif.Canon.0x0010 0x0010 Makernote Long 1 17891328 +Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 5 1234 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Iop.RelatedImageWidth 0x1001 Iop Short 1 2272 +Exif.Iop.RelatedImageLength 0x1002 Iop Short 1 1704 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Ascii 10 2 3 4 5 6 +Exif.Thumbnail.XResolution 0x011a IFD1 Rational 1 180/1 +Exif.Thumbnail.YResolution 0x011b IFD1 Rational 1 180/1 +Exif.Thumbnail.ResolutionUnit 0x0128 IFD1 Short 1 2 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 5448 +---------------------------------------------- +Assignment, non-intrusive changes +Exif.Image.Make 0x010f IFD0 Ascii 6 Canon +Exif.Image.Model 0x0110 IFD0 Ascii 20 Canon PowerShot S40 +Exif.Image.Orientation 0x0112 IFD0 Short 1 2 +Exif.Image.XResolution 0x011a IFD0 Rational 1 180/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 180/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.DateTime 0x0132 IFD0 Ascii 20 Sunday, 11am +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 1 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 196 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/500 +Exif.Photo.FNumber 0x829d Exif Rational 1 49/10 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 50 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 20 Sunday, 11am +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2003:12:14 12:01:44 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.CompressedBitsPerPixel 0x9102 Exif Rational 1 5/1 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 287/32 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 149/32 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/3 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 194698/65536 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.Flash 0x9209 Exif Short 1 24 +Exif.Photo.FocalLength 0x920a Exif Rational 1 682/32 +Exif.Photo.UserComment 0x9286 Exif Undefined 264 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Short 1 2272 +Exif.Photo.PixelYDimension 0xa003 Exif Short 1 1704 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 1416 +Exif.Photo.FocalPlaneXResolution 0xa20e Exif Rational 1 2272000/280 +Exif.Photo.FocalPlaneYResolution 0xa20f Exif Rational 1 1704000/210 +Exif.Photo.FocalPlaneResolutionUnit 0xa210 Exif Short 1 2 +Exif.Photo.SensingMethod 0xa217 Exif Short 1 2 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Photo.CustomRendered 0xa401 Exif Short 1 0 +Exif.Photo.ExposureMode 0xa402 Exif Short 1 0 +Exif.Photo.WhiteBalance 0xa403 Exif Short 1 0 +Exif.Photo.DigitalZoomRatio 0xa404 Exif Rational 1 2272/2272 +Exif.Photo.SceneCaptureType 0xa406 Exif Short 1 0 +Exif.Canon.CameraSettings1 0x0001 Makernote Short 40 80 2 0 5 1 0 0 4 0 1 0 1 0 0 0 0 17 5 1 12291 1 65535 65535 682 227 32 149 192 0 0 0 0 0 0 65535 49 2272 2272 0 1 +Exif.Canon.0x0002 0x0002 Makernote Short 4 2 682 286 215 +Exif.Canon.0x0003 0x0003 Makernote Short 4 0 0 0 0 +Exif.Canon.CameraSettings2 0x0004 Makernote Short 27 54 0 160 276 149 287 0 0 0 0 6 0 0 0 12290 0 0 0 1 782 0 149 289 0 0 0 250 +Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0 +Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0 +Exif.Canon.ImageType 0x0006 Makernote Ascii 32 IMG:PowerShot S40 JPEG +Exif.Canon.FirmwareVersion 0x0007 Makernote Ascii 24 Firmware Version 1.10 +Exif.Canon.ImageNumber 0x0008 Makernote Long 1 1171771 +Exif.Canon.OwnerName 0x0009 Makernote Ascii 32 Andreas Huggel +Exif.Canon.0x0010 0x0010 Makernote Long 1 17891328 +Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Iop.RelatedImageWidth 0x1001 Iop Short 1 2272 +Exif.Iop.RelatedImageLength 0x1002 Iop Short 1 1704 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.XResolution 0x011a IFD1 Rational 1 180/1 +Exif.Thumbnail.YResolution 0x011b IFD1 Rational 1 180/1 +Exif.Thumbnail.ResolutionUnit 0x0128 IFD1 Short 1 2 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 5448 +---------------------------------------------- +Assignment, intrusive changes +Exif.Image.Make 0x010f IFD0 Ascii 6 Canon +Exif.Image.Model 0x0110 IFD0 Ascii 20 Canon PowerShot S40 +Exif.Image.Orientation 0x0112 IFD0 Short 4 2 3 4 5 +Exif.Image.XResolution 0x011a IFD0 Rational 1 180/1 +Exif.Image.YResolution 0x011b IFD0 Rational 1 180/1 +Exif.Image.ResolutionUnit 0x0128 IFD0 Short 1 2 +Exif.Image.DateTime 0x0132 IFD0 Ascii 29 Sunday, 11am and ten minutes +Exif.Image.YCbCrPositioning 0x0213 IFD0 Short 1 1 +Exif.Image.ExifTag 0x8769 IFD0 Long 1 201 +Exif.Photo.ExposureTime 0x829a Exif Rational 1 1/500 +Exif.Photo.FNumber 0x829d Exif Rational 1 49/10 +Exif.Photo.ExifVersion 0x9000 Exif Undefined 4 48 50 50 48 +Exif.Photo.DateTimeOriginal 0x9003 Exif Ascii 29 Sunday, 11am and ten minutes +Exif.Photo.DateTimeDigitized 0x9004 Exif Ascii 20 2003:12:14 12:01:44 +Exif.Photo.ComponentsConfiguration 0x9101 Exif Undefined 4 1 2 3 0 +Exif.Photo.CompressedBitsPerPixel 0x9102 Exif Rational 1 5/1 +Exif.Photo.ShutterSpeedValue 0x9201 Exif SRational 1 287/32 +Exif.Photo.ApertureValue 0x9202 Exif Rational 1 149/32 +Exif.Photo.ExposureBiasValue 0x9204 Exif SRational 1 0/3 +Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1 194698/65536 +Exif.Photo.MeteringMode 0x9207 Exif Short 1 1 +Exif.Photo.Flash 0x9209 Exif Short 1 24 +Exif.Photo.FocalLength 0x920a Exif Rational 1 682/32 +Exif.Photo.UserComment 0x9286 Exif Undefined 264 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +Exif.Photo.FlashpixVersion 0xa000 Exif Undefined 4 48 49 48 48 +Exif.Photo.ColorSpace 0xa001 Exif Short 1 1 +Exif.Photo.PixelXDimension 0xa002 Exif Short 1 2272 +Exif.Photo.PixelYDimension 0xa003 Exif Short 1 1704 +Exif.Photo.InteroperabilityTag 0xa005 Exif Long 1 1430 +Exif.Photo.FocalPlaneXResolution 0xa20e Exif Rational 1 2272000/280 +Exif.Photo.FocalPlaneYResolution 0xa20f Exif Rational 1 1704000/210 +Exif.Photo.FocalPlaneResolutionUnit 0xa210 Exif Short 1 2 +Exif.Photo.SensingMethod 0xa217 Exif Short 1 2 +Exif.Photo.FileSource 0xa300 Exif Undefined 1 3 +Exif.Photo.CustomRendered 0xa401 Exif Short 1 0 +Exif.Photo.ExposureMode 0xa402 Exif Short 1 0 +Exif.Photo.WhiteBalance 0xa403 Exif Short 1 0 +Exif.Photo.DigitalZoomRatio 0xa404 Exif Rational 1 2272/2272 +Exif.Photo.SceneCaptureType 0xa406 Exif Short 1 0 +Exif.Canon.CameraSettings1 0x0001 Makernote Short 40 80 2 0 5 1 0 0 4 0 1 0 1 0 0 0 0 17 5 1 12291 1 65535 65535 682 227 32 149 192 0 0 0 0 0 0 65535 49 2272 2272 0 1 +Exif.Canon.0x0002 0x0002 Makernote Short 4 2 682 286 215 +Exif.Canon.0x0003 0x0003 Makernote Short 4 0 0 0 0 +Exif.Canon.CameraSettings2 0x0004 Makernote Short 27 54 0 160 276 149 287 0 0 0 0 6 0 0 0 12290 0 0 0 1 782 0 149 289 0 0 0 250 +Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0 +Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0 +Exif.Canon.ImageType 0x0006 Makernote Ascii 32 IMG:PowerShot S40 JPEG +Exif.Canon.FirmwareVersion 0x0007 Makernote Ascii 24 Firmware Version 1.10 +Exif.Canon.ImageNumber 0x0008 Makernote Long 1 1171771 +Exif.Canon.OwnerName 0x0009 Makernote Ascii 32 Andreas Huggel +Exif.Canon.0x0010 0x0010 Makernote Long 1 17891328 +Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0 +Exif.Iop.InteroperabilityIndex 0x0001 Iop Ascii 4 123 +Exif.Iop.InteroperabilityVersion 0x0002 Iop Undefined 4 48 49 48 48 +Exif.Iop.RelatedImageWidth 0x1001 Iop Short 1 2272 +Exif.Iop.RelatedImageLength 0x1002 Iop Short 1 1704 +Exif.Thumbnail.Compression 0x0103 IFD1 Short 1 6 +Exif.Thumbnail.Orientation 0x0112 IFD1 Short 1 2 +Exif.Thumbnail.XResolution 0x011a IFD1 Rational 1 180/1 +Exif.Thumbnail.YResolution 0x011b IFD1 Rational 1 180/1 +Exif.Thumbnail.ResolutionUnit 0x0128 IFD1 Short 1 2 +Exif.Thumbnail.JPEGInterchangeFormat 0x0201 IFD1 Long 1 0 +Exif.Thumbnail.JPEGInterchangeFormatLength 0x0202 IFD1 Long 1 5448 diff --git a/test/data/exiv2-gc.jpg b/test/data/exiv2-gc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..447951aaab53351811aed449f5e513ba9b012f90 GIT binary patch literal 11623 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 literal 0 HcmV?d00001 diff --git a/test/data/ifd-test.out b/test/data/ifd-test.out index fa56db10..ebc34c13 100644 --- a/test/data/ifd-test.out +++ b/test/data/ifd-test.out @@ -98,3 +98,33 @@ Data of entry 2: 003c 4c 75 6d 70 75 72 00 Lumpur. Data of entry 3: 0043 4d 61 6c 61 79 73 69 61 00 Malaysia. + +Move data buffer +IFD Offset: 0x00000001, IFD Entries: 4 +Entry Tag Format (Bytes each) Number Offset +----- ------ --------------------- ------ ----------- + 0 0x0001 Ascii (1) 4 54 68 65 00 + 1 0x0002 Ascii (1) 6 0x00000036 + 2 0x0003 Ascii (1) 7 0x0000003c + 3 0x0004 Ascii (1) 9 0x00000043 +Next IFD: 0x00000000 +Data of entry 1: + 0037 4b 75 61 6c 61 00 Kuala. +Data of entry 2: + 003d 4c 75 6d 70 75 72 00 Lumpur. +Data of entry 3: + 0044 54 48 52 45 45 00 00 00 00 THREE.... +IFD Offset: 0x00000001, IFD Entries: 4 +Entry Tag Format (Bytes each) Number Offset +----- ------ --------------------- ------ ----------- + 0 0x0001 Ascii (1) 4 54 68 65 00 + 1 0x0002 Ascii (1) 6 0x00000036 + 2 0x0003 Ascii (1) 7 0x0000003c + 3 0x0004 Ascii (1) 9 0x00000043 +Next IFD: 0x00000000 +Data of entry 1: + 0037 4b 75 61 6c 61 00 Kuala. +Data of entry 2: + 003d 4c 75 6d 70 75 72 00 Lumpur. +Data of entry 3: + 0044 54 48 52 45 45 00 00 00 00 THREE.... diff --git a/test/exifdata-test.sh b/test/exifdata-test.sh new file mode 100755 index 00000000..0d27ef81 --- /dev/null +++ b/test/exifdata-test.sh @@ -0,0 +1,29 @@ +#! /bin/sh +# Test driver for exifdata copy construction and assignment unit tests +results="./tmp/exifdata-test.out" +good="./data/exifdata-test.out" +diffargs="--strip-trailing-cr" +tmpfile=tmp/ttt +touch $tmpfile +diff -q $diffargs $tmpfile $tmpfile 2>/dev/null +if [ $? -ne 0 ] ; then + diffargs="" +fi +( +LD_LIBRARY_PATH=../../src:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH +binpath="../../src" +cp -f ./data/exiv2-gc.jpg ./tmp +cp -f ./data/exiv2-canon-powershot-s40.jpg ./tmp +cd ./tmp +$binpath/exifdata-test exiv2-gc.jpg +$binpath/exifdata-test exiv2-canon-powershot-s40.jpg +) > $results + +diff -q $diffargs $results $good +rc=$? +if [ $rc -eq 0 ] ; then + echo "All testcases passed." +else + diff $diffargs $results $good +fi