diff --git a/config/Doxyfile b/config/Doxyfile index 8dbf1b7b..deb0f618 100644 --- a/config/Doxyfile +++ b/config/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.4.5 +# Doxyfile 1.4.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project @@ -385,7 +385,7 @@ SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is YES. +# in the documentation. The default is NO. SHOW_DIRECTORIES = NO diff --git a/doc/templates/__index1__ b/doc/templates/__index1__ index 413a2088..fde8e94b 100644 --- a/doc/templates/__index1__ +++ b/doc/templates/__index1__ @@ -1,9 +1,9 @@ - +
diff --git a/src/Makefile b/src/Makefile index cdb931be..e7d14df1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -60,7 +60,7 @@ CCSRC = basicio.cpp canonmn.cpp crwimage.cpp datasets.cpp error.cpp exif.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 \ - write2-test.cpp crwparse.cpp + write2-test.cpp crwparse.cpp crwedit.cpp # Main source file of the Exiv2 application EXIV2MAIN = exiv2.cpp diff --git a/src/basicio.cpp b/src/basicio.cpp index 9702a3ea..479afcd2 100644 --- a/src/basicio.cpp +++ b/src/basicio.cpp @@ -184,7 +184,7 @@ namespace Exiv2 { close(); fileIo->close(); // MSVCRT rename that does not overwrite existing files - if (std::remove(path_.c_str()) != 0) { + if (fileExists(path_) && std::remove(path_.c_str()) != 0) { throw Error(2, path_, strError(), "std::remove"); } if (std::rename(fileIo->path_.c_str(), path_.c_str()) == -1) { @@ -192,7 +192,7 @@ namespace Exiv2 { } std::remove(fileIo->path_.c_str()); } - else{ + else { // Generic handling, reopen both to reset to start if (open("w+b") != 0) { throw Error(10, path_, "w+b", strError()); diff --git a/src/crwedit.cpp b/src/crwedit.cpp new file mode 100644 index 00000000..87c37906 --- /dev/null +++ b/src/crwedit.cpp @@ -0,0 +1,131 @@ +// ***************************************************************** -*- C++ -*- +// crwedit.cpp, $Rev$ +// Print the CIFF structure of a CRW file + +#include "crwimage.hpp" +#include "futils.hpp" + +#include +#include + +void remove(Exiv2::CiffHeader* pHead); +void add(Exiv2::CiffHeader* pHead); +void help(); +void write(const std::string& filename, const Exiv2::CiffHeader* pHead); + +int main(int argc, char* const argv[]) +try { + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " file\n"; + std::cout << "Edit the CIFF structure of a CRW file\n"; + return 1; + } + + std::string filename(argv[1]); + Exiv2::FileIo io(filename); + if(io.open() != 0) { + throw Exiv2::Error(9, io.path(), Exiv2::strError()); + } + Exiv2::IoCloser closer(io); + + // Ensure that this is a CRW image + if (!Exiv2::isCrwType(io, false)) { + if (io.error() || io.eof()) throw Exiv2::Error(14); + throw Exiv2::Error(33); + } + + // Read the image into a memory buffer + long len = io.size(); + Exiv2::DataBuf buf(len); + io.read(buf.pData_, len); + if (io.error() || io.eof()) throw Exiv2::Error(14); + + // Parse the image, starting with a CIFF header component + Exiv2::CiffHeader::AutoPtr parseTree(new Exiv2::CiffHeader); + parseTree->read(buf.pData_, buf.size_); + + // Allow user to make changes + bool go = true; + while (go) { + char cmd; + std::cout << "command> "; + std::cin >> cmd; + switch (cmd) { + case 'q': go = false; break; + case 'p': parseTree->print(std::cout); break; + case 'a': add(parseTree.get()); break; + case 'd': remove(parseTree.get()); break; + case 'w': write(filename, parseTree.get()); break; + case 'h': help(); break; + } + } + + return 0; +} +catch (Exiv2::AnyError& e) { + std::cerr << e << "\n"; + return -1; +} + +void write(const std::string& filename, const Exiv2::CiffHeader* pHead) +{ + Exiv2::Blob blob; + pHead->write(blob); + + Exiv2::FileIo io(filename); + if(io.open("wb") != 0) { + throw Exiv2::Error(9, io.path(), Exiv2::strError()); + } + Exiv2::IoCloser closer(io); + long ret = io.write(&blob[0], blob.size()); + if (static_cast(ret) != blob.size()) throw Exiv2::Error(21); + io.close(); +} + +void remove(Exiv2::CiffHeader* pHead) +{ + uint16_t crwTag, crwDir; + std::cout << "crwTag> 0x"; + std::cin >> std::hex >> crwTag; + std::cout << "crwDir> 0x"; + std::cin >> std::hex >> crwDir; + std::cout << "Deleting tag 0x" << std::hex << crwTag + << " in dir 0x" << crwDir << ", ok? "; + char cmd; + std::cin >> cmd; + if (cmd != 'n' && cmd != 'N') { + pHead->remove(crwTag, crwDir); + } + else { + std::cout << "Canceled.\n"; + } +} + +void add(Exiv2::CiffHeader* pHead) +{ + uint16_t crwTag, crwDir; + uint32_t size; + std::cout << "crwTag> 0x"; + std::cin >> std::hex >> crwTag; + std::cout << "crwDir> 0x"; + std::cin >> std::hex >> crwDir; + std::cout << "size> "; + std::cin >> std::dec >> size; + std::cout << "Adding tag 0x" << std::hex << crwTag + << " in dir 0x" << crwDir << ", " << size << " bytes, ok? "; + char cmd; + std::cin >> cmd; + if (cmd != 'n' && cmd != 'N') { + Exiv2::DataBuf buf(size); + memset(buf.pData_, 0xaa, size); + pHead->add(crwTag, crwDir, buf); + } + else { + std::cout << "Canceled.\n"; + } +} + +void help() +{ + std::cout << "a: add tag, d: delete tag, p: print tags, w: write file, q: quit\n"; +} diff --git a/src/crwimage.cpp b/src/crwimage.cpp index 64ec60a3..0dd53c04 100644 --- a/src/crwimage.cpp +++ b/src/crwimage.cpp @@ -38,6 +38,7 @@ EXIV2_RCSID("@(#) $Id$"); #ifdef _MSC_VER # include "exv_msvc.h" #else +# define _XOPEN_SOURCE /* glibc2 needs this for strptime */ # include "exv_conf.h" #endif @@ -56,6 +57,9 @@ EXIV2_RCSID("@(#) $Id$"); #include #include #include +#ifndef EXV_HAVE_TIMEGM +# include "timegm.h" +#endif // ***************************************************************************** // class member definitions @@ -64,15 +68,15 @@ namespace Exiv2 { const CrwMapping CrwMap::crwMapping_[] = { // CrwTag CrwDir Size ExifTag IfdId decodeFct encodeFct // ------ ------ ---- ------- ----- --------- --------- - CrwMapping(0x0805, 0x300a, 0, 0x9286, exifIfdId, decode0x0805, encode0x0805), - CrwMapping(0x080a, 0x2807, 0, 0x010f, ifd0Id, decode0x080a, encode0x080a), + CrwMapping(0x0805, 0x300a, 0, 0, canonIfdId, decode0x0805, encode0x0805), + CrwMapping(0x080a, 0x2807, 0, 0, canonIfdId, decode0x080a, encode0x080a), CrwMapping(0x080b, 0x3004, 0, 0x0007, canonIfdId, decodeBasic, encodeBasic), CrwMapping(0x0810, 0x2807, 0, 0x0009, canonIfdId, decodeBasic, encodeBasic), CrwMapping(0x0815, 0x2804, 0, 0x0006, canonIfdId, decodeBasic, encodeBasic), CrwMapping(0x1029, 0x300b, 0, 0x0002, canonIfdId, decodeBasic, encodeBasic), - CrwMapping(0x102a, 0x300b, 0, 0x0004, canonIfdId, decode0x102a, 0), - CrwMapping(0x102d, 0x300b, 0, 0x0001, canonIfdId, decode0x102d, 0), - CrwMapping(0x1033, 0x300b, 0, 0x000f, canonIfdId, decodeBasic, encodeBasic), + CrwMapping(0x102a, 0x300b, 0, 0x0004, canonIfdId, decodeArray, encodeArray), + CrwMapping(0x102d, 0x300b, 0, 0x0001, canonIfdId, decodeArray, encodeArray), + CrwMapping(0x1033, 0x300b, 0, 0x000f, canonIfdId, decodeArray, encodeArray), CrwMapping(0x1038, 0x300b, 0, 0x0012, canonIfdId, decodeBasic, encodeBasic), CrwMapping(0x10a9, 0x300b, 0, 0x00a9, canonIfdId, decodeBasic, encodeBasic), // Mapped to Exif.Photo.ColorSpace instead (see below) @@ -83,15 +87,12 @@ namespace Exiv2 { CrwMapping(0x10c1, 0x300b, 0, 0x00c1, canonIfdId, decodeBasic, encodeBasic), CrwMapping(0x1807, 0x3002, 0, 0x9206, exifIfdId, decodeBasic, encodeBasic), CrwMapping(0x180b, 0x2807, 0, 0x000c, canonIfdId, decodeBasic, encodeBasic), - CrwMapping(0x180e, 0x300a, 0, 0x9003, exifIfdId, decode0x180e, 0), - CrwMapping(0x1810, 0x300a, 0, 0xa002, exifIfdId, decode0x1810, 0), - CrwMapping(0x1810, 0x300a, 0, 0xa003, exifIfdId, 0, 0), + CrwMapping(0x180e, 0x300a, 0, 0x9003, exifIfdId, decode0x180e, encode0x180e), + CrwMapping(0x1810, 0x300a, 0, 0xa002, exifIfdId, decode0x1810, encode0x1810), CrwMapping(0x1817, 0x300a, 4, 0x0008, canonIfdId, decodeBasic, encodeBasic), //CrwMapping(0x1818, 0x3002, 0, 0x9204, exifIfdId, decodeBasic, encodeBasic), CrwMapping(0x183b, 0x300b, 0, 0x0015, canonIfdId, decodeBasic, encodeBasic), - CrwMapping(0x2008, 0x0000, 0, 0x0201, ifd1Id, decode0x2008, 0), - CrwMapping(0x2008, 0x0000, 0, 0x0202, ifd1Id, 0, 0), - CrwMapping(0x2008, 0x0000, 0, 0x0103, ifd1Id, 0, 0), + CrwMapping(0x2008, 0x0000, 0, 0, ifd1Id, decode0x2008, encode0x2008), // End of list marker CrwMapping(0x0000, 0x0000, 0, 0x0000, ifdIdNotSet, 0, 0) }; // CrwMap::crwMapping_[] @@ -126,30 +127,15 @@ namespace Exiv2 { { 0xffff, 0xffff } }; - const byte CrwImage::blank_[] = { - 0x00 - }; - CrwImage::CrwImage(BasicIo::AutoPtr io, bool create) : io_(io) { if (create) { - initImage(blank_, sizeof(blank_)); + IoCloser closer(*io_); + io_->open(); } } // CrwImage::CrwImage - int CrwImage::initImage(const byte initData[], long dataSize) - { - if (io_->open() != 0) { - return 4; - } - IoCloser closer(*io_); - if (io_->write(initData, dataSize) != dataSize) { - return 4; - } - return 0; - } // CrwImage::initImage - bool CrwImage::good() const { if (io_->open() != 0) return false; @@ -352,29 +338,6 @@ namespace Exiv2 { pRootDir_->readDirectory(pData + offset_, size - offset_, byteOrder_); } // CiffHeader::read - void CiffDirectory::readDirectory(const byte* pData, - uint32_t size, - ByteOrder byteOrder) - { - uint32_t o = getULong(pData + size - 4, byteOrder); - if (o + 2 > size) throw Error(33); - uint16_t count = getUShort(pData + o, byteOrder); - o += 2; - for (uint16_t i = 0; i < count; ++i) { - if (o + 10 > size) throw Error(33); - uint16_t tag = getUShort(pData + o, byteOrder); - AutoPtr m; - switch (CiffComponent::typeId(tag)) { - case directory: m = AutoPtr(new CiffDirectory); break; - default: m = AutoPtr(new CiffEntry); break; - } - m->setDir(this->tag()); - m->read(pData, size, o, byteOrder); - add(m); - o += 10; - } - } // CiffDirectory::readDirectory - void CiffComponent::read(const byte* pData, uint32_t size, uint32_t start, @@ -403,6 +366,13 @@ namespace Exiv2 { offset_ = start + 2; } pData_ = pData + offset_; +#ifdef DEBUG + std::cout << " Entry for tag 0x" + << std::hex << tagId() << " (0x" << tag() + << "), " << std::dec << size_ + << " Bytes, Offset is " << offset_ << "\n"; +#endif + } // CiffComponent::doRead void CiffDirectory::doRead(const byte* pData, @@ -411,9 +381,42 @@ namespace Exiv2 { ByteOrder byteOrder) { CiffComponent::doRead(pData, size, start, byteOrder); +#ifdef DEBUG + std::cout << "Reading directory 0x" << std::hex << tag() << "\n"; +#endif readDirectory(pData + offset(), this->size(), byteOrder); +#ifdef DEBUG + std::cout << "<---- 0x" << std::hex << tag() << "\n"; +#endif } // CiffDirectory::doRead + void CiffDirectory::readDirectory(const byte* pData, + uint32_t size, + ByteOrder byteOrder) + { + uint32_t o = getULong(pData + size - 4, byteOrder); + if (o + 2 > size) throw Error(33); + uint16_t count = getUShort(pData + o, byteOrder); +#ifdef DEBUG + std::cout << "Directory at offset " << std::dec << o + <<", " << count << " entries \n"; +#endif + o += 2; + for (uint16_t i = 0; i < count; ++i) { + if (o + 10 > size) throw Error(33); + uint16_t tag = getUShort(pData + o, byteOrder); + AutoPtr m; + switch (CiffComponent::typeId(tag)) { + case directory: m = AutoPtr(new CiffDirectory); break; + default: m = AutoPtr(new CiffEntry); break; + } + m->setDir(this->tag()); + m->read(pData, size, o, byteOrder); + add(m); + o += 10; + } + } // CiffDirectory::readDirectory + void CiffHeader::decode(Image& image) const { // Nothing to decode from the header itself, just add correct byte order @@ -472,7 +475,6 @@ namespace Exiv2 { ByteOrder byteOrder, uint32_t offset) { - if (remove_) return offset; return doWrite(blob, byteOrder, offset); } @@ -486,6 +488,10 @@ namespace Exiv2 { uint32_t CiffComponent::writeValueData(Blob& blob, uint32_t offset) { if (dataLocation() == valueData) { +#ifdef DEBUG + std::cout << " Data for tag 0x" << std::hex << tagId() + << ", " << std::dec << size_ << " Bytes\n"; +#endif offset_ = offset; append(blob, pData_, size_); offset += size_; @@ -502,8 +508,11 @@ namespace Exiv2 { ByteOrder byteOrder, uint32_t offset) { +#ifdef DEBUG + std::cout << "Writing directory 0x" << std::hex << tag() << "---->\n"; +#endif // Ciff offsets are relative to the start of the directory - uint32_t dirOffset = 0; + uint32_t dirOffset = 0; // Value data const Components::iterator b = components_.begin(); @@ -515,7 +524,7 @@ namespace Exiv2 { // Number of directory entries byte buf[4]; - us2Data(buf, components_.size(), byteOrder); + us2Data(buf, static_cast(components_.size()), byteOrder); append(blob, buf, 2); dirOffset += 2; @@ -534,11 +543,22 @@ namespace Exiv2 { setOffset(offset); setSize(dirOffset); +#ifdef DEBUG + std::cout << "Directory is at offset " << std::dec << dirStart + << ", " << components_.size() << " entries\n" + << "<---- 0x" << std::hex << tag() << "\n"; +#endif return offset + dirOffset; } // CiffDirectory::doWrite void CiffComponent::writeDirEntry(Blob& blob, ByteOrder byteOrder) const { +#ifdef DEBUG + std::cout << " Directory entry for tag 0x" + << std::hex << tagId() << " (0x" << tag() + << "), " << std::dec << size_ + << " Bytes, Offset is " << offset_ << "\n"; +#endif byte buf[4]; DataLocId dl = dataLocation(); @@ -662,46 +682,46 @@ namespace Exiv2 { } // CiffComponent::dataLocation /*! - @brief Finds \em crwTag in directory \em crwDir, returning a pointer to + @brief Finds \em crwTagId in directory \em crwDir, returning a pointer to the component or 0 if not found. */ - CiffComponent* CiffHeader::findComponent(uint16_t crwTag, + CiffComponent* CiffHeader::findComponent(uint16_t crwTagId, uint16_t crwDir) const { if (pRootDir_ == 0) return 0; - return pRootDir_->findComponent(crwTag, crwDir); + return pRootDir_->findComponent(crwTagId, crwDir); } // CiffHeader::findComponent - CiffComponent* CiffComponent::findComponent(uint16_t crwTag, + CiffComponent* CiffComponent::findComponent(uint16_t crwTagId, uint16_t crwDir) const { - return doFindComponent(crwTag, crwDir); + return doFindComponent(crwTagId, crwDir); } // CiffComponent::findComponent - CiffComponent* CiffComponent::doFindComponent(uint16_t crwTag, + CiffComponent* CiffComponent::doFindComponent(uint16_t crwTagId, uint16_t crwDir) const { - if (tagId() == crwTag && dir() == crwDir) { + if (tagId() == crwTagId && dir() == crwDir) { return const_cast(this); } return 0; } // CiffComponent::doFindComponent - CiffComponent* CiffDirectory::doFindComponent(uint16_t crwTag, + CiffComponent* CiffDirectory::doFindComponent(uint16_t crwTagId, uint16_t crwDir) const { CiffComponent* cc = 0; const Components::const_iterator b = components_.begin(); const Components::const_iterator e = components_.end(); for (Components::const_iterator i = b; i != e; ++i) { - cc = (*i)->findComponent(crwTag, crwDir); + cc = (*i)->findComponent(crwTagId, crwDir); if (cc) return cc; } return 0; } // CiffDirectory::doFindComponent - CiffComponent* CiffHeader::addTag(uint16_t crwTag, uint16_t crwDir) + void CiffHeader::add(uint16_t crwTagId, uint16_t crwDir, DataBuf buf) { CrwDirs crwDirs; CrwMap::loadStack(crwDirs, crwDir); @@ -709,28 +729,29 @@ namespace Exiv2 { assert(rootDirectory == 0x0000); crwDirs.pop(); if (!pRootDir_) pRootDir_ = new CiffDirectory; - return pRootDir_->addTag(crwDirs, crwTag); - } // CiffHeader::addTag + CiffComponent* cc = pRootDir_->add(crwDirs, crwTagId); + cc->setValue(buf); + } // CiffHeader::add - CiffComponent* CiffComponent::addTag(CrwDirs& crwDirs, uint16_t crwTag) + CiffComponent* CiffComponent::add(CrwDirs& crwDirs, uint16_t crwTagId) { - return doAddTag(crwDirs, crwTag); - } // CiffComponent::addTag + return doAdd(crwDirs, crwTagId); + } // CiffComponent::add - CiffComponent* CiffComponent::doAddTag(CrwDirs& crwDirs, uint16_t crwTag) + CiffComponent* CiffComponent::doAdd(CrwDirs& crwDirs, uint16_t crwTagId) { return 0; - } // CiffComponent::doAddTag + } // CiffComponent::doAdd - CiffComponent* CiffDirectory::doAddTag(CrwDirs& crwDirs, uint16_t crwTag) + CiffComponent* CiffDirectory::doAdd(CrwDirs& crwDirs, uint16_t crwTagId) { /* - addTag() + add() if stack not empty pop from stack find dir among components if not found, create it - addTag() + add() else find tag among components if not found, create it @@ -758,25 +779,93 @@ namespace Exiv2 { add(m); } // Recursive call to next lower level directory - cc = cc->addTag(crwDirs, crwTag); + cc = cc->add(crwDirs, crwTagId); } else { // Find the tag for (Components::iterator i = b; i != e; ++i) { - if ((*i)->tag() == crwTag) { + if ((*i)->tagId() == crwTagId) { cc = *i; break; } } if (cc == 0) { // Tag doesn't exist yet, add it - AutoPtr m(new CiffEntry(crwTag, tag())); + AutoPtr m(new CiffEntry(crwTagId, tag())); cc = m.get(); add(m); } } return cc; - } // CiffDirectory::doAddTag + } // CiffDirectory::doAdd + + void CiffHeader::remove(uint16_t crwTagId, uint16_t crwDir) + { + if (pRootDir_) { + CrwDirs crwDirs; + CrwMap::loadStack(crwDirs, crwDir); + uint16_t rootDirectory = crwDirs.top().crwDir_; + assert(rootDirectory == 0x0000); + crwDirs.pop(); + pRootDir_->remove(crwDirs, crwTagId); + } + } // CiffHeader::remove + + void CiffComponent::remove(CrwDirs& crwDirs, uint16_t crwTagId) + { + return doRemove(crwDirs, crwTagId); + } // CiffComponent::remove + + void CiffComponent::doRemove(CrwDirs& crwDirs, uint16_t crwTagId) + { + // do nothing + } // CiffComponent::doRemove + + void CiffDirectory::doRemove(CrwDirs& crwDirs, uint16_t crwTagId) + { + const Components::iterator b = components_.begin(); + const Components::iterator e = components_.end(); + Components::iterator i; + + if (!crwDirs.empty()) { + CrwSubDir csd = crwDirs.top(); + crwDirs.pop(); + // Find the directory + for (i = b; i != e; ++i) { + if ((*i)->tag() == csd.crwDir_) { + // Recursive call to next lower level directory + (*i)->remove(crwDirs, crwTagId); + if ((*i)->empty()) components_.erase(i); + break; + } + } + } + else { + // Find the tag + for (i = b; i != e; ++i) { + if ((*i)->tagId() == crwTagId) { + // Remove the entry and abort the loop + components_.erase(i); + break; + } + } + } + } // CiffDirectory::doRemove + + bool CiffComponent::empty() const + { + return doEmpty(); + } + + bool CiffComponent::doEmpty() const + { + return size_ == 0; + } + + bool CiffDirectory::doEmpty() const + { + return components_.empty(); + } void CrwMap::decode(const CiffComponent& ciffComponent, Image& image, @@ -789,11 +878,11 @@ namespace Exiv2 { } } // CrwMap::decode - const CrwMapping* CrwMap::crwMapping(uint16_t dir, uint16_t tagId) + const CrwMapping* CrwMap::crwMapping(uint16_t crwDir, uint16_t crwTagId) { for (int i = 0; crwMapping_[i].ifdId_ != ifdIdNotSet; ++i) { - if ( crwMapping_[i].crwDir_ == dir - && crwMapping_[i].crwTagId_ == tagId) { + if ( crwMapping_[i].crwDir_ == crwDir + && crwMapping_[i].crwTagId_ == crwTagId) { return &(crwMapping_[i]); } } @@ -814,9 +903,7 @@ namespace Exiv2 { Image& image, ByteOrder byteOrder) { - if (ciffComponent.typeId() != asciiString) { - return decodeBasic(ciffComponent, pCrwMapping, image, byteOrder); - } + if (ciffComponent.typeId() != asciiString) return; // Make ExifKey key1("Exif.Image.Make"); @@ -841,10 +928,10 @@ namespace Exiv2 { image.exifData().add(key2, value2.get()); } // CrwMap::decode0x080a - void CrwMap::decode0x102a(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder) + void CrwMap::decodeArray(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder) { if (ciffComponent.typeId() != unsignedShort) { return decodeBasic(ciffComponent, pCrwMapping, image, byteOrder); @@ -853,59 +940,47 @@ namespace Exiv2 { long aperture = 0; long shutterSpeed = 0; - std::string ifdItem(ExifTags::ifdItem(canonCs2IfdId)); - uint16_t c = 1; - while (uint32_t(c)*2 < ciffComponent.size()) { - uint16_t n = 1; - ExifKey key(c, ifdItem); - UShortValue value; - value.read(ciffComponent.pData() + c*2, n*2, byteOrder); - image.exifData().add(key, &value); - if (c == 21) aperture = value.toLong(); - if (c == 22) shutterSpeed = value.toLong(); - c += n; - } - - // Exif.Photo.FNumber - float f = fnumber(canonEv(aperture)); - // Beware: primitive conversion algorithm - uint32_t den = 1000000; - uint32_t nom = static_cast(f * den); - uint32_t g = gcd(nom, den); - URational ur(nom/g, den/g); - URationalValue fn; - fn.value_.push_back(ur); - image.exifData().add(ExifKey("Exif.Photo.FNumber"), &fn); - - // Exif.Photo.ExposureTime - ur = exposureTime(canonEv(shutterSpeed)); - URationalValue et; - et.value_.push_back(ur); - image.exifData().add(ExifKey("Exif.Photo.ExposureTime"), &et); - - } // CrwMap::decode0x102a - - void CrwMap::decode0x102d(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder) - { - if (ciffComponent.typeId() != unsignedShort) { - return decodeBasic(ciffComponent, pCrwMapping, image, byteOrder); + IfdId ifdId = ifdIdNotSet; + switch (pCrwMapping->tag_) { + case 0x0001: ifdId = canonCs1IfdId; break; + case 0x0004: ifdId = canonCs2IfdId; break; + case 0x000f: ifdId = canonCfIfdId; break; } + assert(ifdId != ifdIdNotSet); - std::string ifdItem(ExifTags::ifdItem(canonCs1IfdId)); + std::string ifdItem(ExifTags::ifdItem(ifdId)); uint16_t c = 1; while (uint32_t(c)*2 < ciffComponent.size()) { uint16_t n = 1; ExifKey key(c, ifdItem); UShortValue value; - if (c == 23 && ciffComponent.size() > 50) n = 3; + if (ifdId == canonCs1IfdId && c == 23 && ciffComponent.size() > 50) n = 3; value.read(ciffComponent.pData() + c*2, n*2, byteOrder); image.exifData().add(key, &value); + if (ifdId == canonCs2IfdId && c == 21) aperture = value.toLong(); + if (ifdId == canonCs2IfdId && c == 22) shutterSpeed = value.toLong(); c += n; } - } // CrwMap::decode0x102d + + if (ifdId == canonCs2IfdId) { + // Exif.Photo.FNumber + float f = fnumber(canonEv(aperture)); + // Beware: primitive conversion algorithm + uint32_t den = 1000000; + uint32_t nom = static_cast(f * den); + uint32_t g = gcd(nom, den); + URational ur(nom/g, den/g); + URationalValue fn; + fn.value_.push_back(ur); + image.exifData().add(ExifKey("Exif.Photo.FNumber"), &fn); + + // Exif.Photo.ExposureTime + ur = exposureTime(canonEv(shutterSpeed)); + URationalValue et; + et.value_.push_back(ur); + image.exifData().add(ExifKey("Exif.Photo.ExposureTime"), &et); + } + } // CrwMap::decodeArray void CrwMap::decode0x180e(const CiffComponent& ciffComponent, const CrwMapping* pCrwMapping, @@ -1034,56 +1109,51 @@ namespace Exiv2 { ExifKey ek(pCrwMapping->tag_, ExifTags::ifdItem(pCrwMapping->ifdId_)); ExifData::const_iterator ed = image.exifData().findKey(ek); - // Find the target metadatum in the Ciff parse tree - CiffComponent* cc = pHead->findComponent(pCrwMapping->crwTagId_, - pCrwMapping->crwDir_); - + // Set the new value or remove the entry if (ed != image.exifData().end()) { - // Create the directory and component as needed - if (cc == 0) cc = pHead->addTag(pCrwMapping->crwTagId_, - pCrwMapping->crwDir_); - // Set the new value DataBuf buf(ed->size()); ed->copy(buf.pData_, pHead->byteOrder()); - cc->setValue(buf); + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); } else { - if (cc) cc->remove(); + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); } } // CrwMap::encodeBasic void CrwMap::encode0x0805(const Image& image, - const CrwMapping* /*pCrwMapping*/, + const CrwMapping* pCrwMapping, CiffHeader* pHead) { + assert(pCrwMapping != 0); assert(pHead != 0); std::string comment = image.comment(); - - const uint16_t crwTag = 0x0805; - const uint16_t crwDir = 0x300a; - CiffComponent* cc = pHead->findComponent(crwTag, crwDir); + CiffComponent* cc = pHead->findComponent(pCrwMapping->crwTagId_, + pCrwMapping->crwDir_); if (!comment.empty()) { - if (cc == 0) cc = pHead->addTag(crwTag, crwDir); - DataBuf buf(std::max(cc->size(), comment.size())); + uint32_t size = comment.size(); + if (cc && cc->size() > size) size = cc->size(); + DataBuf buf(size); memset(buf.pData_, 0x0, buf.size_); memcpy(buf.pData_, comment.data(), comment.size()); - cc->setValue(buf); + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); } else { if (cc) { // Just delete the value, do not remove the tag DataBuf buf(cc->size()); memset(buf.pData_, 0x0, buf.size_); + cc->setValue(buf); } } } // CrwMap::encode0x0805 void CrwMap::encode0x080a(const Image& image, - const CrwMapping* /*pCrwMapping*/, + const CrwMapping* pCrwMapping, CiffHeader* pHead) { + assert(pCrwMapping != 0); assert(pHead != 0); const ExifKey k1("Exif.Image.Make"); @@ -1091,25 +1161,125 @@ namespace Exiv2 { const ExifData::const_iterator ed1 = image.exifData().findKey(k1); const ExifData::const_iterator ed2 = image.exifData().findKey(k2); const ExifData::const_iterator edEnd = image.exifData().end(); - - const uint16_t crwTag = 0x080a; - const uint16_t crwDir = 0x2807; - CiffComponent* cc = pHead->findComponent(crwTag, crwDir); long size = 0; if (ed1 != edEnd) size += ed1->size(); if (ed2 != edEnd) size += ed2->size(); if (size != 0) { - if (cc == 0) cc = pHead->addTag(crwTag, crwDir); DataBuf buf(size); if (ed1 != edEnd) ed1->copy(buf.pData_, pHead->byteOrder()); if (ed2 != edEnd) ed2->copy(buf.pData_ + ed1->size(), pHead->byteOrder()); - cc->setValue(buf); + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); } else { - if (cc) cc->remove(); + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); } - } // encode0x080a + } // CrwMap::encode0x080a + + void CrwMap::encodeArray(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead) + { + assert(pCrwMapping != 0); + assert(pHead != 0); + + IfdId ifdId = ifdIdNotSet; + switch (pCrwMapping->tag_) { + case 0x0001: ifdId = canonCs1IfdId; break; + case 0x0004: ifdId = canonCs2IfdId; break; + case 0x000f: ifdId = canonCfIfdId; break; + } + assert(ifdId != ifdIdNotSet); + DataBuf buf = packIfdId(image.exifData(), ifdId, pHead->byteOrder()); + if (buf.size_ == 0) { + // Try the undecoded tag + encodeBasic(image, pCrwMapping, pHead); + } + if (buf.size_ > 0) { + // Write the number of shorts to the beginning of buf + us2Data(buf.pData_, buf.size_, pHead->byteOrder()); + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); + } + else { + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); + } + } // CrwMap::encodeArray + + void CrwMap::encode0x180e(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead) + { + assert(pCrwMapping != 0); + assert(pHead != 0); + + time_t t = 0; + const ExifKey key(pCrwMapping->tag_, ExifTags::ifdItem(pCrwMapping->ifdId_)); + const ExifData::const_iterator ed = image.exifData().findKey(key); + if (ed != image.exifData().end()) { + struct tm tm; + char* p = strptime(ed->toString().c_str(), "%Y:%m:%d %T", &tm); + if (p != 0) t = timegm(&tm); + } + if (t != 0) { + DataBuf buf(12); + memset(buf.pData_, 0x0, 12); + ul2Data(buf.pData_, static_cast(t), pHead->byteOrder()); + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); + } + else { + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); + } + } // CrwMap::encode0x180e + + void CrwMap::encode0x1810(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead) + { + assert(pCrwMapping != 0); + assert(pHead != 0); + + const ExifKey kX("Exif.Photo.PixelXDimension"); + const ExifKey kY("Exif.Photo.PixelYDimension"); + const ExifData::const_iterator edX = image.exifData().findKey(kX); + const ExifData::const_iterator edY = image.exifData().findKey(kY); + const ExifData::const_iterator edEnd = image.exifData().end(); + + CiffComponent* cc = pHead->findComponent(pCrwMapping->crwTagId_, + pCrwMapping->crwDir_); + if (edX != edEnd || edY != edEnd) { + uint32_t size = 28; + if (cc && cc->size() > size) size = cc->size(); + DataBuf buf(size); + memset(buf.pData_, 0x0, buf.size_); + if (cc) memcpy(buf.pData_ + 8, cc->pData() + 8, cc->size() - 8); + if (edX != edEnd && edX->size() == 4) { + edX->copy(buf.pData_, pHead->byteOrder()); + } + if (edY != edEnd && edY->size() == 4) { + edY->copy(buf.pData_ + 4, pHead->byteOrder()); + } + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); + } + else { + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); + } + } // CrwMap::encode0x1810 + + void CrwMap::encode0x2008(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead) + { + assert(pCrwMapping != 0); + assert(pHead != 0); + + DataBuf buf = image.exifData().copyThumbnail(); + if (buf.size_ != 0) { + pHead->add(pCrwMapping->crwTagId_, pCrwMapping->crwDir_, buf); + } + else { + pHead->remove(pCrwMapping->crwTagId_, pCrwMapping->crwDir_); + } + } // CrwMap::encode0x1810 // ************************************************************************* // free functions @@ -1143,4 +1313,27 @@ namespace Exiv2 { return result; } + DataBuf packIfdId(const ExifData& exifData, + IfdId ifdId, + ByteOrder byteOrder) + { + const uint16_t size = 1024; + DataBuf buf(size); + memset(buf.pData_, 0x0, buf.size_); + + uint16_t len = 0; + const ExifData::const_iterator b = exifData.begin(); + const ExifData::const_iterator e = exifData.end(); + for (ExifData::const_iterator i = b; i != e; ++i) { + if (i->ifdId() != ifdId) continue; + const uint16_t s = i->tag()*2 + static_cast(i->size()); + assert(s <= size); + if (len < s) len = s; + i->copy(buf.pData_ + i->tag()*2, byteOrder); + } + // Round the size to make it even. + buf.size_ = len + len%2; + return buf; + } + } // namespace Exiv2 diff --git a/src/crwimage.hpp b/src/crwimage.hpp index 76a85c83..fc605c79 100644 --- a/src/crwimage.hpp +++ b/src/crwimage.hpp @@ -157,12 +157,6 @@ namespace Exiv2 { //@} private: - - //! @name Manipulators - //@{ - int initImage(const byte initData[], long dataSize); - //@} - //! @name Accessors //@{ /*! @@ -191,8 +185,6 @@ namespace Exiv2 { //@} // DATA - static const byte blank_[]; //!< Minimal Crw image - BasicIo::AutoPtr io_; //!< Image data io pointer ExifData exifData_; //!< Exif data container IptcData iptcData_; //!< Iptc data container @@ -254,11 +246,11 @@ namespace Exiv2 { //! Default constructor CiffComponent() : dir_(0), tag_(0), size_(0), offset_(0), pData_(0), - remove_(false), isAllocated_(false) {} + isAllocated_(false) {} //! Constructor taking a tag and directory CiffComponent(uint16_t tag, uint16_t dir) : dir_(dir), tag_(tag), size_(0), offset_(0), pData_(0), - remove_(false), isAllocated_(false) {} + isAllocated_(false) {} //! Virtual destructor. virtual ~CiffComponent(); //@} @@ -269,6 +261,30 @@ namespace Exiv2 { //! Add a component to the composition void add(AutoPtr component); + /*! + @brief Add \em crwTagId to the parse tree, if it doesn't exist + yet. \em crwDirs contains the path of subdirectories, starting + with the root directory, leading to \em crwTagId. Directories + that don't exist yet are added along the way. Returns a pointer + to the newly added component. + + @param crwDirs Subdirectory path from root to the subdirectory + containing the tag to be added. + @param crwTagId Tag to be added. + + @return A pointer to the newly added component. + */ + CiffComponent* add(CrwDirs& crwDirs, uint16_t crwTagId); + /*! + @brief Remove \em crwTagId from the parse tree, if it exists yet. \em + crwDirs contains the path of subdirectories, starting with the + root directory, leading to \em crwTagId. + + @param crwDirs Subdirectory path from root to the subdirectory + containing the tag to be removed. + @param crwTagId Tag to be removed. + */ + void remove(CrwDirs& crwDirs, uint16_t crwTagId); /*! @brief Read a component from a data buffer @@ -294,18 +310,6 @@ namespace Exiv2 { @return New offset */ uint32_t write(Blob& blob, ByteOrder byteOrder, uint32_t offset); - /*! - @brief Add \em crwTag to the parse tree, if it doesn' exist yet. \em - crwDirs contains the path of subdirectories, starting with the - root directory, leading to \em crwTag. Directories that don't - exist yet are added along the way. Returns a pointer to the - newly added component. - - @param crwDirs Subdirectory path from root to the subdirectory containing - the tag to be added. - @param crwTag Tag to be added. - */ - CiffComponent* addTag(CrwDirs& crwDirs, uint16_t crwTag); /*! @brief Writes the entry's value if size is larger than eight bytes. If needed, the value is padded with one 0 byte to make the number @@ -319,8 +323,6 @@ namespace Exiv2 { uint32_t writeValueData(Blob& blob, uint32_t offset); //! Set the directory tag for this component. void setDir(uint16_t dir) { dir_ = dir; } - //! Mark the component as deleted, so that it won't be written. - void remove() { remove_ = true; } //! Set the data value of the entry. void setValue(DataBuf buf); //@} @@ -362,6 +364,9 @@ namespace Exiv2 { //! Return the tag of this component uint16_t tag() const { return tag_; } + //! Return true if the component is empty, else false + bool empty() const; + /*! @brief Return the data size of this component @@ -388,10 +393,10 @@ namespace Exiv2 { DataLocId dataLocation() const { return dataLocation(tag_); } /*! - @brief Finds \em crwTag in directory \em crwDir, returning a pointer to + @brief Finds \em crwTagId in directory \em crwDir, returning a pointer to the component or 0 if not found. */ - CiffComponent* findComponent(uint16_t crwTag, uint16_t crwDir) const; + CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const; //@} protected: @@ -399,6 +404,10 @@ namespace Exiv2 { //@{ //! Implements add() virtual void doAdd(AutoPtr component) =0; + //! Implements add(). The default implementation does nothing. + virtual CiffComponent* doAdd(CrwDirs& crwDirs, uint16_t crwTagId); + //! Implements remove(). The default implementation does nothing. + virtual void doRemove(CrwDirs& crwDirs, uint16_t crwTagId); //! Implements read(). The default implementation reads a directory entry. virtual void doRead(const byte* pData, uint32_t size, @@ -408,8 +417,6 @@ namespace Exiv2 { virtual uint32_t doWrite(Blob& blob, ByteOrder byteOrder, uint32_t offset) =0; - //! Implements addTag(). The default implementation does nothing. - virtual CiffComponent* doAddTag(CrwDirs& crwDirs, uint16_t crwTag); //! Set the size of the data area. void setSize(uint32_t size) { size_ = size; } //! Set the offset for this component. @@ -425,8 +432,10 @@ namespace Exiv2 { virtual void doPrint(std::ostream& os, ByteOrder byteOrder, const std::string& prefix) const; + //! Implements empty(). Default implementation returns true if size is 0. + virtual bool doEmpty() const; //! Implements findComponent(). The default implementation checks the entry. - virtual CiffComponent* doFindComponent(uint16_t crwTag, + virtual CiffComponent* doFindComponent(uint16_t crwTagId, uint16_t crwDir) const; //@} @@ -437,7 +446,6 @@ namespace Exiv2 { uint32_t size_; //!< Size of the data area uint32_t offset_; //!< Offset to the data area from start of dir const byte* pData_; //!< Pointer to the data area - bool remove_; //!< If true, the entry should not be written bool isAllocated_; //!< True if this entry owns the value data }; // class CiffComponent @@ -518,6 +526,10 @@ namespace Exiv2 { //@{ // See base class comment virtual void doAdd(AutoPtr component); + // See base class comment + virtual CiffComponent* doAdd(CrwDirs& crwDirs, uint16_t crwTagId); + // See base class comment + virtual void doRemove(CrwDirs& crwDirs, uint16_t crwTagId); /*! @brief Implements write(). Writes the complete Ciff directory to the blob. @@ -530,8 +542,6 @@ namespace Exiv2 { uint32_t size, uint32_t start, ByteOrder byteOrder); - // See base class comment - virtual CiffComponent* doAddTag(CrwDirs& crwDirs, uint16_t crwTag); //@} //! @name Accessors @@ -544,8 +554,12 @@ namespace Exiv2 { virtual void doPrint(std::ostream& os, ByteOrder byteOrder, const std::string& prefix) const; + + //! See base class comment. A directory is empty if it has no components. + virtual bool doEmpty() const; + // See base class comment - virtual CiffComponent* doFindComponent(uint16_t crwTag, + virtual CiffComponent* doFindComponent(uint16_t crwTagId, uint16_t crwDir) const; //@} @@ -555,7 +569,12 @@ namespace Exiv2 { }; // class CiffDirectory - //! This class models the header of a Crw (Canon Raw data) image. + /*! + @brief This class models the header of a Crw (Canon Raw data) image. It + is the head of a CIFF parse tree, consisting of CiffDirectory and + CiffEntry objects. Most of its methods will walk the parse tree to + perform the requested action. + */ class CiffHeader { public: //! CiffHeader auto_ptr type @@ -586,18 +605,24 @@ namespace Exiv2 { */ void read(const byte* pData, uint32_t size); /*! - @brief Adds an entry for \em crwTag in directory \em crwDir to the - parse tree if it doesn't exist yet. Directories that don't - exist yet are added along the way. Nothing is added if the tag - already exists in the correct directory. Returns the newly - added component. + @brief Set the value of entry \em crwTagId in directory \em crwDir to + \em buf. If this tag doesn't exist, it is added along with all + directories needed. - @param crwTag Tag to be added. - @param crwDir Parent directory of the tag. + @param crwTagId Tag to be added. + @param crwDir Parent directory of the tag. + @param buf Value to be set. + */ + void add(uint16_t crwTagId, uint16_t crwDir, DataBuf buf); + /*! + @brief Remove entry \em crwTagId in directory \em crwDir from the parse + tree. If it's the last entry in the directory, the directory is + removed as well, etc. - @return The newly added component. + @param crwTagId Tag id to be removed. + @param crwDir Parent directory of the tag. */ - CiffComponent* addTag(uint16_t crwTag, uint16_t crwDir); + void remove(uint16_t crwTagId, uint16_t crwDir); //@} //! Return a pointer to the Canon Crw signature. @@ -630,10 +655,10 @@ namespace Exiv2 { //! Return the byte order (little or big endian). ByteOrder byteOrder() const { return byteOrder_; } /*! - @brief Finds \em crwTag in directory \em crwDir in the parse tree, + @brief Finds \em crwTagId in directory \em crwDir in the parse tree, returning a pointer to the component or 0 if not found. */ - CiffComponent* findComponent(uint16_t crwTag, uint16_t crwDir) const; + CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const; //@} private: @@ -734,8 +759,8 @@ namespace Exiv2 { static void loadStack(CrwDirs& crwDirs, uint16_t crwDir); private: - //! Return conversion information for one Crw \em dir and \em tagId - static const CrwMapping* crwMapping(uint16_t dir, uint16_t tagId); + //! Return conversion information for one \em crwDir and \em crwTagId + static const CrwMapping* crwMapping(uint16_t crwDir, uint16_t crwTagId); /*! @brief Standard decode function to convert Crw entries to @@ -763,17 +788,11 @@ namespace Exiv2 { Image& image, ByteOrder byteOrder); - //! Decode Canon Camera Settings 2 - static void decode0x102a(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - //! Decode Canon Camera Settings 1 - static void decode0x102d(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); + //! Decode Canon Camera Settings 1, 2 and Custom Function arrays + static void decodeArray(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); //! Decode the date when the picture was taken static void decode0x180e(const CiffComponent& ciffComponent, @@ -821,6 +840,25 @@ namespace Exiv2 { const CrwMapping* pCrwMapping, CiffHeader* pHead); + //! Encode Canon Camera Settings 1, 2 and Custom Function arrays + static void encodeArray(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); + + //! Encode the date when the picture was taken + static void encode0x180e(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); + + //! Encode image width and height + static void encode0x1810(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); + + //! Encode the thumbnail image + static void encode0x2008(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); private: // DATA static const CrwMapping crwMapping_[]; //!< Metadata conversion table @@ -843,6 +881,15 @@ namespace Exiv2 { //! Check if the file iIo is a Crw image. bool isCrwType(BasicIo& iIo, bool advance); + /*! + @brief Pack the tag values of all \em ifdId tags in \em exifData into a + data buffer. This function is used to pack Canon Camera Settings1,2 + and Custom Function tags. + */ + DataBuf packIfdId(const ExifData& exifData, + IfdId ifdId, + ByteOrder byteOrder); + } // namespace Exiv2 #endif // #ifndef CRWIMAGE_HPP_ diff --git a/test/Makefile b/test/Makefile index 1124cf53..0fd4794a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -15,9 +15,10 @@ SHELL = /bin/sh .PHONY: all test clean distclean maintainer-clean # Add test drivers to this list -TESTS = addmoddel.sh bugfixes-test.sh exifdata-test.sh exiv2-test.sh ifd-test.sh \ - imagetest.sh iotest.sh iptctest.sh makernote-test.sh modify-test.sh \ - path-test.sh write-test.sh write2-test.sh +TESTS = addmoddel.sh bugfixes-test.sh crw-test.sh exifdata-test.sh \ + exiv2-test.sh ifd-test.sh imagetest.sh iotest.sh iptctest.sh \ + makernote-test.sh modify-test.sh path-test.sh write-test.sh \ + write2-test.sh test: @list='$(TESTS)'; for p in $$list; do \ diff --git a/test/crw-test.sh b/test/crw-test.sh index fdd63da4..e1fe4836 100755 --- a/test/crw-test.sh +++ b/test/crw-test.sh @@ -20,34 +20,12 @@ LD_LIBRARY_PATH=../../src:$LD_LIBRARY_PATH export LD_LIBRARY_PATH binpath="$VALGRIND ../../src" cmdfile=cmdfile -crwfile=CanonRaw.crw +crwfile=exiv2-canon-powershot-s40.crw cd ./tmp # ---------------------------------------------------------------------- -# Testcases: Add tags - -# Create an image from scratch with just one tag -# Add one tag to an existing image -# Add a non-CIFF tag -# Add a second tag with the same tag id -# Are new tags created as directory data if possible? - -# ---------------------------------------------------------------------- -# Testcases: Modify tags - -# Modify tag value only -# Change number of components (from directory data to value data) -# Change value type - -# Exif.Canon.FirmwareVersion Ascii -# Exif.Canon.OwnerName Ascii -# Exif.Canon.ImageType Ascii -# Exif.Canon.0x0002 Short -# Exif.Canon.CustomFunctions Short -# Exif.Canon.PictureInfo Short -# Exif.Canon.SerialNumber Short -# Exif.Canon.ImageNumber Long +# Testcases: Add and modify tags cat > $cmdfile < $cmdfile < $results 2>&1 diff --git a/test/data/crw-test.out b/test/data/crw-test.out index 933fd3fa..16923995 100644 Binary files a/test/data/crw-test.out and b/test/data/crw-test.out differ diff --git a/test/data/exiv2-canon-powershot-s40.crw b/test/data/exiv2-canon-powershot-s40.crw new file mode 100644 index 00000000..95bc6246 Binary files /dev/null and b/test/data/exiv2-canon-powershot-s40.crw differ