aboutsummaryrefslogtreecommitdiff
path: root/src/tiff_directory/tiff_directory.h
blob: 855adfc5e4b2f4159b0d793e2fe883cf0927a4bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
//
// TiffDirectory contains an abstraction of an image file directory (IFD) as
// proposed by the TIFF specification.

#ifndef PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_
#define PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_

#include <cstdint>
#include <map>
#include <string>
#include <vector>

namespace piex {
namespace tiff_directory {

enum Endian {
  kLittleEndian = 0,
  kBigEndian = 1,
};

struct Rational {
  std::uint32_t numerator;
  std::uint32_t denominator;
};

struct SRational {
  std::int32_t numerator;
  std::int32_t denominator;
};

enum TiffTypes {
  TIFF_TYPE_NONE = 0,
  TIFF_TYPE_BYTE,      /* 8bit unsigned */
  TIFF_TYPE_ASCII,     /* Ascii string (terminated by \0) */
  TIFF_TYPE_SHORT,     /* 16bit unsigned  */
  TIFF_TYPE_LONG,      /* 32bit unsigned  */
  TIFF_TYPE_RATIONAL,  /* 32bit/32bit unsigned  */
  TIFF_TYPE_SBYTE,     /* 8bit signed */
  TIFF_TYPE_UNDEFINED, /* undefined (depend of tag) */
  TIFF_TYPE_SSHORT,    /* 16bit signed*/
  TIFF_TYPE_SLONG,     /* 32bit signed  */
  TIFF_TYPE_SRATIONAL, /* 32bit/32bit signed */
  TIFF_TYPE_FLOAT,     /* 32-bit IEEE float */
  TIFF_TYPE_DOUBLE,    /* 64-bit IEEE float */
  TIFF_IFD,            /* IFD type */
};

// The TiffDirectory class stores all information necessary to interpret TIFF
// tags and manages also potential sub directories.
class TiffDirectory {
 public:
  typedef std::uint32_t Tag;
  typedef std::uint32_t Type;

  explicit TiffDirectory(Endian endianness);

  // Returns true if the directory contains the specified tag.
  bool Has(const Tag tag) const;

  // Gets the value of a tag of byte vector type.
  // Returns false if the tag is not part of the directory or if the
  // type is not BYTE or UNDEFINED.
  bool Get(const Tag tag, std::vector<std::uint8_t>* value) const;

  // Gets the value of a tag of type "ASCII".
  // Returns false if the tag is not part of the directory or if its
  // type is not ASCII.
  // If *err is not equal to ERR_OK initially, this method does nothing.
  bool Get(const Tag tag, std::string* value) const;

  // Gets the value of a tag of type "SHORT" or "LONG".
  // Returns false
  // - if the tag is not part of the directory or
  // - if the type is not SHORT or LONG, or
  // - if, for the non-vector version, the number of elements is unequal to 1.
  bool Get(const Tag tag, std::uint32_t* value) const;
  bool Get(const Tag tag, std::vector<std::uint32_t>* value) const;

  // Gets the value of a tag of type "SHORT", "LONG" or "RATIONAL".
  // Returns false
  // - if the tag is not part of the directory or
  // - if the type is not SHORT, LONG or RATIONAL, or
  // - if, for the non-vector version, the number of elements is unequal to 1.
  bool Get(const Tag tag, Rational* value) const;
  bool Get(const Tag tag, std::vector<Rational>* value) const;

  // Gets the value of a tag of type "SSHORT", "SLONG" or "SRATIONAL".
  // Returns false
  // - if the tag is not part of the directory or
  // - if the type is not SSHORT, SLONG or SRATIONAL, or
  // - if, for the non-vector version, the number of elements is unequal to 1.
  bool Get(const Tag tag, SRational* value) const;
  bool Get(const Tag tag, std::vector<SRational>* value) const;

  // Gets the 'offset' to the value data in the file and its 'length' in bytes.
  // Returns false if the 'tag' is not part of the directory or if its type does
  // not match the desired 'type'.
  bool GetOffsetAndLength(const Tag tag, const Type type, std::uint32_t* offset,
                          std::uint32_t* length) const;

  // Adds a tag to the directory, setting its type, number of elements
  // ('count'), the offset to the binary data in the file ('offset') and the
  // associated binary data ('value'). The binary data is encoded according to
  // the TIFF specification with the endianness that was specified when this
  // object was constructed. The caller must ensure that the size of 'value' and
  // the data it contains are consistent with 'type' and 'count'. It is not
  // legal to call this method with a tag that is already contained in the
  // directory.
  void AddEntry(const Tag tag, const Type type, const std::uint32_t count,
                const std::uint32_t offset,
                const std::vector<std::uint8_t>& value);

  // Add a subdirectory to the directory.
  void AddSubDirectory(const TiffDirectory& sub_directory);

  // Returns a vector of all subdirectories contained in this directory.
  const std::vector<TiffDirectory>& GetSubDirectories() const;

 private:
  struct DirectoryEntry {
    Type type;
    std::uint32_t count;   // The number of values of type, not a byte count.
    std::uint32_t offset;  // Offset of the entry's data in the file. '0' means
                           // the offset is not set.
    std::vector<std::uint8_t> value;
  };

  const DirectoryEntry* Find(const Tag tag) const;

  std::map<Tag, DirectoryEntry> directory_entries_;
  std::vector<Tag> tag_order_;
  std::vector<TiffDirectory> sub_directories_;
  Endian endian_;
};

// Returns the number of bytes a single value of 'type' requires; this is
// guaranteed to be in the range of 0 to 8.
// Returns 0 if 'type' is TIFF_TYPE_NONE or invalid. Sets 'success' to false if
// 'type' is invalid. If you are not interested in 'success' you can set it to
// a nullptr.
size_t SizeOfType(const TiffDirectory::Type type, bool* success);

}  // namespace tiff_directory
}  // namespace piex

#endif  // PIEX_TIFF_DIRECTORY_TIFF_DIRECTORY_H_