0

Context: I am currently trying to practice my C skills a little bit with the SDL 2.0.7 and SDL2_image-2.0.2.

Problem: I get an error message during the execution of my program "IMG_Load: Couldn't open xxx.png". The error seems stupid as it is very explicit: "i can't find the image", but as the image is in the appropriate folder... I think I need a fresh eye to spot the stupid mistake.

Platform: Windows 10

IDE: Visual Studio 2017

Steps done to solve the problem:

1) Tried to reduce my code lenght/functionalities to its minimum. Result: Error is still here.

2) I created a new project and copy/pasted the simplified code. Result: On the new project, there is no error, everything is working fine.

3) I compared project's options and the folder. To me they are the same:

Options in both projects

Debug folder in both projects

It shouldn't be useful but just in case, here is my:

Code sample:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include <SDL.h>
#include <SDL_image.h>
#include <SDL_render.h>
#include "SDL_timer.h"

int main(int argc, char *argv[])
{
    printf("argc = %d\n", argc);
    for (int i = 0; i < argc; ++i) 
    {
        printf("argv[ %d ] = %s\n", i, argv[i]);
    }

    SDL_Window* pWindow = NULL;
    SDL_Renderer* pRenderer = NULL;
    SDL_Texture* pTexture = NULL;
    SDL_Surface* pLoadedSurface = NULL;
    SDL_Rect* tileClipsArray = NULL;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
    {
        fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
    }

    //Initialize PNG loading
    int imgFlags = IMG_INIT_PNG;
    if (!(IMG_Init(imgFlags) & imgFlags))
    {
        printf("IMG_Load: %s\n", IMG_GetError());
    }

    pWindow = SDL_CreateWindow("TestLoadingImage",
        SDL_WINDOWPOS_CENTERED, // initial X position.
        SDL_WINDOWPOS_CENTERED, // Initial Y position.
        640, // Width, in pixels.
        480, // Height, in pixels.
        SDL_WINDOW_OPENGL); // Window flags

    assert(NULL != pWindow);

    //Create renderer for the window
    pRenderer = SDL_CreateRenderer(pWindow,
        -1, // Index of the rendering driver to initialize, -1 to initialize the first one supporting the requested flags.
        SDL_RENDERER_ACCELERATED
        | SDL_RENDERER_PRESENTVSYNC); // RendererFlags

    assert(NULL != pRenderer);

    //Initialize renderer color
    SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, 0xFF);

    pLoadedSurface = IMG_Load("GroundTiles.png");
    if (NULL == pLoadedSurface)
    {
        printf("IMG_Load: %s\n", IMG_GetError());
        assert(NULL != pLoadedSurface);
    }

    //Create texture from surface pixels
    pTexture = SDL_CreateTextureFromSurface(pRenderer, pLoadedSurface);
    assert(NULL != pTexture);

    //Get image dimensions
    const int textureWidth = pLoadedSurface->w;
    const int textureHeight = pLoadedSurface->h;
    const int tileClipWidth = 128;
    const int tileClipHeight = 128;
    const int nbLines = textureHeight / tileClipHeight;
    const int nbColumns = textureWidth / tileClipWidth;
    const int nbTileClips = nbLines + nbColumns;

    tileClipsArray = malloc(nbTileClips * sizeof(SDL_Rect));

    int tileClipIndex = 0;
    for (int tileClipLineIndex = 0; tileClipLineIndex < nbLines; ++tileClipLineIndex)
    {
        for (int tileClipColumnIndex = 0; tileClipColumnIndex < nbColumns; ++tileClipColumnIndex)
        {
            tileClipsArray[tileClipIndex].x = tileClipColumnIndex * tileClipWidth;
            tileClipsArray[tileClipIndex].y = tileClipLineIndex * tileClipHeight;
            tileClipsArray[tileClipIndex].w = tileClipWidth;
            tileClipsArray[tileClipIndex].h = tileClipHeight;
            ++tileClipIndex;
        }
    }

    //Get rid of old loaded surface
    SDL_FreeSurface(pLoadedSurface);
    pLoadedSurface = NULL;

    int canLoop = 1;
    SDL_Event event;
    int lastUpdate = SDL_GetTicks();
    int now = 0;
    int timeToSpendPerClip = 5000;
    int timeSpentwithThisClip = 0;
    int clipToUse = 0;

    while (canLoop)
    {
        now = SDL_GetTicks();

        if (now - lastUpdate > 16)
        {
            timeSpentwithThisClip += now - lastUpdate;
            lastUpdate = now;

            // We are processing all the events received this frame.
            while (SDL_PollEvent(&event))
            {
                // We need to know what kind of event we are dealing with.
                switch (event.type)
                {
                case SDL_QUIT:
                    canLoop = 0;
                    break;
                }
            }

            SDL_RenderClear(pRenderer);

            if (timeSpentwithThisClip > timeToSpendPerClip)
            {
                clipToUse = rand() % 4;
                timeSpentwithThisClip = 0;
            }
            // Set rendering space and render to screen.
            SDL_Rect renderQuad;
            renderQuad.x = 50;
            renderQuad.y = 50;
            renderQuad.w = tileClipsArray[clipToUse].w;
            renderQuad.h = tileClipsArray[clipToUse].h;

            SDL_RenderCopyEx(pRenderer, pTexture, &tileClipsArray[clipToUse], &renderQuad, 0.0, NULL, SDL_FLIP_NONE);

            SDL_RenderPresent(pRenderer);
        }
    }

    SDL_DestroyTexture(pTexture);
    free(tileClipsArray);

    SDL_DestroyRenderer(pRenderer);
    pRenderer = NULL;

    SDL_DestroyWindow(pWindow);
    pWindow = NULL;

    IMG_Quit();
    SDL_Quit();

    return EXIT_SUCCESS;
}

I'm probably going to copy/paste all my files from the project 1 into the project 2, but I would like to understand my mistake!

genpfault
  • 51,148
  • 11
  • 85
  • 139
ZulKaz
  • 53
  • 1
  • 5
  • 2
    It seems like the directory from which your program is executed is different to directory of you settings, and in this directory the png might not be there. – Pablo Feb 19 '18 at 01:15
  • I am printing the argv at the beginning of the program. When I have the error, it is printing "argv[ 0 ] = C:\Users\UserName\Documents\Visual Studio 2017\Projects\TestSDL2\x64\Debug\TestSDL2.exe". The image is in this folder, as shown in the screenshot =/ Thank you for your quick answer! – ZulKaz Feb 19 '18 at 01:21
  • 3
    `argv[0]` is the path of the executable, this is not necessarily the path of execution. You can be in `C:\myprojects` and call `C:\windows\explorer.exe` from there, the path of execution would be `C:\myprojects` not `C:\windows`. – Pablo Feb 19 '18 at 01:25
  • 3
    Use [`GetCurrentDirectory`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364934(v=vs.85).aspx) and print the current directory when your program starts. This might tell you from which directory the program is being launched. – Pablo Feb 19 '18 at 01:27
  • My code : "TCHAR ExecutionPath[300]; GetCurrentDirectory(300, ExecutionPath);" Result: "C:\Users\UserName\Documents\Visual Studio 2017\Projects\TestSDL2\TestSDL2" You were right! Is there an option in visual studio for setting the path of execution? – ZulKaz Feb 19 '18 at 01:45
  • That I don't know, I don't use visual studio, in fact I don't even use windows. – Pablo Feb 19 '18 at 01:47
  • Look carefully in all your build, environment & debug options. There might be something like "executable path" or "working directory". I cannot image that visual studio does not allow you to change this, sometimes this is a useful test of how your program reacts to when resources are not present. I tried to do a google search, but my lack of experience with Visual Studio terminology prevents me of finding useful information. – Pablo Feb 19 '18 at 01:50
  • Never mind, I'll find that option tomorrow, thank you very much! I'll go to sleep with the satisfaction to know that the problem is (almost) solved :) – ZulKaz Feb 19 '18 at 01:53

0 Answers0