Files
OpenVulkano/openVulkanoCpp/IO/Files/Pfm.hpp
2020-12-16 20:44:33 +01:00

97 lines
2.8 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/.
*/
#pragma once
#include "Base/Utils.hpp"
#include <inttypes.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <memory>
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<PfmHeader, std::unique_ptr<float[]>> ReadImage(std::istream& inStream)
{
std::pair<PfmHeader, std::unique_ptr<float[]>> 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<float[]>(size);
inStream.read(reinterpret_cast<char*>(image.second.get()), size);
return image;
};
};
}