1

I'm trying to load a png image with SDL2. However, even though the file exists and the renderer is created correctly, IMG_LoadTexture will only return a nullptr, for no apparent reason.

The function I'm using IMG_LoadTexture in looks like this, where texture is a SDL_Texture*:

void setTexture(const char* filePath) {
    // check if the specified file exists
    assert(utils::fileExists(filePath) && "Texture file does not exist!");

    // this should set the texture, but never succeeds
    texture = IMG_LoadTexture(Game::renderer, filePath);
    if (!texture) {
        // error handling, this is always true
    }
}

The assert passes, so the file was found. filePath looks something like "assets/texture.png". The Game::renderer is set beforehand and looks like this:

static SDL_Renderer* renderer; // in header

renderer = SDL_CreateRenderer(window, -1, 0); // in implementation
if(renderer) {
    SDL_SetRenderDrawColor(renderer, 100, 200, 255, 255);
} else {
// error handling and quit
}

However, despite IMG_LoadTexture not returning a proper SDL_Texture*, IMG_GetError() is simply empty, meaning

std::cout << IMG_GetError();

after calling IMG_LoadTexture does not output anything.

Seeing as I'm at a complete loss as to why this happens, I hope someone can help me here.

EDIT: As requested, here is a more complete, compilable version of the program that produces the same error.

I'm on Windows 10 Home 64-bit, using the 32-bit version of MingW-w64 to compile on C++17. My SDL2 version is 2.0.8, and my SDL2_image version is 2.0.3.

Here is the image I would like to load: player

The image is contained inside a folder called assets in the original directory and the build directory. (I use CMake to remove the folder in the build directory pre-build and copy paste it post-build).

And here is the code:

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

void quit(SDL_Window* window, SDL_Renderer* renderer) {
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    IMG_Quit();
    SDL_Quit();
    std::cout << "Quit Test." << std::endl;
}

int main(int argv, char** argc) {

    if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
        std::cout << "SDL initialized" << std::endl;
    } else {
        std::cerr << "Failed to initialize SDL" << std::endl;
        std::cerr << SDL_GetError() << std::endl;
        return 1;
    }
    auto window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, 0);
    if (window) {
        std::cout << "Window created." << std::endl;
    } else {
        std::cerr << "Failed to create window." << std::endl;
        return 2;
    }

    auto initError = IMG_Init(IMG_INIT_PNG);
    if (initError == IMG_INIT_PNG) {
        std::cout << "SDL_image initialized" << std::endl;
    } else {
        std::cerr << "Failed to initialize SDL_image" << std::endl;
        std::cerr << "Return value: " << initError << std::endl;
        std::cerr << "Error flags: " << IMG_GetError() << std::endl;
        return 3;
    }

    auto renderer = SDL_CreateRenderer(window, -1, 0);
    if (renderer) {
        SDL_SetRenderDrawColor(renderer, 100, 200, 255, 255);
        std::cout << "Renderer created." << std::endl;
    } else {
        std::cerr << "Failed to create renderer." << std::endl;
        std::cerr << SDL_GetError() << std::endl;
        return 4;
    }

    auto texture = IMG_LoadTexture(renderer, "assets/player.png");
    if (!texture) {
        std::cerr << "Failed to load texture!" << std::endl;
        std::cerr << IMG_GetError() << std::endl;
        return 5;
    }

    quit(window, renderer);

    return 0;
}

Which outputs:

SDL initialized
Window created.
Failed to initialize SDL_image
Return value: 0
Error flags:

Process finished with exit code 3
L. Kue
  • 473
  • 5
  • 19
  • Does IMG_LoadTexture works with a MVCE? – aram Aug 02 '18 at 01:29
  • I find it to be much more likely that problem is in your output code, e.g. not putting `\n` into stdout. Or if you're on windows, you might not see anything you put into stdout at all (without special handling). – keltar Aug 02 '18 at 04:14
  • I thought this was a pretty solid MVCE, but no, reducing the code has not helped me get this to work. @keltar I've tried a number of different print commands, none of them have yielded any result (including adding \n or std::endl, as well as string concatenation or using std::cerr instead) – L. Kue Aug 02 '18 at 10:35
  • @L.Kue my statement was more about can you get anything printed at all, not related to `SDL_image`. As for the MCVE part - it is neither compilable nor verifyable (which would require OS, toolchain, library versions, and your image file). Have you initialised SDL_image with PNG flag set? What return value `IMG_Init` gave you? – keltar Aug 02 '18 at 10:42
  • 2
    Well it clearly failed to initialise, and exited before even trying to load your PNG, but I can't imagine situation when it doesn't set error message (not that it required to - but the code of SDL_image is not that big). I recommend stepping through IMG_Init (probably even building debug libraries), but it is up to you; actual problem is most likely it being unable to load `libpng*.dll` becuause it isn't in system32 or executable's directory, or have wrong architecture (like 32bit dll but 64bit executable). – keltar Aug 02 '18 at 15:59

0 Answers0