libopenraw  0.3.7
ifddir.hpp
1 /* -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil; -*- */
2 /*
3  * libopenraw - ifddir.hpp
4  *
5  * Copyright (C) 2006-2022 Hubert Figuière
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #pragma once
23 
24 #include <stddef.h>
25 #include <stdint.h>
26 #include <sys/types.h>
27 #include <exception>
28 #include <map>
29 #include <memory>
30 #include <vector>
31 
32 #include <libopenraw/debug.h>
33 
34 #include "ifdentry.hpp"
35 #include "trace.hpp"
36 #include "option.hpp"
37 #include "exif/exif_tags.hpp"
38 
39 namespace OpenRaw {
40 namespace Internals {
41 
46 typedef or_ifd_dir_type IfdDirType;
47 
48 class IfdFileContainer;
49 
51 class IfdDir {
52 public:
54  typedef std::weak_ptr<IfdDir> WeakRef;
56  typedef std::shared_ptr<IfdDir> Ref;
61  typedef std::vector<Ref> RefVec;
66  typedef std::map<uint16_t, IfdEntry::Ref> Entries;
67 
74  IfdDir(off_t _offset, RawContainer& _container, IfdDirType _type /*= OR_IFDDIR_OTHER */, const TagTable& tag_table = exif_tag_names);
75  virtual ~IfdDir();
76 
78  IfdDirType type() const
79  { return m_type; }
81  void setType(IfdDirType type_)
82  { m_type = type_; }
83 
88  off_t baseOffset() const
89  { return m_base_offset; }
91  void setBaseOffset(off_t base)
92  { m_base_offset = base; }
93 
98  bool isPrimary() const;
103  bool isThumbnail() const;
104 
106  off_t offset() const { return m_offset; }
108  const RawContainer& container() const { return m_container; }
110  RawContainer& container() { return m_container; }
111 
118  virtual bool load();
120  int numTags() { return m_entries.size(); }
126  IfdEntry::Ref getEntry(uint16_t id) const;
128  const Entries& entries() const
129  {
130  return m_entries;
131  }
138  {
139  return m_endian;
140  }
147  {
148  m_endian = _endian;
149  }
150 
155  template <typename T>
156  Option<T> getValue(uint16_t id) const
157  {
158  IfdEntry::Ref e = getEntry(id);
159  if (e != NULL) {
160  try {
161  return Option<T>(getEntryValue<T>(*e));
162  }
163  catch (const std::exception &ex) {
164  LOGERR("Exception raised %s fetch value for %u\n", ex.what(), id);
165  }
166  }
167  return Option<T>();
168  }
169 
178  Option<uint32_t> getIntegerValue(uint16_t id);
179 
183  off_t nextIFD();
184 
188  Ref getSubIFD(uint32_t idx = 0) const;
189 
194 
198  Ref getExifIFD();
199 
205 
211  void setTagTable(const TagTable& tag_table)
212  {
213  m_tag_table = &tag_table;
214  }
218  const char* getTagName(uint32_t tag) const;
219 
221  template <typename T>
224  template<typename T>
225  T getEntryValue(IfdEntry& e, uint32_t idx = 0, bool ignore_type = false) const;
226 
232  uint32_t getEntryIntegerArrayItemValue(IfdEntry& e, int idx) const;
233 
237  MetaValue* makeMetaValue(IfdEntry& e) const;
238 protected:
241 private:
242  IfdDirType m_type;
243  off_t m_offset;
244  RawContainer& m_container;
245  const TagTable* m_tag_table;
246  off_t m_base_offset;
247  RawContainer::EndianType m_endian;
248 };
249 
250 
256 template <typename T>
258 {
259  try {
260  std::vector<T> array;
261  array.reserve(entry.count());
262  for (uint32_t i = 0; i < entry.count(); i++) {
263  array.push_back(getEntryValue<T>(entry, i));
264  }
265  return Option<decltype(array)>(array);
266  }
267  catch(const std::exception& e)
268  {
269  LOGERR("Exception: %s\n", e.what());
270  }
271  return OptionNone();
272 }
273 
282 template <typename T>
283 T IfdDir::getEntryValue(IfdEntry& e, uint32_t idx, bool ignore_type) const
284  noexcept(false)
285 {
286  /* format undefined means that we don't check the type */
287  if(!ignore_type && (e.type() != IFD::EXIF_FORMAT_UNDEFINED)) {
288  if (e.type() != IfdTypeTrait<T>::type) {
289  throw BadTypeException();
290  }
291  }
292  if (idx + 1 > e.count()) {
293  throw OutOfRangeException();
294  }
295 
296  if (!e.loadData(IfdTypeTrait<T>::size, m_base_offset)) {
297  throw TooBigException();
298  }
299 
300  const uint8_t *data = e.dataptr();
301  data += (IfdTypeTrait<T>::size * idx);
302  T val;
303  if (e.endian() == RawContainer::ENDIAN_LITTLE) {
304  val = IfdTypeTrait<T>::EL(data, e.count() - idx);
305  } else {
306  val = IfdTypeTrait<T>::BE(data, e.count() - idx);
307  }
308  return val;
309 }
310 
312 }
313 }
An IFD directory.
Definition: ifddir.hpp:51
const RawContainer & container() const
The container for the IfdDir, const.
Definition: ifddir.hpp:108
std::vector< Ref > RefVec
Vector of shared ptr of IfdDir.
Definition: ifddir.hpp:61
bool isThumbnail() const
The IFD is for a thumnail.
Definition: ifddir.cpp:46
void setTagTable(const TagTable &tag_table)
Set the tag table for tag to name correspondance.
Definition: ifddir.hpp:211
off_t nextIFD()
Get the offset of the next IFD in absolute.
Definition: ifddir.cpp:116
Ref getMakerNoteIfd(or_rawfile_type file_type)
Get the MakerNote IFD.
Definition: ifddir.cpp:197
const Entries & entries() const
Direct access to the entries.
Definition: ifddir.hpp:128
virtual bool load()
Load the directory to memory.
Definition: ifddir.cpp:65
RawContainer::EndianType endian() const
the Container endian
Definition: ifddir.hpp:137
MetaValue * makeMetaValue(IfdEntry &e) const
Make a meta value out of the IFD entry.
Definition: ifddir.cpp:290
IfdDirType type() const
Get the type of the IfdDir.
Definition: ifddir.hpp:78
Option< T > getValue(uint16_t id) const
Get a T value from an entry.
Definition: ifddir.hpp:156
void setType(IfdDirType type_)
Set the type of the IfdDir.
Definition: ifddir.hpp:81
RawContainer & container()
The container for the IfdDir.
Definition: ifddir.hpp:110
std::map< uint16_t, IfdEntry::Ref > Entries
Ifd Entries map type.
Definition: ifddir.hpp:66
off_t baseOffset() const
Get the base offset for the data.
Definition: ifddir.hpp:88
bool isPrimary() const
The IFD is a primary in the TIFF/EP sense.
Definition: ifddir.cpp:40
Ref getExifIFD()
Get the Exif IFD.
Definition: ifddir.cpp:179
const char * getTagName(uint32_t tag) const
Return the tag name for tag.
Definition: ifddir.cpp:218
void setEndian(RawContainer::EndianType _endian)
Set the endian for the IFD.
Definition: ifddir.hpp:146
uint32_t getEntryIntegerArrayItemValue(IfdEntry &e, int idx) const
Return the integer value at index. It will coerce the type.
Definition: ifddir.cpp:227
Ref getSubIFD(uint32_t idx=0) const
Get the SubIFD at index idx.
Definition: ifddir.cpp:137
void setBaseOffset(off_t base)
Set the base offset.
Definition: ifddir.hpp:91
IfdEntry::Ref getEntry(uint16_t id) const
Get the IfdEntry for the tag id.
Definition: ifddir.cpp:96
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Definition: ifddir.hpp:56
std::weak_ptr< IfdDir > WeakRef
Weak ptr of an IfdDir.
Definition: ifddir.hpp:54
Option< std::vector< IfdDir::Ref > > getSubIFDs()
Get all SubIFDs.
Definition: ifddir.cpp:157
int numTags()
Return the number of entries.
Definition: ifddir.hpp:120
off_t offset() const
Return the offset.
Definition: ifddir.hpp:106
Option< uint32_t > getIntegerValue(uint16_t id)
Get an loosely typed integer value from an entry.
Definition: ifddir.cpp:107
IfdDir(off_t _offset, RawContainer &_container, IfdDirType _type, const TagTable &tag_table=exif_tag_names)
Construct an IfdDir.
Definition: ifddir.cpp:52
An entry in the IfdDir.
Definition: ifdentry.hpp:199
uint32_t count() const noexcept
The count of items in the entry.
Definition: ifdentry.hpp:223
std::shared_ptr< IfdEntry > Ref
IfdEntry reference (ie shared pointer)
Definition: ifdentry.hpp:202
Generic interface for the RAW file container.
EndianType
Define the endian of the container.
Metadata value.
Definition: metavalue.hpp:35
Tag class to help create an empty Option.
Definition: option.hpp:41
An option type inspired by Rust.
Definition: option.hpp:47
T getEntryValue(IfdEntry &e, uint32_t idx=0, bool ignore_type=false) const
Get the typed entry value.
Definition: ifddir.hpp:283
Option< std::vector< T > > getEntryArrayValue(IfdEntry &e) const
Get the entry value as an array.
Definition: ifddir.hpp:257
or_ifd_dir_type
Type of IfdDir.
Definition: consts.h:140
or_rawfile_type
Types of RAW files.
Definition: consts.h:59
Global namespace for libopenraw.
Definition: arwfile.cpp:29
Describe an IFD type.
Definition: ifdentry.hpp:55