diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index d3806157..3f050055 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -282,7 +282,7 @@ bool AssetsLoader::loadExternalTexture( for (auto& path : alternatives) { if (fs::exists(path)) { try { - auto image = imageio::read(path.string()); + auto image = imageio::read(path); assets->store(Texture::from(image.get()), name); return true; } catch (const std::exception& err) { diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index ffe7cc25..399e7959 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -50,7 +50,9 @@ assetload::postfunc assetload::texture( ) { auto actualFile = paths->find(filename + ".png").u8string(); try { - std::shared_ptr image(imageio::read(actualFile).release()); + std::shared_ptr image( + imageio::read(fs::u8path(actualFile)).release() + ); return [name, image, actualFile](auto assets) { assets->store(Texture::from(image.get()), name); }; @@ -96,7 +98,7 @@ static bool append_atlas(AtlasBuilder& atlas, const fs::path& file) { if (atlas.has(name)) { return false; } - auto image = imageio::read(file.string()); + auto image = imageio::read(file); image->fixAlphaColor(); atlas.add(name, std::move(image)); return true; @@ -150,7 +152,7 @@ assetload::postfunc assetload::font( std::string pagefile = filename + "_" + std::to_string(i) + ".png"; auto file = paths->find(pagefile); if (fs::exists(file)) { - pages->push_back(imageio::read(file.u8string())); + pages->push_back(imageio::read(file)); } else if (i == 0) { throw std::runtime_error("font must have page 0"); } else { diff --git a/src/coders/imageio.cpp b/src/coders/imageio.cpp index f13e13cb..a80f422c 100644 --- a/src/coders/imageio.cpp +++ b/src/coders/imageio.cpp @@ -5,12 +5,13 @@ #include #include "graphics/core/ImageData.hpp" +#include "files/files.hpp" #include "png.hpp" namespace fs = std::filesystem; using image_reader = - std::function(const std::string&)>; + std::function(const ubyte*, size_t)>; using image_writer = std::function; static std::unordered_map readers { @@ -33,14 +34,21 @@ inline std::string extensionOf(const std::string& filename) { return fs::u8path(filename).extension().u8string(); } -std::unique_ptr imageio::read(const std::string& filename) { - auto found = readers.find(extensionOf(filename)); +std::unique_ptr imageio::read(const fs::path& filename) { + auto found = readers.find(extensionOf(filename.u8string())); if (found == readers.end()) { throw std::runtime_error( - "file format is not supported (read): " + filename + "file format is not supported (read): " + filename.u8string() + ); + } + auto bytes = files::read_bytes_buffer(filename); + try { + return std::unique_ptr(found->second(bytes.data(), bytes.size())); + } catch (const std::runtime_error& err) { + throw std::runtime_error( + "could not to load image " + filename.u8string() + ": " + err.what() ); } - return std::unique_ptr(found->second(filename)); } void imageio::write(const std::string& filename, const ImageData* image) { diff --git a/src/coders/imageio.hpp b/src/coders/imageio.hpp index 24554b3f..beab88ad 100644 --- a/src/coders/imageio.hpp +++ b/src/coders/imageio.hpp @@ -2,6 +2,7 @@ #include #include +#include class ImageData; @@ -11,6 +12,6 @@ namespace imageio { bool is_read_supported(const std::string& extension); bool is_write_supported(const std::string& extension); - std::unique_ptr read(const std::string& filename); + std::unique_ptr read(const std::filesystem::path& file); void write(const std::string& filename, const ImageData* image); } diff --git a/src/coders/png.cpp b/src/coders/png.cpp index 917f6063..60965ed1 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -92,100 +92,6 @@ int _png_write( return 0; } -std::unique_ptr _png_load(const char* file) { - png_struct* png = png_create_read_struct( - PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr - ); - if (png == nullptr) { - return nullptr; - } - png_info* info = png_create_info_struct(png); - if (info == nullptr) { - png_destroy_read_struct(&png, (png_info**)nullptr, (png_info**)nullptr); - return nullptr; - } - png_info* end_info = png_create_info_struct(png); - if (end_info == nullptr) { - png_destroy_read_struct(&png, (png_info**)nullptr, (png_info**)nullptr); - return nullptr; - } - - if (setjmp(png_jmpbuf(png))) { - png_destroy_read_struct(&png, &info, &end_info); - return nullptr; - } - - FILE* fp = nullptr; - if ((fp = fopen(file, "rb")) == nullptr) { - png_destroy_read_struct(&png, &info, &end_info); - return nullptr; - } - png_init_io(png, fp); - png_read_info(png, info); - - int width = png_get_image_width(png, info); - int height = png_get_image_height(png, info); - png_byte color_type = png_get_color_type(png, info); - int bit_depth = png_get_bit_depth(png, info); - - if (bit_depth == 16) png_set_strip_16(png); - - if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); - - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand_gray_1_2_4_to_8(png); - - if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); - - // These color_type don't have an alpha channel then fill it with 0xff. - if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_PALETTE) - png_set_filler(png, 0xFF, PNG_FILLER_AFTER); - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); - - png_read_update_info(png, info); - - int row_bytes = png_get_rowbytes(png, info); - // color_type = png_get_color_type(png, info); - // png_get_color_type returns 2 (RGB) but raster always have alpha channel - // due to PNG_FILLER_AFTER - - color_type = 6; - bit_depth = png_get_bit_depth(png, info); - - auto image_data = std::make_unique(row_bytes * height); - auto row_pointers = std::make_unique(height); - for (int i = 0; i < height; ++i) { - row_pointers[height - 1 - i] = image_data.get() + i * row_bytes; - } - png_read_image(png, row_pointers.get()); - - ImageFormat format = ImageFormat::rgba8888; - switch (color_type) { - case PNG_COLOR_TYPE_RGBA: - format = ImageFormat::rgba8888; - break; - case PNG_COLOR_TYPE_RGB: - format = ImageFormat::rgb888; - break; - default: - logger.error() << "color type " << color_type - << " is not supported!"; - png_destroy_read_struct(&png, &info, &end_info); - fclose(fp); - return nullptr; - } - auto image = std::make_unique( - format, width, height, std::move(image_data) - ); - png_destroy_read_struct(&png, &info, &end_info); - fclose(fp); - return image; -} - struct InMemoryReader { const ubyte* bytes; size_t size; @@ -205,8 +111,8 @@ static void read_in_memory(png_structp pngPtr, png_bytep dst, png_size_t toread) reader.offset += toread; } -std::unique_ptr png::load_image_inmemory(const ubyte* bytes, size_t size) { - if(!png_check_sig(bytes, size)) { +std::unique_ptr png::load_image(const ubyte* bytes, size_t size) { + if (!png_check_sig(bytes, size)) { throw std::runtime_error("invalid png signature"); } png_structp pngPtr = nullptr; @@ -224,8 +130,6 @@ std::unique_ptr png::load_image_inmemory(const ubyte* bytes, size_t s InMemoryReader reader {bytes, size, 0}; png_set_read_fn(pngPtr, &reader, read_in_memory); - // png_set_sig_bytes(png_ptr, kPngSignatureLength); - png_read_info(pngPtr, infoPtr); png_uint_32 width = 0; @@ -300,22 +204,24 @@ std::unique_ptr png::load_image_inmemory(const ubyte* bytes, size_t s return image; } -std::unique_ptr png::load_image(const std::string& filename) { - auto bytes = files::read_bytes_buffer(fs::u8path(filename)); - auto image = load_image_inmemory(bytes.data(), bytes.size()); - if (image == nullptr) { - throw std::runtime_error("could not load image " + filename); - } - return image; -} - -std::unique_ptr png::load_texture(const std::string& filename) { - auto image = load_image(filename); +std::unique_ptr png::load_texture(const ubyte* bytes, size_t size) { + auto image = load_image(bytes, size); auto texture = GLTexture::from(image.get()); texture->setNearestFilter(); return texture; } +std::unique_ptr png::load_texture(const std::string& filename) { + auto bytes = files::read_bytes_buffer(fs::u8path(filename)); + try { + return load_texture(bytes.data(), bytes.size()); + } catch (const std::runtime_error& err) { + throw std::runtime_error( + "could not to load " + filename + ": " + err.what() + ); + } +} + void png::write_image(const std::string& filename, const ImageData* image) { _png_write( filename.c_str(), diff --git a/src/coders/png.hpp b/src/coders/png.hpp index 3f9cc1fa..9ba2eda9 100644 --- a/src/coders/png.hpp +++ b/src/coders/png.hpp @@ -9,8 +9,8 @@ class Texture; class ImageData; namespace png { - std::unique_ptr load_image_inmemory(const ubyte* bytes, size_t size); - std::unique_ptr load_image(const std::string& filename); + std::unique_ptr load_image(const ubyte* bytes, size_t size); void write_image(const std::string& filename, const ImageData* image); + std::unique_ptr load_texture(const ubyte* bytes, size_t size); std::unique_ptr load_texture(const std::string& filename); } diff --git a/src/engine.cpp b/src/engine.cpp index 6f0d7b6f..7581a57e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -62,7 +62,7 @@ static std::unique_ptr load_icon(const fs::path& resdir) { try { auto file = resdir / fs::u8path("textures/misc/icon.png"); if (fs::exists(file)) { - return imageio::read(file.u8string()); + return imageio::read(file); } } catch (const std::exception& err) { logger.error() << "could not load window icon: " << err.what(); diff --git a/src/logic/scripting/lua/libs/libcore.cpp b/src/logic/scripting/lua/libs/libcore.cpp index c656d0e6..9b048e44 100644 --- a/src/logic/scripting/lua/libs/libcore.cpp +++ b/src/logic/scripting/lua/libs/libcore.cpp @@ -1,22 +1,25 @@ #include #include +#include "api_lua.hpp" +#include "coders/png.hpp" #include "constants.hpp" -#include "engine.hpp" #include "content/Content.hpp" +#include "debug/Logger.hpp" +#include "engine.hpp" #include "files/engine_paths.hpp" +#include "files/files.hpp" #include "files/settings_io.hpp" #include "frontend/menu.hpp" #include "frontend/screens/MenuScreen.hpp" +#include "graphics/core/Texture.hpp" #include "logic/EngineController.hpp" #include "logic/LevelController.hpp" +#include "util/listutil.hpp" #include "window/Events.hpp" #include "window/Window.hpp" -#include "world/generator/WorldGenerator.hpp" #include "world/Level.hpp" -#include "util/listutil.hpp" - -#include "api_lua.hpp" +#include "world/generator/WorldGenerator.hpp" using namespace scripting; @@ -187,24 +190,14 @@ static int l_get_setting_info(lua::State* L) { throw std::runtime_error("unsupported setting type"); } -#include "coders/png.hpp" -#include "debug/Logger.hpp" -#include "files/files.hpp" -#include "graphics/core/Texture.hpp" - -/// FIXME: replace with in-memory implementation - static void load_texture( const ubyte* bytes, size_t size, const std::string& destname ) { - auto path = engine->getPaths()->resolve("export:.__vc_imagedata"); try { - files::write_bytes(path, bytes, size); - engine->getAssets()->store(png::load_texture(path.u8string()), destname); - std::filesystem::remove(path); + engine->getAssets()->store(png::load_texture(bytes, size), destname); } catch (const std::runtime_error& err) { debug::Logger logger("lua.corelib"); - logger.error() << "could not to decode image: " << err.what(); + logger.error() << err.what(); } }