Wrong color with SDL on HDR image? - c

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.

Related

Cannot get SDL_SetTextureColorMod to work

I am trying to change the color of the image displayed. The image contains characters in black and I want to display them in red. So I am trying to use SDL_SetTextureColorMod but it seems I am doing it wrong since the image rendered is still black. Does someone see the problem with my code?
#include "SDL.h"
#include <stdio.h>
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer);
SDL_Surface *surface = SDL_LoadBMP("font.bmp");
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
int keep_going = 1;
while (keep_going) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
keep_going = 0;
}
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
int ret = SDL_SetTextureColorMod(texture, 255, 0, 0);
if(ret != 0){
printf("%s",SDL_GetError());
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
The image I'm using:

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?

SDL2 won't display image

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)"

C SDL2 - Selecting part of an image and then zooming in

So, I have an image that I open in a window with SDL2. I want to implement a zoom function for the image that works as following: I click on two points of the image and I make a rectangle with those points as opposite corners. Then I make a copy of the rectangle and update the window to show the part of the image I selected, and this new image has a bigger width and height than the rectangle I chose because it will be the height and the width of the whole window.
I can detect the mouse clicks, and from the mouse clicks calculate the top left corner of the rectangle in x and y coordinates. However, I don't know how to make a copy of the pixels in those rectangles, nor how to make the window now show the zoomed in part. I've been googling a lot but I don't know what functions to use or how to code my own. How would I write such a function?
Here's what I have so far. The image I want to be able to zoom into is "map.jpg"
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = NULL;
window = SDL_CreateWindow("WarmingUp", TOP_LEFT_CORNER_X,
TOP_LEFT_CORNER_Y, IMAGE_WIDTH, IMAGE_HEIGHT, 0);
if(window == NULL){
printf("Erro a abrir janela gráfica\n");
exit(EXIT_FAILURE);
}
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL){
printf("Erro a criar renderer\n");
exit(EXIT_FAILURE);
}
SDL_Surface *jpgSurface = NULL;
jpgSurface = IMG_Load("map.jpg");
if(jpgSurface == NULL){
printf("Erro a abrir imagem\n");
exit(EXIT_FAILURE);
}
SDL_Texture *jpgTexture = NULL;
jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
if(jpgTexture == NULL){
printf("Erro a criar superfície através de imagem\n");
exit(EXIT_FAILURE);
}
SDL_FreeSurface(jpgSurface);
SDL_Event e;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT)
quit = 1;
SDL_RenderPresent(renderer);
SDL_Delay(15);
SDL_DestroyTexture(jpgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
I know that to make the mouse interaction in my while &eventloop I need to check for if ( event.type == SDL_MOUSEBUTTONUP ), and I can also show you the code to calculate the top left corner x and y position of the desired rectangle to be cropped, but I really can't go any further.
Here is modified code from question:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768
int main(int argc, char **argv) {
(void)argc, (void)argv;
int quit = 0;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = NULL;
window = SDL_CreateWindow("WarmingUp",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
IMAGE_WIDTH, IMAGE_HEIGHT, 0);
if(window == NULL){
printf("Erro a abrir janela gráfica\n");
exit(EXIT_FAILURE);
}
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL){
printf("Erro a criar renderer\n");
exit(EXIT_FAILURE);
}
SDL_Surface *jpgSurface = NULL;
jpgSurface = IMG_Load("map.jpg");
if(jpgSurface == NULL){
printf("Erro a abrir imagem\n");
exit(EXIT_FAILURE);
}
SDL_Texture *jpgTexture = NULL;
jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
if(jpgTexture == NULL){
printf("Erro a criar superfície através de imagem\n");
exit(EXIT_FAILURE);
}
SDL_FreeSurface(jpgSurface);
SDL_Event e;
// rectangle to upscale in second window
const SDL_Rect srcrect = {600, 500, 250, 250};
SDL_Window *second_window = NULL;
SDL_Renderer *second_renderer = NULL;
SDL_Texture *magnified_fragment_texture = NULL;
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT ||
(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) {
quit = 1;
} else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_t &&
!second_window) {
// create empty surface of adequate size
SDL_Surface *const surf = SDL_CreateRGBSurface(0, srcrect.w, srcrect.h, 32,
0xff000000, 0xff0000, 0xff00, 0xff);
SDL_FillRect(surf, NULL, 0);
// copy pixels
SDL_RenderReadPixels(renderer, &srcrect, SDL_PIXELFORMAT_RGBA8888,
surf->pixels, surf->pitch);
// error checking should be done...
second_window = SDL_CreateWindow("mag",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
srcrect.w*2, srcrect.h*2, 0);
second_renderer = SDL_CreateRenderer(second_window, -1, SDL_RENDERER_ACCELERATED);
magnified_fragment_texture = SDL_CreateTextureFromSurface(second_renderer, surf);
SDL_FreeSurface(surf);
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);
SDL_RenderPresent(renderer);
if(second_renderer) {
const SDL_Rect dstrect = {0, 0, srcrect.w*2, srcrect.h*2};
SDL_RenderClear(second_renderer);
// RenderCopy scales texture to destination rect
SDL_RenderCopy(second_renderer, magnified_fragment_texture, NULL, &dstrect);
SDL_RenderPresent(second_renderer);
}
SDL_Delay(15);
}
SDL_DestroyTexture(jpgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
In keypress event handler it creates second window/renderer/texture (not the best place for it), and later it renders second window if it exists.

Resources