6#include "fifechan/backends/sdl3/imageloader.hpp"
14#include <SDL3_image/SDL_image.h>
17#include "fifechan/backends/sdl3/image.hpp"
18#include "fifechan/exception.hpp"
22 ImageLoader::ImageLoader() =
default;
26 std::string resolveFromExecutableDirectory(std::string
const & filename)
28 std::filesystem::path
const requestedPath(filename);
29 if (requestedPath.is_absolute()) {
33 char const * basePathRaw = SDL_GetBasePath();
34 if (basePathRaw ==
nullptr) {
37 std::filesystem::path
const candidate = std::filesystem::path(basePathRaw) / requestedPath;
38 return candidate.string();
46 if (loadedSurface ==
nullptr) {
47 throwException(std::string(
"Unable to load image file: ") + filename);
51 SDL_DestroySurface(loadedSurface);
53 if (surface ==
nullptr) {
54 throwException((std::string(
"Not enough memory to load: ") + filename));
57 auto image = std::make_unique<Image>(surface,
true, mRenderer);
59 if (convertToDisplayFormat) {
60 image->convertToDisplayFormat();
63 return image.release();
73 SDL_Surface* surface = IMG_Load(filename.c_str());
74 if (surface !=
nullptr) {
78 std::string
const resolvedPath = resolveFromExecutableDirectory(filename);
79 if (resolvedPath == filename) {
83 return IMG_Load(resolvedPath.c_str());
88 SDL_Texture* texture = IMG_LoadTexture(mRenderer, filename.c_str());
89 if (texture !=
nullptr) {
93 std::string
const resolvedPath = resolveFromExecutableDirectory(filename);
94 if (resolvedPath == filename) {
98 return IMG_LoadTexture(mRenderer, resolvedPath.c_str());
103 if (surface ==
nullptr) {
108 auto* converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA8888);
110 if (converted ==
nullptr) {
116 bool hasPink =
false;
119 if (SDL_SurfaceHasColorKey(converted)) {
120 if (!SDL_GetSurfaceColorKey(converted, &colorKey)) {
123 Uint8
const r = (colorKey >> 16) & 0xFF;
124 Uint8
const g = (colorKey >> 8) & 0xFF;
125 Uint8
const b = colorKey & 0xFF;
126 if (r == 255 && g == 0 && b == 255) {
134 for (
int y = 0; y < converted->h && !hasPink; ++y) {
135 for (
int x = 0; x < converted->w && !hasPink; ++x) {
141 SDL_ReadSurfacePixel(converted, x, y, &r, &g, &b, &a);
143 if (r == 255 && g == 0 && b == 255) {
151 SDL_SetSurfaceColorKey(converted,
true, SDL_MapSurfaceRGB(converted, 255, 0, 255));
152 SDL_SetSurfaceRLE(converted,
true);
165 mPixelFormat = format;
Abstract holder for image data.
SDL_PixelFormat const & getSDLPixelFormat()
Return the current SDL pixel format used for conversions.
virtual SDL_Surface * convertToStandardFormat(SDL_Surface *surface)
Convert a surface to a standard internal format (internal).
fcn::Image * load(std::string const &filename, bool convertToDisplayFormat) override
Load an image from filename.
virtual SDL_Surface * loadSDLSurface(std::string const &filename)
Load an SDL_Surface from disk (internal).
virtual SDL_Texture * loadSDLTexture(std::string const &filename)
Load an SDL_Texture from disk (internal).
void setSDLPixelFormat(SDL_PixelFormat const &format)
Set the SDL pixel format used for conversions.
void setRenderer(SDL_Renderer *renderer)
Set the SDL renderer used when creating textures.
void throwException(std::string const &message, std::source_location location=std::source_location::current())
Throw an Exception capturing the current source location.