Hi,
I have a question about SDL regarding bits-per-pixel. By default it's set to 32 I think, but you could change that depth to 16 or 8 etc. I understand that it means X bits designated to storing the RGB values. However when trying to manipulate pixels, I noticed that it seems to have "imbalanced" storage. With 8 BPP, there are 3 bits per R, 3 bits per G, 2 bits per blue. With 16 BPP, there are 5 bits R, 6 bits G, 5 bits B. Doesn't that mean one channel has 2x the amount of color values than the other channels...and if so... isn't that.. bad?
My main question is, is that standard bit storage (16: 5R,6G,5B .. 8: 3R, 3G, 2B), or is that just how SDL happens to store it?
The reason I'm worrying about something like this is I'm trying to specifically use a very low BPP palette, and I want to index exact colors, and having the individual channels be different widths is kind of throwing things off.
Thank you for any advice!
1 2 3 4 5 6 7 8
#define BPP 16
// ..
SDL_Surface SCREEN = NULL;
SCREEN = SDL_SetVideoMode(640, 480, BPP, SDL_SWSURFACE);
// ..
// ..
unsignedshort pixel = (*(unsignedshort*)SCREEN->pixels);
// pixel- is just the value representing the 0,0 pixel from SCREEN
LowestOne, see, what you said WOULD make sense to me. Especially for 16-bits, it'd be 1bit alpha, 5,5,5. That'd make perfect sense to me. But I did some tests with with 16-bpp (unsigned short per pixel)
here suddenly the R and G channels are the ones that have more bits.
Technically, using something like 6-bpp or 9-bpp should be possible, since it would then be an even 2 bits per channel, or 3 bits per channel, but SDL fails to initialize when trying to set BPP to values like that.
Let me try to give more detail and re-explain my issue.
I manually created an intentionally low-bit color palette. It is technically a 6-bit palette, since it's 2 bits per channel. This only allows 0,1,2,3 for each channel, which results in 64 total colors (4*4*4). The method I used to generate the palette was literally 3 nested (i=0;i<4) for loops, where it would multiply the index(i) by a pre-set value. First I used 64, but then I changed it to 80. What that means is, my colors for "Blue" can be the following:
00 Blue = 0,0,0
01 Blue = 0,0,80
10 Blue = 0,0,160
11 Blue = 0,0,240
simple right? This means that if I take a screenshot of my "black" color, it's 0,0,0 and if I take a screenshot of my "white" color, it's 240,240,240. Perfectly fine.The math is easier when the color 'steps' are perfectly even values (in this case, 80.).
However.. like I mentioned, in SDL the pixel format (namely for 8 bits-per-pixel) is 3bits R, 3bits G, 2bits B. Let's just talk about the Blue channel first, since it's 2 bits wide, and my palette is 2 bits wide. Should be no issue, right? Well actually there is an issue, because it seems that:
00 Blue = 0,0,0
01 Blue = 0,0,85
10 Blue = 0,0,170
11 Blue = 0,0,255
It increments in an even '85' each step, which isn't really what I wanted. I'd literally have to increase the bit depth in order to get the colors I want? (0,80,160,240) ?
Even worse is looking at one the R or G channel (3bits wide). Those colors produced (checked by PrtScrn) are:
000 Green = 0,0,0
001 Green = 0,36,0 (+36)
010 Green = 0,73,0 (+37)
011 Green = 0,109,0 (+36)
100 Green = 0,146,0 (+37)
101 Green = 0,182,0 (+36)
110 Green = 0,219,0 (+37)
111 Green = 0,255,0 (+36)
As you can see, this is kind of gross because it's not incrementing the same amount each time because it has to end up at 255 as evenly as possible. Now, I understand WHY it increments this way: if it did something neater such as: 0,32,64,96,128,160,192, 224, yes it would be neater, but it would be "wasting" any colors that exist that are brighter than 224.(224-255). I understand that, but I'm trying to get it to behave differently and use my colors instead. (i.e. 0,40,80,160)
Is that in any way possible?
The only thing I can think of is INCREASING the bit depth up until the point where I can stick my desired values in the RGB values cleanly, but that seems kind of silly to increase the BPP so that a "smaller" number can fit properly! :)
The surface returned from SDL_SetVideoMode will never have an alpha channel. 24 and 32 bit depth will use 8 bits for each red, green and blue, so 8 bits are unused if 32 bit is used.
You can use SDL_PixelFormat that LowestOne linked to get the exact format of each type. Note that 8-bit uses a palette.
If not too slow it's probably easiest to use SDL_GetRGB and SDL_MapRGB to convert between the pixel value and 8 bits red, green and blue.
Ahh, that helps a lot. So, since 8 bits per channel means there's possible values 0-255, I should always be able to get the exact value I need by using 24bpp and a normal incremental algorithm. I suppose then that the only difference between 24bit and 32bit color is that the 32bit gets 8 extra bits for alpha or something.
Thank you both very much. Working with manual pixel colors is certainly fun. :)