115 lines
4.6 KiB
C++
115 lines
4.6 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "XmpBuilder.hpp"
|
|
#include "Extensions/FmtFormatter.hpp"
|
|
|
|
namespace OpenVulkano::Image
|
|
{
|
|
XmpBuilder::XmpBuilder()
|
|
{
|
|
xmpData << "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"; // XMP Wrapper
|
|
xmpData << "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"><rdf:RDF"
|
|
" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
|
|
" xmlns:crs=\"http://ns.adobe.com/camera-raw-settings/1.0/\""
|
|
" xmlns:camera=\"http://ns.adobe.com/camera/1.0/\""
|
|
" xmlns:cineGeo=\"http://ns.adobe.com/cineGeo/1.0/\"" // Cinema/Geometric namespace
|
|
" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\"" // EXIF namespace
|
|
" xmlns:aux=\"http://ns.adobe.com/exif/1.0/aux/\"" // Auxiliary EXIF namespace
|
|
" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"" // Base XMP namespace
|
|
" xmlns:photoshop=\"http://ns.adobe.com/photoshop/1.0/\""
|
|
" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\""
|
|
"><rdf:Description rdf:about=\"\">";
|
|
}
|
|
|
|
std::string XmpBuilder::Finalize()
|
|
{
|
|
if (!complete)
|
|
{ // Finalize
|
|
xmpData << "</rdf:Description></rdf:RDF></x:xmpmeta>";
|
|
xmpData << "<?xpacket end=\"w\"?>"; // XMP Wrapper
|
|
complete = true;
|
|
}
|
|
return xmpData.str();
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetCameraIntrinsic(const Math::CameraIntrinsicWithResolution& intrinsic)
|
|
{
|
|
// Calibration matrix in row-major format
|
|
const auto& mat = intrinsic.GetMatrix();
|
|
xmpData << fmt::format("<camera:CalibrationMatrix>{} {} {} {} {} {} {} {} {}</camera:CalibrationMatrix>",
|
|
mat[0][0], mat[1][0], mat[2][0], mat[0][1], mat[1][1], mat[2][1], mat[0][2], mat[1][2], mat[2][2]);
|
|
xmpData << fmt::format("<camera:IntrinsicMatrix><rdf:Description>"
|
|
"<camera:FocalLengthX>{}</camera:FocalLengthX><camera:FocalLengthY>{}</camera:FocalLengthY>"
|
|
"<camera:PrincipalPointX>{}</camera:PrincipalPointX><camera:PrincipalPointY>{}</camera:PrincipalPointY>"
|
|
"</rdf:Description></camera:IntrinsicMatrix>",
|
|
intrinsic.Fx(), intrinsic.Fy(), intrinsic.Cx(), intrinsic.Cy() );
|
|
// Field of View
|
|
xmpData << fmt::format("<camera:FieldOfView><rdf:Description>"
|
|
"<camera:Horizontal>{}</camera:Horizontal><camera:Vertical>{}</camera:Vertical>"
|
|
"</rdf:Description></camera:FieldOfView>",
|
|
Math::Utils::degrees(intrinsic.GetFovX()), Math::Utils::degrees(intrinsic.GetFovY()));
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetPosition(const Math::Vector3f& position)
|
|
{
|
|
xmpData << fmt::format("<cineGeo:Position><rdf:Description>"
|
|
"<cineGeo:X>{}</cineGeo:X><cineGeo:Y>{}</cineGeo:Y><cineGeo:Z>{}</cineGeo:Z>"
|
|
"</rdf:Description></cineGeo:Position>",
|
|
position.x, position.y, position.z);
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetOrientation(const Math::Vector3f& orientation)
|
|
{
|
|
Math::Vector3f ori = Math::Utils::degrees(orientation);
|
|
xmpData << fmt::format("<cineGeo:Rotation><rdf:Description>"
|
|
"<cineGeo:X>{}</cineGeo:X><cineGeo:Y>{}</cineGeo:Y><cineGeo:Z>{}</cineGeo:Z>"
|
|
"</rdf:Description></cineGeo:Rotation>",
|
|
ori.x, ori.y, ori.z);
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetSensorSize(const Math::Vector2f& sensorSize)
|
|
{
|
|
xmpData << fmt::format("<camera:SensorSize><rdf:Description>"
|
|
"<camera:Width>{}</camera:Width><camera:Height>{}</camera:Height>"
|
|
"</rdf:Description></camera:SensorSize>",
|
|
sensorSize.x, sensorSize.y);
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetFocalLength(const float focalLengthMM)
|
|
{
|
|
xmpData << "<camera:FocalLength>" << focalLengthMM << "</camera:FocalLength>";
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetExposureTime(double exposureTime)
|
|
{
|
|
xmpData << fmt::format("<exif:ExposureTime>{0}</exif:ExposureTime><aux:ExposureTime>{0}</aux:ExposureTime>", exposureTime);
|
|
return *this;
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetCreateDateNow()
|
|
{
|
|
std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
SetCreateDate(currentTime);
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetCreateDate(const std::time_t time)
|
|
{
|
|
return SetCreateDate(fmt::format("{:%FT%T%Ez}", fmt::localtime(time)));
|
|
}
|
|
|
|
[[maybe_unused]] XmpBuilder& XmpBuilder::SetCreateDate(const std::string& createDate)
|
|
{
|
|
xmpData << "<xmp:CreateDate>" << createDate << "</xmp:CreateDate>";
|
|
return *this;
|
|
}
|
|
}
|