22 #include "endianutils.hpp"
24 #include "ciffifd.hpp"
25 #include "ciffcontainer.hpp"
26 #include "crwfile.hpp"
33 :
IfdDir(0, container, _type)
42 auto entry = std::make_shared<IfdEntry>(
id, IFD::EXIF_FORMAT_ASCII,
43 str.size() + 1, 0, *
this,
true);
44 entry->setData(
reinterpret_cast<const uint8_t*
>(str.c_str()), str.size() + 1);
57 auto w = img_spec->imageWidth;
58 auto h = img_spec->imageHeight;
59 auto bpc = img_spec->componentBitDepth;
71 auto entry = std::make_shared<IfdEntry>(EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_SHORT,
74 entry = std::make_shared<IfdEntry>(EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_SHORT,
77 entry = std::make_shared<IfdEntry>(EXIF_TAG_BITS_PER_SAMPLE, EXIF_FORMAT_SHORT,
79 m_entries[EXIF_TAG_BITS_PER_SAMPLE] = entry;
82 auto val =
m_file.getOrientation();
84 auto entry = std::make_shared<IfdEntry>(EXIF_TAG_ORIENTATION, EXIF_FORMAT_SHORT,
85 1, val.value(), *
this,
true);
88 auto val_str =
m_file.getMakeOrModel(EXIF_TAG_MAKE);
93 val_str =
m_file.getMakeOrModel(EXIF_TAG_MODEL);
108 typedef std::vector<IfdEntry::Ref> (*Converter)(
const RecordEntry& e,
Heap& heap,
CiffIfd& ifd, uint16_t exifTag);
117 std::vector<IfdEntry::Ref> translateFocalLength(
const RecordEntry& e,
Heap&,
CiffIfd& ifd, uint16_t exifTag)
122 auto data = boost::get<RecordEntry::InRec>(e.
data);
126 fl = IfdTypeTrait<uint16_t>::BE(data.c_array() + 2,
sizeof(uint16_t));
129 CIFFContainer* ciffc =
dynamic_cast<CIFFContainer*
>(&ifd.
container());
130 auto csettings = ciffc->getCameraSettings();
131 if (csettings.size() >= 26) {
135 uint32_t r[] = { fl, fu };
136 auto ifdentry = std::make_shared<IfdEntry>(exifTag, EXIF_FORMAT_RATIONAL, 1, 0, ifd,
true);
137 ifdentry->setData(
reinterpret_cast<uint8_t*
>(&r), 8);
141 std::vector<IfdEntry::Ref> translateDate(
const RecordEntry& e, Heap& heap, CiffIfd& ifd, uint16_t)
145 e.fetchData(&heap, &data, 12);
147 char date[] =
"0000:00:00 00:00:00";
148 auto d2 = gmtime_r(&t, &d);
150 strftime(date, 20,
"%Y:%m:%d %H:%M:%S", d2);
153 ifd.entryForString(EXIF_TAG_DATE_TIME_ORIGINAL, date),
154 ifd.entryForString(EXIF_TAG_DATE_TIME_DIGITIZED, date),
158 std::vector<IfdEntry::Ref> translateSerial(
const RecordEntry& e, Heap& , CiffIfd& ifd, uint16_t exifTag)
161 LOGASSERT(e.inRecord());
162 auto data = boost::get<RecordEntry::InRec>(e.data);
164 serial_v = IfdTypeTrait<uint32_t>::EL(data.c_array(),
sizeof(uint32_t));
166 serial_v = IfdTypeTrait<uint32_t>::BE(data.c_array() + 2,
sizeof(uint32_t));
169 snprintf(serial, 10,
"%X", serial_v);
170 return { ifd.entryForString(exifTag, serial) };
173 std::vector<IfdEntry::Ref> translateString(
const RecordEntry& e, Heap& heap, CiffIfd& ifd, uint16_t exifTag)
175 std::string val_str = e.getString(heap);
176 return { ifd.entryForString(exifTag, val_str) };
179 std::vector<IfdEntry::Ref> translateMakeModel(
const RecordEntry& e, Heap& heap, CiffIfd& ifd, uint16_t exifTag)
181 return { ifd.entryForString(exifTag, e.getString(heap)) };
184 std::vector<IfdEntry::Ref> translateCameraSettings(
const RecordEntry& e, Heap& heap, CiffIfd& ifd, uint16_t )
186 std::vector<IfdEntry::Ref> entries;
187 auto count = e.count();
189 auto file = ifd.container().file();
190 file->seek(heap.offset() + e.offset(), SEEK_SET);
191 size_t countRead = ifd.container().readUInt16Array(file, settings, count);
192 if (count != countRead) {
193 LOGERR(
"Not enough data for camera settings\n");
195 for (uint32_t i = 0; i < count; i++) {
198 if (settings[i] == 1) {
199 auto ifdentry = std::make_shared<IfdEntry>(
200 EXIF_TAG_SUBJECT_DISTANCE_RANGE, EXIF_FORMAT_SHORT, 1,
202 entries.push_back(ifdentry);
207 switch (settings[i]) {
225 auto ifdentry = std::make_shared<IfdEntry>(
226 EXIF_TAG_FLASH, EXIF_FORMAT_SHORT, 1, flash, ifd,
true);
227 entries.push_back(ifdentry);
231 uint16_t metering = 0;
232 switch (settings[i]) {
253 auto ifdentry = std::make_shared<IfdEntry>(
254 EXIF_TAG_METERING_MODE, EXIF_FORMAT_SHORT, 1, metering, ifd,
true);
255 entries.push_back(ifdentry);
259 uint16_t exposure = 0;
260 switch (settings[i]) {
284 auto ifdentry = std::make_shared<IfdEntry>(
285 EXIF_TAG_METERING_MODE, EXIF_FORMAT_SHORT, 1, exposure, ifd,
true);
286 entries.push_back(ifdentry);
298 static const std::multimap<uint16_t, Ciff2Exif> ciff_exif_map = {
299 { TAG_FOCALLENGTH, { EXIF_TAG_FOCAL_LENGTH,
OR_IFD_EXIF, &translateFocalLength } },
303 { TAG_RAWMAKEMODEL, { EXIF_TAG_MAKE,
OR_IFD_MAIN, &translateMakeModel } },
304 { TAG_RAWMAKEMODEL, { EXIF_TAG_MODEL,
OR_IFD_MAIN, &translateMakeModel } },
305 { TAG_OWNERNAME, { EXIF_TAG_CAMERA_OWNER_NAME,
OR_IFD_EXIF, &translateString } },
306 { TAG_SERIALNUMBER, { EXIF_TAG_BODY_SERIAL_NUMBER,
OR_IFD_EXIF, &translateSerial } },
307 { TAG_CAPTUREDTIME, { 0,
OR_IFD_EXIF, &translateDate } },
308 { TAG_CAMERASETTINGS, { 0,
OR_IFD_EXIF, &translateCameraSettings } }
311 std::vector<IfdEntry::Ref> translateRecordEntry(
const RecordEntry& e, Heap& heap, CiffIfd& ifd)
313 std::vector<IfdEntry::Ref> vec;
315 const CIFFContainer* ciffc =
dynamic_cast<const CIFFContainer*
>(&ifd.container());
317 Heap h = e.heap(heap, ciffc);
318 for (
const auto& rec : h.records()) {
319 auto r = translateRecordEntry(rec.second, h, ifd);
320 vec.insert(vec.begin(), r.begin(), r.end());
324 auto iter = ciff_exif_map.find(TAGCODE(e.typeCode));
325 if (iter != ciff_exif_map.end()) {
327 if (iter->first != (TAGCODE(e.typeCode))) {
332 if (iter->second.dest == ifd.type()) {
333 if (iter->second.converter) {
335 iter->second.converter.value_ref()(e, heap, ifd, iter->second.exifTag);
336 vec.insert(vec.end(), values.begin(), values.end());
339 std::make_shared<IfdEntry>(
340 iter->second.exifTag, e.exifType(), e.count(), 0, ifd));
344 }
while(iter != ciff_exif_map.end());
360 for (
const auto& rec : propsRecs) {
361 auto ifdentries = translateRecordEntry(rec.second, *props, *
this);
362 if (!ifdentries.empty()) {
363 for (
auto entry2 : ifdentries) {
371 for (
const auto& rec : exifProps->records()) {
372 auto ifdentries = translateRecordEntry(rec.second, *exifProps, *
this);
373 if (!ifdentries.empty()) {
374 for (
auto entry2 : ifdentries) {
CiffExifIfd(CRWFile &ciff, RawContainer &container)
Construct an Exif IFD for a CIFF file.
virtual bool load() override
Load the directory to memory.
Special IFD to synthesize entries out of a CIFF file.
CiffIfd(CRWFile &ciff, RawContainer &container, IfdDirType _type)
construct a CIFF Ifd.
IfdEntry::Ref entryForString(uint16_t id, const std::string &str) const
CiffMainIfd(CRWFile &ciff, RawContainer &container)
Construct a main IFD for a CIFF file.
virtual bool load() override
Load the directory to memory.
A record entry from a CIFF Heap.
boost::variant< InRec, InHeap > data
virtual RawContainer * getContainer() const override
Get the container.
const RawContainer & container() const
The container for the IfdDir, const.
RawContainer::EndianType endian() const
the Container endian
std::shared_ptr< IfdEntry > Ref
IfdEntry reference (ie shared pointer)
Generic interface for the RAW file container.
Tag class to help create an empty Option.
An option type inspired by Rust.
std::shared_ptr< Heap > HeapRef
Shared ptr to Heap.
or_ifd_dir_type
Type of IfdDir.
@ OR_IFD_MAIN
Main (like in TIFF)
@ OR_IFD_EXIF
Exif metadata.
std::map< uint16_t, RecordEntry > RecordEntries
std::vector< uint16_t > CameraSettings
Camera settings are stored as array of 16-bits int.
Global namespace for libopenraw.