From 3997e8c9bc93ee87152f80233f07076c0c5fcc27 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 25 Mar 2023 15:01:40 -0600 Subject: [PATCH] imglib: add jpg/png loading using stb_image --- common/imglib.cc | 39 +++++++++++++++++++++++++++++++++++++++ include/common/imglib.hh | 15 ++++++++++++--- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/common/imglib.cc b/common/imglib.cc index 5688d9ac..965fe142 100644 --- a/common/imglib.cc +++ b/common/imglib.cc @@ -4,6 +4,9 @@ #include #include +#define STB_IMAGE_IMPLEMENTATION +#include "../3rdparty/stb_image.h" + /* ============================================================================ PALETTE @@ -404,6 +407,42 @@ breakOut:; return tex; // mxd } +std::optional load_stb( + const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game) +{ + int x, y, channels_in_file; + stbi_uc *rgba_data = stbi_load_from_memory(file->data(), file->size(), &x, &y, &channels_in_file, 4); + + if (!rgba_data) { + logging::funcprint("stbi error: {}\n", stbi_failure_reason()); + return {}; + } + + texture tex; + tex.meta.extension = ext::STB; + tex.meta.name = name; + tex.meta.width = tex.width = x; + tex.meta.height = tex.height = y; + + if (!meta_only) { + int num_pixels = x * y; + if (num_pixels < 0) { + return {}; + } + + tex.pixels.resize(num_pixels); + + qvec4b *out = tex.pixels.data(); + for (int i = 0; i < num_pixels; ++i) { + out[i] = {rgba_data[4 * i], rgba_data[4 * i + 1], rgba_data[4 * i + 2], rgba_data[4 * i + 3]}; + } + } + + stbi_image_free(rgba_data); + + return tex; +} + // texture cache std::unordered_map textures; diff --git a/include/common/imglib.hh b/include/common/imglib.hh index 129679b7..9a77febe 100644 --- a/include/common/imglib.hh +++ b/include/common/imglib.hh @@ -31,7 +31,11 @@ enum class ext { TGA, WAL, - MIP + MIP, + /** + * Anything loadable by stb_image.h + */ + STB }; extern std::vector palette; @@ -66,6 +70,7 @@ struct texture // the width/height of the metadata. uint32_t width = 0, height = 0; + // RGBA order std::vector pixels; // the scale required to map a pixel from the @@ -95,14 +100,18 @@ std::optional load_tga( std::optional load_mip( const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game); +// stb_image.h loaders +std::optional load_stb( + const std::string_view &name, const fs::data &file, bool meta_only, const gamedef_t *game); + // list of supported extensions and their loaders constexpr struct { const char *suffix; ext id; decltype(load_wal) *loader; -} extension_list[] = { - {".tga", ext::TGA, load_tga}, {".wal", ext::WAL, load_wal}, {".mip", ext::MIP, load_mip}, {"", ext::MIP, load_mip}}; +} extension_list[] = {{".png", ext::STB, load_stb}, {".jpg", ext::STB, load_stb}, {".tga", ext::TGA, load_tga}, + {".wal", ext::WAL, load_wal}, {".mip", ext::MIP, load_mip}, {"", ext::MIP, load_mip}}; // Attempt to load a texture from the specified name. std::tuple, fs::resolve_result, fs::data> load_texture(