libopenraw
ifdentry.hpp
1/*
2 * libopenraw - ifdentry.hpp
3 *
4 * Copyright (C) 2006-2017 Hubert Figuière
5 *
6 * This library is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21
22#ifndef OR_INTERNALS_IFDENTRY_H
23#define OR_INTERNALS_IFDENTRY_H
24
25#include <stddef.h>
26#include <stdint.h>
27#include <string.h>
28#include <sys/types.h>
29
30#include <exception>
31#include <string>
32#include <vector>
33#include <memory>
34
35#include "exception.hpp"
36#include "trace.hpp"
37#include "endianutils.hpp"
38#include "rawcontainer.hpp"
39#include "ifd.hpp"
40
41namespace OpenRaw {
42
43class MetaValue;
44
45namespace Internals {
46
47class IfdFileContainer;
48
49class IfdEntry;
50
52template <typename T>
54{
55 static const uint16_t type;
56 static const size_t size;
57 static T EL(const uint8_t* d, size_t len) noexcept;
58 static T BE(const uint8_t* d, size_t len) noexcept;
59 static T get(IfdEntry & e, uint32_t idx = 0, bool ignore_type = false)
60 noexcept(false);
61};
62
63
64template <>
65inline uint8_t IfdTypeTrait<uint8_t>::EL(const uint8_t* b, size_t) noexcept
66{
67 return *b;
68}
69
70template <>
71inline uint8_t IfdTypeTrait<uint8_t>::BE(const uint8_t* b, size_t) noexcept
72{
73 return *b;
74}
75
76
77template <>
78inline uint16_t IfdTypeTrait<uint16_t>::EL(const uint8_t* b, size_t) noexcept
79{
80 return EL16(b);
81}
82
83template <>
84inline uint16_t IfdTypeTrait<uint16_t>::BE(const uint8_t* b, size_t) noexcept
85{
86 return BE16(b);
87}
88
89template <>
90inline uint32_t IfdTypeTrait<uint32_t>::EL(const uint8_t* b, size_t) noexcept
91{
92 return EL32(b);
93}
94
95template <>
96inline uint32_t IfdTypeTrait<uint32_t>::BE(const uint8_t* b, size_t) noexcept
97{
98 return BE32(b);
99}
100
101template <>
102inline std::string IfdTypeTrait<std::string>::EL(const uint8_t* b, size_t len) noexcept
103{
104 std::string s;
105 try {
106 s.assign((const char*)b, strnlen((const char*)b, len));
107 }
108 catch(...) {
109 }
110 return s;
111}
112
113template <>
114inline std::string IfdTypeTrait<std::string>::BE(const uint8_t* b, size_t len) noexcept
115{
116 std::string s;
117 try {
118 s.assign((const char*)b, strnlen((const char*)b, len));
119 }
120 catch(...) {
121 }
122 return s;
123}
124
125template <>
126inline IFD::Rational IfdTypeTrait<IFD::Rational>::EL(const uint8_t* b, size_t) noexcept
127{
128 IFD::Rational r;
129 r.num = EL32(b);
130 r.denom = EL32(b + 4);
131 return r;
132}
133
134template <>
135inline IFD::Rational IfdTypeTrait<IFD::Rational>::BE(const uint8_t* b, size_t) noexcept
136{
137 IFD::Rational r;
138 r.num = BE32(b);
139 r.denom = BE32(b + 4);
140 return r;
141}
142
143template <>
144inline IFD::SRational IfdTypeTrait<IFD::SRational>::EL(const uint8_t* b, size_t) noexcept
145{
146 IFD::SRational r;
147 r.num = EL32(b);
148 r.denom = EL32(b + 4);
149 return r;
150}
151
152template <>
153inline IFD::SRational IfdTypeTrait<IFD::SRational>::BE(const uint8_t* b, size_t) noexcept
154{
155 IFD::SRational r;
156 r.num = BE32(b);
157 r.denom = BE32(b + 4);
158 return r;
159}
160
162{
163public:
165 typedef std::shared_ptr<IfdEntry> Ref;
166
167 IfdEntry(uint16_t _id, int16_t _type, int32_t _count,
168 uint32_t _data,
169 IfdFileContainer &_container);
170 virtual ~IfdEntry();
171
172 int16_t type() const noexcept
173 {
174 return m_type;
175 }
176
178 uint32_t count() const noexcept
179 {
180 return m_count;
181 }
182
186 off_t offset() noexcept
187 {
188 if (endian() == RawContainer::ENDIAN_LITTLE) {
189 return IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data, sizeof(uint32_t));
190 }
191 return IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data, sizeof(uint32_t));
192 }
193
194 RawContainer::EndianType endian() const;
195
196public:
197 MetaValue* make_meta_value();
201 static size_t type_unit_size(IFD::ExifTagType _type);
207 bool loadData(size_t unit_size);
208
209
215 template <typename T>
217 {
218 try {
219 std::vector<T> array;
220 array.reserve(m_count);
221 for (uint32_t i = 0; i < m_count; i++) {
222 array.push_back(IfdTypeTrait<T>::get(*this, i));
223 }
224 return Option<decltype(array)>(array);
225 }
226 catch(const std::exception & e)
227 {
228 LOGERR("Exception: %s\n", e.what());
229 }
230 return Option<std::vector<T>>();
231 }
232 uint32_t getIntegerArrayItem(int idx);
233
234private:
235 uint16_t m_id;
236 uint16_t m_type;
237 uint32_t m_count;
238 uint32_t m_data;
239 bool m_loaded;
240 uint8_t *m_dataptr;
241 IfdFileContainer & m_container;
242 template <typename T> friend struct IfdTypeTrait;
243
245 IfdEntry(const IfdEntry& f);
247 IfdEntry & operator=(const IfdEntry&);
248
249};
250
251
252
261template <typename T>
262T IfdTypeTrait<T>::get(IfdEntry & e, uint32_t idx, bool ignore_type)
263 noexcept(false)
264{
265 /* format undefined means that we don't check the type */
266 if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
267 if (e.m_type != IfdTypeTrait<T>::type) {
268 throw BadTypeException();
269 }
270 }
271 if (idx + 1 > e.m_count) {
272 throw OutOfRangeException();
273 }
274 if (!e.m_loaded) {
275 e.m_loaded = e.loadData(IfdTypeTrait<T>::size);
276 if (!e.m_loaded) {
277 throw TooBigException();
278 }
279 }
280 uint8_t *data;
281 if (e.m_dataptr == NULL) {
282 data = (uint8_t*)&e.m_data;
283 }
284 else {
285 data = e.m_dataptr;
286 }
287 data += (IfdTypeTrait<T>::size * idx);
288 T val;
289 if (e.endian() == RawContainer::ENDIAN_LITTLE) {
290 val = IfdTypeTrait<T>::EL(data, e.m_count - idx);
291 }
292 else {
293 val = IfdTypeTrait<T>::BE(data, e.m_count - idx);
294 }
295 return val;
296}
297
298
299}
300}
301
302
303/*
304 Local Variables:
305 mode:c++
306 c-file-style:"stroustrup"
307 c-file-offsets:((innamespace . 0))
308 tab-width:2
309 c-basic-offset:2
310 indent-tabs-mode:nil
311 fill-column:80
312 End:
313*/
314#endif
315
316
uint32_t count() const noexcept
Definition: ifdentry.hpp:178
std::shared_ptr< IfdEntry > Ref
Definition: ifdentry.hpp:165
Option< std::vector< T > > getArray()
Definition: ifdentry.hpp:216
off_t offset() noexcept
Definition: ifdentry.hpp:186
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard....
Definition: arwfile.cpp:30
static const uint16_t type
Definition: ifdentry.hpp:55
static T get(IfdEntry &e, uint32_t idx=0, bool ignore_type=false) noexcept(false)
Definition: ifdentry.hpp:262
static const size_t size
Definition: ifdentry.hpp:56