I have an image stored in memory as an array where the values are between 0 and 255. I would like to display this image to the screen using SDL. I am writing code in C.
I have written the following code based on tutorials that I found on the internet. My impression is that this should display an image. But instead, no matter how I change the data array, I always get a white window.
Can anyone tell me how to fix this? Any help is very appreciated.
void main( void ){
SDL_Window* window;
SDL_Surface* imgSurf;
SDL_Surface* winSurf;
SDL_Event sdlEvent;
unsigned char* data;
size_t i, j;
bool running;
size_t h, w;
window = NULL;
imgSurf = NULL;
winSurf = NULL;
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO );
h = 480;
w = 640;
window = SDL_CreateWindow( "CIMPL Image", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
(int) img->w, (int) img->h, SDL_WINDOW_ALLOW_HIGHDPI );
winSurf = SDL_GetWindowSurface( window );
// Make an image that's black on left and increasing to white on right
data = malloc( sizeof( uint8_t ) * (h*w) );
for( j=0; j < img->h; ++j ){
for( i=0; i < img->w; ++i ){
data[ i + j * img->w ] = (uint8_t) i;
}
}
imgSurf = SDL_CreateRGBSurfaceFrom( (void*) data, (int) img->w, (int) img->h,
8, w, 0, 0, 0, 0 );
running = true;
while( running ){
if( SDL_WaitEvent( &sdlEvent ) ){
// WaitEvent is appropriate if window responds to user events
// If things happen without user events, use SDL_PollEvent
switch( sdlEvent.type ){
case SDL_QUIT:
running = false;
break;
}
}
SDL_BlitSurface( imgSurf, NULL, winSurf, NULL );
SDL_UpdateWindowSurface( window );
}
SDL_FreeSurface( imgSurf ); imgSurf = NULL;
SDL_FreeSurface( winSurf ); winSurf = NULL;
free( data );
SDL_DestroyWindow( window );
SDL_Quit();
return 0;
}
From SDL_CreateRGBSurface
Remarks
If depth is 4 or 8 bits, an empty palette is allocated for the surface.
From SDL_Palette
Remarks
Each pixel in an 8-bit surface is an index into the colors field of the SDL_Palette structure stored in SDL_PixelFormat. An SDL_Palette should never need to be created manually. It is automatically created when SDL allocates an SDL_PixelFormat for a surface. The colors values of an SDL_Surface's palette can be set with SDL_SetPaletteColors().
That means, you have to set set colors in the palette and your allocated data contains the indices to the colors in the palette.
e.g.
/* pixels/indices */
data = malloc( sizeof( uint8_t ) * (h*w) );
for (j=0; j < img->h; ++j) {
for (i=0; i < img->w; ++i) {
data[ i + j * img->w ] = (uint8_t) (((float) i / (float) img->w) * 255);
}
}
/* surface */
imgSurf = SDL_CreateRGBSurfaceFrom(
(void*) data,
(int) img->w, (int) img->h,
8, w,
0, 0, 0, 0
);
/* palette */
SDL_Color colors[256];
for (int i=0; i < 256; ++i)
colors[i].r = colors[i].g = colors[i].b = (Uint8)i;
SDL_SetPaletteColors(imgSurf->format->palette, colors, 0, 256);