Getting rid of black background of Texture when rendering it to the screen / color keying issue

I have the ascii character “A” rendered as a bitmap with freetype, which I have then created a SDL texture of, and have rendered this to the screen. As below.

My problem is that I’m not able to get rid of the black background behind the “A”.

I have tried setting the following:

uint32_t colorkey = SDL_MapRGB(surf->format, 0, 0, 0);
SDL_SetColorKey(surf, SDL_TRUE, colorkey);
SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, surf);
SDL_FreeSurface(surf); surf = nullptr;

but this causes it to blend with the background uniformly?

For context the SDL surface was created like this:

SDL_Surface* surf = SDL_CreateRGBSurfaceWithFormatFrom(
slot->bitmap.buffer,
slot->bitmap.width,
slot->bitmap.rows,
8,
slot->bitmap.pitch,
SDL_PIXELFORMAT_INDEX8);

My goal is to just have the blue “A” rendered onto the screen so that I can draw on top of it with cairo.

Appreciate any help :slight_smile:

Do you mind posting a picture of what you mean? I wrote a test program that loads a bmp image of a letter with a black background, and using your colorkey it seems to work as expected (the true black is transparent, all other colors are drawn normally - this includes any anti-aliased border, it’s drawn as if the black still existed).

Have you tried experimenting with SDL_BlendMode yet?

Make sure you draw something that is not black behind the image. This might sound obvious but I made this mistake when I tried to draw your image and it took me quite a while to figure out why the colorkey didn’t work (it did work, I just didn’t see it because the background was black).

But even if you get the colorkey to work it will still not work correctly because it only gets rid of the pixels that are completely black. The antialiased pixels that are halfway between black and blue will still be visible which will look quite ugly.

I have no experience with using freetype directly but see if you can create it with an alpha channel. If you were using SDL_ttf I would be telling you to use the TTF_Render*_Blended functions (to produce a text with transparent background) instead of TTF_Render*_Shaded functions (which produces a text with an opaque background of a specific colour).

To Peter87: I don’t think they are using the ttf library to load the image, if you look at their line with SDL_CreateRGBSurfaceWithFormatFrom, the data is coming from a pixel-data buffer called slot->bitmap.buffer. This doesn’t rule out the ttf lib, but it’s a strange route to take.

I think we need to see a lot more code before further help can be provided, all I can say is that the provided code snippets seem to be “correct”.

This post was all wrong.

I know. That’s why I started with If you were using SDL_ttf…

The reason I mentioned it was just in case the freetype library worked similar.

Ah, actually, I forgot that they said what lib they were using… Sorry.
Hey, but actually looking at that line, is SDL_PIXELTYPE_INDEX8 something you’d expect to see in the place of a SDL_PIXELFORMAT value? Since I loaded directly from a bmp I did not test that, but I think that’s supposed to be a value from the Pixel Format Values table instead of from the tables in the remarks section.

The code says SDL_PIXELFORMAT_INDEX8 which is one of the official pixel format values. But yeah, it probably needs to be some other format with a proper alpha channel.

Ack!
Attention disorder overload. I’m going to take a break from the internet for today so I don’t embarrass myself further.
Thanks Peter87.

Thanks for the responses, It was in fact due to the pixel format type. I managed to solve the problem with the following:

        uint32_t *argb_pixels = (uint32_t*)(new_surf->pixels);    // ARGB surface
        uint8_t *bw_pixels = (uint8_t*)(surf->pixels);                   // 8bit surface as given by freetype
        for (int y = 0; y < slot->bitmap.rows; y++) {
            for (int x = 0; x < slot->bitmap.width; x++) {
                uint32_t *p = argb_pixels++;
                uint8_t bwp = *(bw_pixels + x + (y * slot->bitmap.width));
   
                if (bwp > 0) { fmt::print("@");   *p = 0x000000ff; }
                else if (bwp == 0) { fmt::print(".");  *p = 0x0000ffff; }
            }
            fmt::print("\n");
        }

        uint32_t colorkey = SDL_MapRGB(new_surf->format, 0, 0xff, 0xff);
        SDL_SetColorKey(new_surf, SDL_TRUE, colorkey);
        SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, new_surf);

Instead of setting *p’s blue channel to its full 0x000000ff, I’m going to use the intensity provided by bwp to hopefully get the antialiasing.

On that note, regarding antialiasing and combining this with another texture, do I need to do more than setting SDL_BLENDMODE_BLEND prior to the RenderCopy call?

Was wondering what the standard (or better) approach was

cheers

edit: I’ll take a quick gander at SDL TTF, my approach might be rather naive