Blame src/crwimage_int.hpp

Packit 01d647
// ***************************************************************** -*- C++ -*-
Packit 01d647
/*
Packit 01d647
 * Copyright (C) 2004-2018 Exiv2 authors
Packit 01d647
 * This program is part of the Exiv2 distribution.
Packit 01d647
 *
Packit 01d647
 * This program is free software; you can redistribute it and/or
Packit 01d647
 * modify it under the terms of the GNU General Public License
Packit 01d647
 * as published by the Free Software Foundation; either version 2
Packit 01d647
 * of the License, or (at your option) any later version.
Packit 01d647
 *
Packit 01d647
 * This program is distributed in the hope that it will be useful,
Packit 01d647
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 01d647
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 01d647
 * GNU General Public License for more details.
Packit 01d647
 *
Packit 01d647
 * You should have received a copy of the GNU General Public License
Packit 01d647
 * along with this program; if not, write to the Free Software
Packit 01d647
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit 01d647
 */
Packit 01d647
/*!
Packit 01d647
  @file    crwimage_int.hpp
Packit 01d647
  @brief   Internal classes to support CRW/CIFF format.
Packit 01d647
  @author  Andreas Huggel (ahu)
Packit 01d647
           ahuggel@gmx.net
Packit 01d647
  @date    28-Aug-05, ahu: created
Packit 01d647
 */
Packit 01d647
#ifndef CRWIMAGE_INT_HPP_
Packit 01d647
#define CRWIMAGE_INT_HPP_
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// included header files
Packit 01d647
#include "tags_int.hpp"
Packit 01d647
#include "image.hpp"
Packit 01d647
Packit 01d647
// + standard includes
Packit 01d647
#include <iosfwd>
Packit 01d647
#include <string>
Packit 01d647
#include <vector>
Packit 01d647
#include <stack>
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// namespace extensions
Packit 01d647
namespace Exiv2 {
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class declarations
Packit 01d647
    class ExifData;
Packit 01d647
Packit 01d647
    namespace Internal {
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class declarations
Packit 01d647
    class CiffHeader;
Packit 01d647
    class CiffComponent;
Packit 01d647
    struct CrwMapping;
Packit 01d647
    struct CrwSubDir;
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// type definitions
Packit 01d647
Packit 01d647
    //! Function pointer for functions to decode Exif tags from a CRW entry
Packit 01d647
    typedef void (*CrwDecodeFct)(const CiffComponent&,
Packit 01d647
                                 const CrwMapping*,
Packit 01d647
                                 Image&,
Packit 01d647
                                 ByteOrder);
Packit 01d647
Packit 01d647
    //! Function pointer for functions to encode CRW entries from Exif tags
Packit 01d647
    typedef void (*CrwEncodeFct)(const Image&,
Packit 01d647
                                 const CrwMapping*,
Packit 01d647
                                 CiffHeader*);
Packit 01d647
Packit 01d647
    //! Stack to hold a path of CRW directories
Packit 01d647
    typedef std::stack<CrwSubDir> CrwDirs;
Packit 01d647
Packit 01d647
    //! Type to identify where the data is stored in a directory
Packit 01d647
    enum DataLocId {
Packit 01d647
        valueData,
Packit 01d647
        directoryData,
Packit 01d647
        lastDataLocId
Packit 01d647
    };
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class definitions
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Interface class for components of the CIFF directory hierarchy of a
Packit 01d647
             CRW (Canon Raw data) image. Both CIFF directories as well as
Packit 01d647
             entries implement this interface. This class is implemented as NVI
Packit 01d647
             (non-virtual interface).
Packit 01d647
     */
Packit 01d647
    class CiffComponent {
Packit 01d647
    public:
Packit 01d647
        //! CiffComponent auto_ptr type
Packit 01d647
        typedef std::auto_ptr<CiffComponent> AutoPtr;
Packit 01d647
        //! Container type to hold all metadata
Packit 01d647
        typedef std::vector<CiffComponent*> Components;
Packit 01d647
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CiffComponent()
Packit 01d647
            : dir_(0), tag_(0), size_(0), offset_(0), pData_(0),
Packit 01d647
              isAllocated_(false) {}
Packit 01d647
        //! Constructor taking a tag and directory
Packit 01d647
        CiffComponent(uint16_t tag, uint16_t dir)
Packit 01d647
            : dir_(dir), tag_(tag), size_(0), offset_(0), pData_(0),
Packit 01d647
              isAllocated_(false) {}
Packit 01d647
        //! Virtual destructor.
Packit 01d647
        virtual ~CiffComponent();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        // Default assignment operator is fine
Packit 01d647
Packit 01d647
        //! Add a component to the composition
Packit 01d647
        void add(AutoPtr component);
Packit 01d647
        /*!
Packit 01d647
          @brief Add \em crwTagId to the parse tree, if it doesn't exist
Packit 01d647
                 yet. \em crwDirs contains the path of subdirectories, starting
Packit 01d647
                 with the root directory, leading to \em crwTagId. Directories
Packit 01d647
                 that don't exist yet are added along the way. Returns a pointer
Packit 01d647
                 to the newly added component.
Packit 01d647
Packit 01d647
          @param crwDirs   Subdirectory path from root to the subdirectory
Packit 01d647
                           containing the tag to be added.
Packit 01d647
          @param crwTagId  Tag to be added.
Packit 01d647
Packit 01d647
          @return A pointer to the newly added component.
Packit 01d647
         */
Packit 01d647
        CiffComponent* add(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        /*!
Packit 01d647
          @brief Remove \em crwTagId from the parse tree, if it exists yet. \em
Packit 01d647
                 crwDirs contains the path of subdirectories, starting with the
Packit 01d647
                 root directory, leading to \em crwTagId.
Packit 01d647
Packit 01d647
          @param crwDirs   Subdirectory path from root to the subdirectory
Packit 01d647
                           containing the tag to be removed.
Packit 01d647
          @param crwTagId  Tag to be removed.
Packit 01d647
         */
Packit 01d647
        void remove(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        /*!
Packit 01d647
          @brief Read a component from a data buffer
Packit 01d647
Packit 01d647
          @param pData     Pointer to the data buffer.
Packit 01d647
          @param size      Number of bytes in the data buffer.
Packit 01d647
          @param start     Component starts at \em pData + \em start.
Packit 01d647
          @param byteOrder Applicable byte order (little or big endian).
Packit 01d647
Packit 01d647
          @throw Error If the component cannot be parsed.
Packit 01d647
         */
Packit 01d647
        void read(const byte* pData,
Packit 01d647
                  uint32_t    size,
Packit 01d647
                  uint32_t    start,
Packit 01d647
                  ByteOrder   byteOrder);
Packit 01d647
        /*!
Packit 01d647
          @brief Write the metadata from the raw metadata component to the
Packit 01d647
                 binary image \em blob. This method may append to the blob.
Packit 01d647
Packit 01d647
          @param blob      Binary image to add metadata to
Packit 01d647
          @param byteOrder Byte order
Packit 01d647
          @param offset    Current offset
Packit 01d647
Packit 01d647
          @return New offset
Packit 01d647
         */
Packit 01d647
        uint32_t write(Blob& blob, ByteOrder byteOrder, uint32_t offset);
Packit 01d647
        /*!
Packit 01d647
          @brief Writes the entry's value if size is larger than eight bytes. If
Packit 01d647
                 needed, the value is padded with one 0 byte to make the number
Packit 01d647
                 of bytes written to the blob even. The offset of the component
Packit 01d647
                 is set to the offset passed in.
Packit 01d647
          @param blob The binary image to write to.
Packit 01d647
          @param offset Offset from the start of the directory for this entry.
Packit 01d647
Packit 01d647
          @return New offset.
Packit 01d647
         */
Packit 01d647
        uint32_t writeValueData(Blob& blob, uint32_t offset);
Packit 01d647
        //! Set the directory tag for this component.
Packit 01d647
        void setDir(uint16_t dir)       { dir_ = dir; }
Packit 01d647
        //! Set the data value of the entry.
Packit 01d647
        void setValue(DataBuf buf);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! Return the type id for a tag
Packit 01d647
        static TypeId typeId(uint16_t tag);
Packit 01d647
        //! Return the data location id for a tag
Packit 01d647
        static DataLocId dataLocation(uint16_t tag);
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        /*!
Packit 01d647
          @brief Decode metadata from the component and add it to
Packit 01d647
                 \em image.
Packit 01d647
Packit 01d647
          @param image Image to add metadata to
Packit 01d647
          @param byteOrder Byte order
Packit 01d647
         */
Packit 01d647
        void decode(Image& image, ByteOrder byteOrder) const;
Packit 01d647
        /*!
Packit 01d647
          @brief Print debug info about a component to \em os.
Packit 01d647
Packit 01d647
          @param os Output stream to write to
Packit 01d647
          @param byteOrder Byte order
Packit 01d647
          @param prefix Prefix to be written before each line of output
Packit 01d647
         */
Packit 01d647
        void print(std::ostream& os,
Packit 01d647
                   ByteOrder byteOrder,
Packit 01d647
                   const std::string& prefix ="") const;
Packit 01d647
        /*!
Packit 01d647
          @brief Write a directory entry for the component to the \em blob.
Packit 01d647
                 If the size of the data is not larger than 8 bytes, the
Packit 01d647
                 data is written to the directory entry.
Packit 01d647
         */
Packit 01d647
        void writeDirEntry(Blob& blob, ByteOrder byteOrder) const;
Packit 01d647
        //! Return the tag of the directory containing this component
Packit 01d647
        uint16_t dir()           const { return dir_; }
Packit 01d647
Packit 01d647
        //! Return the tag of this component
Packit 01d647
        uint16_t tag()           const { return tag_; }
Packit 01d647
Packit 01d647
        //! Return true if the component is empty, else false
Packit 01d647
        bool empty()             const;
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Return the data size of this component
Packit 01d647
Packit 01d647
          @note If the data is contained in the directory entry itself,
Packit 01d647
                this method returns 8, which is the maximum number
Packit 01d647
                of data bytes this component can have. The actual size,
Packit 01d647
                i.e., used data bytes, may be less than 8.
Packit 01d647
         */
Packit 01d647
        uint32_t size()          const { return size_; }
Packit 01d647
Packit 01d647
        //! Return the offset to the data from the start of the directory
Packit 01d647
        uint32_t offset()        const { return offset_; }
Packit 01d647
Packit 01d647
        //! Return a pointer to the data area of this component
Packit 01d647
        const byte* pData()      const { return pData_; }
Packit 01d647
Packit 01d647
        //! Return the tag id of this component
Packit 01d647
        uint16_t tagId()         const { return tag_ & 0x3fff; }
Packit 01d647
Packit 01d647
        //! Return the type id of thi component
Packit 01d647
        TypeId typeId()          const { return typeId(tag_); }
Packit 01d647
Packit 01d647
        //! Return the data location for this component
Packit 01d647
        DataLocId dataLocation() const { return dataLocation(tag_); }
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Finds \em crwTagId in directory \em crwDir, returning a pointer to
Packit 01d647
                 the component or 0 if not found.
Packit 01d647
         */
Packit 01d647
        CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    protected:
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        //! Implements add()
Packit 01d647
        virtual void doAdd(AutoPtr component) =0;
Packit 01d647
        //! Implements add(). The default implementation does nothing.
Packit 01d647
        virtual CiffComponent* doAdd(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        //! Implements remove(). The default implementation does nothing.
Packit 01d647
        virtual void doRemove(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        //! Implements read(). The default implementation reads a directory entry.
Packit 01d647
        virtual void doRead(const byte* pData,
Packit 01d647
                            uint32_t    size,
Packit 01d647
                            uint32_t    start,
Packit 01d647
                            ByteOrder   byteOrder);
Packit 01d647
        //! Implements write()
Packit 01d647
        virtual uint32_t doWrite(Blob&     blob,
Packit 01d647
                                 ByteOrder byteOrder,
Packit 01d647
                                 uint32_t  offset) =0;
Packit 01d647
        //! Set the size of the data area.
Packit 01d647
        void setSize(uint32_t size)        { size_ = size; }
Packit 01d647
        //! Set the offset for this component.
Packit 01d647
        void setOffset(uint32_t offset)    { offset_ = offset; }
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        //! Implements decode()
Packit 01d647
        virtual void doDecode(Image& image,
Packit 01d647
                               ByteOrder byteOrder) const =0;
Packit 01d647
        //! Implements print(). The default implementation prints the entry.
Packit 01d647
        virtual void doPrint(std::ostream&      os,
Packit 01d647
                             ByteOrder          byteOrder,
Packit 01d647
                             const std::string& prefix) const;
Packit 01d647
        //! Implements empty(). Default implementation returns true if size is 0.
Packit 01d647
        virtual bool doEmpty() const;
Packit 01d647
        //! Implements findComponent(). The default implementation checks the entry.
Packit 01d647
        virtual CiffComponent* doFindComponent(uint16_t crwTagId,
Packit 01d647
                                               uint16_t crwDir) const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        // DATA
Packit 01d647
        uint16_t    dir_;         //!< Tag of the directory containing this component
Packit 01d647
        uint16_t    tag_;         //!< Tag of the entry
Packit 01d647
        uint32_t    size_;        //!< Size of the data area
Packit 01d647
        uint32_t    offset_;      //!< Offset to the data area from start of dir
Packit 01d647
        const byte* pData_;       //!< Pointer to the data area
Packit 01d647
        bool        isAllocated_; //!< True if this entry owns the value data
Packit 01d647
Packit 01d647
    }; // class CiffComponent
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief This class models one directory entry of a CIFF directory of
Packit 01d647
             a CRW (Canon Raw data) image.
Packit 01d647
     */
Packit 01d647
    class CiffEntry : public CiffComponent {
Packit 01d647
    public:
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CiffEntry() {}
Packit 01d647
        //! Constructor taking a tag and directory
Packit 01d647
        CiffEntry(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir) {}
Packit 01d647
Packit 01d647
        //! Virtual destructor.
Packit 01d647
        virtual ~CiffEntry();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        // Default assignment operator is fine
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        using CiffComponent::doAdd;
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doAdd(AutoPtr component);
Packit 01d647
        /*!
Packit 01d647
          @brief Implements write(). Writes only the value data of the entry,
Packit 01d647
                 using writeValueData().
Packit 01d647
         */
Packit 01d647
        virtual uint32_t doWrite(Blob&     blob,
Packit 01d647
                                 ByteOrder byteOrder,
Packit 01d647
                                 uint32_t  offset);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doDecode(Image& image, ByteOrder byteOrder) const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    }; // class CiffEntry
Packit 01d647
Packit 01d647
    //! This class models a CIFF directory of a CRW (Canon Raw data) image.
Packit 01d647
    class CiffDirectory : public CiffComponent {
Packit 01d647
    public:
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CiffDirectory() : cc_(NULL) {}
Packit 01d647
        //! Constructor taking a tag and directory
Packit 01d647
        CiffDirectory(uint16_t tag, uint16_t dir) : CiffComponent(tag, dir), cc_(NULL) {}
Packit 01d647
Packit 01d647
        //! Virtual destructor
Packit 01d647
        virtual ~CiffDirectory();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        // Default assignment operator is fine
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Parse a CIFF directory from a memory buffer
Packit 01d647
Packit 01d647
          @param pData     Pointer to the memory buffer containing the directory
Packit 01d647
          @param size      Size of the memory buffer
Packit 01d647
          @param byteOrder Applicable byte order (little or big endian)
Packit 01d647
         */
Packit 01d647
        void readDirectory(const byte* pData,
Packit 01d647
                           uint32_t    size,
Packit 01d647
                           ByteOrder   byteOrder);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doAdd(AutoPtr component);
Packit 01d647
        // See base class comment
Packit 01d647
        virtual CiffComponent* doAdd(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doRemove(CrwDirs& crwDirs, uint16_t crwTagId);
Packit 01d647
        /*!
Packit 01d647
          @brief Implements write(). Writes the complete Ciff directory to
Packit 01d647
                 the blob.
Packit 01d647
         */
Packit 01d647
        virtual uint32_t doWrite(Blob&     blob,
Packit 01d647
                                 ByteOrder byteOrder,
Packit 01d647
                                 uint32_t  offset);
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doRead(const byte* pData,
Packit 01d647
                            uint32_t    size,
Packit 01d647
                            uint32_t    start,
Packit 01d647
                            ByteOrder   byteOrder);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doDecode(Image&    image,
Packit 01d647
                              ByteOrder byteOrder) const;
Packit 01d647
Packit 01d647
        // See base class comment
Packit 01d647
        virtual void doPrint(std::ostream&      os,
Packit 01d647
                             ByteOrder          byteOrder,
Packit 01d647
                             const std::string& prefix) const;
Packit 01d647
Packit 01d647
        //! See base class comment. A directory is empty if it has no components.
Packit 01d647
        virtual bool doEmpty() const;
Packit 01d647
Packit 01d647
        // See base class comment
Packit 01d647
        virtual CiffComponent* doFindComponent(uint16_t crwTagId,
Packit 01d647
                                               uint16_t crwDir) const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        // DATA
Packit 01d647
        Components components_; //!< List of components in this dir
Packit 01d647
        AutoPtr    m_; // used by recursive doAdd
Packit 01d647
        CiffComponent* cc_;
Packit 01d647
Packit 01d647
    }; // class CiffDirectory
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief This class models the header of a CRW (Canon Raw data) image.  It
Packit 01d647
             is the head of a CIFF parse tree, consisting of CiffDirectory and
Packit 01d647
             CiffEntry objects. Most of its methods will walk the parse tree to
Packit 01d647
             perform the requested action.
Packit 01d647
     */
Packit 01d647
    class CiffHeader {
Packit 01d647
    public:
Packit 01d647
        //! CiffHeader auto_ptr type
Packit 01d647
        typedef std::auto_ptr<CiffHeader> AutoPtr;
Packit 01d647
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CiffHeader()
Packit 01d647
            : pRootDir_  (0),
Packit 01d647
              byteOrder_ (littleEndian),
Packit 01d647
              offset_    (0x0000001a),
Packit 01d647
              pPadding_  (0),
Packit 01d647
              padded_    (0)
Packit 01d647
            {}
Packit 01d647
        //! Virtual destructor
Packit 01d647
        virtual ~CiffHeader();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        /*!
Packit 01d647
          @brief Read the CRW image from a data buffer, starting with the Ciff
Packit 01d647
                 header.
Packit 01d647
Packit 01d647
          @param pData Pointer to the data buffer.
Packit 01d647
          @param size  Number of bytes in the data buffer.
Packit 01d647
Packit 01d647
          @throw Error If the image cannot be parsed.
Packit 01d647
         */
Packit 01d647
        void read(const byte* pData, uint32_t size);
Packit 01d647
        /*!
Packit 01d647
          @brief Set the value of entry \em crwTagId in directory \em crwDir to
Packit 01d647
                 \em buf. If this tag doesn't exist, it is added along with all
Packit 01d647
                 directories needed.
Packit 01d647
Packit 01d647
          @param crwTagId Tag to be added.
Packit 01d647
          @param crwDir   Parent directory of the tag.
Packit 01d647
          @param buf      Value to be set.
Packit 01d647
         */
Packit 01d647
        void add(uint16_t crwTagId, uint16_t crwDir, DataBuf buf);
Packit 01d647
        /*!
Packit 01d647
          @brief Remove entry \em crwTagId in directory \em crwDir from the parse
Packit 01d647
                 tree. If it's the last entry in the directory, the directory is
Packit 01d647
                 removed as well, etc.
Packit 01d647
Packit 01d647
          @param crwTagId Tag id to be removed.
Packit 01d647
          @param crwDir   Parent directory of the tag.
Packit 01d647
         */
Packit 01d647
        void remove(uint16_t crwTagId, uint16_t crwDir);
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! Return a pointer to the Canon CRW signature.
Packit 01d647
        static const char* signature() { return signature_; }
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        /*!
Packit 01d647
          @brief Write the CRW image to the binary image \em blob, starting with
Packit 01d647
                 the Ciff header. This method appends to the blob.
Packit 01d647
Packit 01d647
          @param blob Binary image to add to.
Packit 01d647
Packit 01d647
          @throw Error If the image cannot be written.
Packit 01d647
         */
Packit 01d647
        void write(Blob& blob) const;
Packit 01d647
        /*!
Packit 01d647
          @brief Decode the CRW image and add it to \em image.
Packit 01d647
Packit 01d647
          Walk the parse tree and convert CIFF entries to metadata
Packit 01d647
          entries which are added to \em image.
Packit 01d647
Packit 01d647
          @param image Image to add metadata to
Packit 01d647
         */
Packit 01d647
        void decode(Image& image) const;
Packit 01d647
        /*!
Packit 01d647
          @brief Print debug info for the CRW image to \em os.
Packit 01d647
Packit 01d647
          @param os Output stream to write to.
Packit 01d647
          @param prefix Prefix to be written before each line of output.
Packit 01d647
         */
Packit 01d647
        void print(std::ostream& os, const std::string& prefix ="") const;
Packit 01d647
        //! Return the byte order (little or big endian).
Packit 01d647
        ByteOrder byteOrder() const { return byteOrder_; }
Packit 01d647
        /*!
Packit 01d647
          @brief Finds \em crwTagId in directory \em crwDir in the parse tree,
Packit 01d647
                 returning a pointer to the component or 0 if not found.
Packit 01d647
         */
Packit 01d647
        CiffComponent* findComponent(uint16_t crwTagId, uint16_t crwDir) const;
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        // DATA
Packit 01d647
        static const char signature_[];   //!< Canon CRW signature "HEAPCCDR"
Packit 01d647
Packit 01d647
        CiffDirectory*    pRootDir_;      //!< Pointer to the root directory
Packit 01d647
        ByteOrder         byteOrder_;     //!< Applicable byte order
Packit 01d647
        uint32_t          offset_;        //!< Offset to the start of the root dir
Packit 01d647
        byte*             pPadding_;      //!< Pointer to the (unknown) remainder
Packit 01d647
        uint32_t          padded_;        //!< Number of padding-bytes
Packit 01d647
Packit 01d647
    }; // class CiffHeader
Packit 01d647
Packit 01d647
    //! Structure for the CIFF directory hierarchy
Packit 01d647
    struct CrwSubDir {
Packit 01d647
        uint16_t crwDir_;                 //!< Directory tag
Packit 01d647
        uint16_t parent_;                 //!< Parent directory tag
Packit 01d647
    }; // struct CrwSubDir
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Structure for a mapping table for conversion of CIFF entries to
Packit 01d647
             image metadata and vice versa.
Packit 01d647
     */
Packit 01d647
    struct CrwMapping {
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CrwMapping(
Packit 01d647
            uint16_t      crwTagId,
Packit 01d647
            uint16_t      crwDir,
Packit 01d647
            uint32_t      size,
Packit 01d647
            uint16_t      tag,
Packit 01d647
            Internal::IfdId ifdId,
Packit 01d647
            CrwDecodeFct  toExif,
Packit 01d647
            CrwEncodeFct  fromExif)
Packit 01d647
            : crwTagId_ (crwTagId),
Packit 01d647
              crwDir_   (crwDir),
Packit 01d647
              size_     (size),
Packit 01d647
              tag_      (tag),
Packit 01d647
              ifdId_    (ifdId),
Packit 01d647
              toExif_   (toExif),
Packit 01d647
              fromExif_ (fromExif)
Packit 01d647
            {}
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        // DATA
Packit 01d647
        uint16_t      crwTagId_;  //!< CRW tag id
Packit 01d647
        uint16_t      crwDir_;    //!< CRW directory tag
Packit 01d647
        uint32_t      size_;      //!< Data size (overwrites the size from the entry)
Packit 01d647
        uint16_t      tag_;       //!< Exif tag to map to
Packit 01d647
        IfdId         ifdId_;     //!< Exif Ifd id to map to
Packit 01d647
        CrwDecodeFct  toExif_;    //!< Conversion function
Packit 01d647
        CrwEncodeFct  fromExif_;  //!< Reverse conversion function
Packit 01d647
Packit 01d647
    }; // struct CrwMapping
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Static class providing mapping functionality from CRW entries
Packit 01d647
             to image metadata and vice versa
Packit 01d647
     */
Packit 01d647
    class CrwMap {
Packit 01d647
        //! @name Not implemented
Packit 01d647
        //@{
Packit 01d647
        //! Default constructor
Packit 01d647
        CrwMap();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    public:
Packit 01d647
        /*!
Packit 01d647
          @brief Decode image metadata from a CRW entry, convert and add it
Packit 01d647
                 to the image metadata. This function converts only one CRW
Packit 01d647
                 component.
Packit 01d647
Packit 01d647
          @param ciffComponent Source CIFF entry
Packit 01d647
          @param image         Destination image for the metadata
Packit 01d647
          @param byteOrder     Byte order in which the data of the entry
Packit 01d647
                               is encoded
Packit 01d647
         */
Packit 01d647
        static void decode(const CiffComponent& ciffComponent,
Packit 01d647
                                 Image&         image,
Packit 01d647
                                 ByteOrder      byteOrder);
Packit 01d647
        /*!
Packit 01d647
          @brief Encode image metadata from \em image into the CRW parse tree.
Packit 01d647
                 This function converts all Exif metadata that %Exiv2 can
Packit 01d647
                 convert to CRW format, in a loop through the entries of the
Packit 01d647
                 mapping table.
Packit 01d647
Packit 01d647
          @param pHead         Destination parse tree.
Packit 01d647
          @param image         Source image containing the metadata.
Packit 01d647
         */
Packit 01d647
        static void encode(CiffHeader* pHead, const Image& image);
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Load the stack: loop through the CRW subdirs hierarchy and push
Packit 01d647
                 all directories on the path from \em crwDir to root onto the
Packit 01d647
                 stack \em crwDirs. Requires the subdirs array to be arranged in
Packit 01d647
                 bottom-up order to be able to finish in only one pass.
Packit 01d647
         */
Packit 01d647
        static void loadStack(CrwDirs& crwDirs, uint16_t crwDir);
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        //! Return conversion information for one \em crwDir and \em crwTagId
Packit 01d647
        static const CrwMapping* crwMapping(uint16_t crwDir, uint16_t crwTagId);
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Standard decode function to convert CRW entries to
Packit 01d647
                 Exif metadata.
Packit 01d647
Packit 01d647
          Uses the mapping defined in the conversion structure \em pCrwMapping
Packit 01d647
          to convert the data. If the \em size field in the conversion structure
Packit 01d647
          is not 0, then it is used instead of the \em size provided by the
Packit 01d647
          entry itself.
Packit 01d647
         */
Packit 01d647
        static void decodeBasic(const CiffComponent& ciffComponent,
Packit 01d647
                                const CrwMapping*    pCrwMapping,
Packit 01d647
                                      Image&         image,
Packit 01d647
                                      ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode the user comment
Packit 01d647
        static void decode0x0805(const CiffComponent& ciffComponent,
Packit 01d647
                                 const CrwMapping*    pCrwMapping,
Packit 01d647
                                       Image&         image,
Packit 01d647
                                       ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode camera Make and Model information
Packit 01d647
        static void decode0x080a(const CiffComponent& ciffComponent,
Packit 01d647
                                 const CrwMapping*    pCrwMapping,
Packit 01d647
                                       Image&         image,
Packit 01d647
                                       ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode Canon Camera Settings 1, 2 and Custom Function arrays
Packit 01d647
        static void decodeArray(const CiffComponent& ciffComponent,
Packit 01d647
                                const CrwMapping*    pCrwMapping,
Packit 01d647
                                      Image&         image,
Packit 01d647
                                      ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode the date when the picture was taken
Packit 01d647
        static void decode0x180e(const CiffComponent& ciffComponent,
Packit 01d647
                                 const CrwMapping*    pCrwMapping,
Packit 01d647
                                       Image&         image,
Packit 01d647
                                       ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode image width and height
Packit 01d647
        static void decode0x1810(const CiffComponent& ciffComponent,
Packit 01d647
                                 const CrwMapping*    pCrwMapping,
Packit 01d647
                                       Image&         image,
Packit 01d647
                                       ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        //! Decode the thumbnail image
Packit 01d647
        static void decode0x2008(const CiffComponent& ciffComponent,
Packit 01d647
                                 const CrwMapping*    pCrwMapping,
Packit 01d647
                                       Image&         image,
Packit 01d647
                                       ByteOrder      byteOrder);
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Standard encode function to convert Exif metadata to Crw
Packit 01d647
                 entries.
Packit 01d647
Packit 01d647
          This is the basic encode function taking one Exif key and converting
Packit 01d647
          it to one Ciff entry. Both are available in the \em pCrwMapping passed
Packit 01d647
          in.
Packit 01d647
Packit 01d647
          @param image Image with the metadata to encode
Packit 01d647
          @param pCrwMapping Pointer to an entry into the \em crwMapping_ table
Packit 01d647
                       with information on the source and target metadata entries.
Packit 01d647
          @param pHead Pointer to the head of the CIFF parse tree into which
Packit 01d647
                       the metadata from \em image is encoded.
Packit 01d647
         */
Packit 01d647
        static void encodeBasic(const Image&      image,
Packit 01d647
                                const CrwMapping* pCrwMapping,
Packit 01d647
                                      CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode the user comment
Packit 01d647
        static void encode0x0805(const Image&      image,
Packit 01d647
                                 const CrwMapping* pCrwMapping,
Packit 01d647
                                       CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode camera Make and Model information
Packit 01d647
        static void encode0x080a(const Image&      image,
Packit 01d647
                                 const CrwMapping* pCrwMapping,
Packit 01d647
                                       CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode Canon Camera Settings 1, 2 and Custom Function arrays
Packit 01d647
        static void encodeArray(const Image&      image,
Packit 01d647
                                const CrwMapping* pCrwMapping,
Packit 01d647
                                      CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode the date when the picture was taken
Packit 01d647
        static void encode0x180e(const Image&      image,
Packit 01d647
                                 const CrwMapping* pCrwMapping,
Packit 01d647
                                       CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode image width and height
Packit 01d647
        static void encode0x1810(const Image&      image,
Packit 01d647
                                 const CrwMapping* pCrwMapping,
Packit 01d647
                                       CiffHeader* pHead);
Packit 01d647
Packit 01d647
        //! Encode the thumbnail image
Packit 01d647
        static void encode0x2008(const Image&      image,
Packit 01d647
                                 const CrwMapping* pCrwMapping,
Packit 01d647
                                       CiffHeader* pHead);
Packit 01d647
    private:
Packit 01d647
        // DATA
Packit 01d647
        static const CrwMapping crwMapping_[]; //!< Metadata conversion table
Packit 01d647
        static const CrwSubDir  crwSubDir_[];  //!< Ciff directory hierarchy
Packit 01d647
Packit 01d647
    }; // class CrwMap
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// template, inline and free functions
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Pack the tag values of all \em ifdId tags in \em exifData into a
Packit 01d647
             data buffer. This function is used to pack Canon Camera Settings1,2
Packit 01d647
             and Custom Function tags.
Packit 01d647
     */
Packit 01d647
    DataBuf packIfdId(const ExifData& exifData,
Packit 01d647
                            IfdId     ifdId,
Packit 01d647
                            ByteOrder byteOrder);
Packit 01d647
Packit 01d647
}}                                      // namespace Internal, Exiv2
Packit 01d647
Packit 01d647
#endif                                  // #ifndef CRWIMAGE_INT_HPP_