From 496807b616744117fe8ce8dbac50261a7e8b6fbe Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 13 Feb 2025 23:28:23 +0100 Subject: [PATCH] Add exif and xmp to full resolution images saved to disk --- openVulkanoCpp/AR/ArFrame.hpp | 2 ++ openVulkanoCpp/AR/ArRecorder.cpp | 31 +++++++++++++++++++++++++++---- openVulkanoCpp/AR/ArType.hpp | 5 ++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/openVulkanoCpp/AR/ArFrame.hpp b/openVulkanoCpp/AR/ArFrame.hpp index 40f832c..d1dd99d 100644 --- a/openVulkanoCpp/AR/ArFrame.hpp +++ b/openVulkanoCpp/AR/ArFrame.hpp @@ -153,6 +153,8 @@ namespace OpenVulkano::AR [[nodiscard]] virtual Math::Matrix4f GetCameraViewForCurrentDeviceOrientation() = 0; [[nodiscard]] const Math::Matrix4f& GetCameraProjection() const { return frameMetadata.projection; } + + [[nodiscard]] const Math::CameraIntrinsicWithResolution& GetCameraIntrinsic() const { return frameMetadata.intrinsic; } [[nodiscard]] virtual Math::Matrix4f GetCameraProjection(Math::Vector2f viewportSize, float near = 0.25f, float far = 250.0f) = 0; diff --git a/openVulkanoCpp/AR/ArRecorder.cpp b/openVulkanoCpp/AR/ArRecorder.cpp index 1503f31..1c23438 100644 --- a/openVulkanoCpp/AR/ArRecorder.cpp +++ b/openVulkanoCpp/AR/ArRecorder.cpp @@ -14,6 +14,9 @@ #include "Base/BlockProfiler.hpp" #include "Base/Logger.hpp" #include "Image/YuvUtils.hpp" +#include "Image/ExifBuilder.hpp" +#include "Image/XmpBuilder.hpp" +#include "Image/JpegWithTagsWriter.hpp" #include #include #if __has_include("turbojpeg.h") @@ -25,10 +28,10 @@ namespace OpenVulkano::AR { namespace { - constexpr int JPEG_QUALITY_DS = 85; + constexpr int JPEG_QUALITY_DS = 90; constexpr int JPEG_QUALITY_FS = 100; - std::filesystem::path GeneratePath(const std::filesystem::path& baseDir, std::string_view name) + std::filesystem::path GeneratePath(const std::filesystem::path& baseDir, const std::string_view name) { std::stringstream ss; auto t = std::time(nullptr); @@ -108,9 +111,29 @@ namespace OpenVulkano::AR colorWriter->AddFile(fileName.c_str(), outBuffer, size); if (path) [[unlikely]] { - std::ofstream outFile(*path, std::ios::binary); + /*std::ofstream outFile(*path, std::ios::binary); outFile.write(reinterpret_cast(outBuffer), size); - outFile.close(); + outFile.close();*/ + Image::ExifBuilder exifBuilder; + exifBuilder.model = arFrame->GetLensModel(); + exifBuilder.exposureTime = Image::RationalValue(1, 1.0f / arFrame->GetExposureTime()); + exifBuilder.SetOrientation(atan2f(arFrame->GetCameraTransformation()[0][1], arFrame->GetCameraTransformation()[1][1])); + exifBuilder.dateTaken = exifBuilder.GetCurrentTimestamp(); + exifBuilder.make = arFrame->GetArSession()->GetArType().GetVendorName(); + exifBuilder.SetResolution(); + exifBuilder.fNumber = arFrame->GetFNumber(); + exifBuilder.focalLength = arFrame->GetFocalLength(); + auto exif = exifBuilder.Build(); + Image::XmpBuilder xmpBuilder; + xmpBuilder.SetPose(arFrame->GetPose()); + xmpBuilder.SetCreateDate(exifBuilder.dateTaken); //TODO + xmpBuilder.SetExposureTime(arFrame->GetExposureTime()); + xmpBuilder.SetFocalLength(arFrame->GetFocalLength()); + xmpBuilder.SetCameraIntrinsic(arFrame->GetCameraIntrinsic()); + JpegWithTagsWriter writer(*path); + writer.WriteExifTag(exif); + writer.WriteXmpTag(xmpBuilder.Finalize()); + writer.WriteImageData({ outBuffer, size }); } } tjFree(outBuffer); diff --git a/openVulkanoCpp/AR/ArType.hpp b/openVulkanoCpp/AR/ArType.hpp index 4ef1298..dafab85 100644 --- a/openVulkanoCpp/AR/ArType.hpp +++ b/openVulkanoCpp/AR/ArType.hpp @@ -12,7 +12,8 @@ namespace OpenVulkano::AR { class ArType final { - static inline constexpr std::string_view HUMAN_READABLE_NAMES[] = { "Unknown", "ARKit", "ARCore" }; + static constexpr std::string_view HUMAN_READABLE_NAMES[] = { "Unknown", "ARKit", "ARCore" }; + static constexpr std::string_view VENDOR_NAME[] = { "Unknown", "Apple", "Google" }; public: enum Type : uint8_t { UNKNOWN = 0, AR_KIT, AR_CORE }; @@ -38,6 +39,8 @@ namespace OpenVulkano::AR return HUMAN_READABLE_NAMES[m_type]; } + [[nodiscard]] const std::string_view& GetVendorName() const { return VENDOR_NAME[m_type]; } + static ArType GetFromHumanReadableName(const std::string_view& name) { uint8_t i = 0;