in cpp/spectrum/image/metadata/Entries.cpp [287:350]
std::vector<std::uint8_t> Entries::makeData() const {
const std::uint16_t count = expectedCountOfTiffEntries();
const std::uint32_t tiffIfdValuesOffset = MemoryLayout::DEFAULT_OFFSET +
sizeof(std::uint16_t) + count * sizeof(Entry::MemoryLayout) +
sizeof(std::uint32_t);
std::vector<std::uint8_t> data = utils::makeDataFromValue(MemoryLayout());
std::vector<std::uint8_t> trailingData;
// In reality data will need a bit more space as it also contains the trailing
// variable-length values.
data.reserve(
(count + _exif.size() + _gps.size()) * sizeof(Entry::MemoryLayout));
// Add tiff entries count to data.
utils::insertValueIntoData(count, data);
for (const auto& pair : _tiff) {
if (pair.first != Entry::EXIF_IFD_POINTER &&
pair.first != Entry::GPS_INFO_IFD_POINTER) {
pair.second.insertIntoDataAndValuesData(
data, trailingData, tiffIfdValuesOffset);
}
}
const std::uint32_t tiffValuesSize =
SPECTRUM_CONVERT_OR_THROW(trailingData.size(), std::uint32_t);
// EXIF IFD begins after the tiff values. This only works because both entries
// that will be conditionally added later (EXIF_IFD & GPS_IFD) have already
// been accounted for in tiffIfdValuesOffset *and* we're sure both entry's
// values fit within an entry's fixed size.
const std::uint32_t exifIfdOffset = tiffIfdValuesOffset +
SPECTRUM_CONVERT_OR_THROW(trailingData.size(), std::uint32_t);
if (!_exif.empty()) {
Entry(Entry::EXIF_IFD_POINTER, Entry::LONG, exifIfdOffset)
.insertIntoData(data);
}
// Add EXIF entries to trailingData. They cannot be added to data directly as
// the GPS IFD offset entry may be added later on if needed.
insertSecondaryEntriesIntoData(_exif, trailingData, exifIfdOffset);
const std::uint32_t gpsIfdOffset = exifIfdOffset +
SPECTRUM_CONVERT_OR_THROW(trailingData.size(), std::uint32_t) -
tiffValuesSize;
if (!_gps.empty()) {
Entry(Entry::GPS_INFO_IFD_POINTER, Entry::LONG, gpsIfdOffset)
.insertIntoData(data);
}
// Adds Next IFD offset
utils::insertValueIntoData(std::uint32_t{0}, data);
// By this point we won't be adding any more tiff entries so we can safely
// append the TIFF values + EXIF entries & values at the end of data.
data.insert(data.end(), trailingData.begin(), trailingData.end());
// And finally append both GPS entries & values if needed.
insertSecondaryEntriesIntoData(_gps, data, gpsIfdOffset);
SPECTRUM_ERROR_IF(data.size() > MAX_DATA_LENGTH, error::ExifLengthTooLarge);
return data;
}