SDL2 won't display image - c

I want to use SDL2 to open a window and display an image (a meme, to be precise). For some reason, the image doesn't appear; when I run the program, only a blank window opens.
This is my code:
#include <stdio.h>
#include <SDL2/SDL.h>
#include <time.h>
#include <stdbool.h>
#include "SDL2_image/SDL_image.h"
typedef struct
{
SDL_Texture *meme1;
SDL_Window *window;
SDL_Renderer *renderer;
}Meme;
void load(Meme *meme)
{
SDL_Surface *surface = NULL;
surface = IMG_Load("meme1.jpg");
meme->meme1 = SDL_CreateTextureFromSurface(meme->renderer, surface);
if(surface == NULL)
{
printf("Could not find meme1.jpg\n");
EXIT_FAILURE;
}
if(SDL_CreateTextureFromSurface(meme->renderer, surface) < 0 )
{
printf("\n\n\nSDL_CreateTextureFromSurface failed: %s\n\n\n", SDL_GetError());
}
SDL_FreeSurface(surface);
}
int process()
{
int quit = 0;
SDL_Event quitEvent;
while(quit==0)
{
while(SDL_PollEvent(&quitEvent))
{
if(quitEvent.type == SDL_QUIT)
{
quit = 1;
}
}
}
return quit;
}
void doRender(SDL_Renderer *renderer, Meme *meme)
{
renderer = SDL_CreateRenderer(meme->window, -1, 0);
SDL_RenderCopy(renderer, meme->meme1, NULL, NULL);
SDL_RenderPresent(renderer);
}
int main(int argc, char *argv[])
{
//creates the main window
SDL_Window *window = NULL;
Meme meme;
SDL_Renderer *renderer = NULL;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
0);
if (window == NULL)
{
printf("\nFailed to create window: %s\n", SDL_GetError());
return 1;
}
load(&meme);
int done = 0;
while(!done)
{
done = process();
doRender(renderer, &meme);
}
SDL_DestroyWindow(window);
SDL_DestroyTexture(meme.meme1);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

You should try converting the meme to a bmp image and the using the function SDL_LoadBmp
(use a surface to use this function)
if you need more help or need details check the syntax at
https://wiki.libsdl.org/SDL_LoadBMP

the error comes from the fact that you did not initialize SDL_image
with the function
"IMG_Init (arg)"

Related

Wrong color with SDL on HDR image?

I have my program that is displaying my image:
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
void Clean_ressources(SDL_Window *w, SDL_Renderer *r, SDL_Texture *t)
{
if (t!= NULL)
SDL_DestroyTexture(t);
if (t!= NULL)
SDL_DestroyRenderer(r);
if (w!= NULL)
SDL_DestroyWindow(w);
SDL_Quit();
}
void SDL_ExitWithError(const char *message);
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Surface *surface = NULL;
SDL_Texture *texture, *tmp = NULL;
SDL_Rect dest_rest = {0, 0, 640, 480};
//SDL Init
if(SDL_Init(SDL_INIT_VIDEO) != 0)
SDL_ExitWithError("SDL init failed");
//Create Window
window = SDL_CreateWindow("My Viewer 10 bits", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED ,1000, 1000, 0);
if(window == NULL)
{
Clean_ressources(NULL, NULL, NULL);
SDL_ExitWithError("Window creation failed");
}
//Create Renderer
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
if(renderer == NULL)
{
Clean_ressources(window, NULL, NULL);
SDL_ExitWithError("Renderer creation failed");
}
//Load image
// https://github.com/codelogic/wide-gamut-tests/blob/master/R2020-sRGB-red.jpg
surface = IMG_Load("src/red.jpg");
if(surface == NULL)
{
Clean_ressources(window, renderer, NULL);
SDL_ExitWithError("Load image failed");
}
tmp = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
if(tmp == NULL)
{
Clean_ressources(window, renderer, NULL);
SDL_ExitWithError("Create texture from surface failed");
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB2101010, SDL_TEXTUREACCESS_TARGET, surface->w, surface->h);
if(texture == NULL)
{
Clean_ressources(window, renderer, NULL);
SDL_ExitWithError("Create texture failed");
}
if(SDL_QueryTexture(texture, NULL, NULL, &dest_rest.w, &dest_rest.h) != 0)
{
Clean_ressources(window, renderer, NULL);
SDL_ExitWithError("Query texture failed");
}
if(SDL_RenderCopy(renderer, tmp, NULL, NULL) != 0)
{
Clean_ressources(window, renderer, NULL);
SDL_ExitWithError("Render copy failed");
}
SDL_SetRenderTarget(renderer, texture);
SDL_RenderPresent(renderer);
SDL_DestroyTexture(tmp);
SDL_FreeSurface(surface);
SDL_SetRenderTarget(renderer, NULL);
/*--------------------------------------------------------------*/
SDL_bool program_launched = SDL_TRUE;
while(program_launched)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
program_launched = SDL_FALSE;
break;
default:
break;
}
}
}
/*--------------------------------------------------------------*/
Clean_ressources(window, renderer, texture);
SDL_Quit();
return EXIT_SUCCESS;
}
void SDL_ExitWithError(const char *message)
{
SDL_Log("ERROR :%s > %s\n", message, SDL_GetError());
exit(EXIT_FAILURE);
}
I tried with different image and everything seems fine, but with this image I don't understand the color is very different in my window.
Here is the image in input:
And this is the image in my window in SDL2:
I'm aware that this image is not a high dynamic range color but I would like to display in my HDR screen an image that have HDR color (10 bits depth color) in SDL but if my sdl window have color problem I won't be able to do that.
I also tried with SDL_PIXELFORMAT_RGBA8888 and nothing changed.

Issue closing window with SDL2 in C

I have this code that is setting up a window, along with the close button functionality.
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
int initialize();
void handle_input();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
bool running;
int FPS;
int width;
int height;
bool close_requested;
} Game;
Game game = {
.running = true,
.FPS = 60,
.width = 600,
.height = 600,
.close_requested = false,
};
int main(int argc, char* argv[]) {
initialize();
handle_input();
while(game.running) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, game.width, game.height, 0); //creates window
if (!window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
}
void handle_input() {
SDL_Event event;
while (!game.close_requested) { //close button
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}
}
However, whenever I try to run this program, the window won't even open and I'm getting 0 errors in the console, besides a warning that states control may reach end of non-void function at the initialize() function. What does that warning mean? What is going on with my code? What did I do wrong?
I see 2 issues here:
you call handle_input() in your main before you enter the main loop and it gets stuck there until you exit, so SDL_RenderPresent() is never called.
the initialize function doesn't return anything in case of success, this is why you see the warning.
Try with the following changes, in main() move your input handling inside the loop:
int main(int argc, char* argv[]) {
initialize();
while(game.running && !game.close_requested) {
handle_input(); // <-- move here
SDL_SetRenderDrawColor(game.renderer, 255, 0, 0, 255);
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
}
// the rest...
}
In initialize() add a return 0; at the end.
In handle_input() remove the outer loop:
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
}
}

SDL_TTF, Render Modes are identical in quality

I have a click based game to code, and It contains some text that need to be rendererd in real-time,I tried to render the text with TTF_RenderText_Solid() , TTF_RenderText_Shaded(),TTF_RenderText_Blended() but they all render the same poor quality text. I have tried to change the BlendMode of the renderer, Surface and Texture, but still the same result, You might think it is because of using the same surface over and over, but I am sure it's not that.
screenshot
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#define Title "Test"
#define font01 "src/fonts/Roboto-Regular.ttf"
#define font01_size 48
typedef struct {
SDL_Texture *txtu;
SDL_Rect rect;
SDL_Color clr;
char* text;
} text_t;
int main(int argc,char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init();
SDL_Window *window = SDL_CreateWindow(Title,SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,480,720,SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_TARGETTEXTURE);
TTF_Font *font1 = TTF_OpenFont(font01,font01_size);
SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);
SDL_Surface *Load_srfc = NULL;
SDL_SetSurfaceBlendMode(Load_srfc,SDL_BLENDMODE_BLEND);
//SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,480,720);
SDL_SetRenderDrawColor(renderer,0,0,0,255);
SDL_RenderFillRect(renderer,NULL);
SDL_Delay(500);
text_t text1 = {NULL,{0,0,220,60},{255,255,255,240},"015:32.665 ms"};
text_t text2 = {NULL,{20,70,220,60},{255,255,255,240},"015:32.665 ms"};
text_t text3 = {NULL,{40,140,220,60},{255,255,255,240},"015:32.665 ms"};
Load_srfc = TTF_RenderText_Solid(font1,text1.text,text1.clr);
text1.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text1.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text1.txtu,NULL,&text1.rect);
SDL_RenderPresent(renderer);
SDL_Delay(500);
SDL_Color back = {240,30,50,245};
Load_srfc = TTF_RenderText_Shaded(font1,text2.text,text2.clr,back);
text2.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text2.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text2.txtu,NULL,&text2.rect);
SDL_RenderPresent(renderer);
SDL_Delay(500);
Load_srfc = TTF_RenderText_Blended(font1,text3.text,text3.clr);
text3.txtu = SDL_CreateTextureFromSurface(renderer,Load_srfc);
SDL_SetTextureBlendMode(text2.txtu,SDL_BLENDMODE_BLEND);
SDL_FreeSurface(Load_srfc); Load_srfc=NULL;
SDL_RenderCopy(renderer,text3.txtu,NULL,&text3.rect);
SDL_RenderPresent(renderer);
bool quit=0;
while(!quit)
{
SDL_Event evt;
while (SDL_PollEvent(&evt))
{
if(evt.type == SDL_QUIT ||
(evt.type == SDL_WINDOWEVENT && evt.window.event == SDL_WINDOWEVENT_CLOSE) ||
(evt.type == SDL_KEYDOWN && evt.key.keysym.sym == SDLK_ESCAPE)) {
quit = 1;
}
}
}
SDL_DestroyTexture(text1.txtu);
SDL_DestroyTexture(text2.txtu);
SDL_DestroyTexture(text3.txtu);
SDL_FreeSurface(Load_srfc);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
}

Handling multiple images in SDL2

I'm wondering how to handle more than one image using IMG_Load(); Do I always have to create a surface for every image? Or I have to create some loop that will create texture only using this one surface?
SDL_Surface* surface = IMG_Load("resources/hello.png");
SDL_Texture* tex = SDL_CreateTextureFromSurface(rend, surface);
Here is the code:
#include <stdio.h>
#include <SDL.h>
#include <SDL_timer.h>
#include <SDL_image.h>
int main(void)
{
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
{
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
SDL_Window* win = SDL_CreateWindow("Hello, SDL2!",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480, 0);
if (!win)
{
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer* rend = SDL_CreateRenderer(win, -1, render_flags);
if (!rend)
{
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_Surface* surface = IMG_Load("resources/hello.png");
if (!surface)
{
printf("error creating surface\n");
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_Texture* tex = SDL_CreateTextureFromSurface(rend, surface);
SDL_FreeSurface(surface);
if (!tex)
{
printf("error creating texture: %s\n", SDL_GetError());
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_RenderClear(rend);
SDL_RenderCopy(rend, tex, NULL, NULL);
SDL_RenderPresent(rend);
SDL_Delay(5000);
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
What I usually do when I have lots of images to load is create a vector or array of type SDL_Texture* that is a member of a class, and set it up with a for loop, loading in the images and appending them

SDL_CreateRenderer cannot find a matching driver to create a renderer

Here is a simple code to control the movement a rectangle on the screen.
The platform is Windows 10 and mingw32 is used to compile the code.
The follwing cmake script is used to build the code.
cmake_minimum_required(VERSION 3.12)
project(main C)
set(CMAKE_C_STANDARD 11)
add_executable(main main.c)
target_link_libraries(main mingw32 SDL2main SDL2)
When ran the following output is generated.
Error in create_renderer Couldn't find matching render driver
Process finished with exit code 1
And the code is as follows.
// #define SDL_MAIN_HANDLED
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
void init() {
int error = SDL_Init(SDL_INIT_EVERYTHING);
if (error){
printf("Error in init: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
}
SDL_Window* create_window(SDL_Point size, const char* title) {
SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, size.x, size.y, SDL_WINDOW_OPENGL);
if (window == NULL) {
printf("Error in create_window %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
return window;
}
SDL_Renderer* create_renderer(SDL_Window *window, SDL_Point size) {
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
printf("Error in create_renderer %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
exit(1);
}
SDL_RenderSetLogicalSize(renderer, size.x, size.y);
return renderer;
}
void clean_up(SDL_Renderer *renderer, SDL_Window *window) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int argc, char *argv[]) {
init();
SDL_Window *window;
SDL_Point window_size = {1280, 720};
window = create_window(window_size, "Window");
SDL_Renderer *renderer;
renderer = create_renderer(window, window_size);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_Rect player = {100, 100, 20, 20};
int should_exit = 0;
while (!should_exit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
should_exit = 1;
clean_up(renderer, window);
}
else if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_RIGHT:
player.x++;
break;
case SDLK_LEFT:
player.x--;
break;
case SDLK_DOWN:
player.y++;
break;
case SDLK_UP:
player.y--;
break;
default:
break;
}
}
}
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderFillRect(renderer, &player);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderPresent(renderer);
}
return 0;
}
I searched for duplicate questions and their solution was to update the graphics driver and check that the corresponding subsystems are initialized before calling SDL_CreateRenderer.
I have the latest nvidia drivers installed to no avail, and as you can see the initialization order is correct. Can you guide me as to find the reason why?

Resources