diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index ce8ec971..d202efe2 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -16,4 +16,5 @@ add_subdirectory(./sdl) add_subdirectory(./imgui) add_subdirectory(./stb) +add_subdirectory(./libwebp) diff --git a/external/libwebp/CMakeLists.txt b/external/libwebp/CMakeLists.txt new file mode 100644 index 00000000..1c718ed8 --- /dev/null +++ b/external/libwebp/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.9 FATAL_ERROR) + +set(WEBP_LINK_STATIC ON CACHE INTERNAL "") + +add_subdirectory(./libwebp EXCLUDE_FROM_ALL) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b0e4bbd..dcaad908 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,8 @@ add_executable(tomato ./image_loader_sdl_bmp.cpp ./image_loader_stb.hpp ./image_loader_stb.cpp + ./image_loader_webp.hpp + ./image_loader_webp.cpp ./theme.hpp ./texture_uploader.hpp @@ -57,5 +59,6 @@ target_link_libraries(tomato PUBLIC imgui_backend_sdlrenderer3 stb_image + webpdemux ) diff --git a/src/image_loader_webp.cpp b/src/image_loader_webp.cpp new file mode 100644 index 00000000..b0cd7a64 --- /dev/null +++ b/src/image_loader_webp.cpp @@ -0,0 +1,78 @@ +#include "./image_loader_webp.hpp" + +#include +#include + +#include + +ImageLoaderWebP::ImageInfo ImageLoaderWebP::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) { + ImageInfo res; + + WebPData webp_data; + WebPDataInit(&webp_data); + webp_data.bytes = data; + webp_data.size = data_size; + + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + dec_options.color_mode = MODE_RGBA; + + WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options); + if (dec == nullptr) { + return res; + } + + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + res.width = anim_info.canvas_width; + res.height = anim_info.canvas_height; + + return res; +} + +ImageLoaderWebP::ImageResult ImageLoaderWebP::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) { + ImageResult res; + + WebPData webp_data; + WebPDataInit(&webp_data); + webp_data.bytes = data; + webp_data.size = data_size; + + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + dec_options.color_mode = MODE_RGBA; + + WebPAnimDecoder* dec = WebPAnimDecoderNew(&webp_data, &dec_options); + if (dec == nullptr) { + return res; + } + + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + res.width = anim_info.canvas_width; + res.height = anim_info.canvas_height; + + int prev_timestamp = 0; + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + + // just be dumb and append + auto& new_frame = res.frames.emplace_back(); + new_frame.ms = timestamp-prev_timestamp; + prev_timestamp = timestamp; + new_frame.data.insert(new_frame.data.end(), buf, buf+(res.width*res.height*4)); + } + + WebPAnimDecoderDelete(dec); + + assert(anim_info.frame_count == res.frames.size()); + + return res; +} + diff --git a/src/image_loader_webp.hpp b/src/image_loader_webp.hpp new file mode 100644 index 00000000..f7e79e0c --- /dev/null +++ b/src/image_loader_webp.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "./image_loader.hpp" + +struct ImageLoaderWebP : 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 b47f9dd6..8adfc548 100644 --- a/src/tox_avatar_loader.cpp +++ b/src/tox_avatar_loader.cpp @@ -2,6 +2,7 @@ #include "./image_loader_sdl_bmp.hpp" #include "./image_loader_stb.hpp" +#include "./image_loader_webp.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()); }