5#include "fifechan/backends/sdl2/imageloader.hpp"
11#include "fifechan/backends/sdl2/image.hpp"
12#include "fifechan/exception.hpp"
18 std::string resolveFromExecutableDirectory(std::string
const & filename)
20 std::filesystem::path
const requestedPath(filename);
21 if (requestedPath.is_absolute()) {
25 char* basePathRaw = SDL_GetBasePath();
26 if (basePathRaw ==
nullptr) {
30 std::filesystem::path
const candidate = std::filesystem::path(basePathRaw) / requestedPath;
31 SDL_free(basePathRaw);
32 return candidate.string();
40 if (loadedSurface ==
nullptr) {
41 throwException(std::string(
"Unable to load image file: ") + filename);
45 SDL_FreeSurface(loadedSurface);
47 if (surface ==
nullptr) {
48 throwException((std::string(
"Not enough memory to load: ") + filename));
51 Image* image =
new Image(surface,
true, mRenderer);
53 if (convertToDisplayFormat) {
67 SDL_Surface* surface = IMG_Load(filename.c_str());
68 if (surface !=
nullptr) {
72 std::string
const resolvedPath = resolveFromExecutableDirectory(filename);
73 if (resolvedPath == filename) {
77 return IMG_Load(resolvedPath.c_str());
82 SDL_Texture* texture = IMG_LoadTexture(mRenderer, filename.c_str());
83 if (texture !=
nullptr) {
87 std::string
const resolvedPath = resolveFromExecutableDirectory(filename);
88 if (resolvedPath == filename) {
92 return IMG_LoadTexture(mRenderer, resolvedPath.c_str());
97 if (surface ==
nullptr) {
101 bool hasPink =
false;
103 int const pixels = surface->w * surface->h;
105 for (
int i = 0; i < pixels; ++i) {
111 SDL_GetRGBA(
reinterpret_cast<Uint32*
>(surface->pixels)[i], surface->format, &r, &g, &b, &a);
113 if (r == 255 && g == 0 && b == 255) {
121#if SDL_BYTEORDER == SDL_BIG_ENDIAN
122 uint32_t rmask = 0xff000000;
123 uint32_t gmask = 0x00ff0000;
124 uint32_t bmask = 0x0000ff00;
125 uint32_t amask = 0x000000ff;
127 uint32_t
const rmask = 0x000000ff;
128 uint32_t
const gmask = 0x0000ff00;
129 uint32_t
const bmask = 0x00ff0000;
130 uint32_t
const amask = 0xff000000;
134 auto* targetFormatSurface = SDL_CreateRGBSurface(0, surface->w, surface->h, 32, rmask, gmask, bmask, amask);
136 if (targetFormatSurface ==
nullptr) {
141 auto* converted = SDL_ConvertSurface(surface, targetFormatSurface->format, 0);
142 SDL_FreeSurface(targetFormatSurface);
144 if (converted ==
nullptr) {
149 SDL_SetColorKey(converted, SDL_TRUE, SDL_MapRGB(converted->format, 255, 0, 255));
150 SDL_SetSurfaceRLE(converted, 1);
163 mPixelFormat = format;
Abstract holder for image data.
virtual SDL_Texture * loadSDLTexture(std::string const &filename)
Load an SDL_Texture from disk (internal).
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).
void setRenderer(SDL_Renderer *renderer)
Set the SDL renderer used when creating textures.
SDL_PixelFormat const & getSDLPixelFormat()
Return the current SDL pixel format used for conversions.
void setSDLPixelFormat(SDL_PixelFormat const &format)
Set the SDL pixel format used for conversions.
SDL2-specific implementation of Image.
void convertToDisplayFormat() override
Converts the image, if possible, to display format.
Unified header for the SDL backend.
fcn::sdl2::Image Image
Backend alias for the SDL image implementation.