RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
CiffEntry.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) 2014 Pedro CĂ´rte-Real
6 Copyright (C) 2017-2018 Roman Lebedev
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/CiffEntry.h"
25#include "adt/Invariant.h"
26#include "adt/NORangesSet.h"
27#include "adt/Optional.h"
28#include "io/Buffer.h"
29#include "io/ByteStream.h"
31#include "tiff/CiffTag.h"
32#include <cstdint>
33#include <string>
34#include <string_view>
35#include <vector>
36
37using std::vector;
38
39namespace rawspeed {
40
42 uint32_t count_)
43 : data(data_), tag(tag_), type(type_), count(count_) {}
44
46 ByteStream valueData, ByteStream dirEntry) {
47 uint16_t p = dirEntry.getU16();
48
49 const auto tag = static_cast<CiffTag>(p & 0x3fff);
50 uint16_t datalocation = (p & 0xc000);
51 const auto type = static_cast<CiffDataType>(p & 0x3800);
52
53 uint32_t data_offset;
54 uint32_t bytesize;
55
57
58 switch (datalocation) {
59 case 0x0000:
60 // Data is offset in value_data
61 bytesize = dirEntry.getU32();
62 data_offset = dirEntry.getU32();
63 data = valueData.getSubStream(data_offset, bytesize);
64 if (!valueDatas->insert(*data))
65 ThrowCPE("Two valueData's overlap. Raw corrupt!");
66 break;
67 case 0x4000:
68 // Data is stored directly in entry
69 data_offset = dirEntry.getPosition();
70 // Maximum of 8 bytes of data (the size and offset fields)
71 bytesize = 8;
72 data = dirEntry.getStream(bytesize);
73 break;
74 default:
75 ThrowCPE("Don't understand data location 0x%x", datalocation);
76 }
77 invariant(data.has_value());
78
79 // Set the number of items using the shift
80 uint32_t count = bytesize >> getElementShift(type);
81
82 return {*data, tag, type, count};
83}
84
86 switch (type) {
87 using enum CiffDataType;
88 case SHORT:
89 return 1;
90 case LONG:
91 case MIX:
92 case SUB1:
93 case SUB2:
94 return 2;
95 default:
96 // e.g. BYTE or ASCII
97 return 0;
98 }
99}
100
101uint32_t RAWSPEED_READONLY CiffEntry::getElementSize() const {
102 switch (type) {
103 using enum CiffDataType;
104 case BYTE:
105 case ASCII:
106 return 1;
107 case SHORT:
108 return 2;
109 case LONG:
110 case MIX:
111 case SUB1:
112 case SUB2:
113 return 4;
114 }
115 __builtin_unreachable();
116}
117
118bool RAWSPEED_READONLY CiffEntry::isInt() const {
119 using enum CiffDataType;
120 return (type == LONG || type == SHORT || type == BYTE);
121}
122
124 if (!isInt()) {
125 ThrowCPE(
126 "Wrong type 0x%x encountered. Expected Long, Short or Byte at 0x%x",
127 static_cast<unsigned>(type), static_cast<unsigned>(tag));
128 }
129
131 return getByte(num);
133 return getU16(num);
134
135 return data.peek<uint32_t>(num);
136}
137
140 ThrowCPE("Wrong type 0x%x encountered. Expected Short at 0x%x",
141 static_cast<unsigned>(type), static_cast<unsigned>(tag));
142
143 return data.peek<uint16_t>(num);
144}
145
146uint8_t CiffEntry::getByte(uint32_t num) const {
148 ThrowCPE("Wrong type 0x%x encountered. Expected Byte at 0x%x",
149 static_cast<unsigned>(type), static_cast<unsigned>(tag));
150
151 return data.peek<uint8_t>(num);
152}
153
154std::string_view CiffEntry::getString() const {
156 ThrowCPE("Wrong type 0x%x encountered. Expected Ascii",
157 static_cast<unsigned>(type));
158
159 if (count == 0)
160 return "";
161
162 return data.peekString();
163}
164
165vector<std::string> CiffEntry::getStrings() const {
167 ThrowCPE("Wrong type 0x%x encountered. Expected Ascii",
168 static_cast<unsigned>(type));
169
170 const std::string str(reinterpret_cast<const char*>(data.peekData(count)),
171 count);
172
173 vector<std::string> strs;
174
175 uint32_t start = 0;
176 for (uint32_t i = 0; i < count; i++) {
177 if (str[i] != 0)
178 continue;
179
180 strs.emplace_back(&str[start]);
181 start = i + 1;
182 }
183
184 return strs;
185}
186
187bool RAWSPEED_READONLY CiffEntry::isString() const {
188 return (type == CiffDataType::ASCII);
189}
190
191} // namespace rawspeed
#define ThrowCPE(...)
#define invariant(expr)
Definition Invariant.h:27
ByteStream getSubStream(size_type offset, size_type size_) const
Definition ByteStream.h:54
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
size_type getPosition() const
Definition ByteStream.h:78
ByteStream data
Definition CiffEntry.h:57
static uint32_t getElementShift(CiffDataType type) RAWSPEED_READONLY
Definition CiffEntry.cpp:85
static CiffEntry Create(NORangesSet< Buffer > *valueDatas, ByteStream valueData, ByteStream dirEntry)
Definition CiffEntry.cpp:45
uint32_t RAWSPEED_READONLY getElementSize() const
std::vector< std::string > getStrings() const
CiffDataType type
Definition CiffEntry.h:81
uint32_t getU32(uint32_t num=0) const
std::string_view getString() const
CiffEntry(ByteStream data, CiffTag tag, CiffDataType type, uint32_t count)
Definition CiffEntry.cpp:41
uint8_t getByte(uint32_t num=0) const
CiffTag tag
Definition CiffEntry.h:80
uint16_t getU16(uint32_t num=0) const
bool RAWSPEED_READONLY isInt() const
uint32_t count
Definition CiffEntry.h:82
bool RAWSPEED_READONLY isString() const
bool insert(const T &newElt)
Definition NORangesSet.h:61