mirror of
https://github.com/encounter/aurora.git
synced 2026-07-09 18:19:33 -07:00
f7f3d52cfc
* Implement PNG & arb texture replacements Fixes #119 For arb textures it's just making sure the file parsing can handle them. Idk if we need to do something special for it. * Allow non-mipmapped textures to be replaced by mipmapped textures Some of Henriko's textures (like the cuttable grass) rely on this. The mipmap bool is no longer part of the runtime key. * Make texture name the texture replacement key Might as well? Helped me debug some stuff * Oops that broke it bad * libpng instead of spng * I did it again * Update libpng fetch * Add zlib fetch * Forgot to set the hash * Add zlib redirect * Add INCLUDE_DIR(S) to redirect * Prefer shared for libpng * Set CMAKE_FIND_PACKAGE_TARGETS_GLOBAL --------- Co-authored-by: Luke Street <luke@street.dev>
102 lines
2.8 KiB
C++
102 lines
2.8 KiB
C++
#include "png_io.hpp"
|
|
|
|
#include <fstream>
|
|
|
|
#include "dds_io.hpp"
|
|
#include "png.h"
|
|
#include "../fs_helper.hpp"
|
|
|
|
static aurora::Module Log("aurora::gfx::png");
|
|
|
|
namespace aurora::gfx::png {
|
|
|
|
struct PngStructs {
|
|
png_structp pStruct;
|
|
png_infop pInfo;
|
|
std::ifstream file;
|
|
|
|
~PngStructs() {
|
|
png_destroy_read_struct(&pStruct, &pInfo, nullptr);
|
|
}
|
|
};
|
|
|
|
static void readPngData(png_structp png, png_bytep data, const size_t length) {
|
|
auto structs = static_cast<PngStructs*>(png_get_io_ptr(png));
|
|
structs->file.read(reinterpret_cast<char*>(data), static_cast<std::streamsize>(length));
|
|
|
|
if (structs->file.eof() || structs->file.fail()) {
|
|
png_error(png, "file read failed!");
|
|
}
|
|
}
|
|
|
|
std::optional<ConvertedTexture>
|
|
load_png_file(const std::filesystem::path& path) noexcept {
|
|
PngStructs structs{};
|
|
|
|
structs.file = std::move(std::ifstream(path, std::ifstream::in | std::ifstream::binary));
|
|
if (!structs.file) {
|
|
Log.error("failed to open file: {}", fs_path_to_string(path));
|
|
return std::nullopt;
|
|
}
|
|
|
|
structs.pStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
|
if (!structs.pStruct) {
|
|
Log.error("png_create_read_struct failed");
|
|
return std::nullopt;
|
|
}
|
|
|
|
structs.pInfo = png_create_info_struct(structs.pStruct);
|
|
if (!structs.pInfo) {
|
|
Log.error("png_create_info_struct failed");
|
|
return std::nullopt;
|
|
}
|
|
|
|
// I'm scared of putting any locals after that setjmp.
|
|
std::vector<png_bytep> rowPointers;
|
|
ByteBuffer imageData{};
|
|
png_uint_32 width, height;
|
|
int bit_depth, color_type, interlace_type, compression_type, filter_type;
|
|
size_t rowBytes;
|
|
int i;
|
|
|
|
if (setjmp(png_jmpbuf(structs.pStruct))) {
|
|
Log.error("libpng encountered an error");
|
|
return std::nullopt;
|
|
}
|
|
|
|
png_set_read_fn(structs.pStruct, &structs, readPngData);
|
|
png_read_info(structs.pStruct, structs.pInfo);
|
|
|
|
if (!png_get_IHDR(structs.pStruct, structs.pInfo, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) {
|
|
Log.error("libpng unable to read IHDR");
|
|
return std::nullopt;
|
|
}
|
|
|
|
// Always read as RGBA8.
|
|
png_set_gray_to_rgb(structs.pStruct);
|
|
png_set_filler(structs.pStruct, 0xFF, PNG_FILLER_AFTER);
|
|
png_set_expand(structs.pStruct);
|
|
png_set_strip_16(structs.pStruct);
|
|
|
|
png_read_update_info(structs.pStruct, structs.pInfo);
|
|
rowBytes = png_get_rowbytes(structs.pStruct, structs.pInfo);
|
|
rowPointers.resize(height);
|
|
|
|
imageData.append_zeroes(rowBytes * height);
|
|
|
|
for (i = 0; i < height; i++) {
|
|
rowPointers[i] = imageData.data() + i * rowBytes;
|
|
}
|
|
|
|
png_read_image(structs.pStruct, rowPointers.data());
|
|
png_read_end(structs.pStruct, nullptr);
|
|
|
|
return ConvertedTexture{
|
|
.format = wgpu::TextureFormat::RGBA8Unorm,
|
|
.width = width,
|
|
.height = height,
|
|
.mips = 1,
|
|
.data = std::move(imageData)
|
|
};
|
|
}
|
|
} |