02.05 - Resolution and Color Depth

Started by
21 comments, last by Teej 21 years, 1 month ago
Anon: As I''ve stated above, we do start by figuring out how much red, green and blue we''d like in a pixel. Depending on the color mode that you are working with, there''s a maximum value allowed for each of these color components. If we are talking about a simple 8.8.8 RGB pattern, then yes, we just take each value and dump it into memory. If however we''re using another mode (e.g. 5.6.5), you need to think in terms of bits and not bytes. Of course, we don''t do this stuff manually...here''s an example of a macro that takes RGB values and creates a single value for us:

#define RGB16((r << 11) | (g << 5) | b)

Here, we assume 5 bits for red, 6 bits for green and 5 bits for blue. Since 5 bits can store 32 possible values, that''s the range you''re allowed for that color. So here''s our layout:

RED: 0-31
GREEN: 0-63
BLUE: 0-31

Drop your choices into the macro and the computer will handle all of the bit merging needed to make the final color value.

Teej

Advertisement
Better late than never. . .

Ok, there's a lot of stuff I'd liek some explanations about.

I never used this kind of hex code in my courses (0x00FF00)
So I'd liek to know how it is used, when why and whatnot.
Same thing with BYTE.
Is this some DirectX only type? Why is it all caps (unlike other types)? Where does it come from??? Did I miss a typedef or what?

the SIMPLIFY THINGS section to me is kinda absurd because I never used macros in C/C++. . . doesn't simplify much I'll tell you that

Then , there's those << and | operators.
I know << is for switching, butI only been introduced to this concept in an old assembly class and am in the fog as to what it does here. The pipe | is the bitwise operator IIRC but I fail to get it's meaning purpose and goal in the code.

#define RGB16((r << 11) | (g<< 5)| b)


BTW, this site is slooooooooow.






Edited by - Diabolus on May 7, 2001 9:40:26 PM

Edited by - Diabolus on May 8, 2001 12:42:47 PM
Ð!@ßأܧ
ok, this is just how i resolved 0x07E0 would be the appropriate value of 15bit GREEN
since u cannot work on subsets of bytes(8bits) here , you should work on the bit-basis, like teej and the others said:

15bit color means u have 3 times 5 bits that represent RED, GREEN, BLUE

5 bits means u can have 32 values (0-31) because 2^5 = 32

we want to have a green with maximum intensity which would look like this:

00000 11111 00000
red green blue

but this is only in binary, how do we get it into 07E0 hex?
this goes back to the general question why base16 (hex) is such a common base when it comes to bits and bytes.

4 bits can have 16 (0-15)values: 1111 = 15 = F (hex)

so any group of four bits can be converted to exactly one digit in hex.

to convert the 15bits to hex we simply regroup them to groups of 4 starting on the RIGHT:

old: 00000 11111 00000
new: 000 0011 1110 0000

note that we still have the same binary number as before, just another groupung.

now we can convert each group into hex easily:

bin: 000 0011 1110 0000
hex: 0 3 E 0

each group in detail:

000 = 0
0011 = 3
1110 = E
0000 = 0

GREEN = 0x03E0



red would be:

11111 00000 00000

new grouping:

bin: 111 1100 0000 0000
hex: 7 C 0 0

RED = 0x07E0

(111 is regarded as 0111 = 7hex)

hope this helps?


concerning the macros i think i have to go read my c-books

awesome job, teej

cyas

marlowe

Edited by - marlowe on May 22, 2001 1:03:46 PM
marlowe: You''re very close to understanding what the macros do...for everyone interested, here goes:

The operators >> and << are bit-shifters. Just as the way they ''point'', that''s the direction bits get shifted, and the number you give represents the number of bits to shift over. Here''s that macro again:

#define RGB16 ( (r << 11) + (g << 5) + b)

In english, it reads "Take the value of r and shift it 11 bits over. Take the value of g, shift it 5 bits over and add it to the result of the r-shift. Finally, add the value of b."

It helps for this macro to think in terms of bits. Since r and b can get any value between 0 (0 0000) and 31 (1 1111), and g can be any value between 0 (00 0000) and 63 (11 1111), we can take their binary representations and literally ''shove'' them over to the left.

First, let''s use the letters r,g,b in an example.

Here''s what the final value should look like:

rrrrrggggggbbbbb

Notice how you can create this value by taking each component and lining up the bits like so:

rrrrr00000000000
00000gggggg00000
00000000000bbbbb

What the macro is designed to do is exactly what you see here. If we take r''s 5 bits and shift them over 11 times to the left, they fall into the correct place for our final 16-bit value. Likewise, shifting g over 5 places lines it up properly, and b only needs to be added in -- no shifting is necessary.

Pretend that we wanted to create the following value:

aaabbccccdddeeee

What rules do we need to apply to create this value? Since values start from the right-hand side like so:

0000 0000 0000 0aaa
0000 0000 0000 00bb
0000 0000 0000 cccc
0000 0000 0000 0ddd
0000 0000 0000 eeee

...you can easily visualize how far each value needs to be moved to get to its proper place:

a << 13
b << 11
c << 7
d << 4
e

...and here''s the resulting macro:

#define EXAMPLE( (a<<13) + (b<<11) + (c<<7) + (d<<4) + e)

It''s important that the values used in the macro actually fit in the number of bits allowed. For instance, our RGB16 macro will give improper results if r>31, g>63 or b>31. If we wanted to, we could have checked these values in the macro like so:

#define RGB16 ( ((r%32)<<11) + ((g%64)<<5) + (b%32) )

The modulo operator gives the remainder of a division, and works well for ranges such as this. And in case you''re not well-versed with using ''%'', here''s a quick table to convince you:

1 % 5 = 1 (0, remainder 1)
2 % 5 = 2 (0, remainder 2)
3 % 5 = 3 (0, remainder 3)
4 % 5 = 4 (0, remainder 4)
5 % 5 = 0 (1, remainder 0)
6 % 5 = 1 (1, remainder 1)
7 % 5 = 2 (1, remainder 2)
8 % 5 = 3 (1, remainder 3)
9 % 5 = 4 (1, remainder 4)
10 % 5 = 0 (2, remainder 0)
11 % 5 = 1 (2, remainder 1)

What this pattern shows is that for any number you give it (first column), you''ll always get 0 to n-1 for the divisor you choose (second column).

Here''s another very useful example:

rand() returns a pseudo-random number between 0 and 32,767. If you wanted say a number between 0 and 31, you could use:

rand() % 32

Just as with the table above, this will give categorize all possible values into the range 0-31, which is what you want.

There ya go.

Teej



Hey - great tutorial teej... I think Im finally starting to understand stuff.

Just one query - is there any particular reason for the extra bit being given to green in 16bit color mode? (as opposed to red or blue I mean)... just seems a bit random.

thanx.
Java is far less fun than holding my head down a toilet for several hours.
The order of the color on the C64 number keys is:

1 Black
2 White
3 Red
4 Cyan
5 Green
6 Blue
8 Yellow

Impressed??

Anyway.. Nice tutorial..

(To be honest i had to look on my good ol'' Commodore to remember what color the number 4 key was....)


Will code anything for free beer!
I have a question about something near the beginning of the article. I don''t understand how in 640x480 resolution there are only 307x200 pixels on the screen. Please help me understand this.
I think you''ve just misread what Teej has said.
If the dimesions of the screen are 640x480 then there are 307,200 visible pixels on the screen not 307x200
Oops...my bad. My computer clock is off and it wasn't 9:30. It was more like 2:30 in the morning, and I was really tired. Sorry about that.

Edited by - Minion on June 12, 2001 9:04:44 PM
So far this tutorial has been great! Impressive read. Just wish I had more time to devote to it NOW...

Anyway, I''ve got a semi-related question, about the various bitwise operators...

Teej, you''ve used a couple macros here to assemble color components into a single hex value, ie:
#define RGB16((r << 11) | (g << 5) | b)

But, say you wanted to deconstruct a hex value into it''s corresponding color components? Would something like this work, or am I in crack heaven?

#define R16((c & 0xFF0000) >> 11) // to get the Red component of a 16-bit pixel value ''c''
#define G16((c & 0x00FF00) >> 5) // to get the Grn component
etc.

??

(Just trying to get a better understanding of bitwise functions and bitmasks..

Thanks!

This topic is closed to new replies.

Advertisement