Dealing with colors

I have some questions about the format of a pixel used by different modes:

  1. in 8 bbp, does the SDL_MapRGB() searches for an entry into the palette
    similar to the requested color and returns its color number into the
    palette? Writing a number of a color into a pixel seems infact to work…

  2. in 16bpp mode, shouldn’t the three components be respectively 5, 6 and 5
    bits wide? if so, does SDL make a conversion, translating them in 8bit
    values? I tried to write 255, 255, 255 to obtain white, and I got, but the
    actual colors written (or, at least, the ones returnet by SDL_GetRGB() )
    were 248, 252, 248( printing the color Uint32 value, i gor 65535, and this
    is right…). How does all this work?

  3. In a 16bit file, aren’t the components stored using 5, 6 and 5 bits for
    the 3 components? How should I deal with is, building my own loading
    functions?

  4. What are RGB shift, mask and loss, into the format structure, used for?

  5. Finally, how are the various modes managed? I mean: determining the
    color, the pitch, how the various bits are packet into one ore more bytes
    (i.e: 12bpp mode, 15 bpp mode…), conversions during blits, etc…

Thanx a lot… (the docs don’t contain anything about this stuff, and
making experiments and watching code examples is not enough…)

Marco Iannaccone @Marco_Iannaccone
ICQ: 18748121 Tolkien

“I’ve… seen things you people wouldn’t believe. Attack ships on fire off
the shoulder of Orion.
I watched C-beams… glitter in the dark near the Tanhauser Gate. All
those… moments will be lost… in time…, like… tears… in… rain.”

FAQ it.comp.lang.c: http://www.programmazione.it/linguaggi/c/itcomplangc.htm
FAQ it.comp.lang.c++: http://www.programmazione.it/linguaggi/c/lang_faq.htm

  1. in 8 bbp, does the SDL_MapRGB() searches for an entry into the palette
    similar to the requested color and returns its color number into the
    palette? Writing a number of a color into a pixel seems infact to work…

Yes, this is how it’s supposed to work

  1. in 16bpp mode, shouldn’t the three components be respectively 5, 6 and 5
    bits wide? if so, does SDL make a conversion, translating them in 8bit
    values? I tried to write 255, 255, 255 to obtain white, and I got, but the
    actual colors written (or, at least, the ones returnet by SDL_GetRGB() )
    were 248, 252, 248( printing the color Uint32 value, i gor 65535, and this
    is right…). How does all this work?

SDL_GetRGB() returns the values rescaled to 8 bits/component. SDL <= 1.1.4
just returns the bit fields shifted left the appropriate amount (which
is why you get (248,252,248) as white). This has been fixed in SDL CVS,
where it does slightly better rescaling (so SDL_GetRGB will return
16-bit white as (255, 255, 255)).
(Martin, how about clarifying this in the docs?)

  1. In a 16bit file, aren’t the components stored using 5, 6 and 5 bits for
    the 3 components? How should I deal with is, building my own loading
    functions?

Few file formats support 16 bit pixel formats. BMP and TGA do, and
SDL/SDL_image can load those (but SDL_SaveBMP won’t save anything in
that format). Most people use a 24-bit file format instead (PNG, TGA,
JPEG, BMP, PPM, PCX, …), but if you make your own file format you have
to write your own loader of course. It is usually not worth the trouble.

  1. What are RGB shift, mask and loss, into the format structure, used for?

“mask” is the bitmask for that particular bit field (ones covering the
bit field, zeroes elsewhere). “shift” is number of bits to the right
of the bit field. “loss” is 8 - (bit field size in bits).

Example: RGB565:
Rmask = 0b1111100000000000 = 0xf800, Rshift = 11, Rloss = 3
Gmask = 0b0000011111100000 = 0x07e0, Gshift = 5, Gloss = 2
Bmask = 0b0000000000011111 = 0x001f, Bshift = 0, Bloss = 3

They are of course used for the pixel value <-> RGB values conversion.

  1. Finally, how are the various modes managed? I mean: determining the
    color, the pitch, how the various bits are packet into one ore more bytes
    (i.e: 12bpp mode, 15 bpp mode…), conversions during blits, etc…

Formats that are fully supported are:
8bpp indexed
15, 16bpp (555, 565)
24bpp (not very fast)
32bpp (with or without alpha channel)

Semi-supported (i.e. may work but usually not optimised)
1bpp bitmaps
odd bit field divisions (like ARGB4444 in 16bpp)

Thanx a lot… (the docs don’t contain anything about this stuff, and
making experiments and watching code examples is not enough…)

Then you haven’t done enough experiments, and haven’t read enough code.
Both SDL’s source and other people’s code could be a guidance.

But ask away if you have any questions. That’s what this list is for. :slight_smile:

SDL_GetRGB() returns the values rescaled to 8 bits/component. SDL <= 1.1.4
just returns the bit fields shifted left the appropriate amount (which
is why you get (248,252,248) as white). This has been fixed in SDL CVS,
where it does slightly better rescaling (so SDL_GetRGB will return
16-bit white as (255, 255, 255)).
(Martin, how about clarifying this in the docs?)

  1. In a 16bit file, aren’t the components stored using 5, 6 and 5 bits
    for

the 3 components? How should I deal with is, building my own loading
functions?

Few file formats support 16 bit pixel formats. BMP and TGA do, and
SDL/SDL_image can load those (but SDL_SaveBMP won’t save anything in
that format). Most people use a 24-bit file format instead (PNG, TGA,
JPEG, BMP, PPM, PCX, …), but if you make your own file format you have
to write your own loader of course. It is usually not worth the trouble.

So, in a image file, a 16bit pixel is stored as 5,6,5 or 8, 8, 8? And 15bit?
Are the values of the components of a color of the palette, in 8 bpp, stored
as 8,8,8 or 6, 6, 6?
(I’m asking this, cause I programmed in the VGA under DOS in 13h mode
(3202008bpp),
and only six bits were used for every color component…
If, for exemple in 16bpp, the components are stored in a file as 5,6,5 bits,
does the LoadBmp()
function permorm a shift, using the mask, loss, and mask values?

  1. What are RGB shift, mask and loss, into the format structure, used
    for?

“mask” is the bitmask for that particular bit field (ones covering the
bit field, zeroes elsewhere). “shift” is number of bits to the right
of the bit field. “loss” is 8 - (bit field size in bits).

Example: RGB565:
Rmask = 0b1111100000000000 = 0xf800, Rshift = 11, Rloss = 3
Gmask = 0b0000011111100000 = 0x07e0, Gshift = 5, Gloss = 2
Bmask = 0b0000000000011111 = 0x001f, Bshift = 0, Bloss = 3

They are of course used for the pixel value <-> RGB values conversion.

You mean Rloss = 0, isn’t it?
With “bit field” you mean the bits used for a particular color component,
right?

Then you haven’t done enough experiments, and haven’t read enough code.
Both SDL’s source and other people’s code could be a guidance.
You’re right, but, for a newbie, having a guide is better…

Thanx!

Marco Iannaccone @Marco_Iannaccone
ICQ: 18748121 Tolkien

“I’ve… seen things you people wouldn’t believe. Attack ships on fire off
the shoulder of Orion.
I watched C-beams… glitter in the dark near the Tanhauser Gate. All
those… moments will be lost… in time…, like… tears… in… rain.”

FAQ it.comp.lang.c: http://www.programmazione.it/linguaggi/c/itcomplangc.htm
FAQ it.comp.lang.c++: http://www.programmazione.it/linguaggi/c/lang_faq.htm

Example: RGB565:
Rmask = 0b1111100000000000 = 0xf800, Rshift = 11, Rloss = 3
Gmask = 0b0000011111100000 = 0x07e0, Gshift = 5, Gloss = 2
Bmask = 0b0000000000011111 = 0x001f, Bshift = 0, Bloss = 3

They are of course used for the pixel value <-> RGB values conversion.

You mean Rloss = 0, isn’t it?

Sorry, I was wrong…
Anyway, what’s the purpose of RGBloss?
And Mask? And Shift?

Marco Iannaccone @Marco_Iannaccone
ICQ: 18748121 Tolkien

“I’ve… seen things you people wouldn’t believe. Attack ships on fire off
the shoulder of Orion.
I watched C-beams… glitter in the dark near the Tanhauser Gate. All
those… moments will be lost… in time…, like… tears… in… rain.”

FAQ it.comp.lang.c: http://www.programmazione.it/linguaggi/c/itcomplangc.htm
FAQ it.comp.lang.c++: http://www.programmazione.it/linguaggi/c/lang_faq.htm

Example: RGB565:
Rmask = 0b1111100000000000 = 0xf800, Rshift = 11, Rloss = 3
Gmask = 0b0000011111100000 = 0x07e0, Gshift = 5, Gloss = 2
Bmask = 0b0000000000011111 = 0x001f, Bshift = 0, Bloss = 3

They are of course used for the pixel value <-> RGB values conversion.

You mean Rloss = 0, isn’t it?

Sorry, I was wrong…
Anyway, what’s the purpose of RGBloss?
And Mask? And Shift?

Marco Iannaccone @Marco_Iannaccone
ICQ: 18748121 Tolkien

“I’ve… seen things you people wouldn’t believe. Attack ships on fire off
the shoulder of Orion.
I watched C-beams… glitter in the dark near the Tanhauser Gate. All
those… moments will be lost… in time…, like… tears… in… rain.”

FAQ it.comp.lang.c: http://www.programmazione.it/linguaggi/c/itcomplangc.htm
FAQ it.comp.lang.c++: http://www.programmazione.it/linguaggi/c/lang_faq.htm

So, in a image file, a 16bit pixel is stored as 5,6,5 or 8, 8, 8? And 15bit?

That depends on the file format, of course. TGA only stores the 555 format,
and I think BMP does too. http://www.wotsit.org/ has descriptions
of various file formats.

Are the values of the components of a color of the palette, in 8 bpp, stored
as 8,8,8 or 6, 6, 6?

Again this depends on the file format. You are free to invent your own
bizarre format (and far too many people have). Usually 8 bits per component
are stored in most common formats.

If, for exemple in 16bpp, the components are stored in a file as 5,6,5 bits,
does the LoadBmp()
function permorm a shift, using the mask, loss, and mask values?

The file reading functions usually create a surface of the same format
as the pixels in the file, if possible. Go and read the source.

You’re right, but, for a newbie, having a guide is better…

No, sorry. There’s no shortcut, you have to do some work yourself.

Marco Iannaccone wrote:

Example: RGB565:
Rmask = 0b1111100000000000 = 0xf800, Rshift = 11, Rloss = 3
Gmask = 0b0000011111100000 = 0x07e0, Gshift = 5, Gloss = 2
Bmask = 0b0000000000011111 = 0x001f, Bshift = 0, Bloss = 3

They are of course used for the pixel value <-> RGB values
conversion.

Anyway, what’s the purpose of RGBloss?
And Mask? And Shift?

SDL Color Channel Manipulation

First some terms:

loss = bits lost in the conversion.
shift = position of channel within a pixel.
mask = color channel bitmask.

The “loss” is the number of bits lost in a color channel conversion. The
term “loss” indicates precision loss (i.e. you lose the lower 3 bits when
you stuff an 8-bit value into a 5-bit field).

The “shift” is used to move the channel into position within the pixel after
shifting out the loss.

The “mask” can be used in its inverted form (~mask) to clear a color
channel. It can also be used to get rid of the extra bits when reading a
channel.

Examples:

The following code sets the red channel in a pixel. Note that the mask is
used to clear the old bits in the channel before the new bits are set.

Uint32 pixel;
Uint8 red;

/* clear the old red bits */
pixel &= ~format->Rmask;

/* set the new red bits */
pixel |= ((red >> format->Rloss) << format->Rshift);

The following code reads the green channel from a pixel. Note that shifts
are in the opposite order and direction when reading a color channel.

Uint32 pixel;
Uint8 green;

/* read the green channel */
green = ((pixel & format->Gmask) >> format->Gshift) << format->Gloss;

  • Randi

Regimental Command
Generic Armored Combat System
http://regcom.sourceforge.net

Mattias Engdeg?rd wrote:

SDL_GetRGB() returns the values rescaled to 8 bits/component.
SDL <= 1.1.4 just returns the bit fields shifted left the
appropriate amount (which is why you get (248,252,248) as
white). This has been fixed in SDL CVS,where it does slightly
better rescaling (so SDL_GetRGB will return 16-bit white as
(255, 255, 255)).

Has this been committed to CVS yet? I don’t have CVS access here but the
latest 8/29/2000 CVS snapshot has the same rescaling in it and the
SDL_pixels.c file is dated 8/6/2000.

I think that quantization correction basically boils down to copying the
upper “n” bits (of an 8-bit channel byte) into the lower “n” bits where "n"
is the loss for the individual channel. This distributes the quantization
error over the sample.

  • Randi

Regimental Command
Generic Armored Combat System
http://regcom.sourceforge.net

Randi J. Relander wrote:

I think that quantization correction basically boils down to
copying the upper “n” bits (of an 8-bit channel byte) into
the lower “n” bits where “n” is the loss for the individual
channel. This distributes the quantization error over the
sample.

Which is just an 8-bit rotate instead of a shift … :slight_smile:

Where is my C rotate operator! What do you mean I can't access the carry flag!
  • Randi

Regimental Command
Generic Armored Combat System
http://regcom.sourceforge.net

Randi J. Relander wrote:

Randi J. Relander wrote:

I think that quantization correction basically boils
down to copying the upper “n” bits (of an 8-bit channel
byte) into the lower “n” bits where “n” is the loss for
the individual channel. This distributes the quantization
error over the sample.

Which is just an 8-bit rotate instead of a shift … :slight_smile:

Hmmm … nope, not a rotate. (Never mind :slight_smile:

I guess it would look something like the following:

r |= (r >> (8 - image->Rloss));
g |= (g >> (8 - image->Gloss));
b |= (b >> (8 - image->Bloss));

  • Randi

Regimental Command
Generic Armored Combat System
http://regcom.sourceforge.net

Randi J. Relander wrote:

Hmmm … nope, not a rotate. (Never mind :slight_smile:

I guess it would look something like the following:

r |= (r >> (8 - image->Rloss));
g |= (g >> (8 - image->Gloss));
b |= (b >> (8 - image->Bloss));

Where “image” is a pixel format pointer that should be called “format” of
course … good grief, I give up :slight_smile:

Don’t drink too much coffee kids. <Brak, Cartoon Planet>

  • Randi

Regimental Command
Generic Armored Combat System
http://regcom.sourceforge.net

SDL_GetRGB() returns the values rescaled to 8 bits/component.

Has this been committed to CVS yet? I don’t have CVS access here but the
latest 8/29/2000 CVS snapshot has the same rescaling in it and the
SDL_pixels.c file is dated 8/6/2000.

It’s part of the big patch that sam has been to scared to apply yet :slight_smile:

I think that quantization correction basically boils down to copying the
upper “n” bits (of an 8-bit channel byte) into the lower “n” bits where "n"
is the loss for the individual channel. This distributes the quantization
error over the sample.

If you like. You can see it as a multiplication by 255 / 2**(n-1) as well,
and it’s easily derived by doing a power series expansion.
(No, I didn’t do it properly. It will fail for bit fields < 4 bits wide,
but they seem to be nonexistent. My only concern is 1-bit alpha, and whether
we should support it.)

Which is just an 8-bit rotate instead of a shift … :slight_smile:

no, it’s a biased replication of a smaller bitfield inside a larger one

Where is my C rotate operator!

Few CPUs have rotate instructions, and for those who have it a C compiler
should be able to generate it from a shift + mask operation.
Besides, a rotate operator would have to be trinary to make sense
(operand, number of steps, and width)

What do you mean I can’t access the carry flag!

That is a more serious shortcoming of C, especially when doing multiprecision
arithmetic

It’s part of the big patch that sam has been to scared to apply yet :slight_smile:

grin Have the semantics of alpha blending to an RGBA surface been
settled yet? I haven’t seen a whole lot of discussion on them.

(No, I didn’t do it properly. It will fail for bit fields < 4 bits wide,
but they seem to be nonexistent. My only concern is 1-bit alpha, and whether
we should support it.)

I think not, as it boils down to a special case of transparency.

Comments?
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

It’s part of the big patch that sam has been to scared to apply yet :slight_smile:

grin Have the semantics of alpha blending to an RGBA surface been
settled yet? I haven’t seen a whole lot of discussion on them.

Not quite, but it only affects a small part of the patch anyway, and
will be easy to correct later. I think it’s more important to get the
alpha flip firmly bolted both into the code and into people’s minds,
so that they can test it out, find bugs, and convert their own code.
Almost all use of alpha channels will be of the RGBA->RGB variety
anyway, and there’s no disagreement there :slight_smile:
(It would also help prevent patch rot.)

I think we should eventually support premultiplied alpha in SDL for
a variety of reasons, but we can do it in baby steps and ponder it
for a while until we find out what we really need. We probably also want
to allow for non-premultiplied alpha as well (since that is what
most image file formats use).

(No, I didn’t do it properly. It will fail for bit fields < 4 bits wide,
but they seem to be nonexistent. My only concern is 1-bit alpha, and whether
we should support it.)

I think not, as it boils down to a special case of transparency.

That has been my view as well — most cases of ARGB1555 can be
transformed to RGB555+colourkey by setting all transparent pixels to
the same value (= the colour key). We can’t handle dynamic change of
the transparent bit, but then Don’t Do That™.

I was browsing the G4’s vector instruction set (AltiVec) yesterday,
and wow - if we only had this on all platforms… It’s cooler than any
other I’ve seen, including VIS, MMX, SSE, 3DNow. Anyway, AltiVec
has an 8888->1555 packing instruction (8 pixels with one single
instruction!), so maybe it’s something used by modern Macs.