Home | History | Annotate | Download | only in tiff_directory
      1 // Copyright 2015 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 ////////////////////////////////////////////////////////////////////////////////
     16 //
     17 // TiffDirectory contains an abstraction of an image file directory (IFD) as
     18 // proposed by the TIFF specification.
     19 
     20 #ifndef PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_
     21 #define PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_
     22 
     23 #include <cstdint>
     24 #include <map>
     25 #include <string>
     26 #include <vector>
     27 
     28 namespace piex {
     29 namespace tiff_directory {
     30 
     31 enum Endian {
     32   kLittleEndian = 0,
     33   kBigEndian = 1,
     34 };
     35 
     36 struct Rational {
     37   std::uint32_t numerator;
     38   std::uint32_t denominator;
     39 };
     40 
     41 struct SRational {
     42   std::int32_t numerator;
     43   std::int32_t denominator;
     44 };
     45 
     46 enum TiffTypes {
     47   TIFF_TYPE_NONE = 0,
     48   TIFF_TYPE_BYTE,      /* 8bit unsigned */
     49   TIFF_TYPE_ASCII,     /* Ascii string (terminated by \0) */
     50   TIFF_TYPE_SHORT,     /* 16bit unsigned  */
     51   TIFF_TYPE_LONG,      /* 32bit unsigned  */
     52   TIFF_TYPE_RATIONAL,  /* 32bit/32bit unsigned  */
     53   TIFF_TYPE_SBYTE,     /* 8bit signed */
     54   TIFF_TYPE_UNDEFINED, /* undefined (depend of tag) */
     55   TIFF_TYPE_SSHORT,    /* 16bit signed*/
     56   TIFF_TYPE_SLONG,     /* 32bit signed  */
     57   TIFF_TYPE_SRATIONAL, /* 32bit/32bit signed */
     58   TIFF_TYPE_FLOAT,     /* 32-bit IEEE float */
     59   TIFF_TYPE_DOUBLE,    /* 64-bit IEEE float */
     60   TIFF_IFD,            /* IFD type */
     61 };
     62 
     63 // The TiffDirectory class stores all information necessary to interpret TIFF
     64 // tags and manages also potential sub directories.
     65 class TiffDirectory {
     66  public:
     67   typedef std::uint32_t Tag;
     68   typedef std::uint32_t Type;
     69 
     70   explicit TiffDirectory(Endian endianness);
     71 
     72   // Returns true if the directory contains the specified tag.
     73   bool Has(const Tag tag) const;
     74 
     75   // Gets the value of a tag of byte vector type.
     76   // Returns false if the tag is not part of the directory or if the
     77   // type is not BYTE or UNDEFINED.
     78   bool Get(const Tag tag, std::vector<std::uint8_t>* value) const;
     79 
     80   // Gets the value of a tag of type "ASCII".
     81   // Returns false if the tag is not part of the directory or if its
     82   // type is not ASCII.
     83   // If *err is not equal to ERR_OK initially, this method does nothing.
     84   bool Get(const Tag tag, std::string* value) const;
     85 
     86   // Gets the value of a tag of type "SHORT" or "LONG".
     87   // Returns false
     88   // - if the tag is not part of the directory or
     89   // - if the type is not SHORT or LONG, or
     90   // - if, for the non-vector version, the number of elements is unequal to 1.
     91   bool Get(const Tag tag, std::uint32_t* value) const;
     92   bool Get(const Tag tag, std::vector<std::uint32_t>* value) const;
     93 
     94   // Gets the value of a tag of type "SHORT", "LONG" or "RATIONAL".
     95   // Returns false
     96   // - if the tag is not part of the directory or
     97   // - if the type is not SHORT, LONG or RATIONAL, or
     98   // - if, for the non-vector version, the number of elements is unequal to 1.
     99   bool Get(const Tag tag, Rational* value) const;
    100   bool Get(const Tag tag, std::vector<Rational>* value) const;
    101 
    102   // Gets the value of a tag of type "SSHORT", "SLONG" or "SRATIONAL".
    103   // Returns false
    104   // - if the tag is not part of the directory or
    105   // - if the type is not SSHORT, SLONG or SRATIONAL, or
    106   // - if, for the non-vector version, the number of elements is unequal to 1.
    107   bool Get(const Tag tag, SRational* value) const;
    108   bool Get(const Tag tag, std::vector<SRational>* value) const;
    109 
    110   // Gets the 'offset' to the value data in the file and its 'length' in bytes.
    111   // Returns false if the 'tag' is not part of the directory or if its type does
    112   // not match the desired 'type'.
    113   bool GetOffsetAndLength(const Tag tag, const Type type, std::uint32_t* offset,
    114                           std::uint32_t* length) const;
    115 
    116   // Adds a tag to the directory, setting its type, number of elements
    117   // ('count'), the offset to the binary data in the file ('offset') and the
    118   // associated binary data ('value'). The binary data is encoded according to
    119   // the TIFF specification with the endianness that was specified when this
    120   // object was constructed. The caller must ensure that the size of 'value' and
    121   // the data it contains are consistent with 'type' and 'count'. It is not
    122   // legal to call this method with a tag that is already contained in the
    123   // directory.
    124   void AddEntry(const Tag tag, const Type type, const std::uint32_t count,
    125                 const std::uint32_t offset,
    126                 const std::vector<std::uint8_t>& value);
    127 
    128   // Add a subdirectory to the directory.
    129   void AddSubDirectory(const TiffDirectory& sub_directory);
    130 
    131   // Returns a vector of all subdirectories contained in this directory.
    132   const std::vector<TiffDirectory>& GetSubDirectories() const;
    133 
    134  private:
    135   struct DirectoryEntry {
    136     Type type;
    137     std::uint32_t count;   // The number of values of type, not a byte count.
    138     std::uint32_t offset;  // Offset of the entry's data in the file. '0' means
    139                            // the offset is not set.
    140     std::vector<std::uint8_t> value;
    141   };
    142 
    143   const DirectoryEntry* Find(const Tag tag) const;
    144 
    145   std::map<Tag, DirectoryEntry> directory_entries_;
    146   std::vector<Tag> tag_order_;
    147   std::vector<TiffDirectory> sub_directories_;
    148   Endian endian_;
    149 };
    150 
    151 // Returns the number of bytes a single value of 'type' requires; this is
    152 // guaranteed to be in the range of 0 to 8.
    153 // Returns 0 if 'type' is TIFF_TYPE_NONE or invalid. Sets 'success' to false if
    154 // 'type' is invalid. If you are not interested in 'success' you can set it to
    155 // a nullptr.
    156 size_t SizeOfType(const TiffDirectory::Type type, bool* success);
    157 
    158 }  // namespace tiff_directory
    159 }  // namespace piex
    160 
    161 #endif  // PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_
    162