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