2

first question and I really need help. So I was trying to learn
SDL2 api on C++ . I am using a raspberry pi 3 model B . I was first following a tutorial on Youtube (CodingMadeEasy to be more specific) but now i am following lazyfoo's tutorials. I copied CME's code and tried displaying an image(.bmp) but the window showed nothing , also SDL_GetError() didn't report anything wrong. I thought there must
be something wrong with the code I wrote or the image that I downloaded from the internet may not be .bmp so I went to lazyfoo's tutorials here http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php and downloaded the source code and .bmp file . But when I run it , I get the same output: a blank window and SDL_GetError() not reporting anything on the console. Here's the code:

    /*This source code copyrighted by Lazy Foo' Productions 

(2004-2015)
and may not be redistributed without written permission.*/

//Using SDL and standard IO
#include <SDL2/SDL.h>
#include <stdio.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;

//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;

//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;

bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}

bool loadMedia()
{
    //Loading success flag
    bool success = true;

    //Load splash image
    gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
    if( gHelloWorld == NULL )
    {
        printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
        success = false;
    }

    return success;
}

void close()
{
    //Deallocate surface
    SDL_FreeSurface( gHelloWorld );
    gHelloWorld = NULL;

    //Destroy window
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Start up SDL and create window
    if( !init() )
    {
        printf( "Failed to initialize!\n" );
    }
    else
    {
        //Load media
        if( !loadMedia() )
        {
            printf( "Failed to load media!\n" );
        }
        else
        {
            //Apply the image
            SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );

            //Update the surface
            SDL_UpdateWindowSurface( gWindow );

            //Wait two seconds
            SDL_Delay( 2000 );
        }
    }

    //Free resources and close SDL
    close();

    return 0;
}

If you want the .bmp file , please visit the link above and download the source code and files. Its not letting me upload it. Here's the output I get:Output . This transparant-ish , greyish window . I am using gnu c++ compiler and compiled it using

g++ 02_getting_an_image_on_the_screen.cpp -w -lSDL2 -o hl

and get that transparant-ish greyish window . I guess its transparant because my terminal is configured like that. To see what the problem was , i removed the .bmp to see if sdl reports an error and it did which meant it was able to read the .bmp when it was in the right location , just not able to display it. I searched google for hours found nothing . On stack overflow , the closest problem to mine was this SDL window does not show I even tried polling events so as to give the system its chance to have it's event loop run ,as suggested there, but no matter how long the window stays open , the .bmp does not show up. What's even more bizarre is that this isn't happening to me first time. I tried learning SDL2 an year ago but the same thing happened back then. I was using a cheap Windows 10 notebook with 2GBs of RAM and was using code::blocks (mingw compiler version) and the same thing happened except the window wasn't transparant , it was white , just as you get when you create a window with sdl in Windows without displaying anything on it. For some reason , codeblocks didn't let me set the window to nullptr saying it didn't recognized what it was so i had to set it to NULL instead . Because of this, I thought the window not displaying .bmp was the compiler's fault too. So I downloaded Microsoft visual studio 2015 but the result was same : no image displayed . At that point , I gave up , but now I came back because I have a new machine ( rpi model 3 b) and a new compiler (gnu c/c++) on it thinking SDL won't haunt me again but SDL doesn't seem to give up . I really need help . And yes, the .bmp is in right location , and i've included its right name in the code . Keep in mind that I've tried doing this on 2 machines , 3 compilers , 2 very different operating systems and 2 different cpu architectures( armv71 and x86) and at this point its getting frustrating . I've got some amazing ideas which can easily be implemented if SDL2 lets me . Sorry for the long post and any help is appreciated . Thank you.

  • 1. unless you're absolutely know what you're doing, never ever use `-w` compiler switch. 2. your path says your image is in subdirectory, is it? 3. From your screenshot it doesn't seem like you're running your program from terminal, where do you expect to see error output then? 4. Judging from screemshot, your window don't get updated at all (all you see is "bachground" of file manager and desktop), bmp loading is unlikely to be the source of your problem; the fact that you don't redraw on specific events is. Make event loop and rendering loop. Drawing once and waiting is not a way to display. – keltar Sep 15 '18 at 16:28
  • I always ran it from the terminal but for the this screenshot , I just executed the output file('hl'). And no, I didn't see any errors even when I ran it from the terminal. @keltar , can you please explain what do you mean by rendering loop ? I'm kinda new in game development. – HashirSibtain Sep 16 '18 at 04:26
  • It is described in the next part of tutorial you refered to. Most common way is to make a loop that breaks on exit condition, and on each iteration it processes events and redraws whatever you want to display. – keltar Sep 16 '18 at 04:39
  • I tried what you said . Even downloaded the source code and bmp from the tutorial . Didn't work. Thanks anyway. – HashirSibtain Sep 16 '18 at 05:13
  • Sorry but I can't mindread. Please edit your question to include your actual code, as well as output of `ls -la` in this directory, and full output of a program. Because the code in question technically isn't required to display anything. Also it might be a good time to start using debugger to inspect program flow and variables values. – keltar Sep 16 '18 at 05:35
  • your problem is that you are doing this: `SDL_Delay( 2000 );`. Instead you should actually run an event loop (with `SDL_PollEvent()`). Many of the SDL2 renderer backends require this in order to draw anything. I hate that this is not documented and that tutorials do this non-portable crap. – Brad Allred Sep 18 '18 at 15:05

2 Answers2

0

Your code works fine on my iMac. The only changes I made are as follows so maybe try making the same changes to see if it works for you.

Firstly, there are many different types of BMP files and it may be that you have got hold of one that works fine in your picture viewer application but SDL is "unhappy" about loading it. For the absence of doubt, create your own BMP file with ImageMagick then you can be sure you have a good one. I used this in Terminal:

convert -size 640x480 gradient:red-cyan image.bmp

Secondly, run your program outside of any "Integrated Development Environment" , i.e. just from a Terminal and with all images in the current directory (no paths) and all without spaces in their names. The reason is that IDEs can play havoc with event loops and screen updates, and that IDEs often appear to be running one program but are actually running /some/where/else/Debug/program instead and that messes up the paths to files you open, e.g. your "02_getting_an_image_on_the_screen/hello_world.bmp" and it also means that directory separators don't cause issues.

Thirdly, consider using pkgconfig to get the header paths and libraries. On my Mac for example, it adds a define for thread safety that I may not have been aware of:

pkg-config --cflags --libs sdl2

Sample Output

-D_THREAD_SAFE -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2

So, to compile, I use:

g++ main.cpp $(pkg-config --cflags --libs sdl2) -o main
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Thanks for the help . I tried but the output is still same: .bmp doesn't show up . Thank you for telling me about ImageMagick though. Its really good. – HashirSibtain Sep 15 '18 at 12:50
  • Maybe try changing the ImageMagick command to make a GIF and see if that will load in SDL. – Mark Setchell Sep 15 '18 at 15:46
0

Please forgive me if I break some rule by replying to this old question, but it helped me find a solution to a similar problem I was facing. I had almost exact same code with only a difference in the main function following the 9/17/22 version of the Lazy Foo guide to SDL2. Here is my code edited without removing its meaning.

int main(int argc, char *argv[])
{
    if (game_init() == 0) {
        printf("Failed to initialize game!\n");
        exit(EXIT_FAILURE);
    }

    if (game_load_media() == 0) {
        printf("Failed to load media!\n");
        exit(EXIT_FAILURE);
    }

    SDL_BlitSurface(gHelloSurface, NULL, gScreenSurface, NULL);

    SDL_UpdateWindowSurface(gWindow);

    SDL_Event e;
    int quit = 0;
    while( quit == 0 ) {
        SDL_PollEvent( &e );
        if( e.type == SDL_QUIT )
            quit = true;
    }

    game_close();

    return 0;
}

The issue is that the window was transparent sometimes and other times it loaded the image correctly and showed the bmp image. Through experimentation with SDL_WindowFlags and arrangement of function calls I found that by either delaying:

SDL_BlitSurface(gHelloSurface, NULL, gScreenSurface, NULL);
SDL_Delay(100);
SDL_UpdateWindowSurface(gWindow);

or simply moving the SDL_UpdateWindowSurface(gWindow); inside the while loop fixed the issue. Being only a beginner my guess is that something is not initialized in time, but with a delayed call or repeated calls fixes this.

Also. I faced this issue both on Window 10 and Kubuntu 22.04 with KDE Plasma 5.24.7, KDE Framework 5.92.0, Qt 5.15.3, and kernel 5.15, on X11. And the same hack fixed issue for both platforms.

The_Matrix
  • 85
  • 7