RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
TiffEntry.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2015 Pedro CĂ´rte-Real
6 Copyright (C) 2017 Axel Waggershauser
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22
23#include "rawspeedconfig.h"
24#include "tiff/TiffEntry.h"
25#include "adt/Casts.h"
26#include "adt/NotARational.h"
27#include "common/Common.h"
28#include "io/Buffer.h"
29#include "io/ByteStream.h"
30#include "io/Endianness.h"
32#include "tiff/TiffIFD.h"
33#include "tiff/TiffTag.h"
34#include <algorithm>
35#include <array>
36#include <cassert>
37#include <cstdint>
38#include <string>
39
40namespace rawspeed {
41
42// order see TiffDataType
43const std::array<uint32_t, 14> TiffEntry::datashifts = {0, 0, 0, 1, 2, 3, 0,
44 0, 1, 2, 3, 2, 3, 2};
45// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
46
47void TiffEntry::anchor() const {
48 // Empty out-of-line definition for the purpose of anchoring
49 // the class's vtable to this Translational Unit.
50}
51
53 // Empty out-of-line definition for the purpose of anchoring
54 // the class's vtable to this Translational Unit.
55}
56
58 : parent(parent_), tag(static_cast<TiffTag>(bs.getU16())) {
59 const uint16_t numType = bs.getU16();
60 if (numType > static_cast<uint16_t>(TiffDataType::OFFSET))
61 ThrowTPE("Error reading TIFF structure. Unknown Type 0x%x encountered.",
62 numType);
63 type = static_cast<TiffDataType>(numType);
64 count = bs.getU32();
65
66 // check for count << datashift overflow
67 if (count > UINT32_MAX >> datashifts[numType])
68 ThrowTPE("integer overflow in size calculation.");
69
70 uint32_t byte_size = count << datashifts[numType];
71 uint32_t data_offset = UINT32_MAX;
72
73 if (byte_size <= 4) {
74 data_offset = bs.getPosition();
75 data = bs.getSubStream(bs.getPosition(), byte_size);
76 bs.skipBytes(4);
77 } else {
78 data_offset = bs.getU32();
83 // preserve offset for SUB_IFD/EXIF/MAKER_NOTE data
84 if constexpr ((false)) {
85 // limit access to range from 0 to data_offset+byte_size
86 data = bs.getSubStream(data_offset, byte_size);
87 } else {
88 // allow access to whole file, necessary if offsets inside the maker
89 // note point to outside data, which is forbidden due to the TIFF/DNG
90 // spec but may happen none the less (see e.g. "old" ORF files like
91 // EX-1, note: the tags outside of the maker note area are currently not
92 // used anyway)
93 data = bs;
94 data.setPosition(data_offset);
95 (void)data.check(byte_size);
96 }
97 } else {
98 data = bs.getSubStream(data_offset, byte_size);
99 }
100 }
101}
102
104 uint32_t count_, ByteStream data_)
105 : parent(parent_), data(data_), tag(tag_), type(type_), count(count_) {
106 // check for count << datashift overflow
107 if (count > UINT32_MAX >> datashifts[static_cast<uint32_t>(type)])
108 ThrowTPE("integer overflow in size calculation.");
109
111
112 if (data.getSize() != bytesize)
113 ThrowTPE("data set larger than entry size given");
114}
115
116void TiffEntry::setData(ByteStream data_) { data = data_; }
117
119 TiffDataType type_, uint32_t count_,
120 Buffer mirror)
121 : TiffEntry(parent_, tag_, type_, /*count=*/0, ByteStream()),
122 data(mirror.begin(), mirror.end()) {
126 count = count_;
127}
128
129bool RAWSPEED_READONLY TiffEntry::isInt() const {
130 using enum TiffDataType;
131 return type == LONG || type == SHORT || type == BYTE;
132}
133
134bool RAWSPEED_READONLY TiffEntry::isString() const {
135 return type == TiffDataType::ASCII;
136}
137
138bool RAWSPEED_READONLY TiffEntry::isFloat() const {
139 switch (type) {
140 using enum TiffDataType;
141 case FLOAT:
142 case DOUBLE:
143 case RATIONAL:
144 case SRATIONAL:
145 case LONG:
146 case SLONG:
147 case SHORT:
148 case SSHORT:
149 return true;
150 default:
151 return false;
152 }
153}
154
155bool RAWSPEED_READONLY TiffEntry::isRational() const {
156 switch (type) {
157 using enum TiffDataType;
158 case SHORT:
159 case LONG:
160 case RATIONAL:
161 return true;
162 default:
163 return false;
164 }
165}
166
167bool RAWSPEED_READONLY TiffEntry::isSRational() const {
168 switch (type) {
169 using enum TiffDataType;
170 case SSHORT:
171 case SLONG:
172 case SRATIONAL:
173 return true;
174 default:
175 return false;
176 }
177}
178
179uint8_t TiffEntry::getByte(uint32_t index) const {
181 ThrowTPE("Wrong type %u encountered. Expected Byte on 0x%x",
182 static_cast<unsigned>(type), static_cast<unsigned>(tag));
183
184 return data.peekByte(index);
185}
186
189 ThrowTPE("Wrong type %u encountered. Expected Short or Undefined on 0x%x",
190 static_cast<unsigned>(type), static_cast<unsigned>(tag));
191
192 return data.peek<uint16_t>(index);
193}
194
197 ThrowTPE("Wrong type %u encountered. Expected Short or Undefined on 0x%x",
198 static_cast<unsigned>(type), static_cast<unsigned>(tag));
199
200 return data.peek<int16_t>(index);
201}
202
204 using enum TiffDataType;
205 if (type == SHORT)
206 return getU16(index);
207
208 switch (type) {
209 case LONG:
210 case OFFSET:
211 case BYTE:
212 case UNDEFINED:
213 case RATIONAL:
214 break;
215 default:
216 ThrowTPE("Wrong type %u encountered. Expected Long, Offset, Rational or "
217 "Undefined on 0x%x",
218 static_cast<unsigned>(type), static_cast<unsigned>(tag));
219 }
220
221 return data.peek<uint32_t>(index);
222}
223
225 using enum TiffDataType;
226 if (type == SSHORT)
227 return getI16(index);
228 if (type != SLONG && type != SRATIONAL && type != UNDEFINED)
229 ThrowTPE("Wrong type %u encountered. Expected SLong or Undefined on 0x%x",
230 static_cast<unsigned>(type), static_cast<unsigned>(tag));
231
232 return data.peek<int32_t>(index);
233}
234
236 if (!isRational()) {
237 ThrowTPE("Wrong type 0x%x encountered. Expected Rational",
238 static_cast<unsigned>(type));
239 }
240
242 return {getU32(index), 1};
243
244 auto a = getU32(index * 2);
245 auto b = getU32((index * 2) + 1);
246 return {a, b};
247}
248
250 if (!isSRational()) {
251 ThrowTPE("Wrong type 0x%x encountered. Expected SRational",
252 static_cast<unsigned>(type));
253 }
254
256 return {getI32(index), 1};
257
258 auto a = getI32(index * 2);
259 auto b = getI32((index * 2) + 1);
260 return {a, b};
261}
262
263float TiffEntry::getFloat(uint32_t index) const {
264 if (!isFloat()) {
265 ThrowTPE("Wrong type 0x%x encountered. Expected Float or something "
266 "convertible on 0x%x",
267 static_cast<unsigned>(type), static_cast<unsigned>(tag));
268 }
269
270 switch (type) {
271 using enum TiffDataType;
272 case DOUBLE:
273 return implicit_cast<float>(data.peek<double>(index));
274 case FLOAT:
275 return data.peek<float>(index);
276 case LONG:
277 case SHORT:
278 return static_cast<float>(getU32(index));
279 case SLONG:
280 case SSHORT:
281 return static_cast<float>(getI32(index));
282 case RATIONAL: {
283 auto r = getRational(index);
284 return r.den ? static_cast<float>(r) : 0.0F;
285 }
286 case SRATIONAL: {
287 auto r = getSRational(index);
288 return r.den ? static_cast<float>(r) : 0.0F;
289 }
290 default:
291 // unreachable
292 return 0.0F;
293 }
294}
295
296std::string TiffEntry::getString() const {
298 ThrowTPE("Wrong type 0x%x encountered. Expected Ascii or Byte",
299 static_cast<unsigned>(type));
300
301 // *NOT* ByteStream::peekString() !
302 Buffer tmp = data.peekBuffer(data.getRemainSize());
303 const auto* termIter = std::find(tmp.begin(), tmp.end(), '\0');
304 return {reinterpret_cast<const char*>(tmp.begin()),
305 reinterpret_cast<const char*>(termIter)};
306}
307
309 const TiffIFD* p = parent;
310 const TiffRootIFD* r = nullptr;
311 while (p) {
312 r = dynamic_cast<const TiffRootIFD*>(p);
313 if (r)
314 break;
315 p = p->parent;
316 }
317 if (!r)
318 ThrowTPE("Internal error in TiffIFD data structure.");
319
320 assert(r != nullptr);
321 return r->rootBuffer;
322}
323
324} // namespace rawspeed
#define ThrowTPE(...)
assert(dim.area() >=area)
const uint8_t * begin() const
Definition Buffer.h:99
const uint8_t * end() const
Definition Buffer.h:102
ByteStream getSubStream(size_type offset, size_type size_) const
Definition ByteStream.h:54
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
size_type getPosition() const
Definition ByteStream.h:78
DataBuffer getRootIfdData() const
TiffTag tag
Definition TiffEntry.h:82
int16_t getI16(uint32_t index=0) const
bool RAWSPEED_READONLY isSRational() const
NotARational< uint32_t > getRational(uint32_t index=0) const
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
bool RAWSPEED_READONLY isInt() const
bool RAWSPEED_READONLY isString() const
std::string getString() const
bool RAWSPEED_READONLY isFloat() const
uint32_t count
Definition TiffEntry.h:84
NotARational< int32_t > getSRational(uint32_t index=0) const
ByteStream data
Definition TiffEntry.h:64
TiffIFD * parent
Definition TiffEntry.h:63
uint16_t getU16(uint32_t index=0) const
TiffDataType type
Definition TiffEntry.h:83
uint8_t getByte(uint32_t index=0) const
TiffEntry(TiffIFD *parent, TiffTag tag, TiffDataType type, uint32_t count, ByteStream data)
static const std::array< uint32_t, 14 > datashifts
Definition TiffEntry.h:134
void setData(ByteStream data_)
bool RAWSPEED_READONLY isRational() const
int32_t getI32(uint32_t index=0) const
virtual void anchor() const
Definition TiffEntry.cpp:47
friend class TiffIFD
Definition TiffEntry.h:68
const std::vector< uint8_t > data
Definition TiffEntry.h:138
void anchor() const override
Definition TiffEntry.cpp:52
TiffEntryWithData(TiffIFD *parent, TiffTag tag, TiffDataType type, uint32_t count, Buffer mirror)
const DataBuffer rootBuffer
Definition TiffIFD.h:142
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
bool RAWSPEED_READONLY isIn(const T value, const std::initializer_list< T2 > &list)
Definition Common.h:156