diff --git a/openVulkanoCpp/IO/Files/Pfm.hpp b/openVulkanoCpp/IO/Files/Pfm.hpp new file mode 100644 index 0000000..c987ef0 --- /dev/null +++ b/openVulkanoCpp/IO/Files/Pfm.hpp @@ -0,0 +1,97 @@ +/* + * 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 "Base/Utils.hpp" +#include +#include +#include +#include +#include + +namespace openVulkanoCpp +{ + //TODO handle comments + class PfmHeader + { + public: + static constexpr std::string_view FILE_TYPE = "PFM"; + static constexpr std::string_view FILE_EXT = ".pfm"; + + uint32_t width, height; + float maxValue; + bool color, littleEndian; + + PfmHeader() : width(0), height(0), maxValue(0), color(false), littleEndian(Utils::IsLittleEndian()) {} + + PfmHeader(uint32_t width, uint32_t height, float maxValue, bool color) : + width(width), height(height), maxValue(maxValue), color(color), littleEndian(Utils::IsLittleEndian()) + {} + + constexpr PfmHeader(uint32_t width, uint32_t height, float maxValue, bool color, bool littleEndian) : + width(width), height(height), maxValue(maxValue), color(color), littleEndian(littleEndian) + {} + + std::string ToString() const + { + std::stringstream headerStream; + headerStream << *this; + return headerStream.str(); + } + + friend std::ostream& operator<< (std::ostream& outStream, const PfmHeader& pfmHeader) + { + outStream << (pfmHeader.color ? "PF" : "Pf") << '\n'; + outStream << pfmHeader.width << ' ' << pfmHeader.height << '\n'; + if (pfmHeader.littleEndian) outStream << '-'; + outStream << std::fixed << std::setprecision(1) << pfmHeader.maxValue << '\n'; + return outStream; + } + + friend std::istream& operator>> (std::istream& inStream, PfmHeader& pfmHeader) + { + std::string marker; + inStream >> marker; + if (marker == "PF") pfmHeader.color = true; + else if (marker == "Pf") pfmHeader.color = false; + else throw std::runtime_error("Malformed PFM header!"); + inStream >> pfmHeader.width >> pfmHeader.height; + inStream >> pfmHeader.maxValue; + if (pfmHeader.maxValue < 0) + { + pfmHeader.maxValue *= -1; + pfmHeader.littleEndian = true; + } + else + { + pfmHeader.littleEndian = false; + } + return inStream; + } + + constexpr size_t GetImageSize() const + { + size_t size = height * width * sizeof(float); + if (color) size *= 3; + return size; + } + + static std::pair> ReadImage(std::istream& inStream) + { + std::pair> image; + inStream >> image.first; + + if (Utils::IsLittleEndian() != image.first.littleEndian) + throw std::runtime_error("Conversion support for endianness not implemented"); + + size_t size = image.first.height * image.first.width; + image.second = std::make_unique(size); + inStream.read(reinterpret_cast(image.second.get()), size); + return image; + }; + }; +} \ No newline at end of file