From a144459e8d80041ca5bf0dc582d70ebc3695a8a5 Mon Sep 17 00:00:00 2001 From: Green Sky Date: Tue, 1 Aug 2023 20:17:38 +0200 Subject: [PATCH] add stb image loader (avatar png support) --- src/CMakeLists.txt | 4 +++ src/chat_gui4.cpp | 2 +- src/image_loader_stb.cpp | 65 +++++++++++++++++++++++++++++++++++++++ src/image_loader_stb.hpp | 9 ++++++ src/tox_avatar_loader.cpp | 3 +- 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/image_loader_stb.cpp create mode 100644 src/image_loader_stb.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5334745..4b0e4bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,8 @@ add_executable(tomato ./image_loader.hpp ./image_loader_sdl_bmp.hpp ./image_loader_sdl_bmp.cpp + ./image_loader_stb.hpp + ./image_loader_stb.cpp ./theme.hpp ./texture_uploader.hpp @@ -53,5 +55,7 @@ target_link_libraries(tomato PUBLIC imgui imgui_backend_sdl3 imgui_backend_sdlrenderer3 + + stb_image ) diff --git a/src/chat_gui4.cpp b/src/chat_gui4.cpp index 626c513..65bbb5c 100644 --- a/src/chat_gui4.cpp +++ b/src/chat_gui4.cpp @@ -135,7 +135,7 @@ void ChatGui4::render(void) { if (ImGui::BeginMenuBar()) { ImGui::Checkbox("show extra info", &_show_chat_extra_info); if (ImGui::SmallButton("test")) { - _cr.emplace_or_replace(*_selected_contact, "tomato_v1_256.bmp"); + _cr.emplace_or_replace(*_selected_contact, "tomato_v1_256.png"); _cr.emplace_or_replace(*_selected_contact); std::cout << "DEBUG: added AvatarFile comp to contact\n"; } diff --git a/src/image_loader_stb.cpp b/src/image_loader_stb.cpp new file mode 100644 index 0000000..167264a --- /dev/null +++ b/src/image_loader_stb.cpp @@ -0,0 +1,65 @@ +#include "./image_loader_stb.hpp" + +#include + +ImageLoaderSTB::ImageInfo ImageLoaderSTB::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) { + ImageInfo res; + + int x,y; + if (stbi_info_from_memory(data, data_size, &x, &y, nullptr) == 0) { + return res; // failed to load + } + + res.width = x; + res.height = y; + + return res; +} + +ImageLoaderSTB::ImageResult ImageLoaderSTB::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) { + ImageResult res; + + int x = 0; + int y = 0; + { // try gif before to support animations + int* delays = nullptr; + int z = 0; // number of frames + uint8_t* img_data = stbi_load_gif_from_memory(data, data_size, &delays, &x, &y, &z, nullptr, 4); + + if (img_data) { + res.width = x; + res.height = y; + + const size_t stride = x * y * 4; + + // TODO: test this with asan + for (int i = 0; i < z; i++) { + auto& new_frame = res.frames.emplace_back(); + new_frame.ms = delays[i]; + new_frame.data.insert(new_frame.data.cbegin(), img_data + (i*stride), img_data + ((i+1)*stride)); + } + + stbi_image_free(delays); // hope this is right + stbi_image_free(img_data); + return res; + } + } + + uint8_t* img_data = stbi_load_from_memory(data, data_size, &x, &y, nullptr, 4); + + if (img_data == nullptr) { + // not readable + return res; + } + + res.width = x; + res.height = y; + + auto& new_frame = res.frames.emplace_back(); + new_frame.ms = 0; + new_frame.data.insert(new_frame.data.cbegin(), img_data, img_data+(x*y*4)); + + stbi_image_free(img_data); + return res; +} + diff --git a/src/image_loader_stb.hpp b/src/image_loader_stb.hpp new file mode 100644 index 0000000..1ba44ab --- /dev/null +++ b/src/image_loader_stb.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "./image_loader.hpp" + +struct ImageLoaderSTB : public ImageLoaderI { + ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) override; + ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) override; +}; + diff --git a/src/tox_avatar_loader.cpp b/src/tox_avatar_loader.cpp index a45bb53..b47f9dd 100644 --- a/src/tox_avatar_loader.cpp +++ b/src/tox_avatar_loader.cpp @@ -1,6 +1,7 @@ #include "./tox_avatar_loader.hpp" #include "./image_loader_sdl_bmp.hpp" +#include "./image_loader_stb.hpp" #include #include @@ -15,7 +16,7 @@ ToxAvatarLoader::ToxAvatarLoader(Contact3Registry& cr) : _cr(cr) { _image_loaders.push_back(std::make_unique()); //_image_loaders.push_back(std::make_unique()); - //_image_loaders.push_back(std::make_unique()); + _image_loaders.push_back(std::make_unique()); } static float getHue_6bytes(const uint8_t* data) {