/* * 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/. */ #pragma once #include #include #include #include #include #include namespace OpenVulkano::Image { struct RationalValue { uint32_t nominator; uint32_t denominator; RationalValue() : nominator(0), denominator(0) {} explicit RationalValue(float val) : nominator(val * 10000), denominator(10000) {} explicit RationalValue(double val) : nominator(val * 10000), denominator(10000) {} explicit RationalValue(uint32_t nominator, uint32_t denominator = 1) : nominator(nominator), denominator(denominator) {} operator bool() const { return nominator || denominator; } RationalValue& operator =(float val) { nominator = val * 10000; denominator = 10000; return *this; } RationalValue& operator =(uint32_t val) { nominator = val; denominator = 1; return *this; } RationalValue& operator =(const RationalValue& val) = default; }; enum class LatitudeRef { NORTH, SOUTH, }; enum class LongitudeRef { EAST, WEST, }; enum class GPSTrackRef { TRUE_NORTH, MAGNETIC }; struct GPSCoords { int32_t degrees, minutes, seconds; std::variant ref; GPSCoords(float decimalDegrees, bool isLatitude); GPSCoords(int32_t degrees, int32_t minutes, int32_t seconds, LatitudeRef ref); GPSCoords(int32_t degrees, int32_t minutes, int32_t seconds, LongitudeRef ref); }; struct GPSInfo { GPSCoords latitude = { 0, 0, 0, LatitudeRef::NORTH }; GPSCoords longitude = { 0, 0, 0, LongitudeRef::EAST }; bool altitudeIsAboveSeaLevel = true; uint32_t altitude = 0; GPSTrackRef trackRef = GPSTrackRef::TRUE_NORTH; float track = 0; // range is [0.0; 360.0) void SetAltitude(float level); }; class ExifBuilder { public: int orientation = 0; std::string make; std::string model; RationalValue xResolution, yResolution; int resolutionUnit = 0; RationalValue exposureTime, fNumber, focalLength; std::string dateTaken; // format: yyyy:mm:dd hh:mm:ss std::string softwareUsed = "OpenVulkano"; std::optional gpsInfo; void SetResolution(uint32_t dpi = 72) { xResolution = yResolution = dpi; resolutionUnit = 2;} void SetOrientation(float orientationRad); void SetTime(std::time_t timestamp); // Typical usage is -> jpeg_write_marker(cinfo, JPEG_APP0 + 1, exif_data.data(), exif_data.size()); [[nodiscard]] std::vector Build(); [[nodiscard]] static std::string StringFromTime(std::time_t time); [[nodiscard]] static std::string GetCurrentTimestamp(); }; }