diff --git a/external/sdl_image/CMakeLists.txt b/external/sdl_image/CMakeLists.txt index 60d3826..570b724 100644 --- a/external/sdl_image/CMakeLists.txt +++ b/external/sdl_image/CMakeLists.txt @@ -9,6 +9,7 @@ if (NOT TARGET SDL3_image::SDL3_image) set(SDL3IMAGE_BACKEND_STB OFF CACHE BOOL "" FORCE) # important for security set(SDL3IMAGE_BACKEND_IMAGEIO OFF CACHE BOOL "" FORCE) # some funky apple cmake bug set(SDL3IMAGE_JXL ON CACHE BOOL "" FORCE) + set(SDL3IMAGE_QOI OFF CACHE BOOL "" FORCE) # we have our own FetchContent_Declare(SDL3_image GIT_REPOSITORY https://github.com/libsdl-org/SDL_image diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d37118..e82d70e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,8 @@ add_executable(tomato ./image_loader_webp.cpp ./image_loader_qoi.hpp ./image_loader_qoi.cpp + ./image_loader_sdl_image.hpp + ./image_loader_sdl_image.cpp ./texture_uploader.hpp ./sdlrenderer_texture_uploader.hpp @@ -98,5 +100,6 @@ target_link_libraries(tomato PUBLIC webpdemux libwebpmux # the f why (needed for anim encode) qoi + SDL3_image::SDL3_image ) diff --git a/src/image_loader_sdl_image.cpp b/src/image_loader_sdl_image.cpp new file mode 100644 index 0000000..a1a06d3 --- /dev/null +++ b/src/image_loader_sdl_image.cpp @@ -0,0 +1,118 @@ +#include "./image_loader_sdl_image.hpp" + +#include + +#include +#include + +static std::optional getExt(SDL_IOStream* ios) { + if (IMG_isAVIF(ios)) { + return "avif"; + } else if (IMG_isCUR(ios)) { + return "cur"; + } else if (IMG_isICO(ios)) { + return "ico"; + } else if (IMG_isBMP(ios)) { + return "bmp"; + } else if (IMG_isGIF(ios)) { + return "gif"; + } else if (IMG_isJPG(ios)) { + return "jpg"; + } else if (IMG_isJXL(ios)) { + return "jxl"; + } else if (IMG_isLBM(ios)) { + return "lbm"; + } else if (IMG_isPCX(ios)) { + return "pcx"; + } else if (IMG_isPNG(ios)) { + return "png"; + } else if (IMG_isPNM(ios)) { + return "pnm"; + } else if (IMG_isSVG(ios)) { + return "svg"; + } else if (IMG_isTIF(ios)) { + return "tiff"; + } else if (IMG_isXCF(ios)) { + return "xcf"; + } else if (IMG_isXPM(ios)) { + return "xpm"; + } else if (IMG_isXV(ios)) { + return "xv"; + } else if (IMG_isWEBP(ios)) { + return "webp"; + } else if (IMG_isQOI(ios)) { + return "qoi"; + } else { + return std::nullopt; + } +} + +ImageLoaderSDLImage::ImageInfo ImageLoaderSDLImage::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) { + ImageInfo res; + + auto* ios = SDL_IOFromConstMem(data, data_size); + + // we ignore tga + auto ext_opt = getExt(ios); + if (!ext_opt.has_value()) { + return res; + } + + SDL_Surface* surf = IMG_Load_IO(ios, SDL_TRUE); + if (surf == nullptr) { + return res; + } + + res.width = surf->w; + res.height = surf->h; + res.file_ext = ext_opt.value(); + + SDL_DestroySurface(surf); + + return res; +} + +ImageLoaderSDLImage::ImageResult ImageLoaderSDLImage::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) { + ImageResult res; + + auto* ios = SDL_IOFromConstMem(data, data_size); + + // we ignore tga + auto ext_opt = getExt(ios); + if (!ext_opt.has_value()) { + return res; + } + + IMG_Animation* anim = IMG_LoadAnimation_IO(ios, SDL_TRUE); + if (anim == nullptr) { + return res; + } + + for (int i = 0; i < anim->count; i++) { + SDL_Surface* conv_surf = SDL_ConvertSurfaceFormat(anim->frames[i], SDL_PIXELFORMAT_RGBA32); + if (conv_surf == nullptr) { + return res; + } + + + SDL_LockSurface(conv_surf); + + auto& new_frame = res.frames.emplace_back(); + new_frame.ms = anim->delays[i]; + new_frame.data.insert(new_frame.data.cbegin(), (const uint8_t*)conv_surf->pixels, ((const uint8_t*)conv_surf->pixels) + (anim->w*anim->h*4)); + + SDL_UnlockSurface(conv_surf); + SDL_DestroySurface(conv_surf); + } + + res.width = anim->w; + res.height = anim->h; + res.file_ext = ext_opt.value(); + + IMG_FreeAnimation(anim); + + std::cout << "IL_SDLI: loaded img " << res.width << "x" << res.height << "\n"; + + return res; +} + diff --git a/src/image_loader_sdl_image.hpp b/src/image_loader_sdl_image.hpp new file mode 100644 index 0000000..2cd99a6 --- /dev/null +++ b/src/image_loader_sdl_image.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "./image_loader.hpp" + +struct ImageLoaderSDLImage : public ImageLoaderI { + ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) override; + ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) override; +}; +