diff --git a/openVulkanoCpp/Image/ExifBuilder.cpp b/openVulkanoCpp/Image/ExifBuilder.cpp index 8a24616..d8e911b 100644 --- a/openVulkanoCpp/Image/ExifBuilder.cpp +++ b/openVulkanoCpp/Image/ExifBuilder.cpp @@ -127,6 +127,16 @@ namespace return result; } + int appendRational(std::vector& array, const OpenVulkano::Image::RationalValue& rational, bool endianSwap = false) + { + int result = array.size(); + + appendU32(array, rational.nominator, endianSwap); + appendU32(array, rational.denominator, endianSwap); + + return result; + } + int appendGPSCoords(std::vector& array, const OpenVulkano::Image::GPSCoords& coords, bool endianSwap = false) { int result = array.size(); @@ -210,30 +220,42 @@ namespace OpenVulkano::Image } // XResolution + int xresolutionOffset = 0; if(xresolution.nominator || xresolution.denominator) { appendU16(result, (uint16_t)IFDTag::XRESOLUTION, true); appendU16(result, (uint16_t)IFDValueType::RATIONAL, true); - appendU32(result, xresolution.nominator, true); - appendU32(result, xresolution.denominator, true); + appendU32(result, 1, true); // number of components + xresolutionOffset = appendU32(result, data.size(), true); + int offsetInData = appendRational(data, xresolution, true); + uint32_t* ptr = (uint32_t *)(result.data() + xresolutionOffset); + *ptr = offsetInData; } // YResolution + int yresolutionOffset = 0; if(yresolution.nominator || yresolution.denominator) { appendU16(result, (uint16_t)IFDTag::YRESOLUTION, true); appendU16(result, (uint16_t)IFDValueType::RATIONAL, true); - appendU32(result, yresolution.nominator, true); - appendU32(result, yresolution.denominator, true); + appendU32(result, 1, true); // number of components + yresolutionOffset = appendU32(result, data.size(), true); + int offsetInData = appendRational(data, yresolution, true); + uint32_t* ptr = (uint32_t *)(result.data() + yresolutionOffset); + *ptr = offsetInData; } // Exposure Time + int exposureTimeOffset = 0; if(exposureTime.nominator || exposureTime.denominator) { appendU16(result, (uint16_t)IFDTag::EXPOSURE_TIME, true); appendU16(result, (uint16_t)IFDValueType::RATIONAL, true); - appendU32(result, exposureTime.nominator, true); - appendU32(result, exposureTime.denominator, true); + appendU32(result, 1, true); // number of components + exposureTimeOffset = appendU32(result, data.size(), true); + int offsetInData = appendRational(data, exposureTime, true); + uint32_t* ptr = (uint32_t *)(result.data() + exposureTimeOffset); + *ptr = offsetInData; } // ResolutionUnit @@ -285,20 +307,41 @@ namespace OpenVulkano::Image appendVector(result, data); int ifdAndSubdataSize = result.size(); - if(modelOffset) + if(model != "") { uint32_t *ptr = (uint32_t *) (result.data() + modelOffset); *ptr += resultSize - EXIF_HEADER_SIZE; *ptr = endianSwap(*ptr); } - if(makeOffset) + if(make != "") { uint32_t *ptr = (uint32_t *) (result.data() + makeOffset); *ptr += resultSize - EXIF_HEADER_SIZE; *ptr = endianSwap(*ptr); } + if(xresolutionOffset) + { + uint32_t *ptr = (uint32_t *) (result.data() + xresolutionOffset); + *ptr += resultSize - EXIF_HEADER_SIZE; + *ptr = endianSwap(*ptr); + } + + if(yresolutionOffset) + { + uint32_t *ptr = (uint32_t *) (result.data() + yresolutionOffset); + *ptr += resultSize - EXIF_HEADER_SIZE; + *ptr = endianSwap(*ptr); + } + + if(exposureTimeOffset) + { + uint32_t *ptr = (uint32_t *) (result.data() + exposureTimeOffset); + *ptr += resultSize - EXIF_HEADER_SIZE; + *ptr = endianSwap(*ptr); + } + if(dateTakenOffset) { uint32_t *ptr = (uint32_t *) (result.data() + dateTakenOffset); @@ -319,7 +362,7 @@ namespace OpenVulkano::Image } // Writing GPS Info structure - int numberOfGPSInfoTags = 6; + int numberOfGPSInfoTags = 8; appendU16(result, numberOfGPSInfoTags, true); // Latitude Ref @@ -367,6 +410,23 @@ namespace OpenVulkano::Image appendU32(result, 1, true); // number of components int altitudeOffset = appendU32(result, 48); // 6 * sizeof(RationalValue) + // Track Ref + appendU16(result, 14, true); + appendU16(result, (uint16_t) IFDValueType::ASCII, true); + appendU32(result, 2, true); // 2 for T/M + \0 + appendU8(result, trackRef == GPSTrackRef::TRUE_ ? 'T' : 'M'); + appendU8(result, 0); + appendU8(result, 0); // padding + appendU8(result, 0); // padding + + // Track + appendU16(result, 15, true); + appendU16(result, (uint16_t) IFDValueType::RATIONAL, true); + appendU32(result, 1, true); // number of components + int trackOffset = appendU32(result, 56); // 7 * sizeof(RationalValue) + + // + int sizeOfResultSoFar = result.size(); // Latitude @@ -390,13 +450,25 @@ namespace OpenVulkano::Image *ptr = endianSwap(*ptr); } + // Track + { + uint32_t *ptr = (uint32_t *) (result.data() + trackOffset); + *ptr += sizeOfResultSoFar - EXIF_HEADER_SIZE; + *ptr = endianSwap(*ptr); + } + // appendGPSCoords(result, latitude, true); appendGPSCoords(result, longitude, true); + appendU32(result, altitude, true); appendU32(result, 1, true); // denominator for altitude + int const TRACK_PRECISION = 10000; + appendU32(result, track * TRACK_PRECISION, true); + appendU32(result, TRACK_PRECISION, true); + return result; } } \ No newline at end of file diff --git a/openVulkanoCpp/Image/ExifBuilder.hpp b/openVulkanoCpp/Image/ExifBuilder.hpp index 3b30024..b7062a4 100644 --- a/openVulkanoCpp/Image/ExifBuilder.hpp +++ b/openVulkanoCpp/Image/ExifBuilder.hpp @@ -27,6 +27,11 @@ namespace OpenVulkano::Image EAST, WEST, }; + enum class GPSTrackRef + { + TRUE_, + MAGNETIC + }; struct GPSCoords { @@ -55,6 +60,9 @@ namespace OpenVulkano::Image bool altitudeIsAboveSeaLevel = true; uint32_t altitude = 0; + GPSTrackRef trackRef = GPSTrackRef::TRUE_; + float track = 0; // range is [0.0; 360.0) + // Typical usage is -> jpeg_write_marker(cinfo, JPEG_APP0 + 1, exif_data.data(), exif_data.size()); std::vector build(); };