27 #include "io/stream.hpp"
28 #include "ifdfilecontainer.hpp"
30 #include "makernotedir.hpp"
31 #include "metavalue.hpp"
32 #include "exif/exif_tags.hpp"
34 using namespace Debug;
40 bool IfdDir::isPrimary()
const
42 auto result = getValue<uint32_t>(IFD::EXIF_TAG_NEW_SUBFILE_TYPE);
43 return result && (result.value() == 0);
46 bool IfdDir::isThumbnail()
const
48 auto result = getValue<uint32_t>(IFD::EXIF_TAG_NEW_SUBFILE_TYPE);
49 return result && (result.value() == 1);
54 , m_offset(_offset), m_container(_container), m_entries()
55 , m_tag_table(&tag_table)
57 , m_endian(_container.endian())
67 LOGDBG1(
"IfdDir::load() m_offset =%lld\n", (
long long int)m_offset);
69 auto file = m_container.file();
71 file->seek(m_offset, SEEK_SET);
73 int16_t numEntries = m_container.
readInt16(file, m_endian).value_or(0);
74 LOGDBG1(
"num entries %d\n", numEntries);
76 for (int16_t i = 0; i < numEntries; i++) {
78 auto id = m_container.
readUInt16(file, m_endian);
80 auto count = m_container.
readInt32(file, m_endian);
81 size_t sz = file->read(&data, 4);
82 if (
id.empty() ||
type.empty() || count.empty() || sz != 4) {
83 LOGERR(
"Failed to read entry %d\n", i);
86 uint16_t n_id =
id.value();
88 std::make_shared<IfdEntry>(n_id,
type.value(),
89 count.value(), data, *
this);
98 std::map<uint16_t, IfdEntry::Ref>::const_iterator iter;
118 int16_t numEntries = 0;
119 auto file = m_container.file();
122 file->seek(m_offset, SEEK_SET);
123 numEntries = m_container.
readInt16(file, m_endian).value_or(0);
124 LOGDBG1(
"numEntries =%d shifting %d bytes\n", numEntries, (numEntries * 12) + 2);
129 file->seek(m_offset + (numEntries * 12) + 2, SEEK_SET);
131 return m_container.
readInt32(file, m_endian).value_or(0);
142 auto result = getEntryArrayValue<uint32_t>(*e);
144 std::vector<uint32_t> offsets = result.value();
145 if (idx >= offsets.size()) {
146 Ref ref = std::make_shared<IfdDir>(offsets[idx], m_container,
OR_IFD_SUBIFD);
151 LOGERR(
"Can't get SubIFD offsets\n");
159 std::vector<IfdDir::Ref> ifds;
162 auto result = getEntryArrayValue<uint32_t>(*e);
164 std::vector<uint32_t> offsets = result.value();
165 for (
auto offset_ : offsets) {
181 auto result = getValue<uint32_t>(IFD::EXIF_TAG_EXIF_IFD_POINTER);
182 if (result.empty()) {
183 LOGDBG1(
"Exif IFD offset not found.\n");
187 uint32_t val_offset = result.value();
188 LOGDBG1(
"Exif IFD offset (uncorrected) = %u\n", val_offset);
189 val_offset += m_container.exifOffsetCorrection();
190 LOGDBG1(
"Exif IFD offset = %u\n", val_offset);
192 Ref ref = std::make_shared<IfdDir>(val_offset, m_container,
OR_IFD_EXIF);
199 uint32_t val_offset = 0;
202 LOGDBG1(
"MakerNote IFD offset not found.\n");
203 return MakerNoteDir::Ref();
205 val_offset = e->offset();
206 LOGDBG1(
"MakerNote IFD offset (uncorrected) = %u\n", val_offset);
207 val_offset += m_container.exifOffsetCorrection();
208 LOGDBG1(
"MakerNote IFD offset = %u\n", val_offset);
220 auto iter = m_tag_table->find(tag);
221 if (iter != m_tag_table->end()) {
234 case IFD::EXIF_FORMAT_LONG:
235 v = getEntryValue<uint32_t>(e, idx);
237 case IFD::EXIF_FORMAT_SHORT:
238 v = getEntryValue<uint16_t>(e, idx);
240 case IFD::EXIF_FORMAT_RATIONAL:
242 IFD::ORRational r = getEntryValue<IFD::ORRational>(e, idx);
254 catch (
const std::exception & ex) {
255 LOGERR(
"Exception raised %s fetch integer value for %d\n", ex.what(), e.
id());
269 std::vector<T> v = result.value();
270 values.insert(values.end(), v.cbegin(), v.cend());
275 template<
class T,
class T2>
276 void convert(
const IfdDir& dir, Internals::IfdEntry& e, std::vector<MetaValue::value_t>& values)
278 auto result = dir.getEntryArrayValue<T>(e);
281 std::vector<T> v = result.value();
282 for (
const auto & elem : v) {
283 values.push_back(T2(elem));
292 std::vector<MetaValue::value_t> values;
294 switch (entry.
type()) {
295 case Internals::IFD::EXIF_FORMAT_BYTE:
297 convert<uint8_t, uint32_t>(*
this, entry, values);
300 case Internals::IFD::EXIF_FORMAT_ASCII:
302 convert<std::string>(*
this, entry, values);
305 case Internals::IFD::EXIF_FORMAT_SHORT:
307 convert<uint16_t, uint32_t>(*
this, entry, values);
310 case Internals::IFD::EXIF_FORMAT_LONG:
312 convert<uint32_t>(*
this, entry, values);
315 case Internals::IFD::EXIF_FORMAT_RATIONAL:
317 convert<Internals::IFD::ORRational>(*
this, entry, values);
320 case Internals::IFD::EXIF_FORMAT_SBYTE:
322 convert<int8_t, int32_t>(*
this, entry, values);
325 case Internals::IFD::EXIF_FORMAT_UNDEFINED:
327 convert<uint8_t>(*
this, entry, values);
330 case Internals::IFD::EXIF_FORMAT_SSHORT:
332 convert<int16_t, int32_t>(*
this, entry, values);
335 case Internals::IFD::EXIF_FORMAT_SLONG:
337 convert<int32_t>(*
this, entry, values);
340 case Internals::IFD::EXIF_FORMAT_SRATIONAL:
342 convert<Internals::IFD::ORSRational>(*
this, entry, values);
346 LOGDBG1(
"unhandled type %d\n",
type());
off_t nextIFD()
Get the offset of the next IFD in absolute.
Ref getMakerNoteIfd(or_rawfile_type file_type)
Get the MakerNote IFD.
virtual bool load()
Load the directory to memory.
MetaValue * makeMetaValue(IfdEntry &e) const
Make a meta value out of the IFD entry.
IfdDirType type() const
Get the type of the IfdDir.
Ref getExifIFD()
Get the Exif IFD.
const char * getTagName(uint32_t tag) const
Return the tag name for tag.
uint32_t getEntryIntegerArrayItemValue(IfdEntry &e, int idx) const
Return the integer value at index. It will coerce the type.
Ref getSubIFD(uint32_t idx=0) const
Get the SubIFD at index idx.
IfdEntry::Ref getEntry(uint16_t id) const
Get the IfdEntry for the tag id.
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Option< std::vector< IfdDir::Ref > > getSubIFDs()
Get all SubIFDs.
Option< uint32_t > getIntegerValue(uint16_t id)
Get an loosely typed integer value from an entry.
int16_t id() const noexcept
id (i.e. tag) of the entry
int16_t type() const noexcept
Type of the entry data.
std::shared_ptr< IfdEntry > Ref
IfdEntry reference (ie shared pointer)
static Ref createMakerNote(off_t offset, RawContainer &container, or_rawfile_type file_type)
Generic interface for the RAW file container.
Option< uint16_t > readUInt16(const IO::Stream::Ptr &f, EndianType endian) const
Read an uint16 following the m_endian set.
Option< int32_t > readInt32(const IO::Stream::Ptr &f, EndianType endian) const
Read an int32 following the m_endian set.
Option< int16_t > readInt16(const IO::Stream::Ptr &f, EndianType endian) const
Read an int16 following the m_endian set.
An option type inspired by Rust.
Option< std::vector< T > > getEntryArrayValue(IfdEntry &e) const
Get the entry value as an array.
or_ifd_dir_type
Type of IfdDir.
or_rawfile_type
Types of RAW files.
@ OR_IFD_EXIF
Exif metadata.
Global namespace for libopenraw.