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