5#include <BufferStream.h>
16 BufferStreamReadOnly reader{pplData};
19 const auto imageCount = reader.read<uint32_t>();
20 reader.skip<uint32_t>(4);
21 for (uint32_t i = 0; i < imageCount; i++) {
22 const auto lod = reader.read<uint32_t>();
23 const auto offset = reader.read<uint32_t>();
24 const auto length = reader.read<uint32_t>();
25 const auto width = reader.read<uint32_t>();
26 const auto height = reader.read<uint32_t>();
27 reader.skip<uint32_t>(3);
32 .data = {pplData.data() + offset, pplData.data() + offset + length},
38 :
PPL(
fs::readFileBuffer(pplPath)) {}
40PPL::operator bool()
const {
41 return !this->
images.empty();
65 for (
auto& [width, height, data] : this->
images | std::views::values) {
72 return this->
images.contains(lod);
76 auto view = std::views::keys(this->
images);
77 return {view.begin(), view.end()};
84 return &this->
images.at(lod);
91 const auto& [width, height, data] = this->
images.at(lod);
103bool PPL::setImage(std::span<const std::byte> imageData,
ImageFormat format_, uint32_t width, uint32_t height, uint32_t lod,
float quality) {
104 if (!width || !height) {
116 if (!width || !height || !resizedWidth || !resizedHeight) {
128bool PPL::setImage(
const std::filesystem::path& imagePath, uint32_t lod,
float quality) {
130 int inputWidth, inputHeight, inputFrameCount;
134 if (inputFormat ==
ImageFormat::EMPTY || !inputWidth || !inputHeight || !inputFrameCount) {
139 if (inputFrameCount == 1) {
140 return this->
setImage(imageData_, inputFormat, inputWidth, inputHeight, lod, quality);
149 int inputWidth, inputHeight, inputFrameCount;
153 if (inputFormat ==
ImageFormat::EMPTY || !inputWidth || !inputHeight || !inputFrameCount) {
158 if (inputFrameCount == 1) {
159 return this->
setImage(imageData_, inputFormat, inputWidth, inputHeight, resizedWidth, resizedHeight, lod, filter, quality);
163 return this->
setImage({imageData_.data(),
ImageFormatDetails::getDataLength(inputFormat, inputWidth, inputHeight)}, inputFormat, inputWidth, inputHeight, resizedWidth, resizedHeight, lod, filter, quality);
167 if (this->
images.contains(lod)) {
182 if (
auto data = this->
saveImageToFile(lod, fileFormat); !data.empty()) {
189 static constexpr auto ALIGNMENT = 512;
191 std::vector<std::byte> out;
192 BufferStream writer{out};
194 static constexpr auto HEADER_SIZE =
sizeof(uint32_t) * 8;
196 writer.write<uint32_t>(this->
images.size());
198 while (writer.tell() < ALIGNMENT) {
199 writer.write<uint32_t>(0);
201 writer.seek(HEADER_SIZE);
203 uint32_t currentOffset = ALIGNMENT;
204 for (
const auto& [lod, image] : this->
images) {
205 writer << lod << currentOffset << static_cast<uint32_t>(image.data.size()) << image.width << image.height;
206 for (
int i = 0; i < 3; i++) {
207 writer.write<uint32_t>(0);
209 const auto seekPoint = writer.tell();
210 writer.seek_u(currentOffset).write(image.data);
212 for (
int i = 0; i < alignment; i++) {
213 writer.write<uint8_t>(0);
215 writer.seek_u(seekPoint);
216 currentOffset += image.data.size() + alignment;
218 writer.seek(0, std::ios::end);
220 out.resize(writer.size());
ImageFormat getFormat() const
const Image * getImageRaw(uint32_t lod=0) const
std::vector< std::byte > saveImageToFile(uint32_t lod=0, ImageConversion::FileFormat fileFormat=ImageConversion::FileFormat::DEFAULT) const
std::optional< Image > getImageAsRGB888(uint32_t lod=0) const
bool hasImageForLOD(uint32_t lod) const
std::vector< std::byte > bake()
uint32_t getVersion() const
bool removeImage(uint32_t lod)
std::unordered_map< uint32_t, Image > images
void setFormat(ImageFormat newFormat, float quality=ImageConversion::DEFAULT_COMPRESSED_QUALITY)
PPL(uint32_t modelChecksum, ImageFormat format_=ImageFormat::RGB888, uint32_t version_=0)
std::optional< Image > getImageAs(ImageFormat newFormat, uint32_t lod=0) const
std::vector< uint32_t > getImageLODs() const
void setVersion(uint32_t newVersion)
bool setImage(std::span< const std::byte > imageData, ImageFormat format_, uint32_t width, uint32_t height, uint32_t lod=0, float quality=ImageConversion::DEFAULT_COMPRESSED_QUALITY)
uint32_t getModelChecksum() const
void setModelChecksum(uint32_t newChecksum)
bool writeFileBuffer(const std::filesystem::path &filepath, std::span< const std::byte > buffer)
std::vector< std::byte > readFileBuffer(const std::filesystem::path &filepath, std::size_t startOffset=0)
constexpr uint16_t paddingForAlignment(uint16_t alignment, uint64_t n)
std::vector< std::byte > convertFileToImageData(std::span< const std::byte > fileData, ImageFormat &format, int &width, int &height, int &frameCount)
std::vector< std::byte > convertImageDataToFile(std::span< const std::byte > imageData, ImageFormat format, uint16_t width, uint16_t height, FileFormat fileFormat=FileFormat::DEFAULT)
Converts image data to the given file format (PNG or EXR by default).
std::vector< std::byte > convertImageDataToFormat(std::span< const std::byte > imageData, ImageFormat oldFormat, ImageFormat newFormat, uint16_t width, uint16_t height, float quality=DEFAULT_COMPRESSED_QUALITY)
Converts an image from one format to another.
std::vector< std::byte > resizeImageData(std::span< const std::byte > imageData, ImageFormat format, uint16_t width, uint16_t newWidth, uint16_t height, uint16_t newHeight, bool srgb, ResizeFilter filter, ResizeEdge edge=ResizeEdge::CLAMP)
Resize given image data to the new dimensions.