libopenraw
ifdentry.hpp
1 /*
2  * libopenraw - ifdentry.h
3  *
4  * Copyright (C) 2006-2016 Hubert Figuiere
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 <sys/types.h>
28 #include <exception>
29 #include <string>
30 #include <vector>
31 #include <memory>
32 
33 #include "exception.hpp"
34 #include "endianutils.hpp"
35 #include "rawcontainer.hpp"
36 #include "ifd.hpp"
37 
38 namespace OpenRaw {
39 
40 class MetaValue;
41 
42 namespace Internals {
43 
44 class IfdFileContainer;
45 
46 class IfdEntry;
47 
49 template <typename T>
51 {
52  static const uint16_t type;
53  static const size_t size;
54  static T EL(const uint8_t* d) noexcept;
55  static T BE(const uint8_t* d) noexcept;
56  static T get(IfdEntry & e, uint32_t idx = 0, bool ignore_type = false)
57  noexcept(false);
58 };
59 
60 
61 template <>
62 inline uint8_t IfdTypeTrait<uint8_t>::EL(const uint8_t* b) noexcept
63 {
64  return *b;
65 }
66 
67 template <>
68 inline uint8_t IfdTypeTrait<uint8_t>::BE(const uint8_t* b) noexcept
69 {
70  return *b;
71 }
72 
73 
74 template <>
75 inline uint16_t IfdTypeTrait<uint16_t>::EL(const uint8_t* b) noexcept
76 {
77  return EL16(b);
78 }
79 
80 template <>
81 inline uint16_t IfdTypeTrait<uint16_t>::BE(const uint8_t* b) noexcept
82 {
83  return BE16(b);
84 }
85 
86 template <>
87 inline uint32_t IfdTypeTrait<uint32_t>::EL(const uint8_t* b) noexcept
88 {
89  return EL32(b);
90 }
91 
92 template <>
93 inline uint32_t IfdTypeTrait<uint32_t>::BE(const uint8_t* b) noexcept
94 {
95  return BE32(b);
96 }
97 
98 template <>
99 inline std::string IfdTypeTrait<std::string>::EL(const uint8_t* b) noexcept
100 {
101  std::string s;
102  try {
103  s = (const char*)b;
104  }
105  catch(...) {
106  }
107  return s;
108 }
109 
110 template <>
111 inline std::string IfdTypeTrait<std::string>::BE(const uint8_t* b) noexcept
112 {
113  std::string s;
114  try {
115  s = (const char*)b;
116  }
117  catch(...) {
118  }
119  return s;
120 }
121 
122 #if defined(__APPLE_CC__)
123 // Apple broken C++ needs this
124 // Now that we are C++11 we might not even need this anymore.
125 template <>
126 inline unsigned long IfdTypeTrait<unsigned long>::EL(const uint8_t* b)
127 {
128  return EL32(b);
129 }
130 
131 template <>
132 inline unsigned long IfdTypeTrait<unsigned long>::BE(const uint8_t* b)
133 {
134  return BE32(b);
135 }
136 #endif
137 
138 template <>
139 inline IFD::Rational IfdTypeTrait<IFD::Rational>::EL(const uint8_t* b) noexcept
140 {
141  IFD::Rational r;
142  r.num = EL32(b);
143  r.denom = EL32(b + 4);
144  return r;
145 }
146 
147 template <>
148 inline IFD::Rational IfdTypeTrait<IFD::Rational>::BE(const uint8_t* b) noexcept
149 {
150  IFD::Rational r;
151  r.num = BE32(b);
152  r.denom = BE32(b + 4);
153  return r;
154 }
155 
156 template <>
157 inline IFD::SRational IfdTypeTrait<IFD::SRational>::EL(const uint8_t* b) noexcept
158 {
159  IFD::SRational r;
160  r.num = EL32(b);
161  r.denom = EL32(b + 4);
162  return r;
163 }
164 
165 template <>
166 inline IFD::SRational IfdTypeTrait<IFD::SRational>::BE(const uint8_t* b) noexcept
167 {
168  IFD::SRational r;
169  r.num = BE32(b);
170  r.denom = BE32(b + 4);
171  return r;
172 }
173 
174 class IfdEntry
175 {
176 public:
178  typedef std::shared_ptr<IfdEntry> Ref;
179 
180  IfdEntry(uint16_t _id, int16_t _type, int32_t _count,
181  uint32_t _data,
182  IfdFileContainer &_container);
183  virtual ~IfdEntry();
184 
185  int16_t type() const noexcept
186  {
187  return m_type;
188  }
189 
191  uint32_t count() const noexcept
192  {
193  return m_count;
194  }
195 
199  off_t offset() noexcept
200  {
201  if (endian() == RawContainer::ENDIAN_LITTLE) {
202  return IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data);
203  }
204  return IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data);
205  }
206 
207  RawContainer::EndianType endian() const;
208 
209 public:
210  MetaValue* make_meta_value();
211 
217  bool loadData(size_t unit_size);
218 
219 
225  template <typename T>
226  void getArray(std::vector<T> & array) noexcept(false)
227  {
228  try {
229  array.reserve(m_count);
230  for (uint32_t i = 0; i < m_count; i++) {
231  array.push_back(IfdTypeTrait<T>::get(*this, i));
232  }
233  }
234  catch(std::exception & e)
235  {
236  throw e;
237  }
238  }
239  uint32_t getIntegerArrayItem(int idx);
240 
241 private:
242  uint16_t m_id;
243  uint16_t m_type;
244  uint32_t m_count;
245  uint32_t m_data;
246  bool m_loaded;
247  uint8_t *m_dataptr;
248  IfdFileContainer & m_container;
249  template <typename T> friend struct IfdTypeTrait;
250 
252  IfdEntry(const IfdEntry& f);
254  IfdEntry & operator=(const IfdEntry&);
255 
256 };
257 
258 
259 
268 template <typename T>
269 T IfdTypeTrait<T>::get(IfdEntry & e, uint32_t idx, bool ignore_type)
270  noexcept(false)
271 {
272  /* format undefined means that we don't check the type */
273  if(!ignore_type && (e.m_type != IFD::EXIF_FORMAT_UNDEFINED)) {
274  if (e.m_type != IfdTypeTrait<T>::type) {
275  throw BadTypeException();
276  }
277  }
278  if (idx + 1 > e.m_count) {
279  throw OutOfRangeException();
280  }
281  if (!e.m_loaded) {
282  e.m_loaded = e.loadData(IfdTypeTrait<T>::size);
283  if (!e.m_loaded) {
284  throw TooBigException();
285  }
286  }
287  uint8_t *data;
288  if (e.m_dataptr == NULL) {
289  data = (uint8_t*)&e.m_data;
290  }
291  else {
292  data = e.m_dataptr;
293  }
294  data += (IfdTypeTrait<T>::size * idx);
295  T val;
296  if (e.endian() == RawContainer::ENDIAN_LITTLE) {
297  val = IfdTypeTrait<T>::EL(data);
298  }
299  else {
300  val = IfdTypeTrait<T>::BE(data);
301  }
302  return val;
303 }
304 
305 
306 }
307 }
308 
309 
310 /*
311  Local Variables:
312  mode:c++
313  c-file-style:"stroustrup"
314  c-file-offsets:((innamespace . 0))
315  tab-width:2
316  c-basic-offset:2
317  indent-tabs-mode:nil
318  fill-column:80
319  End:
320 */
321 #endif
322 
323 
uint32_t count() const noexcept
Definition: ifdentry.hpp:191
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
Definition: arwfile.cpp:30
static T get(IfdEntry &e, uint32_t idx=0, bool ignore_type=false) noexcept(false)
Definition: ifdentry.hpp:269
void getArray(std::vector< T > &array) noexcept(false)
Definition: ifdentry.hpp:226
std::shared_ptr< IfdEntry > Ref
Definition: ifdentry.hpp:178
static const size_t size
Definition: ifdentry.hpp:53
off_t offset() noexcept
Definition: ifdentry.hpp:199
static const uint16_t type
Definition: ifdentry.hpp:52