[SOLVED] Loading BMP Image results in transparent window

New to SDL, I’m following this tutorial which has the end result of displaying a bmp image within an SDL window. Simple stuff. However, when my program is run the contents of the window are transparent.

My program is a modified version of the source within the tutorial and is written in C ( as opposed to
C++, which really isn’t much of a difference in this case ).

The following is my source:

#include <SDL2/SDL.h>
#include <stdio.h>

typedef enum { false, true } bool;

// Starts up SDL and creates window
bool init( SDL_Window*, SDL_Surface*, int, int );
// Loads media
bool loadMedia( SDL_Surface*, char* );
// Frees media and shuts down SDL
void end( SDL_Surface*, SDL_Window* );

const int SCREEN_WIDTH= 640;
const int SCREEN_HEIGHT= 480;

/*
*
*/
bool init( SDL_Window* sdlWindow, SDL_Surface* sdlScreenSurface, 
   int height, int width ) 
{
 // 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
   sdlWindow= SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED,
       SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );

   if( sdlWindow == NULL ) {
     printf( "Window could not be created! SDL_Error: %s\n",
         SDL_GetError() );
     success= false;
   } else {
     // Get Window surface
     sdlScreenSurface= SDL_GetWindowSurface( sdlWindow );
   }
 }

 return success;
}

/**
*
*/
bool loadMedia( SDL_Surface* sdlImage, char* imagePath )
{
 // Loading success flag
 bool success= true;

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

 return success;
}


/**
*
*/
void end( SDL_Surface* sdlImage, SDL_Window* sdlWindow )
{
 // Dallocate surface
 SDL_FreeSurface( sdlImage );
 sdlImage= NULL;

 // Destroy window
 SDL_DestroyWindow( sdlWindow );

 // Quit SDL subsystems
 SDL_Quit();
}

/**
*
*/
int main( int argc, char* args[] ) 
{
 
 // The window we'll be rendering to
 SDL_Window* sdlWindow= NULL;
 // The surface contained by the window
 SDL_Surface* sdlScreenSurface= NULL;
 // The image we will load and show on the screen
 SDL_Surface* sdlImage= NULL;
 char* imagePath= "assets/helloSDL.bmp";

 // Start up SDL and create window
 if( !init( sdlWindow, sdlScreenSurface, SCREEN_HEIGHT, SCREEN_WIDTH ) ) {
   printf( "Failed to initialize!\n" );
 } else {
   // Load media
   if( !loadMedia( sdlImage, imagePath ) ) {
     printf( "Failed to load media!\n" );
   } else {
     // Apply the image
     SDL_BlitSurface( sdlImage, NULL, sdlScreenSurface, NULL );
     // Update the surface
     SDL_UpdateWindowSurface( sdlWindow );
     // Wait two seconds
     SDL_Delay( 2000 );
   }

 }

 // Free resources and close SDL
 end( sdlImage, sdlWindow );

 return 0;
}

I’m a relative beginner with C++ and SDL myself, so my answer is likely not exhaustive, as well as poorly explained, but you’ve an error with how you’re passing the sdlWindow, sdlScreenSurface arguments in init(), as well as sdlImage in loadMedia().

With those functions, you’ve written the functions to copy the arguments by value. In your call to init(), for example, passing sdlWindow and sdlScreenSurface is actually passing the values NULL to initialize the functions various pointer parameters. From there, any changes to the pointer inside the function remains restricted to the local pointer.

You could perhaps rewrite the functions to take pointers to pointers of types (e.g. SDL_Surface ** sdlImage, rather than SDL_Surface * sdlImage), although this will also require reworking of your function’s implementations.

EDIT:
I’ve edited your code with a working example. I’m not knowledgeable enough to say whether this is the best solution - but it does work.

#include <SDL2/SDL.h>
#include <stdio.h>

typedef enum { false, true } bool;

// Starts up SDL and creates window
bool init( SDL_Window**, SDL_Surface**, int, int );
// Loads media
bool loadMedia( SDL_Surface**, char* );
// Frees media and shuts down SDL
void end( SDL_Surface**, SDL_Window** );

const int SCREEN_WIDTH= 640;
const int SCREEN_HEIGHT= 480;

/*
*
*/
bool init( SDL_Window** sdlWindow, SDL_Surface** sdlScreenSurface, 
   int height, int width ) 
{
 // 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
   *sdlWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED,
       SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );

   if( *sdlWindow == NULL ) {
     printf( "Window could not be created! SDL_Error: %s\n",
         SDL_GetError() );
     success= false;
   } else {
     // Get Window surface
     *sdlScreenSurface= SDL_GetWindowSurface( *sdlWindow );
   }
 }

 return success;
}

/**
*
*/
bool loadMedia( SDL_Surface** sdlImage, char* imagePath )
{
 // Loading success flag
 bool success= true;

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

 return success;
}


/**
*
*/
void end( SDL_Surface** sdlImage, SDL_Window** sdlWindow )
{
 // Dallocate surface
 SDL_FreeSurface( *sdlImage );
 *sdlImage= NULL;

 // Destroy window
 SDL_DestroyWindow( *sdlWindow );

 // Quit SDL subsystems
 SDL_Quit();
}

/**
*
*/
int main( int argc, char* args[] ) 
{
 
 // The window we'll be rendering to
 SDL_Window* sdlWindow= NULL;
 // The surface contained by the window
 SDL_Surface* sdlScreenSurface= NULL;
 // The image we will load and show on the screen
 SDL_Surface* sdlImage= NULL;
 char* imagePath= "assets/helloSDL.bmp";

 // Start up SDL and create window
 if( !init( &sdlWindow, &sdlScreenSurface, SCREEN_HEIGHT, SCREEN_WIDTH ) ) {
   printf( "Failed to initialize!\n" );
 } else {
   // Load media
   if( !loadMedia( &sdlImage, imagePath ) ) {
     printf( "Failed to load media!\n" );
   } else {
     // Apply the image
     SDL_BlitSurface( sdlImage, NULL, sdlScreenSurface, NULL );
     // Update the surface
     SDL_UpdateWindowSurface( sdlWindow );
     // Wait two seconds
     SDL_Delay( 2000 );
   }

 }

 // Free resources and close SDL
 end( &sdlImage, &sdlWindow );

 return 0;
}

Thanks @JessJ! That did it. I haven’t programmed C in a while (not that I was an expert when I did), so this also helps as a strategy when dealing with functions in the other exercises. I wouldn’t mind knowing a solution which didn’t have me dereferencing the pointers in the function body. Nonetheless, thank you for your help!

If you dont want to pass pointers to pointers and deref then use the return statement to return the window.

SDL_Window* createWindow() {
// do stuff
return window;
}

No problem dracut. To my mind, Smiles’ solution is probably cleaner, but if you want a solution that doesn’t have you dereferencing pointers in your function bodies, but essentially works the same as your first example, you could replace your pointer arguments with references to pointers as below.

This seems nice, given that it doesn’t change your initial code outside of the parameter declarations, but personally, I’d prefer to rewrite code than to use the (to my mind) ugly references to pointers.

#include <SDL2/SDL.h>
#include <stdio.h>

typedef enum { false, true } bool;

// Starts up SDL and creates window
bool init( SDL_Window *(&), SDL_Surface *(&), int, int );
// Loads media
bool loadMedia( SDL_Surface *(&), char* );
// Frees media and shuts down SDL
void end( SDL_Surface*(&), SDL_Window*(&) );

const int SCREEN_WIDTH= 640;
const int SCREEN_HEIGHT= 480;

/*
*
*/
bool init( SDL_Window *(&sdlWindow), SDL_Surface *(&sdlScreenSurface), 
   int height, int width ) 
{
 // 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
   sdlWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED,
       SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );

   if( sdlWindow == NULL ) {
     printf( "Window could not be created! SDL_Error: %s\n",
         SDL_GetError() );
     success= false;
   } else {
     // Get Window surface
     sdlScreenSurface= SDL_GetWindowSurface( sdlWindow );
   }
 }

 return success;
}

/**
*
*/
bool loadMedia( SDL_Surface* (&sdlImage), char* imagePath )
{
 // Loading success flag
 bool success= true;

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

 return success;
}


/**
*
*/
void end( SDL_Surface* (&sdlImage), SDL_Window* (&sdlWindow) )
{
 // Dallocate surface
 SDL_FreeSurface( sdlImage );
 sdlImage= NULL;

 // Destroy window
 SDL_DestroyWindow( sdlWindow );

 // Quit SDL subsystems
 SDL_Quit();
}

/**
*
*/
int main( int argc, char* args[] ) 
{
 
 // The window we'll be rendering to
 SDL_Window* sdlWindow= NULL;
 // The surface contained by the window
 SDL_Surface* sdlScreenSurface= NULL;
 // The image we will load and show on the screen
 SDL_Surface* sdlImage= NULL;
 char* imagePath= "assets/helloSDL.bmp";

 // Start up SDL and create window
 if( !init( sdlWindow, sdlScreenSurface, SCREEN_HEIGHT, SCREEN_WIDTH ) ) {
   printf( "Failed to initialize!\n" );
 } else {
   // Load media
   if( !loadMedia( sdlImage, imagePath ) ) {
     printf( "Failed to load media!\n" );
   } else {
     // Apply the image
     SDL_BlitSurface( sdlImage, NULL, sdlScreenSurface, NULL );
     // Update the surface
     SDL_UpdateWindowSurface( sdlWindow );
     // Wait two seconds
     SDL_Delay( 2000 );
   }

 }

 // Free resources and close SDL
 end( sdlImage, sdlWindow );

 return 0;
}