0

Context

In my SDL2 app, I am trying to load a png image(transparent). I want to give a background color to this image with SDL2 because I want to reuse the image somewhere else in the program and I do not want to have multiple version of the same image.

Question

How to give a background color to a SDL_Surface* or a SDL_Texture* with SDL2?

Important Details

OS : Windows
Text Editor : VScode
Building Mehtod : Makefile

My code

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int main(int argc, char* argv[]){
    SDL_Init(SDL_INIT_EVERYTHING);
    IMG_Init(IMG_INIT_PNG);

    SDL_Window* window = NULL;
    SDL_Renderer* renderer = NULL;

    SDL_CreateWindowAndRenderer(900, 500, SDL_WINDOW_RESIZABLE, &window, &renderer);
    SDL_SetWindowTitle(window, "StackOverflowApp");
    
    SDL_Surface* surface = IMG_Load("./yourImage.png");
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);

    SDL_Event event;
    bool run = true;
    while (run) {
        if(SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                run = false;
            }
        }

        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    SDL_FreeSurface(surface);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

Makefile

all:
    @cls
    g++ -I src/include -L src/lib -std=c++23 -o main main.cpp -lmingw32 -lSDL2main -lSDL2 -lSDL2_image 
    ./main
Meniev
  • 148
  • 1
  • 13

1 Answers1

2

Here is the solution:

To give a background color to your transparent image, you will need to fill the image's surface with the desired background color before creating a texture from it. Here's how you can achieve that:

  1. Create a new surface of the same dimensions as your image.
  2. Fill that new surface with your desired background color using SDL_FillRect.
  3. Blit (copy) your image onto the new surface.
  4. Create a texture from the new surface.

Here's a modified version of your code demonstrating this:

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int main(int argc, char* argv[]){
    SDL_Init(SDL_INIT_EVERYTHING);
    IMG_Init(IMG_INIT_PNG);

    SDL_Window* window = NULL;
    SDL_Renderer* renderer = NULL;

    SDL_CreateWindowAndRenderer(900, 500, SDL_WINDOW_RESIZABLE, &window, &renderer);
    SDL_SetWindowTitle(window, "StackOverflowApp");
    
    SDL_Surface* loadedSurface = IMG_Load("./yourImage.png");

    // Create a new surface with the same dimensions as the loaded image
    SDL_Surface* backgroundSurface = SDL_CreateRGBSurface(0, loadedSurface->w, loadedSurface->h, 32, 0, 0, 0, 0);

    // Fill the new surface with a color, for instance, white
    SDL_FillRect(backgroundSurface, NULL, SDL_MapRGB(loadedSurface->format, 255, 255, 255));
    
    // Blit (copy) the loaded image onto the background
    SDL_BlitSurface(loadedSurface, NULL, backgroundSurface, NULL);

    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, backgroundSurface);

    SDL_Event event;
    bool run = true;
    while (run) {
        if(SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                run = false;
            }
        }

        SDL_RenderCopy(renderer, texture, NULL, NULL);
        SDL_RenderPresent(renderer);
    }

    SDL_FreeSurface(loadedSurface);
    SDL_FreeSurface(backgroundSurface);
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

In the above code, we create a new surface (backgroundSurface) and fill it with white color. After that, we blit the loadedSurface (your transparent PNG image) onto the backgroundSurface. The resulting texture will be your PNG image with a white background. Adjust the RGB values in SDL_MapRGB to change the background color.

  • Ok thank you it worked but it is strange that in the `SDL_MapRGB`, the blue and the red are reverse. What I mean is if I do `SDL_MapRGB(loadedSurface->format, 255, 0, 0)` you will have blue and if you do `SDL_MapRGB(loadedSurface->format, 0, 0, 255)` you will have red. – Meniev Aug 20 '23 at 14:05