From 00a3ef321b16882f1f6d424a10a753d2712334dd Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Sun, 3 Aug 2008 15:31:36 +0000 Subject: [PATCH] Removed CIFF classes from published API, doc tweaks. --- samples/Makefile | 2 - src/Makefile | 8 +- {samples => src}/crwedit.cpp | 19 +- src/crwimage.cpp | 286 ++++++------- src/crwimage.hpp | 714 +------------------------------- src/crwimage_int.hpp | 749 ++++++++++++++++++++++++++++++++++ {samples => src}/crwparse.cpp | 7 +- src/datasets.hpp | 6 +- src/error.hpp | 2 +- src/exif.hpp | 4 +- src/iptc.hpp | 4 +- src/properties.cpp | 24 +- src/properties.hpp | 11 +- src/tags.hpp | 6 +- src/tiffimage.cpp | 4 - src/types.hpp | 6 - test/crw-test.sh | 2 +- 17 files changed, 971 insertions(+), 883 deletions(-) rename {samples => src}/crwedit.cpp (86%) create mode 100644 src/crwimage_int.hpp rename {samples => src}/crwparse.cpp (87%) diff --git a/samples/Makefile b/samples/Makefile index a346b90b..83ba239d 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -56,8 +56,6 @@ include $(top_srcdir)/config/config.mk # Add source files of sample programs to this list BINSRC = addmoddel.cpp \ convert-test.cpp \ - crwedit.cpp \ - crwparse.cpp \ exifcomment.cpp \ exifdata-test.cpp \ exifprint.cpp \ diff --git a/src/Makefile b/src/Makefile index 6e681113..42d0f146 100644 --- a/src/Makefile +++ b/src/Makefile @@ -94,7 +94,8 @@ ifdef HAVE_LIBZ CCSRC += pngimage.cpp \ pngchunk.cpp endif -CCSRC += psdimage.cpp \ +CCSRC += properties.cpp \ + psdimage.cpp \ rafimage.cpp \ sigmamn.cpp \ pentaxmn.cpp \ @@ -107,7 +108,6 @@ CCSRC += psdimage.cpp \ types.cpp \ value.cpp \ version.cpp \ - properties.cpp \ xmp.cpp \ xmpsidecar.cpp @@ -117,7 +117,9 @@ CSRC = localtime.c endif # Add source files of simple applications to this list -BINSRC = taglist.cpp +BINSRC = crwedit.cpp \ + crwparse.cpp \ + taglist.cpp # Source files for the Exiv2 application EXIV2MAIN = exiv2.cpp diff --git a/samples/crwedit.cpp b/src/crwedit.cpp similarity index 86% rename from samples/crwedit.cpp rename to src/crwedit.cpp index 764e9c79..3f785bfb 100644 --- a/samples/crwedit.cpp +++ b/src/crwedit.cpp @@ -2,17 +2,18 @@ // crwedit.cpp, $Rev$ // Print the CIFF structure of a CRW file -#include -#include +#include "crwimage.hpp" +#include "crwimage_int.hpp" +#include "futils.hpp" #include #include #include -void remove(Exiv2::CiffHeader* pHead); -void add(Exiv2::CiffHeader* pHead); +void remove(Exiv2::Internal::CiffHeader* pHead); +void add(Exiv2::Internal::CiffHeader* pHead); void help(); -void write(const std::string& filename, const Exiv2::CiffHeader* pHead); +void write(const std::string& filename, const Exiv2::Internal::CiffHeader* pHead); int main(int argc, char* const argv[]) try { @@ -42,7 +43,7 @@ try { 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); + Exiv2::Internal::CiffHeader::AutoPtr parseTree(new Exiv2::Internal::CiffHeader); parseTree->read(buf.pData_, buf.size_); // Allow user to make changes @@ -68,7 +69,7 @@ catch (Exiv2::AnyError& e) { return -1; } -void write(const std::string& filename, const Exiv2::CiffHeader* pHead) +void write(const std::string& filename, const Exiv2::Internal::CiffHeader* pHead) { Exiv2::Blob blob; pHead->write(blob); @@ -83,7 +84,7 @@ void write(const std::string& filename, const Exiv2::CiffHeader* pHead) io.close(); } -void remove(Exiv2::CiffHeader* pHead) +void remove(Exiv2::Internal::CiffHeader* pHead) { uint16_t crwTag, crwDir; std::cout << "crwTag> 0x"; @@ -102,7 +103,7 @@ void remove(Exiv2::CiffHeader* pHead) } } -void add(Exiv2::CiffHeader* pHead) +void add(Exiv2::Internal::CiffHeader* pHead) { uint16_t crwTag, crwDir; uint32_t size; diff --git a/src/crwimage.cpp b/src/crwimage.cpp index 1da0ab31..55d492dc 100644 --- a/src/crwimage.cpp +++ b/src/crwimage.cpp @@ -42,6 +42,7 @@ EXIV2_RCSID("@(#) $Id$") #endif #include "crwimage.hpp" +#include "crwimage_int.hpp" #include "error.hpp" #include "futils.hpp" #include "value.hpp" @@ -87,6 +88,153 @@ namespace { // class member definitions namespace Exiv2 { + using namespace Internal; + + CrwImage::CrwImage(BasicIo::AutoPtr io, bool /*create*/) + : Image(ImageType::crw, mdExif | mdComment, io) + { + } // CrwImage::CrwImage + + int CrwImage::pixelWidth() const + { + Exiv2::ExifData::const_iterator widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension")); + return (widthIter == exifData_.end()) ? 0 : widthIter->toLong(); + } + + int CrwImage::pixelHeight() const + { + Exiv2::ExifData::const_iterator heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension")); + return (heightIter == exifData_.end()) ? 0 : heightIter->toLong(); + } + + void CrwImage::setIptcData(const IptcData& /*iptcData*/) + { + // not supported + throw(Error(32, "IPTC metadata", "CRW")); + } + + void CrwImage::readMetadata() + { +#ifdef DEBUG + std::cerr << "Reading CRW file " << io_->path() << "\n"; +#endif + if (io_->open() != 0) { + throw Error(9, io_->path(), strError()); + } + IoCloser closer(*io_); + // Ensure that this is the correct image type + if (!isCrwType(*io_, false)) { + if (io_->error() || io_->eof()) throw Error(14); + throw Error(33); + } + clearMetadata(); + CrwParser::decode(this, io_->mmap(), io_->size()); + + } // CrwImage::readMetadata + + void CrwImage::writeMetadata() + { +#ifdef DEBUG + std::cerr << "Writing CRW file " << io_->path() << "\n"; +#endif + // Read existing image + DataBuf buf; + if (io_->open() == 0) { + IoCloser closer(*io_); + // Ensure that this is the correct image type + if (isCrwType(*io_, false)) { + // Read the image into a memory buffer + buf.alloc(io_->size()); + io_->read(buf.pData_, buf.size_); + if (io_->error() || io_->eof()) { + buf.reset(); + } + } + } + + Blob blob; + CrwParser::encode(blob, buf.pData_, buf.size_, this); + + // Write new buffer to file + BasicIo::AutoPtr tempIo(io_->temporary()); // may throw + assert(tempIo.get() != 0); + tempIo->write(&blob[0], static_cast(blob.size())); + io_->close(); + io_->transfer(*tempIo); // may throw + + } // CrwImage::writeMetadata + + void CrwParser::decode(CrwImage* pCrwImage, const byte* pData, uint32_t size) + { + assert(pCrwImage != 0); + assert(pData != 0); + + // Parse the image, starting with a CIFF header component + CiffHeader::AutoPtr head(new CiffHeader); + head->read(pData, size); +#ifdef DEBUG + head->print(std::cerr); +#endif + head->decode(*pCrwImage); + + } // CrwParser::decode + + void CrwParser::encode( + Blob& blob, + const byte* pData, + uint32_t size, + const CrwImage* pCrwImage + ) + { + // Parse image, starting with a CIFF header component + CiffHeader::AutoPtr head(new CiffHeader); + if (size != 0) { + head->read(pData, size); + } + + // Encode Exif tags from image into the CRW parse tree and write the + // structure to the binary image blob + CrwMap::encode(head.get(), *pCrwImage); + head->write(blob); + + } // CrwParser::encode + + // ************************************************************************* + // free functions + Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create) + { + Image::AutoPtr image(new CrwImage(io, create)); + if (!image->good()) { + image.reset(); + } + return image; + } + + bool isCrwType(BasicIo& iIo, bool advance) + { + bool result = true; + byte tmpBuf[14]; + iIo.read(tmpBuf, 14); + if (iIo.error() || iIo.eof()) { + return false; + } + if (!( ('I' == tmpBuf[0] && 'I' == tmpBuf[1]) + || ('M' == tmpBuf[0] && 'M' == tmpBuf[1]))) { + result = false; + } + if ( true == result + && std::memcmp(tmpBuf + 6, CiffHeader::signature(), 8) != 0) { + result = false; + } + if (!advance || !result) iIo.seek(-14, BasicIo::cur); + return result; + } + +} // namespace Exiv2 + +namespace Exiv2 { + namespace Internal { + /* Mapping table used to decode and encode CIFF tags to/from Exif tags. Only a subset of the Exif tags can be mapped to known tags found in CRW files @@ -165,113 +313,6 @@ namespace Exiv2 { { 0xffff, 0xffff } }; - CrwImage::CrwImage(BasicIo::AutoPtr io, bool /*create*/) - : Image(ImageType::crw, mdExif | mdComment, io) - { - } // CrwImage::CrwImage - - int CrwImage::pixelWidth() const - { - Exiv2::ExifData::const_iterator widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension")); - return (widthIter == exifData_.end()) ? 0 : widthIter->toLong(); - } - - int CrwImage::pixelHeight() const - { - Exiv2::ExifData::const_iterator heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension")); - return (heightIter == exifData_.end()) ? 0 : heightIter->toLong(); - } - - void CrwImage::setIptcData(const IptcData& /*iptcData*/) - { - // not supported - throw(Error(32, "IPTC metadata", "CRW")); - } - - void CrwImage::readMetadata() - { -#ifdef DEBUG - std::cerr << "Reading CRW file " << io_->path() << "\n"; -#endif - if (io_->open() != 0) { - throw Error(9, io_->path(), strError()); - } - IoCloser closer(*io_); - // Ensure that this is the correct image type - if (!isCrwType(*io_, false)) { - if (io_->error() || io_->eof()) throw Error(14); - throw Error(33); - } - clearMetadata(); - CrwParser::decode(this, io_->mmap(), io_->size()); - - } // CrwImage::readMetadata - - void CrwImage::writeMetadata() - { -#ifdef DEBUG - std::cerr << "Writing CRW file " << io_->path() << "\n"; -#endif - // Read existing image - DataBuf buf; - if (io_->open() == 0) { - IoCloser closer(*io_); - // Ensure that this is the correct image type - if (isCrwType(*io_, false)) { - // Read the image into a memory buffer - buf.alloc(io_->size()); - io_->read(buf.pData_, buf.size_); - if (io_->error() || io_->eof()) { - buf.reset(); - } - } - } - - // Parse image, starting with a CIFF header component - CiffHeader::AutoPtr head(new CiffHeader); - if (buf.size_ != 0) { - head->read(buf.pData_, buf.size_); - } - - Blob blob; - CrwParser::encode(blob, head.get(), this); - - // Write new buffer to file - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw - assert (tempIo.get() != 0); - tempIo->write(&blob[0], static_cast(blob.size())); - io_->close(); - io_->transfer(*tempIo); // may throw - - } // CrwImage::writeMetadata - - void CrwParser::decode(CrwImage* pCrwImage, const byte* pData, uint32_t size) - { - assert(pCrwImage != 0); - assert(pData != 0); - - // Parse the image, starting with a CIFF header component - CiffHeader::AutoPtr head(new CiffHeader); - head->read(pData, size); -#ifdef DEBUG - head->print(std::cerr); -#endif - head->decode(*pCrwImage); - - } // CrwParser::decode - - void CrwParser::encode(Blob& blob, CiffHeader* pHead, const CrwImage* pCrwImage) - { - assert(pCrwImage != 0); - assert(pHead != 0); - - // Encode Exif tags from image into the Crw parse tree and write the structure - // to the binary image blob - CrwMap::encode(pHead, *pCrwImage); - pHead->write(blob); - - } // CrwParser::encode - const char CiffHeader::signature_[] = "HEAPCCDR"; CiffHeader::~CiffHeader() @@ -1299,35 +1340,6 @@ namespace Exiv2 { // ************************************************************************* // free functions - Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create) - { - Image::AutoPtr image(new CrwImage(io, create)); - if (!image->good()) { - image.reset(); - } - return image; - } - - bool isCrwType(BasicIo& iIo, bool advance) - { - bool result = true; - byte tmpBuf[14]; - iIo.read(tmpBuf, 14); - if (iIo.error() || iIo.eof()) { - return false; - } - if (!( ('I' == tmpBuf[0] && 'I' == tmpBuf[1]) - || ('M' == tmpBuf[0] && 'M' == tmpBuf[1]))) { - result = false; - } - if ( true == result - && std::memcmp(tmpBuf + 6, CiffHeader::signature(), 8) != 0) { - result = false; - } - if (!advance || !result) iIo.seek(-14, BasicIo::cur); - return result; - } - DataBuf packIfdId(const ExifData& exifData, IfdId ifdId, ByteOrder byteOrder) @@ -1351,7 +1363,7 @@ namespace Exiv2 { return buf; } -} // namespace Exiv2 +}} // namespace Internal, Exiv2 // ***************************************************************************** // local definitions diff --git a/src/crwimage.hpp b/src/crwimage.hpp index c10203f2..94ebf2c6 100644 --- a/src/crwimage.hpp +++ b/src/crwimage.hpp @@ -20,7 +20,7 @@ */ /*! @file crwimage.hpp - @brief Class CrwImage to access Canon Crw images.
+ @brief Class CrwImage to access Canon CRW images.
References:
The Canon RAW (CRW) File Format by Phil Harvey @version $Rev$ @@ -40,8 +40,6 @@ // + standard includes #include #include -#include -#include // ***************************************************************************** // namespace extensions @@ -51,34 +49,13 @@ namespace Exiv2 { // class declarations class ExifData; class IptcData; - class CiffHeader; - class CiffComponent; - struct CrwMapping; - struct CrwSubDir; - -// ***************************************************************************** -// type definitions - - //! Function pointer for functions to decode Exif tags from a Crw entry - typedef void (*CrwDecodeFct)(const CiffComponent&, - const CrwMapping*, - Image&, - ByteOrder); - - //! Function pointer for functions to encode Crw entries from Exif tags - typedef void (*CrwEncodeFct)(const Image&, - const CrwMapping*, - CiffHeader*); - - //! Stack to hold a path of Crw directories - typedef std::stack CrwDirs; // ***************************************************************************** // class definitions - // Add Crw to the supported image formats + // Add CRW to the supported image formats namespace ImageType { - const int crw = 3; //!< Crw image type (see class CrwImage) + const int crw = 3; //!< CRW image type (see class CrwImage) } /*! @@ -137,687 +114,49 @@ namespace Exiv2 { }; // class CrwImage /*! - Stateless parser class for Canon Crw images (Ciff format). + Stateless parser class for Canon CRW images (Ciff format). */ class CrwParser { public: /*! - @brief Decode metadata from a Canon Crw image in data buffer \em pData + @brief Decode metadata from a Canon CRW image in data buffer \em pData of length \em size into \em crwImage. This is the entry point to access image data in Ciff format. The parser uses classes CiffHeader, CiffEntry, CiffDirectory. - @param pCrwImage Pointer to the %Exiv2 Crw image to hold the metadata + @param pCrwImage Pointer to the %Exiv2 CRW image to hold the metadata read from the buffer. @param pData Pointer to the data buffer. Must point to the data of - a Crw image; no checks are performed. + a CRW image; no checks are performed. @param size Length of the data buffer. @throw Error If the data buffer cannot be parsed. */ static void decode(CrwImage* pCrwImage, const byte* pData, uint32_t size); /*! - @brief Encode metadata from the Crw image into a data buffer (the - binary Crw image). + @brief Encode metadata from the CRW image into a data buffer (the + binary CRW image). @param blob Data buffer for the binary image (target). - @param pCrwImage Pointer to the %Exiv2 Crw image with the metadata to + @param pData Pointer to the binary image data buffer. Must + point to data in CRW format; no checks are + performed. + @param size Length of the data buffer. + @param pCrwImage Pointer to the %Exiv2 CRW image with the metadata to encode. - @param pHead Parse tree containing the existing image. - @throw Error If the metadata from the Crw image cannot be encoded. + @throw Error If the metadata from the CRW image cannot be encoded. */ - static void encode(Blob& blob, CiffHeader* pHead, const CrwImage* pCrwImage); + static void encode( + Blob& blob, + const byte* pData, + uint32_t size, + const CrwImage* pCrwImage + ); }; // class CrwParser - /*! - @brief Interface class for components of the CIFF directory hierarchy of a - Crw (Canon Raw data) image. Both CIFF directories as well as - entries implement this interface. This class is implemented as NVI - (non-virtual interface). - */ - class CiffComponent { - public: - //! CiffComponent auto_ptr type - typedef std::auto_ptr AutoPtr; - //! Container type to hold all metadata - typedef std::vector Components; - - //! @name Creators - //@{ - //! Default constructor - CiffComponent() - : dir_(0), tag_(0), size_(0), offset_(0), pData_(0), - 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), - isAllocated_(false) {} - //! Virtual destructor. - virtual ~CiffComponent(); - //@} - - //! @name Manipulators - //@{ - // Default assignment operator is fine - - //! 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 - - @param pData Pointer to the data buffer. - @param size Number of bytes in the data buffer. - @param start Component starts at \em pData + \em start. - @param byteOrder Applicable byte order (little or big endian). - - @throw Error If the component cannot be parsed. - */ - void read(const byte* pData, - uint32_t size, - uint32_t start, - ByteOrder byteOrder); - /*! - @brief Write the metadata from the raw metadata component to the - binary image \em blob. This method may append to the blob. - - @param blob Binary image to add metadata to - @param byteOrder Byte order - @param offset Current offset - - @return New offset - */ - uint32_t write(Blob& blob, ByteOrder byteOrder, uint32_t offset); - /*! - @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 - of bytes written to the blob even. The offset of the component - is set to the offset passed in. - @param blob The binary image to write to. - @param offset Offset from the start of the directory for this entry. - - @return New offset. - */ - uint32_t writeValueData(Blob& blob, uint32_t offset); - //! Set the directory tag for this component. - void setDir(uint16_t dir) { dir_ = dir; } - //! Set the data value of the entry. - void setValue(DataBuf buf); - //@} - - //! Return the type id for a tag - static TypeId typeId(uint16_t tag); - //! Return the data location id for a tag - static DataLocId dataLocation(uint16_t tag); - - //! @name Accessors - //@{ - /*! - @brief Decode metadata from the component and add it to - \em image. - - @param image Image to add metadata to - @param byteOrder Byte order - */ - void decode(Image& image, ByteOrder byteOrder) const; - /*! - @brief Print debug info about a component to \em os. - - @param os Output stream to write to - @param byteOrder Byte order - @param prefix Prefix to be written before each line of output - */ - void print(std::ostream& os, - ByteOrder byteOrder, - const std::string& prefix ="") const; - /*! - @brief Write a directory entry for the component to the \em blob. - If the size of the data is not larger than 8 bytes, the - data is written to the directory entry. - */ - void writeDirEntry(Blob& blob, ByteOrder byteOrder) const; - //! Return the tag of the directory containing this component - uint16_t dir() const { return dir_; } - - //! 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 - - @note If the data is contained in the directory entry itself, - this method returns 8, which is the maximum number - of data bytes this component can have. The actual size, - i.e., used data bytes, may be less than 8. - */ - uint32_t size() const { return size_; } - - //! Return the offset to the data from the start of the directory - uint32_t offset() const { return offset_; } - - //! Return a pointer to the data area of this component - const byte* pData() const { return pData_; } - - //! Return the tag id of this component - uint16_t tagId() const { return tag_ & 0x3fff; } - - //! Return the type id of thi component - TypeId typeId() const { return typeId(tag_); } - - //! Return the data location for this component - DataLocId dataLocation() const { return dataLocation(tag_); } - - /*! - @brief Finds \em crwTagId in directory \em crwDir, returning a pointer to - the component or 0 if not found. - */ - CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const; - //@} - - protected: - //! @name Manipulators - //@{ - //! 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, - uint32_t start, - ByteOrder byteOrder); - //! Implements write() - virtual uint32_t doWrite(Blob& blob, - ByteOrder byteOrder, - uint32_t offset) =0; - //! Set the size of the data area. - void setSize(uint32_t size) { size_ = size; } - //! Set the offset for this component. - void setOffset(uint32_t offset) { offset_ = offset; } - //@} - - //! @name Accessors - //@{ - //! Implements decode() - virtual void doDecode(Image& image, - ByteOrder byteOrder) const =0; - //! Implements print(). The default implementation prints the entry. - 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 crwTagId, - uint16_t crwDir) const; - //@} - - private: - // DATA - uint16_t dir_; //!< Tag of the directory containing this component - uint16_t tag_; //!< Tag of the entry - 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 isAllocated_; //!< True if this entry owns the value data - - }; // class CiffComponent - - /*! - @brief This class models one directory entry of a CIFF directory of - a Crw (Canon Raw data) image. - */ - class CiffEntry : public CiffComponent { - public: - //! @name Creators - //@{ - //! Default constructor - CiffEntry() {} - //! Constructor taking a tag and directory - CiffEntry(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {} - - //! Virtual destructor. - virtual ~CiffEntry() {} - //@} - - // Default assignment operator is fine - - private: - //! @name Manipulators - //@{ - using CiffComponent::doAdd; - // See base class comment - virtual void doAdd(AutoPtr component); - /*! - @brief Implements write(). Writes only the value data of the entry, - using writeValueData(). - */ - virtual uint32_t doWrite(Blob& blob, - ByteOrder byteOrder, - uint32_t offset); - //@} - - //! @name Accessors - //@{ - // See base class comment - virtual void doDecode(Image& image, ByteOrder byteOrder) const; - //@} - - }; // class CiffEntry - - //! This class models a CIFF directory of a Crw (Canon Raw data) image. - class CiffDirectory : public CiffComponent { - public: - //! @name Creators - //@{ - //! Default constructor - CiffDirectory() {} - //! Constructor taking a tag and directory - CiffDirectory(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {} - - //! Virtual destructor - virtual ~CiffDirectory(); - //@} - - //! @name Manipulators - //@{ - // Default assignment operator is fine - - /*! - @brief Parse a CIFF directory from a memory buffer - - @param pData Pointer to the memory buffer containing the directory - @param size Size of the memory buffer - @param byteOrder Applicable byte order (little or big endian) - */ - void readDirectory(const byte* pData, - uint32_t size, - ByteOrder byteOrder); - //@} - - private: - //! @name Manipulators - //@{ - // 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. - */ - virtual uint32_t doWrite(Blob& blob, - ByteOrder byteOrder, - uint32_t offset); - // See base class comment - virtual void doRead(const byte* pData, - uint32_t size, - uint32_t start, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - // See base class comment - virtual void doDecode(Image& image, - ByteOrder byteOrder) const; - - // See base class comment - 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 crwTagId, - uint16_t crwDir) const; - //@} - - private: - // DATA - Components components_; //!< List of components in this dir - - }; // class CiffDirectory - - /*! - @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 - typedef std::auto_ptr AutoPtr; - - //! @name Creators - //@{ - //! Default constructor - CiffHeader() - : pRootDir_ (0), - byteOrder_ (littleEndian), - offset_ (0x0000001a), - pPadding_ (0), - padded_ (0) - {} - //! Virtual destructor - virtual ~CiffHeader(); - //@} - - //! @name Manipulators - //@{ - /*! - @brief Read the Crw image from a data buffer, starting with the Ciff - header. - - @param pData Pointer to the data buffer. - @param size Number of bytes in the data buffer. - - @throw Error If the image cannot be parsed. - */ - void read(const byte* pData, uint32_t size); - /*! - @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 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. - - @param crwTagId Tag id to be removed. - @param crwDir Parent directory of the tag. - */ - void remove(uint16_t crwTagId, uint16_t crwDir); - //@} - - //! Return a pointer to the Canon Crw signature. - static const char* signature() { return signature_; } - - //! @name Accessors - //@{ - /*! - @brief Write the Crw image to the binary image \em blob, starting with - the Ciff header. This method appends to the blob. - - @param blob Binary image to add to. - - @throw Error If the image cannot be written. - */ - void write(Blob& blob) const; - /*! - @brief Decode the Crw image and add it to \em image. - - Walk the parse tree and convert CIFF entries to metadata - entries which are added to \em image. - - @param image Image to add metadata to - */ - void decode(Image& image) const; - /*! - @brief Print debug info for the Crw image to \em os. - - @param os Output stream to write to. - @param prefix Prefix to be written before each line of output. - */ - void print(std::ostream& os, const std::string& prefix ="") const; - //! Return the byte order (little or big endian). - ByteOrder byteOrder() const { return byteOrder_; } - /*! - @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 crwTagId, uint16_t crwDir) const; - //@} - - private: - // DATA - static const char signature_[]; //!< Canon Crw signature "HEAPCCDR" - - CiffDirectory* pRootDir_; //!< Pointer to the root directory - ByteOrder byteOrder_; //!< Applicable byte order - uint32_t offset_; //!< Offset to the start of the root dir - byte* pPadding_; //!< Pointer to the (unknown) remainder - uint32_t padded_; //!< Number of padding-bytes - - }; // class CiffHeader - - //! Structure for the CIFF directory hierarchy - struct CrwSubDir { - uint16_t crwDir_; //!< Directory tag - uint16_t parent_; //!< Parent directory tag - }; // struct CrwSubDir - - /*! - @brief Structure for a mapping table for conversion of CIFF entries to - image metadata and vice versa. - */ - struct CrwMapping { - //! @name Creators - //@{ - //! Default constructor - CrwMapping( - uint16_t crwTagId, - uint16_t crwDir, - uint32_t size, - uint16_t tag, - IfdId ifdId, - CrwDecodeFct toExif, - CrwEncodeFct fromExif) - : crwTagId_ (crwTagId), - crwDir_ (crwDir), - size_ (size), - tag_ (tag), - ifdId_ (ifdId), - toExif_ (toExif), - fromExif_ (fromExif) - {} - //@} - - // DATA - uint16_t crwTagId_; //!< Crw tag id - uint16_t crwDir_; //!< Crw directory tag - uint32_t size_; //!< Data size (overwrites the size from the entry) - uint16_t tag_; //!< Exif tag to map to - IfdId ifdId_; //!< Exif Ifd id to map to - CrwDecodeFct toExif_; //!< Conversion function - CrwEncodeFct fromExif_; //!< Reverse conversion function - - }; // struct CrwMapping - - /*! - @brief Static class providing mapping functionality from Crw entries - to image metadata and vice versa - */ - class CrwMap { - //! @name Not implemented - //@{ - //! Default constructor - CrwMap(); - //@} - - public: - /*! - @brief Decode image metadata from a Crw entry convert and add it - to the image metadata. This function converts only one Crw - component. - - @param ciffComponent Source CIFF entry - @param image Destination image for the metadata - @param byteOrder Byte order in which the data of the entry - is encoded - */ - static void decode(const CiffComponent& ciffComponent, - Image& image, - ByteOrder byteOrder); - /*! - @brief Encode image metadata from \em image into the Crw parse tree. - This function converts all Exif metadata that %Exiv2 can - convert to Crw format, in a loop through the entries of the - mapping table. - - @param pHead Destination parse tree. - @param image Source image containing the metadata. - */ - static void encode(CiffHeader* pHead, const Image& image); - - /*! - @brief Load the stack: loop through the Crw subdirs hierarchy and push - all directories on the path from \em crwDir to root onto the - stack \em crwDirs. Requires the subdirs array to be arranged in - bottom-up order to be able to finish in only one pass. - */ - static void loadStack(CrwDirs& crwDirs, uint16_t crwDir); - - private: - //! 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 - Exif metadata. - - Uses the mapping defined in the conversion structure \em pCrwMapping - to convert the data. If the \em size field in the conversion structure - is not 0, then it is used instead of the \em size provided by the - entry itself. - */ - static void decodeBasic(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - //! Decode the user comment - static void decode0x0805(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - //! Decode camera Make and Model information - static void decode0x080a(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, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - //! Decode image width and height - static void decode0x1810(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - //! Decode the thumbnail image - static void decode0x2008(const CiffComponent& ciffComponent, - const CrwMapping* pCrwMapping, - Image& image, - ByteOrder byteOrder); - - /*! - @brief Standard encode function to convert Exif metadata to Crw - entries. - - This is the basic encode function taking one Exif key and converting - it to one Ciff entry. Both are available in the \em pCrwMapping passed - in. - - @param image Image with the metadata to encode - @param pCrwMapping Pointer to an entry into the \em crwMapping_ table - with information on the source and target metadata entries. - @param pHead Pointer to the head of the CIFF parse tree into which - the metadata from \em image is encoded. - */ - static void encodeBasic(const Image& image, - const CrwMapping* pCrwMapping, - CiffHeader* pHead); - - //! Encode the user comment - static void encode0x0805(const Image& image, - const CrwMapping* pCrwMapping, - CiffHeader* pHead); - - //! Encode camera Make and Model information - static void encode0x080a(const Image& image, - 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 - static const CrwSubDir crwSubDir_[]; //!< Ciff directory hierarchy - - }; // class CrwMap - // ***************************************************************************** // template, inline and free functions @@ -830,18 +169,9 @@ namespace Exiv2 { */ Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create); - //! Check if the file iIo is a Crw image. + //! 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/src/crwimage_int.hpp b/src/crwimage_int.hpp new file mode 100644 index 00000000..083cbb4c --- /dev/null +++ b/src/crwimage_int.hpp @@ -0,0 +1,749 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2004-2008 Andreas Huggel + * + * This program is part of the Exiv2 distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. + */ +/*! + @file crwimage_int.hpp + @brief Internal classes to support CRW/CIFF format. + @version $Rev$ + @author Andreas Huggel (ahu) + ahuggel@gmx.net + @date 28-Aug-05, ahu: created + */ +#ifndef CRWIMAGE_INT_HPP_ +#define CRWIMAGE_INT_HPP_ + +// ***************************************************************************** +// included header files +#include "types.hpp" +#include "image.hpp" +#include "basicio.hpp" + +// + standard includes +#include +#include +#include +#include + +// ***************************************************************************** +// namespace extensions +namespace Exiv2 { + +// ***************************************************************************** +// class declarations + class ExifData; + + namespace Internal { + +// ***************************************************************************** +// class declarations + class CiffHeader; + class CiffComponent; + struct CrwMapping; + struct CrwSubDir; + +// ***************************************************************************** +// type definitions + + //! Function pointer for functions to decode Exif tags from a CRW entry + typedef void (*CrwDecodeFct)(const CiffComponent&, + const CrwMapping*, + Image&, + ByteOrder); + + //! Function pointer for functions to encode CRW entries from Exif tags + typedef void (*CrwEncodeFct)(const Image&, + const CrwMapping*, + CiffHeader*); + + //! Stack to hold a path of CRW directories + typedef std::stack CrwDirs; + + //! Type to identify where the data is stored in a directory + enum DataLocId { + invalidDataLocId, + valueData, + directoryData, + lastDataLocId + }; + +// ***************************************************************************** +// class definitions + + /*! + @brief Interface class for components of the CIFF directory hierarchy of a + CRW (Canon Raw data) image. Both CIFF directories as well as + entries implement this interface. This class is implemented as NVI + (non-virtual interface). + */ + class CiffComponent { + public: + //! CiffComponent auto_ptr type + typedef std::auto_ptr AutoPtr; + //! Container type to hold all metadata + typedef std::vector Components; + + //! @name Creators + //@{ + //! Default constructor + CiffComponent() + : dir_(0), tag_(0), size_(0), offset_(0), pData_(0), + 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), + isAllocated_(false) {} + //! Virtual destructor. + virtual ~CiffComponent(); + //@} + + //! @name Manipulators + //@{ + // Default assignment operator is fine + + //! 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 + + @param pData Pointer to the data buffer. + @param size Number of bytes in the data buffer. + @param start Component starts at \em pData + \em start. + @param byteOrder Applicable byte order (little or big endian). + + @throw Error If the component cannot be parsed. + */ + void read(const byte* pData, + uint32_t size, + uint32_t start, + ByteOrder byteOrder); + /*! + @brief Write the metadata from the raw metadata component to the + binary image \em blob. This method may append to the blob. + + @param blob Binary image to add metadata to + @param byteOrder Byte order + @param offset Current offset + + @return New offset + */ + uint32_t write(Blob& blob, ByteOrder byteOrder, uint32_t offset); + /*! + @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 + of bytes written to the blob even. The offset of the component + is set to the offset passed in. + @param blob The binary image to write to. + @param offset Offset from the start of the directory for this entry. + + @return New offset. + */ + uint32_t writeValueData(Blob& blob, uint32_t offset); + //! Set the directory tag for this component. + void setDir(uint16_t dir) { dir_ = dir; } + //! Set the data value of the entry. + void setValue(DataBuf buf); + //@} + + //! Return the type id for a tag + static TypeId typeId(uint16_t tag); + //! Return the data location id for a tag + static DataLocId dataLocation(uint16_t tag); + + //! @name Accessors + //@{ + /*! + @brief Decode metadata from the component and add it to + \em image. + + @param image Image to add metadata to + @param byteOrder Byte order + */ + void decode(Image& image, ByteOrder byteOrder) const; + /*! + @brief Print debug info about a component to \em os. + + @param os Output stream to write to + @param byteOrder Byte order + @param prefix Prefix to be written before each line of output + */ + void print(std::ostream& os, + ByteOrder byteOrder, + const std::string& prefix ="") const; + /*! + @brief Write a directory entry for the component to the \em blob. + If the size of the data is not larger than 8 bytes, the + data is written to the directory entry. + */ + void writeDirEntry(Blob& blob, ByteOrder byteOrder) const; + //! Return the tag of the directory containing this component + uint16_t dir() const { return dir_; } + + //! 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 + + @note If the data is contained in the directory entry itself, + this method returns 8, which is the maximum number + of data bytes this component can have. The actual size, + i.e., used data bytes, may be less than 8. + */ + uint32_t size() const { return size_; } + + //! Return the offset to the data from the start of the directory + uint32_t offset() const { return offset_; } + + //! Return a pointer to the data area of this component + const byte* pData() const { return pData_; } + + //! Return the tag id of this component + uint16_t tagId() const { return tag_ & 0x3fff; } + + //! Return the type id of thi component + TypeId typeId() const { return typeId(tag_); } + + //! Return the data location for this component + DataLocId dataLocation() const { return dataLocation(tag_); } + + /*! + @brief Finds \em crwTagId in directory \em crwDir, returning a pointer to + the component or 0 if not found. + */ + CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const; + //@} + + protected: + //! @name Manipulators + //@{ + //! 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, + uint32_t start, + ByteOrder byteOrder); + //! Implements write() + virtual uint32_t doWrite(Blob& blob, + ByteOrder byteOrder, + uint32_t offset) =0; + //! Set the size of the data area. + void setSize(uint32_t size) { size_ = size; } + //! Set the offset for this component. + void setOffset(uint32_t offset) { offset_ = offset; } + //@} + + //! @name Accessors + //@{ + //! Implements decode() + virtual void doDecode(Image& image, + ByteOrder byteOrder) const =0; + //! Implements print(). The default implementation prints the entry. + 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 crwTagId, + uint16_t crwDir) const; + //@} + + private: + // DATA + uint16_t dir_; //!< Tag of the directory containing this component + uint16_t tag_; //!< Tag of the entry + 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 isAllocated_; //!< True if this entry owns the value data + + }; // class CiffComponent + + /*! + @brief This class models one directory entry of a CIFF directory of + a CRW (Canon Raw data) image. + */ + class CiffEntry : public CiffComponent { + public: + //! @name Creators + //@{ + //! Default constructor + CiffEntry() {} + //! Constructor taking a tag and directory + CiffEntry(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {} + + //! Virtual destructor. + virtual ~CiffEntry() {} + //@} + + // Default assignment operator is fine + + private: + //! @name Manipulators + //@{ + using CiffComponent::doAdd; + // See base class comment + virtual void doAdd(AutoPtr component); + /*! + @brief Implements write(). Writes only the value data of the entry, + using writeValueData(). + */ + virtual uint32_t doWrite(Blob& blob, + ByteOrder byteOrder, + uint32_t offset); + //@} + + //! @name Accessors + //@{ + // See base class comment + virtual void doDecode(Image& image, ByteOrder byteOrder) const; + //@} + + }; // class CiffEntry + + //! This class models a CIFF directory of a CRW (Canon Raw data) image. + class CiffDirectory : public CiffComponent { + public: + //! @name Creators + //@{ + //! Default constructor + CiffDirectory() {} + //! Constructor taking a tag and directory + CiffDirectory(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {} + + //! Virtual destructor + virtual ~CiffDirectory(); + //@} + + //! @name Manipulators + //@{ + // Default assignment operator is fine + + /*! + @brief Parse a CIFF directory from a memory buffer + + @param pData Pointer to the memory buffer containing the directory + @param size Size of the memory buffer + @param byteOrder Applicable byte order (little or big endian) + */ + void readDirectory(const byte* pData, + uint32_t size, + ByteOrder byteOrder); + //@} + + private: + //! @name Manipulators + //@{ + // 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. + */ + virtual uint32_t doWrite(Blob& blob, + ByteOrder byteOrder, + uint32_t offset); + // See base class comment + virtual void doRead(const byte* pData, + uint32_t size, + uint32_t start, + ByteOrder byteOrder); + //@} + + //! @name Accessors + //@{ + // See base class comment + virtual void doDecode(Image& image, + ByteOrder byteOrder) const; + + // See base class comment + 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 crwTagId, + uint16_t crwDir) const; + //@} + + private: + // DATA + Components components_; //!< List of components in this dir + + }; // class CiffDirectory + + /*! + @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 + typedef std::auto_ptr AutoPtr; + + //! @name Creators + //@{ + //! Default constructor + CiffHeader() + : pRootDir_ (0), + byteOrder_ (littleEndian), + offset_ (0x0000001a), + pPadding_ (0), + padded_ (0) + {} + //! Virtual destructor + virtual ~CiffHeader(); + //@} + + //! @name Manipulators + //@{ + /*! + @brief Read the CRW image from a data buffer, starting with the Ciff + header. + + @param pData Pointer to the data buffer. + @param size Number of bytes in the data buffer. + + @throw Error If the image cannot be parsed. + */ + void read(const byte* pData, uint32_t size); + /*! + @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 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. + + @param crwTagId Tag id to be removed. + @param crwDir Parent directory of the tag. + */ + void remove(uint16_t crwTagId, uint16_t crwDir); + //@} + + //! Return a pointer to the Canon CRW signature. + static const char* signature() { return signature_; } + + //! @name Accessors + //@{ + /*! + @brief Write the CRW image to the binary image \em blob, starting with + the Ciff header. This method appends to the blob. + + @param blob Binary image to add to. + + @throw Error If the image cannot be written. + */ + void write(Blob& blob) const; + /*! + @brief Decode the CRW image and add it to \em image. + + Walk the parse tree and convert CIFF entries to metadata + entries which are added to \em image. + + @param image Image to add metadata to + */ + void decode(Image& image) const; + /*! + @brief Print debug info for the CRW image to \em os. + + @param os Output stream to write to. + @param prefix Prefix to be written before each line of output. + */ + void print(std::ostream& os, const std::string& prefix ="") const; + //! Return the byte order (little or big endian). + ByteOrder byteOrder() const { return byteOrder_; } + /*! + @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 crwTagId, uint16_t crwDir) const; + //@} + + private: + // DATA + static const char signature_[]; //!< Canon CRW signature "HEAPCCDR" + + CiffDirectory* pRootDir_; //!< Pointer to the root directory + ByteOrder byteOrder_; //!< Applicable byte order + uint32_t offset_; //!< Offset to the start of the root dir + byte* pPadding_; //!< Pointer to the (unknown) remainder + uint32_t padded_; //!< Number of padding-bytes + + }; // class CiffHeader + + //! Structure for the CIFF directory hierarchy + struct CrwSubDir { + uint16_t crwDir_; //!< Directory tag + uint16_t parent_; //!< Parent directory tag + }; // struct CrwSubDir + + /*! + @brief Structure for a mapping table for conversion of CIFF entries to + image metadata and vice versa. + */ + struct CrwMapping { + //! @name Creators + //@{ + //! Default constructor + CrwMapping( + uint16_t crwTagId, + uint16_t crwDir, + uint32_t size, + uint16_t tag, + IfdId ifdId, + CrwDecodeFct toExif, + CrwEncodeFct fromExif) + : crwTagId_ (crwTagId), + crwDir_ (crwDir), + size_ (size), + tag_ (tag), + ifdId_ (ifdId), + toExif_ (toExif), + fromExif_ (fromExif) + {} + //@} + + // DATA + uint16_t crwTagId_; //!< CRW tag id + uint16_t crwDir_; //!< CRW directory tag + uint32_t size_; //!< Data size (overwrites the size from the entry) + uint16_t tag_; //!< Exif tag to map to + IfdId ifdId_; //!< Exif Ifd id to map to + CrwDecodeFct toExif_; //!< Conversion function + CrwEncodeFct fromExif_; //!< Reverse conversion function + + }; // struct CrwMapping + + /*! + @brief Static class providing mapping functionality from CRW entries + to image metadata and vice versa + */ + class CrwMap { + //! @name Not implemented + //@{ + //! Default constructor + CrwMap(); + //@} + + public: + /*! + @brief Decode image metadata from a CRW entry, convert and add it + to the image metadata. This function converts only one CRW + component. + + @param ciffComponent Source CIFF entry + @param image Destination image for the metadata + @param byteOrder Byte order in which the data of the entry + is encoded + */ + static void decode(const CiffComponent& ciffComponent, + Image& image, + ByteOrder byteOrder); + /*! + @brief Encode image metadata from \em image into the CRW parse tree. + This function converts all Exif metadata that %Exiv2 can + convert to CRW format, in a loop through the entries of the + mapping table. + + @param pHead Destination parse tree. + @param image Source image containing the metadata. + */ + static void encode(CiffHeader* pHead, const Image& image); + + /*! + @brief Load the stack: loop through the CRW subdirs hierarchy and push + all directories on the path from \em crwDir to root onto the + stack \em crwDirs. Requires the subdirs array to be arranged in + bottom-up order to be able to finish in only one pass. + */ + static void loadStack(CrwDirs& crwDirs, uint16_t crwDir); + + private: + //! 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 + Exif metadata. + + Uses the mapping defined in the conversion structure \em pCrwMapping + to convert the data. If the \em size field in the conversion structure + is not 0, then it is used instead of the \em size provided by the + entry itself. + */ + static void decodeBasic(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); + + //! Decode the user comment + static void decode0x0805(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); + + //! Decode camera Make and Model information + static void decode0x080a(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, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); + + //! Decode image width and height + static void decode0x1810(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); + + //! Decode the thumbnail image + static void decode0x2008(const CiffComponent& ciffComponent, + const CrwMapping* pCrwMapping, + Image& image, + ByteOrder byteOrder); + + /*! + @brief Standard encode function to convert Exif metadata to Crw + entries. + + This is the basic encode function taking one Exif key and converting + it to one Ciff entry. Both are available in the \em pCrwMapping passed + in. + + @param image Image with the metadata to encode + @param pCrwMapping Pointer to an entry into the \em crwMapping_ table + with information on the source and target metadata entries. + @param pHead Pointer to the head of the CIFF parse tree into which + the metadata from \em image is encoded. + */ + static void encodeBasic(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); + + //! Encode the user comment + static void encode0x0805(const Image& image, + const CrwMapping* pCrwMapping, + CiffHeader* pHead); + + //! Encode camera Make and Model information + static void encode0x080a(const Image& image, + 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 + static const CrwSubDir crwSubDir_[]; //!< Ciff directory hierarchy + + }; // class CrwMap + +// ***************************************************************************** +// template, inline and free functions + + /*! + @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 Internal, Exiv2 + +#endif // #ifndef CRWIMAGE_INT_HPP_ diff --git a/samples/crwparse.cpp b/src/crwparse.cpp similarity index 87% rename from samples/crwparse.cpp rename to src/crwparse.cpp index e844fe89..bb25387c 100644 --- a/samples/crwparse.cpp +++ b/src/crwparse.cpp @@ -2,8 +2,9 @@ // crwparse.cpp, $Rev$ // Print the CIFF structure of a CRW file -#include -#include +#include "crwimage.hpp" +#include "crwimage_int.hpp" +#include "futils.hpp" #include @@ -34,7 +35,7 @@ try { 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); + Exiv2::Internal::CiffHeader::AutoPtr parseTree(new Exiv2::Internal::CiffHeader); parseTree->read(buf.pData_, buf.size_); parseTree->print(std::cout); diff --git a/src/datasets.hpp b/src/datasets.hpp index 25c43c48..59f0c1dc 100644 --- a/src/datasets.hpp +++ b/src/datasets.hpp @@ -46,7 +46,7 @@ namespace Exiv2 { // ***************************************************************************** // class definitions - //! Contains information about one record + //! Details of an IPTC record. struct RecordInfo { //! Constructor RecordInfo(uint16_t recordId, const char* name, const char* desc); @@ -55,7 +55,7 @@ namespace Exiv2 { const char* desc_; //!< Record description }; - //! Dataset information + //! Details of an IPTC dataset. struct DataSet { //! Constructor DataSet( @@ -84,7 +84,7 @@ namespace Exiv2 { const char* photoshop_; //!< Photoshop string }; // struct DataSet - //! Container for IPTC dataset information. Implemented as a static class. + //! IPTC dataset reference, implemented as a static class. class IptcDataSets { public: /*! diff --git a/src/error.hpp b/src/error.hpp index b1086ad7..6b97fbe0 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -46,7 +46,7 @@ namespace Exiv2 { // ***************************************************************************** // class definitions - //! Helper structure defining an error message + //! Helper structure defining an error message. struct ErrMsg { //! Constructor ErrMsg(int code, const char* message) diff --git a/src/exif.hpp b/src/exif.hpp index 68958b7f..d0c62529 100644 --- a/src/exif.hpp +++ b/src/exif.hpp @@ -57,8 +57,8 @@ namespace Exiv2 { // class definitions /*! - @brief Information related to one Exif tag. An Exif metadatum consists of - an ExifKey and a Value and provides methods to manipulate these. + @brief An Exif metadatum, consisting of an ExifKey and a Value and + methods to manipulate these. */ class Exifdatum : public Metadatum { template friend Exifdatum& setValue(Exifdatum&, const T&); diff --git a/src/iptc.hpp b/src/iptc.hpp index 084f28e1..1d454337 100644 --- a/src/iptc.hpp +++ b/src/iptc.hpp @@ -49,8 +49,8 @@ namespace Exiv2 { // class definitions /*! - @brief Information related to one IPTC dataset. An IPTC metadatum consists - of an IptcKey and a Value and provides methods to manipulate these. + @brief An IPTC metadatum ("dataset"), consisting of an IptcKey and a + Value and methods to manipulate these. */ class Iptcdatum : public Metadatum { public: diff --git a/src/properties.cpp b/src/properties.cpp index 97bacd53..ea1b99ff 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -46,10 +46,28 @@ EXIV2_RCSID("@(#) $Id$") #include #include +// ***************************************************************************** +namespace { + + //! Struct used in the lookup table for pretty print functions + struct XmpPrintInfo { + //! Comparison operator for key + bool operator==(const std::string& key) const + { + return std::string(key_) == key; + } + + const char* key_; //!< XMP key + Exiv2::PrintFct printFct_; //!< Print function + }; + +} + // ***************************************************************************** // class member definitions namespace Exiv2 { + //! @cond IGNORE extern const XmpPropertyInfo xmpDcInfo[]; extern const XmpPropertyInfo xmpDigikamInfo[]; extern const XmpPropertyInfo xmpXmpInfo[]; @@ -690,11 +708,6 @@ namespace Exiv2 { return n == name; } - bool XmpPrintInfo::operator==(const std::string& key) const - { - return std::string(key_) == key; - } - XmpProperties::NsRegistry XmpProperties::nsRegistry_; const XmpNsInfo* XmpProperties::lookupNsRegistry(const XmpNsInfo::Prefix& prefix) @@ -985,5 +998,6 @@ namespace Exiv2 { << ( property.xmpCategory_ == xmpExternal ? "External" : "Internal" ) << ",\t" << property.desc_ << "\n"; } + //! @endcond } // namespace Exiv2 diff --git a/src/properties.hpp b/src/properties.hpp index 71ef3a22..350d033f 100644 --- a/src/properties.hpp +++ b/src/properties.hpp @@ -71,15 +71,6 @@ namespace Exiv2 { const char* desc_; //!< Property description }; - //! Struct used in the lookup table for pretty print functions - struct XmpPrintInfo { - //! Comparison operator for key - bool operator==(const std::string& key) const; - - const char* key_; //!< XMP key - PrintFct printFct_; //!< Print function - }; - //! Structure mapping XMP namespaces and (preferred) prefixes. struct XmpNsInfo { //! For comparison with prefix @@ -107,7 +98,7 @@ namespace Exiv2 { const char* desc_; //!< Brief description of the namespace }; - //! Container for XMP property information. Implemented as a static class. + //! XMP property reference, implemented as a static class. class XmpProperties { //! Prevent construction: not implemented. XmpProperties(); diff --git a/src/tags.hpp b/src/tags.hpp index 43ab9e47..9f39bbc3 100644 --- a/src/tags.hpp +++ b/src/tags.hpp @@ -72,7 +72,7 @@ namespace Exiv2 { // ***************************************************************************** // class definitions - //! Contains information pertaining to one IFD + //! The details of an IFD. struct IfdInfo { struct Item; bool operator==(IfdId ifdId) const; //!< Comparison operator for IFD id @@ -90,7 +90,7 @@ namespace Exiv2 { std::string i_; //!< IFD item }; - //! Contains information pertaining to one section + //! The details of a section. struct SectionInfo { SectionId sectionId_; //!< Section id const char* name_; //!< Section name (one word) @@ -190,7 +190,7 @@ namespace Exiv2 { //! Shortcut for the printTagBitmask template which requires typing the array name only once. #define EXV_PRINT_TAG_BITMASK(array) printTagBitmask - //! Container for Exif tag information. Implemented as a static class. + //! Exif tag reference, implemented as a static class. class ExifTags { //! Prevent construction: not implemented. ExifTags(); diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index 857ffabd..13ba804a 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -59,7 +59,6 @@ EXIV2_RCSID("@(#) $Id$") Todo: - + Support all TIFF data types + Review boundary checking, is it better to check the offsets? + Define and implement consistent error handling for recursive hierarchy + Make TiffImage a template StandardImage, which can be parametrized with @@ -83,9 +82,6 @@ EXIV2_RCSID("@(#) $Id$") + Fix CiffHeader according to TiffHeade2 + Combine Error(15) and Error(33), add format argument %1 + Search crwimage for todos, fix writeMetadata comment - + Add Ciff components to TIFF component hierarchy - + rename all Ciff stuff to Crw for easier reference - not needed when CIFF - components are part of the TIFF hierarchy + rename loadStack to getPath for consistency -------------------------------------------------------------------------- */ diff --git a/src/types.hpp b/src/types.hpp index 9a6cbe22..2eb5984b 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -132,7 +132,6 @@ namespace Exiv2 { lastTypeId =0x1ffff //!< Last type id. }; - // Todo: decentralize IfdId, so that new ids can be defined elsewhere //! Type to specify the IFD to which a metadata belongs enum IfdId { ifdIdNotSet, ifd0Id, exifIfdId, gpsIfdId, iopIfdId, ifd1Id, @@ -145,11 +144,6 @@ namespace Exiv2 { olympusIfdId, panasonicIfdId, pentaxIfdId, sigmaIfdId, sonyIfdId, lastIfdId }; - //! Type to identify where the data is stored in a directory - enum DataLocId { invalidDataLocId, - valueData, directoryData, - lastDataLocId }; - //! Container for binary data typedef std::vector Blob; diff --git a/test/crw-test.sh b/test/crw-test.sh index 97bf62f0..ebebabc5 100755 --- a/test/crw-test.sh +++ b/test/crw-test.sh @@ -16,7 +16,7 @@ fi # ---------------------------------------------------------------------- # Main routine ( -binpath="$VALGRIND ../../samples" +binpath="$VALGRIND ../../src" exiv2="$VALGRIND exiv2" cmdfile=cmdfile crwfile=exiv2-canon-powershot-s40.crw