Home > Mobile >  How to blit a transparent surface onto screen ie. for it to not be displayed
How to blit a transparent surface onto screen ie. for it to not be displayed

Time:12-11

Hey I'm trying to find out which channel is alpha.
But everytime I blit what I think should be a completely transparent surface it turns out to modify the RGB channels as well.
SDL 1.2-master

Here's my code and what I've problem with:

#include <SDL/SDL.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
int main(int argc, char** argv) {
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == -1) {
        fprintf(stderr, "Couldn't initialize SDL: %s.\n", SDL_GetError());
        exit(-1);
    }

    SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
    if(!modes) {
        printf(":(\n");
        return 1;
    }
    
    SDL_Surface* screen = SDL_SetVideoMode(modes[0]->w, modes[0]->h, 0, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);
    if(!screen) {
        printf(":(\n");
        return 1;
    }

    SDL_Surface* surface = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA, 32, 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    if(!surface) {
        printf(":((\n");
        return 1;
    }

    for(int i=0; i!=32; i  ) {
        for(int j=0; j!=32; j  ) {
            // 0 blue
            // 1 green
            // 2 red
            // 3 alpha?
            ((char*)(surface->pixels))[0 i*4*32 j*4] = 0xff;
            ((char*)(surface->pixels))[1 i*4*32 j*4] = 0xff;
            ((char*)(surface->pixels))[2 i*4*32 j*4] = 0xff;
((char*)(surface->pixels))[3 i*4*32 j*4] = 0xff; // SDL_OPAQUE_ALPHA is 0xFF

            // not an alpha channel
        }
    }
    int ret = SDL_BlitSurface(surface, NULL, screen, NULL);

SDL_Flip(screen);
sleep(2);

    for(int i=0; i!=32; i  ) {
        for(int j=0; j!=32; j  ) {
            // 0 blue
            // 1 green
            // 2 red
            // 3 alpha?
            ((char*)(surface->pixels))[0 i*4*32 j*4] = 0x30;
            ((char*)(surface->pixels))[1 i*4*32 j*4] = 0x40;
            ((char*)(surface->pixels))[2 i*4*32 j*4] = 0x50;
((char*)(surface->pixels))[3 i*4*32 j*4] = 0x00;// This surface should be transparent, SDL_TRANSPARENT_ALPHA is 0

            // not an alpha channel
        }
    }
    int ret = SDL_BlitSurface(surface, NULL, screen, NULL);
    
    while(1) {
        SDL_Flip(screen);
//if the color is anything but pure white, alpha channel modification failed.
    }
}

I basically need this code working for font handling. For now I do one surface per glyph(Yeah I should do something else). I need to be able to set the alpha channel to a value of the surface and have a guarantee that if the alpha is set to partial/full transparency that the RGB values of the texture don't get blitted.

CodePudding user response:

Consider this example:

void main(void) {
    unsigned int t = 0x000000ff;
    unsigned char *ct = (unsigned char*)&t;
    printf("0x%x 0x%x 0x%x 0x%x\n", ct[0], ct[1], ct[2], ct[3]);
}

On little-endian machine (i.e. most machines nowadays) it will output 0xff 0x0 0x0 0x0. You set alpha mask to 0x000000ff, meaning when you access pixels your byte offset for alpha channel is 0 (i.e. in memory it is placed as A,B,G,R).

On a big-endian machine the output would be 0x0 0x0 0x0 0xff, as byte order in integer is opposite (R,G,B,A in memory).

If you look at SDL 1.2 documentation for SDL_CreateRGBSurface you may notice that example code checks for SDL_BYTEORDER and reverses masks upon surface creation to keep consistent byte order.

You already set SDL_SRCALPHA flag upon surface creation, so no SDL_SetAlpha is required; but when you set surface values you set alpha value to incorrect offset, as alpha is at offset 0 (if you're on little-endian machine).

  •  Tags:  
  • csdl
  • Related