From 2095e82f1aee841ea8ecc8debdece852828c0269 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 19 Nov 2025 19:21:09 +0300 Subject: [PATCH] add Canvas.decode static method --- src/coders/imageio.cpp | 40 +++++++++++++++---- src/coders/imageio.hpp | 3 ++ .../lua/usertypes/lua_type_canvas.cpp | 20 ++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/coders/imageio.cpp b/src/coders/imageio.cpp index dc9a78b8..b63c65fc 100644 --- a/src/coders/imageio.cpp +++ b/src/coders/imageio.cpp @@ -1,3 +1,4 @@ +#define VC_ENABLE_REFLECTION #include "imageio.hpp" #include @@ -7,28 +8,34 @@ #include "io/io.hpp" #include "png.hpp" +using namespace imageio; + using image_reader = std::function(const ubyte*, size_t)>; using image_writer = std::function; -static std::unordered_map readers { - {".png", png::load_image}, +static std::unordered_map readers { + {ImageFileFormat::PNG, png::load_image}, }; -static std::unordered_map writers { - {".png", png::write_image}, +static std::unordered_map writers { + {ImageFileFormat::PNG, png::write_image}, }; bool imageio::is_read_supported(const std::string& extension) { - return readers.find(extension) != readers.end(); + return extension == ".png"; } bool imageio::is_write_supported(const std::string& extension) { - return writers.find(extension) != writers.end(); + return extension == ".png"; } std::unique_ptr imageio::read(const io::path& file) { - auto found = readers.find(file.extension()); + ImageFileFormat format; + if (!ImageFileFormatMeta.getItem(file.extension().substr(1), format)) { + throw std::runtime_error("unsupported image format"); + } + auto found = readers.find(format); if (found == readers.end()) { throw std::runtime_error( "file format is not supported (read): " + file.string() @@ -44,8 +51,25 @@ std::unique_ptr imageio::read(const io::path& file) { } } +std::unique_ptr imageio::decode( + ImageFileFormat format, util::span src +) { + auto found = readers.find(format); + try { + return std::unique_ptr(found->second(src.data(), src.size())); + } catch (const std::runtime_error& err) { + throw std::runtime_error( + "could not to decode image: " + std::string(err.what()) + ); + } +} + void imageio::write(const io::path& file, const ImageData* image) { - auto found = writers.find(file.extension()); + ImageFileFormat format; + if (!ImageFileFormatMeta.getItem(file.extension().substr(1), format)) { + throw std::runtime_error("unsupported image format"); + } + auto found = writers.find(format); if (found == writers.end()) { throw std::runtime_error( "file format is not supported (write): " + file.string() diff --git a/src/coders/imageio.hpp b/src/coders/imageio.hpp index e844cf67..782d51f5 100644 --- a/src/coders/imageio.hpp +++ b/src/coders/imageio.hpp @@ -6,6 +6,8 @@ #include "io/fwd.hpp" #include "util/Buffer.hpp" #include "util/EnumMetadata.hpp" +#include "util/span.hpp" +#include "typedefs.hpp" class ImageData; @@ -25,5 +27,6 @@ namespace imageio { std::unique_ptr read(const io::path& file); void write(const io::path& file, const ImageData* image); + std::unique_ptr decode(ImageFileFormat format, util::span src); util::Buffer encode(ImageFileFormat format, const ImageData& image); } diff --git a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp index 25839659..f89c9d5e 100644 --- a/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp +++ b/src/logic/scripting/lua/usertypes/lua_type_canvas.cpp @@ -374,6 +374,23 @@ static int l_meta_meta_call(lua::State* L) { ); } +static int l_canvas_decode(lua::State* L) { + auto bytes = bytearray_as_string(L, 1); + auto formatName = require_lstring(L, 2); + imageio::ImageFileFormat format; + if (!imageio::ImageFileFormatMeta.getItem(formatName, format)) { + throw std::runtime_error("unsupported image format"); + } + return newuserdata( + L, + nullptr, + imageio::decode( + format, + {reinterpret_cast(bytes.data()), bytes.size()} + ) + ); +} + int LuaCanvas::createMetatable(State* L) { createtable(L, 0, 3); pushcfunction(L, lua::wrap); @@ -385,5 +402,8 @@ int LuaCanvas::createMetatable(State* L) { pushcfunction(L, lua::wrap); setfield(L, "__call"); setmetatable(L); + + pushcfunction(L, lua::wrap); + setfield(L, "decode"); return 1; }