/* * 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 "ImageLoaderPfm.hpp" #include "Scene/DataFormat.hpp" #include #include #include #include #include namespace OpenVulkano::Image { std::unique_ptr ImageLoaderPfm::loadFromFile(const std::string& filePath) { std::ifstream file(filePath, std::ios::binary); if (!file.is_open()) { throw std::runtime_error("Failed to open PFM file: " + filePath); } std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); return loadFromMemory(buffer); } std::unique_ptr ImageLoaderPfm::loadFromMemory(const std::vector& buffer) { std::istringstream stream(std::string(buffer.begin(), buffer.end()), std::ios::binary); PfmImageHeader header = parseHeader(stream); size_t numChannels = header.isColor ? 3 : 1; size_t dataSize = header.width * header.height * numChannels * sizeof(float); std::vector data(header.width * header.height * numChannels); stream.read(reinterpret_cast(data.data()), dataSize); if (!header.isLittleEndian) { for (float& value : data) { uint8_t* ptr = reinterpret_cast(&value); std::reverse(ptr, ptr + sizeof(float)); } } for (int y = 0; y < header.height / 2; ++y) { for (int x = 0; x < header.width * numChannels; ++x) { std::swap(data[y * header.width * numChannels + x], data[(header.height - 1 - y) * header.width * numChannels + x]); } } auto image = std::make_unique(); image->resolution = { static_cast(header.width), static_cast(header.height), 1 }; image->dataFormat = header.isColor ? DataFormat::Format::R32G32B32_SFLOAT : DataFormat::Format::R32_SFLOAT; image->data = Array(dataSize); memcpy(image->data.Data(), data.data(), dataSize); return image; } Math::Vector2i ImageLoaderPfm::GetImageDimensions(const std::string& filename) { std::ifstream file(filename, std::ios::binary); if (!file.is_open()) { throw std::runtime_error("Failed to open PFM file: " + filename); } std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); std::istringstream stream(std::string(buffer.begin(), buffer.end()), std::ios::binary); PfmImageHeader header = parseHeader(stream); return { header.width, header.height }; } ImageLoaderPfm::PfmImageHeader ImageLoaderPfm::parseHeader(std::istringstream& stream) { ImageLoaderPfm::PfmImageHeader header; std::string magic; stream >> magic; header.isColor = (magic == "PF"); float endianess; stream >> header.width >> header.height >> endianess; stream.ignore(); header.isLittleEndian = endianess < 0; return header; } }