SDL surface pixel color/bits-per-pixel

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);
  // ..
  // ..
  unsigned short pixel = (*(unsigned short*)SCREEN->pixels);
  // pixel- is just the value representing the 0,0 pixel from SCREEN 
I dont think the amounts are imbalanced, it seems you are forgeting about alpha. A 32 bit color is generally 0xRRGGBBAA, giving 8 bits per color.

Check out GetVideoInfo():
http://www.libsdl.org/cgi/docwiki.fcg/SDL_VideoInfo
particuallry the SDL_PixelFormat member
http://www.libsdl.org/cgi/docwiki.fcg/SDL_PixelFormat
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)

255,0,0 = 11111000 00000000
0,255,0 = 00000111 11100000
0,0,255 = 00000000 00011111

With 8 bits it's:

255,0,0 = 11100000
0,255,0 = 00011100
0,0,255 = 00000011

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. :)
Last edited on
Topic archived. No new replies allowed.