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